Skip to content

Commit

Permalink
Decouple DecisionContext and DecisionValueContext (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrezero authored Jan 24, 2025
1 parent b016834 commit 8fb2d66
Show file tree
Hide file tree
Showing 66 changed files with 245 additions and 298 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { decisionLoader } from '../../../../../decisions';
import {
createColorValue,
createDecisionContext,
createDecisionValueContext,
createSpaceValue,
} from '@noodlestan/designer-decisions';

Expand Down
11 changes: 6 additions & 5 deletions docs/designer-decisions/src/pages/decision-models/[type].astro
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ export async function getStaticPaths() {
const { decisionType } = Astro.props;
const { Content } = await render(decisionType);
const decisions = store.records();
const records = store.records();
const decisionByModel = (m: DecisionModelMeta) => {
return decisions.filter(d => d.model === m.model)[0];
const decisionByModel = (meta: DecisionModelMeta) => {
// WIP make sure we use only decisions from the sample set (name includes "Sample")
return records.filter(record => record.model === meta.model)[0];
}
const decisionDataByModel = (m: DecisionModelMeta) => {
const d= decisionByModel(m)
const d = decisionByModel(m)
const [, decision] = store.decision({ $name: d.name });
const json = JSON.stringify(decision?.input(), null, 2);
const json = JSON.stringify(decision?.inputs()[0], null, 2);
return json;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/libs/designer-decisions/src/context/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @index(['./*.{ts,tsx}', '!./*.test.ts', '!./*.test.tsx', './!(private|parts|functions)*/index.{ts,tsx}'], f => `export * from '${f.path.replace(/\/index$/, '')}';`)
export * from './isLookupContext';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, expect, it } from 'vitest';

import type { LookupContexts } from '../types';

import { isLookupContext } from './isLookupContext';

describe('isLookupContext', () => {
it('returns true for a valid LookupContexts object', () => {
const validContext: LookupContexts = { all: [] };
expect(isLookupContext(validContext)).toBe(true);
});

it('returns false for an object missing the "all" property', () => {
const invalidContext = { some: [] };
expect(isLookupContext(invalidContext)).toBe(false);
});

it('returns false for null', () => {
expect(isLookupContext(null)).toBe(false);
});

it('returns false for non-object types', () => {
expect(isLookupContext(undefined)).toBe(false);
expect(isLookupContext('string')).toBe(false);
expect(isLookupContext(123)).toBe(false);
expect(isLookupContext([])).toBe(false);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { LookupContexts } from '../types';

export const isLookupContext = (contexts: unknown): contexts is LookupContexts => {
return typeof contexts === 'object' && contexts !== null && 'all' in contexts;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import type {
DecisionContext,
DecisionError,
DecisionInputBase,
DecisionRef,
DecisionRefResolver,
LookupContexts,
} from '../types';

export const createDecisionContext = (
ref: DecisionRef,
resolver: DecisionRefResolver,
owner: DecisionInputBase,
contexts: LookupContexts = { all: [] },
inputs: DecisionInputBase[],
): DecisionContext => {
const errors: DecisionError[] = [];

Expand All @@ -18,9 +18,9 @@ export const createDecisionContext = (
};

return {
ref: () => ref,
resolve: resolver,
owner: () => owner,
contexts: () => contexts,
inputs: () => inputs,
errors: () => errors,
hasErrors: () => Boolean(errors.length),
addError,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { DecisionContextsInput, LookupContexts } from '../types';

export const createLookupContexts = (contexts?: DecisionContextsInput): LookupContexts => {
export const createLookupContext = (contexts?: DecisionContextsInput): LookupContexts => {
const { all, any } = Array.isArray(contexts) ? { all: contexts } : contexts || { all: [] };

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { StaticDecisionMap, StaticInputMap } from '../inputs';
import type { Decision, DecisionContext, DecisionInputBase, DecisionRef } from '../types';

import {
createDecisionContext,
createInputNotFoundError,
createStaticStoreDecision,
createUnexpectedError,
} from '.';

export const createStaticDecisionMap = (inputStore: StaticInputMap): StaticDecisionMap => {
const _createDecision = (context: DecisionContext, inputs: DecisionInputBase[]) => {
try {
return createStaticStoreDecision(context, inputs);
} catch (error) {
const err = createUnexpectedError(context, error);
context.addError(err);
}
};

const resolver = <V = unknown>(
ref: DecisionRef,
): [DecisionContext, Decision<V> | undefined] => {
const inputs = inputStore.records(r => '$name' in ref && r.name === ref.$name); // WIP ref matching
if (inputs.length) {
const context = createDecisionContext(ref, resolver, inputs);
const decision = _createDecision(context, inputs);
return [context, decision as Decision<V>];
}
const context = createDecisionContext(ref, resolver, []);
const error = createInputNotFoundError(context, ref);
context.addError(error);
return [context, undefined];
};

return {
resolve: resolver,
};
};
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
import type { Decision, DecisionContext, DecisionInputBase, ParentValueContext } from '../types';
import type {
Decision,
DecisionContext,
DecisionInputBase,
DecisionValue,
LookupContexts,
ParentValueContext,
} from '../types';
import { createDecisionValueContext } from '../values';

import { getDecisionModelFactory } from '.';

export const createStaticStoreDecision = <V = unknown>(
context: DecisionContext,
input: DecisionInputBase,
decisionContext: DecisionContext,
inputs: DecisionInputBase[],
): Decision<V> => {
const modelFactory = getDecisionModelFactory<V>(input.model);
const model = modelFactory();
const produce = (context?: LookupContexts | ParentValueContext): DecisionValue<V> => {
const input = inputs[0]; // WIP match context
const modelFactory = getDecisionModelFactory<V>(input.model);
const model = modelFactory();

const produce = (parentContext?: ParentValueContext) => {
const valueContext = parentContext
? parentContext.createChildContext()
: createDecisionValueContext(context);
const valueContext = createDecisionValueContext(decisionContext, context, input);
return model.produce(valueContext, input.params);
};

const api: Decision<V> = {
input: () => input,
uuid: () => inputs[0].uuid,
type: () => inputs[0].model.split('/')[0],
name: () => inputs[0].name,
description: () => inputs[0].description,
inputs: () => inputs,
input: () => inputs[0], // WIP match context
model: () => inputs[0].model, // WIP match context
params: () => inputs[0].params, // WIP match context
produce,
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { DecisionContext, DecisionError } from '../../types';

export const createUnexpectedError = (context: DecisionContext, err?: unknown): DecisionError => {
const owner = `in "${context.owner.name}`;
const ref = context.ref();
const inRef = `in "${'$name' in ref ? ref.$name : ref.$uuid}"`; // WIP stringify ref
const errStr = err && ` Error: "${err instanceof Error ? err.stack : JSON.stringify(err)}"`;
const msg = `Unexpected error in ${owner}: ${errStr}.`;
const msg = `Unexpected error ${inRef}: ${errStr}.`;
return {
msg,
};
Expand Down
2 changes: 1 addition & 1 deletion packages/libs/designer-decisions/src/decisions/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @index(['./*.{ts,tsx}', './!(private|parts|functions)*/index.{ts,tsx}'], f => `export * from '${f.path.replace(/\/index$/, '')}';`)
export * from './createDecisionContext';
export * from './createDecisionFactory';
export * from './createLookupContexts';
export * from './createStaticDecisionMap';
export * from './createStaticStoreDecision';
export * from './errors';
export * from './getDecisionModelFactory';

This file was deleted.

This file was deleted.

3 changes: 0 additions & 3 deletions packages/libs/designer-decisions/src/helpers/index.ts

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 1 addition & 2 deletions packages/libs/designer-decisions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// @index(['./*.{ts,tsx}', './!(private|parts|functions)*/index.{ts,tsx}'], f => `export * from '${f.path.replace(/\/index$/, '')}';`)
export * from './constants';
export * from './sample-data';
export * from './decisions';
export * from './helpers';
export * from './inputs';
export * from './meta';
export * from './models';
export * from './primitives';
export * from './sample-data';
export * from './types';
export * from './values';
15 changes: 1 addition & 14 deletions packages/libs/designer-decisions/src/inputs/types.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import type {
Decision,
DecisionContext,
DecisionInputBase,
DecisionInputError,
DecisionRef,
DecisionRefResolver,
LookupContexts,
} from '../types';
import type { DecisionInputBase, DecisionInputError, DecisionRefResolver } from '../types';

export type StaticInputMap = {
hasErrors: () => boolean;
validationErrors: () => DecisionInputError[];
records: (filter?: (item: DecisionInputBase) => boolean) => DecisionInputBase[];
record: (ref: DecisionRef, contexts?: LookupContexts) => DecisionInputBase | undefined;
};

export type StaticDecisionMap = {
create: <V = unknown>(
input: DecisionInputBase,
contexts?: LookupContexts,
) => [DecisionContext, Decision<V> | undefined];
resolve: DecisionRefResolver;
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { DECISION_COLOR_OKLAB_CHROMA_SCALE } from '../../../constants';
import { isDecisionOfType } from '../../../helpers';
import type { ColorOklabChromaScaleDecision, DecisionUnknown } from '../../../types';

export const isColorOklabChromaScaleDecision = (
decision: DecisionUnknown,
): decision is ColorOklabChromaScaleDecision => {
return isDecisionOfType(decision, DECISION_COLOR_OKLAB_CHROMA_SCALE);
return decision.type() === DECISION_COLOR_OKLAB_CHROMA_SCALE;
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { DECISION_COLOR_OKLAB_CHROMA_VALUE } from '../../../constants';
import { isDecisionOfType } from '../../../helpers';
import type { ColorOklabChromaValueDecision, DecisionUnknown } from '../../../types';

export const isColorOklabChromaValueDecision = (
decision: DecisionUnknown,
): decision is ColorOklabChromaValueDecision => {
return isDecisionOfType(decision, DECISION_COLOR_OKLAB_CHROMA_VALUE);
return decision.type() === DECISION_COLOR_OKLAB_CHROMA_VALUE;
};
Loading

0 comments on commit 8fb2d66

Please sign in to comment.