@shirudo/ddd-kit 3.0.0-rc.12 → 3.0.0-rc.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -8
- package/dist/chunks/kit-errors.d.ts +25 -26
- package/dist/chunks/kit-errors.js +51 -52
- package/dist/chunks/kit-errors.js.map +1 -1
- package/dist/chunks/read-stream-pages.js +91 -1365
- package/dist/chunks/read-stream-pages.js.map +1 -1
- package/dist/chunks/snapshot-store.d.ts +79 -129
- package/dist/chunks/value-object.js +1275 -0
- package/dist/chunks/value-object.js.map +1 -0
- package/dist/index.d.ts +130 -390
- package/dist/index.js +200 -868
- package/dist/index.js.map +1 -1
- package/dist/money.d.ts +3 -3
- package/dist/money.js +3 -3
- package/dist/money.js.map +1 -1
- package/dist/state-machine.d.ts +227 -0
- package/dist/state-machine.js +673 -0
- package/dist/state-machine.js.map +1 -0
- package/dist/testing.d.ts +4 -4
- package/dist/testing.js +12 -11
- package/dist/testing.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-machine.js","names":["#snapshot","#evaluating"],"sources":["../src/domain/state-machine/errors.ts","../src/domain/state-machine/machine-data.ts","../src/domain/state-machine/definition.ts","../src/domain/state-machine/snapshot.ts","../src/domain/state-machine/transition.ts","../src/domain/state-machine/analyzer.ts","../src/domain/state-machine/domain-state-machine.ts"],"sourcesContent":["import { DomainError, KitWiringError } from \"../../errors/kit-errors\";\n\n/** No transition is defined for the input in the current state. */\nexport class InvalidDomainTransitionError extends DomainError<\"INVALID_DOMAIN_TRANSITION\"> {\n\tconstructor(\n\t\tpublic readonly state: string,\n\t\tpublic readonly inputType: string,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"INVALID_DOMAIN_TRANSITION\",\n\t\t\tmessage: `No domain transition from \"${state}\" on \"${inputType}\".`,\n\t\t});\n\t}\n}\n\n/** A defined transition was rejected by its domain guard. */\nexport class DomainTransitionGuardRejectedError extends DomainError<\"DOMAIN_TRANSITION_GUARD_REJECTED\"> {\n\tconstructor(\n\t\tpublic readonly state: string,\n\t\tpublic readonly inputType: string,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"DOMAIN_TRANSITION_GUARD_REJECTED\",\n\t\t\tmessage: `Domain transition guard rejected \"${inputType}\" from \"${state}\".`,\n\t\t});\n\t}\n}\n\n/** The machine definition violates its runtime contract. */\nexport class InvalidDomainMachineDefinitionError extends KitWiringError<\"INVALID_DOMAIN_MACHINE_DEFINITION\"> {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"INVALID_DOMAIN_MACHINE_DEFINITION\", message, cause);\n\t}\n}\n\n/** Context contains unsupported or unsafe runtime data. */\nexport class InvalidDomainMachineContextError extends KitWiringError<\"INVALID_DOMAIN_MACHINE_CONTEXT\"> {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"INVALID_DOMAIN_MACHINE_CONTEXT\", message, cause);\n\t}\n}\n\n/** A supplied or produced snapshot is malformed or violates invariants. */\nexport class InvalidDomainMachineSnapshotError extends KitWiringError<\"INVALID_DOMAIN_MACHINE_SNAPSHOT\"> {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"INVALID_DOMAIN_MACHINE_SNAPSHOT\", message, cause);\n\t}\n}\n\n/** An input is malformed or contains unsupported runtime data. */\nexport class InvalidDomainMachineInputError extends KitWiringError<\"INVALID_DOMAIN_MACHINE_INPUT\"> {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"INVALID_DOMAIN_MACHINE_INPUT\", message, cause);\n\t}\n}\n\n/** A guard returned a value other than `boolean` or `DomainError`. */\nexport class InvalidDomainTransitionGuardResultError extends KitWiringError<\"INVALID_DOMAIN_TRANSITION_GUARD_RESULT\"> {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"INVALID_DOMAIN_TRANSITION_GUARD_RESULT\", message, cause);\n\t}\n}\n\n/** A reducer returned a malformed result or unsupported output data. */\nexport class InvalidDomainTransitionResultError extends KitWiringError<\"INVALID_DOMAIN_TRANSITION_RESULT\"> {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"INVALID_DOMAIN_TRANSITION_RESULT\", message, cause);\n\t}\n}\n\n/** A callback attempted to evaluate the same stateful machine recursively. */\nexport class ReentrantDomainStateMachineEvaluationError extends KitWiringError<\"REENTRANT_DOMAIN_STATE_MACHINE_EVALUATION\"> {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"REENTRANT_DOMAIN_STATE_MACHINE_EVALUATION\",\n\t\t\t\"Domain state machine callbacks cannot evaluate the same machine.\",\n\t\t);\n\t}\n}\n","import {\n\tfindPropertyDescriptor,\n\tisBuiltInObject,\n\tisIntrinsicConstructorPrototype,\n} from \"../../internal/structural/is-built-in\";\nimport { deepFreeze } from \"../value-object/value-object\";\nimport type { DomainMachineInput, DomainMachineReadonly } from \"./contracts\";\nimport {\n\tInvalidDomainMachineContextError,\n\tInvalidDomainMachineInputError,\n\tInvalidDomainTransitionResultError,\n} from \"./errors\";\n\ntype DomainMachineDataErrorFactory = (\n\tmessage: string,\n\tcause?: unknown,\n) =>\n\t| InvalidDomainMachineContextError\n\t| InvalidDomainMachineInputError\n\t| InvalidDomainTransitionResultError;\n\nconst DOMAIN_MACHINE_DATA_MAX_DEPTH = 256;\nconst DOMAIN_MACHINE_DATA_MAX_NODES = 10_000;\nconst DOMAIN_MACHINE_DATA_MAX_PROPERTIES = 100_000;\n\ntype DomainMachineDataTraversal = {\n\tnodes: number;\n\tproperties: number;\n};\n\nexport function copyDomainMachineOutputs<TOutput>(\n\toutputs: readonly (TOutput | DomainMachineReadonly<TOutput>)[] | undefined,\n): readonly DomainMachineReadonly<TOutput>[] {\n\ttry {\n\t\tconst copiedOutputs = cloneDomainMachineDataValue(\n\t\t\toutputs ?? [],\n\t\t\tcreateDomainTransitionOutputError,\n\t\t);\n\t\treturn deepFreeze(\n\t\t\tcopiedOutputs,\n\t\t) as readonly DomainMachineReadonly<TOutput>[];\n\t} catch (cause) {\n\t\tif (cause instanceof InvalidDomainTransitionResultError) {\n\t\t\tthrow cause;\n\t\t}\n\t\tthrow new InvalidDomainTransitionResultError(\n\t\t\t\"Domain transition result outputs must contain cloneable, deeply immutable data.\",\n\t\t\tcause,\n\t\t);\n\t}\n}\n\nexport function copyDomainMachineInput<TInput extends DomainMachineInput>(\n\tinput: TInput,\n): DomainMachineReadonly<TInput> {\n\ttry {\n\t\treturn deepFreeze(\n\t\t\tcloneDomainMachineDataValue(input, createDomainMachineInputError),\n\t\t) as DomainMachineReadonly<TInput>;\n\t} catch (cause) {\n\t\tif (cause instanceof InvalidDomainMachineInputError) {\n\t\t\tthrow cause;\n\t\t}\n\t\tthrow new InvalidDomainMachineInputError(\n\t\t\t\"Domain machine input must contain cloneable, deeply immutable data.\",\n\t\t\tcause,\n\t\t);\n\t}\n}\n\nexport function copyDomainMachineContext<TContext>(\n\tcontext: TContext | DomainMachineReadonly<TContext>,\n): DomainMachineReadonly<TContext> {\n\ttry {\n\t\treturn deepFreeze(\n\t\t\tcloneDomainMachineDataValue(context, createDomainMachineContextError),\n\t\t) as DomainMachineReadonly<TContext>;\n\t} catch (cause) {\n\t\tif (cause instanceof InvalidDomainMachineContextError) {\n\t\t\tthrow cause;\n\t\t}\n\t\tthrow new InvalidDomainMachineContextError(\n\t\t\t\"Domain machine context must contain cloneable, deeply immutable data.\",\n\t\t\tcause,\n\t\t);\n\t}\n}\n\nfunction createDomainMachineContextError(\n\tmessage: string,\n\tcause?: unknown,\n): InvalidDomainMachineContextError {\n\treturn new InvalidDomainMachineContextError(message, cause);\n}\n\nfunction createDomainMachineInputError(\n\tmessage: string,\n\tcause?: unknown,\n): InvalidDomainMachineInputError {\n\treturn new InvalidDomainMachineInputError(message, cause);\n}\n\nfunction createDomainTransitionOutputError(\n\tmessage: string,\n\tcause?: unknown,\n): InvalidDomainTransitionResultError {\n\treturn new InvalidDomainTransitionResultError(message, cause);\n}\n\nfunction cloneDomainMachineDataValue<TValue>(\n\tvalue: TValue,\n\terrorFactory: DomainMachineDataErrorFactory,\n\tseen = new WeakMap<object, unknown>(),\n\ttraversal: DomainMachineDataTraversal = { nodes: 0, properties: 0 },\n\tdepth = 0,\n): TValue {\n\tif (typeof value === \"function\") {\n\t\tthrow errorFactory(\"Domain machine data cannot contain function values.\");\n\t}\n\tif (value === null || typeof value !== \"object\") return value;\n\n\tconst source = value as object;\n\tif (depth > DOMAIN_MACHINE_DATA_MAX_DEPTH) {\n\t\tthrow errorFactory(\n\t\t\t`Domain machine data exceeds the maximum depth of ${DOMAIN_MACHINE_DATA_MAX_DEPTH}.`,\n\t\t);\n\t}\n\tconst existing = seen.get(source);\n\tif (existing !== undefined) return existing as TValue;\n\ttraversal.nodes += 1;\n\tif (traversal.nodes > DOMAIN_MACHINE_DATA_MAX_NODES) {\n\t\tthrow errorFactory(\n\t\t\t`Domain machine data contains more than ${DOMAIN_MACHINE_DATA_MAX_NODES.toLocaleString(\"en-US\")} object nodes.`,\n\t\t);\n\t}\n\tconst toStringTagDescriptor = findPropertyDescriptor(\n\t\tsource,\n\t\tSymbol.toStringTag,\n\t);\n\tif (\n\t\ttoStringTagDescriptor !== undefined &&\n\t\t!(\"value\" in toStringTagDescriptor)\n\t) {\n\t\tthrow errorFactory(\n\t\t\t\"Domain machine data cannot contain accessor properties.\",\n\t\t);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\tif (!isIntrinsicArrayPrototype(Object.getPrototypeOf(value))) {\n\t\t\tthrow errorFactory(\n\t\t\t\t\"Domain machine data cannot contain custom Array instances.\",\n\t\t\t);\n\t\t}\n\t\tconst cloned: unknown[] = new Array(value.length);\n\t\tseen.set(source, cloned);\n\n\t\tfor (const key of readDomainMachineDataKeys(\n\t\t\tsource,\n\t\t\terrorFactory,\n\t\t\ttraversal,\n\t\t)) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(source, key);\n\t\t\tif (!descriptor) continue;\n\n\t\t\tif (!(\"value\" in descriptor)) {\n\t\t\t\tthrow errorFactory(\n\t\t\t\t\t\"Domain machine data cannot contain accessor properties.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (key === \"length\") continue;\n\n\t\t\tdescriptor.value = cloneDomainMachineDataValue(\n\t\t\t\tdescriptor.value,\n\t\t\t\terrorFactory,\n\t\t\t\tseen,\n\t\t\t\ttraversal,\n\t\t\t\tdepth + 1,\n\t\t\t);\n\t\t\tObject.defineProperty(cloned, key, descriptor);\n\t\t}\n\t\treturn cloned as TValue;\n\t}\n\n\tconst prototype = Object.getPrototypeOf(source);\n\tif (prototype !== null && !isIntrinsicObjectPrototype(prototype)) {\n\t\tthrow errorFactory(\n\t\t\t\"Domain machine data cannot contain custom class instances.\",\n\t\t);\n\t}\n\n\tconst tag = Object.prototype.toString.call(source);\n\tif (isBuiltInObject(source, tag) || ArrayBuffer.isView(source)) {\n\t\tthrow errorFactory(\n\t\t\t`Domain machine data cannot contain ${tag.slice(8, -1)} object values.`,\n\t\t);\n\t}\n\n\tconst cloned = Object.create(prototype === null ? null : Object.prototype);\n\tseen.set(source, cloned);\n\n\tfor (const key of readDomainMachineDataKeys(\n\t\tsource,\n\t\terrorFactory,\n\t\ttraversal,\n\t)) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(source, key);\n\t\tif (!descriptor) continue;\n\n\t\tif (!(\"value\" in descriptor)) {\n\t\t\tthrow errorFactory(\n\t\t\t\t\"Domain machine data cannot contain accessor properties.\",\n\t\t\t);\n\t\t}\n\n\t\tdescriptor.value = cloneDomainMachineDataValue(\n\t\t\tdescriptor.value,\n\t\t\terrorFactory,\n\t\t\tseen,\n\t\t\ttraversal,\n\t\t\tdepth + 1,\n\t\t);\n\t\tObject.defineProperty(cloned, key, descriptor);\n\t}\n\n\treturn cloned as TValue;\n}\n\nfunction readDomainMachineDataKeys(\n\tvalue: object,\n\terrorFactory: DomainMachineDataErrorFactory,\n\ttraversal: DomainMachineDataTraversal,\n): readonly PropertyKey[] {\n\tconst keys = Reflect.ownKeys(value);\n\ttraversal.properties += keys.length;\n\tif (traversal.properties > DOMAIN_MACHINE_DATA_MAX_PROPERTIES) {\n\t\tthrow errorFactory(\n\t\t\t`Domain machine data contains more than ${DOMAIN_MACHINE_DATA_MAX_PROPERTIES.toLocaleString(\"en-US\")} own properties.`,\n\t\t);\n\t}\n\treturn keys;\n}\n\nexport function isRecord(\n\tvalue: unknown,\n): value is Record<PropertyKey, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function isPlainRecord(\n\tvalue: unknown,\n): value is Record<PropertyKey, unknown> {\n\tif (!isRecord(value)) return false;\n\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === null || isIntrinsicObjectPrototype(prototype);\n}\n\nfunction isIntrinsicArrayPrototype(prototype: object | null): boolean {\n\tif (prototype === null || !Array.isArray(prototype)) return false;\n\tif (!isIntrinsicConstructorPrototype(prototype, \"Array\")) return false;\n\n\tconst parentPrototype = Object.getPrototypeOf(prototype);\n\treturn (\n\t\tparentPrototype !== null && isIntrinsicObjectPrototype(parentPrototype)\n\t);\n}\n\nfunction isIntrinsicObjectPrototype(prototype: object): boolean {\n\treturn (\n\t\tObject.getPrototypeOf(prototype) === null &&\n\t\tisIntrinsicConstructorPrototype(prototype, \"Object\")\n\t);\n}\n\nexport function hasOwn<T extends object>(\n\tvalue: T,\n\tkey: PropertyKey,\n): key is keyof T {\n\treturn Object.hasOwn(value, key);\n}\n","import type {\n\tDomainMachineDefinition,\n\tDomainMachineInput,\n\tDomainMachineSnapshot,\n\tDomainStateNode,\n\tDomainTransition,\n} from \"./contracts\";\nimport { InvalidDomainMachineDefinitionError } from \"./errors\";\nimport { hasOwn, isPlainRecord } from \"./machine-data\";\n\nconst DOMAIN_MACHINE_DEFINITION_KEYS: ReadonlySet<PropertyKey> = new Set([\n\t\"initial\",\n\t\"initialContext\",\n\t\"validateSnapshot\",\n\t\"states\",\n]);\nconst DOMAIN_MACHINE_STATE_NODE_KEYS: ReadonlySet<PropertyKey> = new Set([\n\t\"terminal\",\n\t\"validateContext\",\n\t\"on\",\n]);\nconst DOMAIN_MACHINE_TRANSITION_KEYS: ReadonlySet<PropertyKey> = new Set([\n\t\"target\",\n\t\"guard\",\n\t\"reduce\",\n]);\n\nexport function copyDomainMachineDefinition<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n): DomainMachineDefinition<TState, TContext, TInput, TOutput> {\n\tconst states = readDomainMachineDefinitionProperty(\n\t\tdefinition,\n\t\t\"states\",\n\t) as DomainMachineDefinition<TState, TContext, TInput, TOutput>[\"states\"];\n\tconst copiedStates = Object.create(null) as {\n\t\t[TName in TState]: DomainStateNode<TState, TContext, TInput, TOutput>;\n\t};\n\n\tfor (const state of Object.keys(states) as TState[]) {\n\t\tconst node = readDomainMachineDefinitionProperty(\n\t\t\tstates,\n\t\t\tstate,\n\t\t) as DomainStateNode<TState, TContext, TInput, TOutput>;\n\t\tconst transitions = readOptionalDomainMachineDefinitionProperty(\n\t\t\tnode,\n\t\t\t\"on\",\n\t\t) as DomainStateNode<TState, TContext, TInput, TOutput>[\"on\"] | undefined;\n\t\tconst copiedTransitions = Object.create(null) as {\n\t\t\t[TType in TInput[\"type\"]]?: DomainTransition<\n\t\t\t\tTState,\n\t\t\t\tTContext,\n\t\t\t\tExtract<TInput, { readonly type: TType }>,\n\t\t\t\tTOutput\n\t\t\t>;\n\t\t};\n\n\t\tfor (const inputType of Object.keys(\n\t\t\ttransitions ?? {},\n\t\t) as TInput[\"type\"][]) {\n\t\t\tconst transition = readDomainMachineDefinitionProperty(\n\t\t\t\ttransitions as object,\n\t\t\t\tinputType,\n\t\t\t) as\n\t\t\t\t| DomainTransition<\n\t\t\t\t\t\tTState,\n\t\t\t\t\t\tTContext,\n\t\t\t\t\t\tExtract<TInput, { readonly type: typeof inputType }>,\n\t\t\t\t\t\tTOutput\n\t\t\t\t >\n\t\t\t\t| undefined;\n\t\t\tif (transition) {\n\t\t\t\tconst copiedTransition = Object.freeze({\n\t\t\t\t\ttarget: readDomainMachineDefinitionProperty(transition, \"target\"),\n\t\t\t\t\tguard: readOptionalDomainMachineDefinitionProperty(\n\t\t\t\t\t\ttransition,\n\t\t\t\t\t\t\"guard\",\n\t\t\t\t\t),\n\t\t\t\t\treduce: readOptionalDomainMachineDefinitionProperty(\n\t\t\t\t\t\ttransition,\n\t\t\t\t\t\t\"reduce\",\n\t\t\t\t\t),\n\t\t\t\t}) as DomainTransition<\n\t\t\t\t\tTState,\n\t\t\t\t\tTContext,\n\t\t\t\t\tExtract<TInput, { readonly type: typeof inputType }>,\n\t\t\t\t\tTOutput\n\t\t\t\t>;\n\t\t\t\tObject.defineProperty(copiedTransitions, inputType, {\n\t\t\t\t\tvalue: copiedTransition,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tObject.defineProperty(copiedStates, state, {\n\t\t\tvalue: Object.freeze({\n\t\t\t\tterminal: readOptionalDomainMachineDefinitionProperty(node, \"terminal\"),\n\t\t\t\tvalidateContext: readOptionalDomainMachineDefinitionProperty(\n\t\t\t\t\tnode,\n\t\t\t\t\t\"validateContext\",\n\t\t\t\t),\n\t\t\t\ton: Object.freeze(copiedTransitions),\n\t\t\t}),\n\t\t\tenumerable: true,\n\t\t});\n\t}\n\n\treturn Object.freeze({\n\t\tinitial: readDomainMachineDefinitionProperty(\n\t\t\tdefinition,\n\t\t\t\"initial\",\n\t\t) as TState,\n\t\tinitialContext: readDomainMachineDefinitionProperty(\n\t\t\tdefinition,\n\t\t\t\"initialContext\",\n\t\t) as () => TContext,\n\t\tvalidateSnapshot: readOptionalDomainMachineDefinitionProperty(\n\t\t\tdefinition,\n\t\t\t\"validateSnapshot\",\n\t\t) as\n\t\t\t| ((snapshot: DomainMachineSnapshot<TState, TContext>) => boolean)\n\t\t\t| undefined,\n\t\tstates: Object.freeze(copiedStates),\n\t});\n}\n\n/**\n * Registry of definitions produced by `prepareDomainMachineDefinition`:\n * validated, defensively copied, deeply frozen. The runtime membership\n * proof lives in this module-private WeakSet (the stable copies are\n * frozen and must stay pure data, so no runtime brand property); the\n * compile-time proof is the required type brand on\n * {@link PreparedDomainMachineDefinition}. Only\n * `prepareDomainMachineDefinition` below adds to the set, so membership\n * always implies validated + copied + frozen.\n */\nconst preparedDefinitions = new WeakSet<object>();\n\ndeclare const preparedDefinitionBrand: unique symbol;\n\n/**\n * A machine definition that `prepareDomainMachineDefinition` has\n * validated, defensively copied, and deeply frozen. Assignable wherever\n * a plain `DomainMachineDefinition` is accepted; the reverse does NOT\n * hold (the brand is required), so an API that demands a prepared\n * definition rejects raw ones at compile time. The pure functions and\n * the `DomainStateMachine` constructor recognize prepared definitions\n * at runtime and skip their per-call validate-and-copy.\n */\nexport type PreparedDomainMachineDefinition<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput = never,\n> = DomainMachineDefinition<TState, TContext, TInput, TOutput> & {\n\treadonly [preparedDefinitionBrand]: true;\n};\n\n/**\n * The entry-point normalization every pure function and the\n * `DomainStateMachine` constructor share: a prepared definition passes\n * through untouched (already validated, copied, frozen); anything else\n * pays the documented per-call validate-and-copy.\n */\nexport function ensureStableDomainMachineDefinition<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n): DomainMachineDefinition<TState, TContext, TInput, TOutput> {\n\tif (preparedDefinitions.has(definition)) return definition;\n\tvalidateDomainMachineDefinition(definition);\n\tconst stable = copyDomainMachineDefinition(definition);\n\t// Re-validate the COPY: a Proxy can legally answer the copy's reads\n\t// differently from validation's (TOCTOU), so the object that will\n\t// actually be dispatched against must itself pass validation. Costs a\n\t// second pass on the raw path only; prepared definitions skip all of\n\t// this.\n\tvalidateDomainMachineDefinition(stable);\n\treturn stable;\n}\n\n/**\n * Validates and stabilizes a machine definition ONCE, for repeated use\n * with the pure functions. Without it, `transitionDomainState` and\n * `canTransitionDomainState` re-validate and defensively re-copy the\n * WHOLE definition on every call (the documented safety of the raw\n * path); on a hot dispatch path that is avoidable O(definition) work.\n * The `DomainStateMachine` class does the equivalent once in its\n * constructor; this export brings the same amortization to pure-API\n * users:\n *\n * ```ts\n * const prepared = prepareDomainMachineDefinition(orderLifecycle);\n * // per dispatch: no re-validation, no definition copy\n * const outcome = transitionDomainState(prepared, snapshot, input);\n * ```\n *\n * The returned definition is a deeply frozen copy, isolated from later\n * mutation of the input object. Preparing an already-prepared\n * definition returns it unchanged.\n */\nexport function prepareDomainMachineDefinition<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n): PreparedDomainMachineDefinition<TState, TContext, TInput, TOutput> {\n\tconst stable = ensureStableDomainMachineDefinition(definition);\n\tpreparedDefinitions.add(stable);\n\treturn stable as PreparedDomainMachineDefinition<\n\t\tTState,\n\t\tTContext,\n\t\tTInput,\n\t\tTOutput\n\t>;\n}\n\nexport function getTransition<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tstate: TState,\n\tinput: TInput,\n): DomainTransition<TState, TContext, TInput, TOutput> | undefined {\n\tconst transitions = definition.states[state].on;\n\tif (!transitions || !hasOwn(transitions, input.type)) return undefined;\n\n\treturn transitions[input.type as TInput[\"type\"]] as\n\t\t| DomainTransition<TState, TContext, TInput, TOutput>\n\t\t| undefined;\n}\n\nexport function validateDomainMachineDefinition<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n): void {\n\tconst candidate = definition as unknown;\n\tif (!isPlainRecord(candidate)) {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine definition must be a plain object.\",\n\t\t);\n\t}\n\tassertDomainMachineDefinitionDataProperties(\n\t\tcandidate,\n\t\tDOMAIN_MACHINE_DEFINITION_KEYS,\n\t);\n\n\tconst initial = readDomainMachineDefinitionProperty(candidate, \"initial\");\n\tif (typeof initial !== \"string\") {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine initial state must be a string data property.\",\n\t\t);\n\t}\n\n\tif (\n\t\ttypeof readDomainMachineDefinitionProperty(candidate, \"initialContext\") !==\n\t\t\"function\"\n\t) {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine initialContext must be a function data property.\",\n\t\t);\n\t}\n\n\tconst validateSnapshot = readOptionalDomainMachineDefinitionProperty(\n\t\tcandidate,\n\t\t\"validateSnapshot\",\n\t);\n\tif (\n\t\tvalidateSnapshot !== undefined &&\n\t\ttypeof validateSnapshot !== \"function\"\n\t) {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine validateSnapshot must be a function data property.\",\n\t\t);\n\t}\n\n\tconst statesCandidate = readDomainMachineDefinitionProperty(\n\t\tcandidate,\n\t\t\"states\",\n\t);\n\tif (!isPlainRecord(statesCandidate)) {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine states must be a plain object data property.\",\n\t\t);\n\t}\n\tconst states: Record<PropertyKey, unknown> = statesCandidate;\n\tassertDomainMachineDefinitionEntryMap(states, \"state\");\n\n\tif (!hasOwn(states, initial)) {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t`Initial domain machine state \"${initial}\" is not defined.`,\n\t\t);\n\t}\n\n\tfor (const state of Object.keys(states)) {\n\t\tconst node: unknown = readDomainMachineDefinitionProperty(states, state);\n\t\tif (!isPlainRecord(node)) {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Domain machine state \"${state}\" must be a plain object data property.`,\n\t\t\t);\n\t\t}\n\t\tassertDomainMachineDefinitionDataProperties(\n\t\t\tnode,\n\t\t\tDOMAIN_MACHINE_STATE_NODE_KEYS,\n\t\t);\n\n\t\tconst terminal: unknown = readOptionalDomainMachineDefinitionProperty(\n\t\t\tnode,\n\t\t\t\"terminal\",\n\t\t);\n\t\tif (terminal !== undefined && typeof terminal !== \"boolean\") {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Domain machine state \"${state}\" terminal flag must be a boolean.`,\n\t\t\t);\n\t\t}\n\n\t\tconst validateContext: unknown =\n\t\t\treadOptionalDomainMachineDefinitionProperty(node, \"validateContext\");\n\t\tif (\n\t\t\tvalidateContext !== undefined &&\n\t\t\ttypeof validateContext !== \"function\"\n\t\t) {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Domain machine state \"${state}\" validateContext must be a function.`,\n\t\t\t);\n\t\t}\n\n\t\tconst transitions: unknown = readOptionalDomainMachineDefinitionProperty(\n\t\t\tnode,\n\t\t\t\"on\",\n\t\t);\n\t\tif (transitions !== undefined && !isPlainRecord(transitions)) {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Domain machine state \"${state}\" transitions must be a plain object.`,\n\t\t\t);\n\t\t}\n\t\tif (isPlainRecord(transitions)) {\n\t\t\tassertDomainMachineDefinitionEntryMap(transitions, \"input\");\n\t\t}\n\n\t\tconst inputTypes = Object.keys(transitions ?? {});\n\t\tif (terminal === true && inputTypes.length > 0) {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Terminal domain machine state \"${state}\" cannot declare transitions.`,\n\t\t\t);\n\t\t}\n\n\t\tfor (const inputType of inputTypes) {\n\t\t\tconst transition: unknown = readDomainMachineDefinitionProperty(\n\t\t\t\ttransitions as object,\n\t\t\t\tinputType,\n\t\t\t);\n\t\t\tif (!isPlainRecord(transition)) {\n\t\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t\t`Domain transition from \"${state}\" on \"${inputType}\" must be a plain object.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tassertDomainMachineDefinitionDataProperties(\n\t\t\t\ttransition,\n\t\t\t\tDOMAIN_MACHINE_TRANSITION_KEYS,\n\t\t\t);\n\n\t\t\tconst target: unknown = readDomainMachineDefinitionProperty(\n\t\t\t\ttransition,\n\t\t\t\t\"target\",\n\t\t\t);\n\t\t\tif (typeof target !== \"string\") {\n\t\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t\t`Domain transition from \"${state}\" on \"${inputType}\" must target a string state.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!hasOwn(states, target)) {\n\t\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t\t`Domain transition from \"${state}\" on \"${inputType}\" targets unknown state \"${target}\".`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst guard: unknown = readOptionalDomainMachineDefinitionProperty(\n\t\t\t\ttransition,\n\t\t\t\t\"guard\",\n\t\t\t);\n\t\t\tif (guard !== undefined && typeof guard !== \"function\") {\n\t\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t\t`Domain transition from \"${state}\" on \"${inputType}\" guard must be a function.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst reduce: unknown = readOptionalDomainMachineDefinitionProperty(\n\t\t\t\ttransition,\n\t\t\t\t\"reduce\",\n\t\t\t);\n\t\t\tif (reduce !== undefined && typeof reduce !== \"function\") {\n\t\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t\t`Domain transition from \"${state}\" on \"${inputType}\" reduce must be a function.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction assertDomainMachineDefinitionDataProperties(\n\tvalue: object,\n\tallowedKeys?: ReadonlySet<PropertyKey>,\n): void {\n\tfor (const key of Reflect.ownKeys(value)) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\t\tif (descriptor !== undefined && !(\"value\" in descriptor)) {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t\"Domain machine definition must contain data properties only.\",\n\t\t\t);\n\t\t}\n\t\tif (allowedKeys !== undefined && !allowedKeys.has(key)) {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Domain machine definition contains unknown property \"${String(key)}\".`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction assertDomainMachineDefinitionEntryMap(\n\tvalue: object,\n\tentryName: \"state\" | \"input\",\n): void {\n\tassertDomainMachineDefinitionDataProperties(value);\n\n\tfor (const key of Reflect.ownKeys(value)) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\t\tif (typeof key !== \"string\" || descriptor?.enumerable !== true) {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Domain machine ${entryName} names must be enumerable string properties.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction readDomainMachineDefinitionProperty(\n\tvalue: object,\n\tkey: PropertyKey,\n): unknown {\n\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\tif (descriptor === undefined || !(\"value\" in descriptor)) {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine definition must contain data properties only.\",\n\t\t);\n\t}\n\n\treturn descriptor.value;\n}\n\nfunction readOptionalDomainMachineDefinitionProperty(\n\tvalue: object,\n\tkey: PropertyKey,\n): unknown {\n\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\tif (descriptor === undefined) return undefined;\n\tif (!(\"value\" in descriptor)) {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine definition must contain data properties only.\",\n\t\t);\n\t}\n\n\treturn descriptor.value;\n}\n","import { DomainError } from \"../../errors/kit-errors\";\nimport type {\n\tDomainMachineDefinition,\n\tDomainMachineInput,\n\tDomainMachineReadonly,\n\tDomainMachineSnapshot,\n\tDomainTransitionResult,\n} from \"./contracts\";\nimport {\n\tInvalidDomainMachineDefinitionError,\n\tInvalidDomainMachineInputError,\n\tInvalidDomainMachineSnapshotError,\n\tInvalidDomainTransitionGuardResultError,\n\tInvalidDomainTransitionResultError,\n} from \"./errors\";\nimport {\n\tcopyDomainMachineContext,\n\thasOwn,\n\tisPlainRecord,\n\tisRecord,\n} from \"./machine-data\";\n\nconst DOMAIN_TRANSITION_RESULT_KEYS: ReadonlySet<PropertyKey> = new Set([\n\t\"context\",\n\t\"outputs\",\n]);\n\nexport function prepareDomainMachineSnapshot<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tsnapshot: DomainMachineSnapshot<TState, TContext>,\n): DomainMachineSnapshot<TState, TContext> {\n\tvalidateDomainMachineSnapshot(definition, snapshot);\n\tconst preparedSnapshot = createDomainMachineSnapshot<TState, TContext>(\n\t\tsnapshot,\n\t);\n\t// Re-validate the COPY: a Proxy can answer the copy's reads differently\n\t// from validation's (TOCTOU), and the copy is what the machine runs on.\n\tvalidateDomainMachineSnapshot(definition, preparedSnapshot);\n\tvalidateDomainMachineSnapshotInvariant(definition, preparedSnapshot);\n\treturn preparedSnapshot;\n}\n\nexport function createDomainMachineSnapshotFromPreparedContext<\n\tTState extends string,\n\tTContext,\n>(\n\tstate: TState,\n\tcontext: DomainMachineReadonly<TContext>,\n): DomainMachineSnapshot<TState, TContext> {\n\treturn Object.freeze({ state, context });\n}\n\nexport function createDomainMachineSnapshot<\n\tTState extends string,\n\tTContext,\n>(snapshot: {\n\treadonly state: TState;\n\treadonly context: TContext | DomainMachineReadonly<TContext>;\n}): DomainMachineSnapshot<TState, TContext> {\n\treturn Object.freeze({\n\t\tstate: readDomainMachineSnapshotState(snapshot),\n\t\tcontext: copyDomainMachineContext<TContext>(\n\t\t\treadDomainMachineSnapshotContext(snapshot),\n\t\t),\n\t}) as DomainMachineSnapshot<TState, TContext>;\n}\n\nexport function validateDomainMachineSnapshot<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tsnapshot: DomainMachineSnapshot<TState, TContext>,\n): void {\n\tif (!isRecord(snapshot)) {\n\t\tthrow new InvalidDomainMachineSnapshotError(\n\t\t\t\"Domain machine snapshot must be an object.\",\n\t\t);\n\t}\n\n\tconst state = readDomainMachineSnapshotState(snapshot);\n\treadDomainMachineSnapshotContext(snapshot);\n\n\tif (!hasOwn(definition.states, state)) {\n\t\tthrow new InvalidDomainMachineSnapshotError(\n\t\t\t`Domain machine snapshot state \"${state}\" is not defined.`,\n\t\t);\n\t}\n}\n\nexport function validateDomainMachineSnapshotInvariant<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tsnapshot: DomainMachineSnapshot<TState, TContext>,\n): void {\n\tconst stateNode = definition.states[snapshot.state];\n\tif (stateNode.validateContext !== undefined) {\n\t\tconst validContext = stateNode.validateContext({\n\t\t\tstate: snapshot.state,\n\t\t\tcontext: snapshot.context,\n\t\t});\n\t\tif (typeof validContext !== \"boolean\") {\n\t\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\t`Domain machine state \"${snapshot.state}\" validateContext must return a boolean.`,\n\t\t\t);\n\t\t}\n\t\tif (!validContext) {\n\t\t\tthrow new InvalidDomainMachineSnapshotError(\n\t\t\t\t`Domain machine snapshot violates the context invariant for state \"${snapshot.state}\".`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (definition.validateSnapshot === undefined) return;\n\n\tconst valid = definition.validateSnapshot(snapshot);\n\tif (typeof valid !== \"boolean\") {\n\t\tthrow new InvalidDomainMachineDefinitionError(\n\t\t\t\"Domain machine validateSnapshot must return a boolean.\",\n\t\t);\n\t}\n\n\tif (!valid) {\n\t\tthrow new InvalidDomainMachineSnapshotError(\n\t\t\t`Domain machine snapshot violates invariants for state \"${snapshot.state}\".`,\n\t\t);\n\t}\n}\n\nfunction readDomainMachineSnapshotState<TState extends string>(snapshot: {\n\treadonly state: TState;\n}): TState {\n\tconst stateDescriptor = Object.getOwnPropertyDescriptor(snapshot, \"state\");\n\tif (\n\t\tstateDescriptor === undefined ||\n\t\t!(\"value\" in stateDescriptor) ||\n\t\ttypeof stateDescriptor.value !== \"string\"\n\t) {\n\t\tthrow new InvalidDomainMachineSnapshotError(\n\t\t\t\"Domain machine snapshot state must be a string data property.\",\n\t\t);\n\t}\n\n\treturn stateDescriptor.value as TState;\n}\n\nfunction readDomainMachineSnapshotContext<TContext>(snapshot: {\n\treadonly context: TContext;\n}): TContext {\n\tconst contextDescriptor = Object.getOwnPropertyDescriptor(\n\t\tsnapshot,\n\t\t\"context\",\n\t);\n\tif (contextDescriptor === undefined || !(\"value\" in contextDescriptor)) {\n\t\tthrow new InvalidDomainMachineSnapshotError(\n\t\t\t\"Domain machine snapshot context must be present as a data property.\",\n\t\t);\n\t}\n\n\treturn contextDescriptor.value as TContext;\n}\n\nexport function validateDomainMachineInput(\n\tinput: unknown,\n): asserts input is DomainMachineInput {\n\tif (!isDomainMachineInput(input)) {\n\t\tthrow new InvalidDomainMachineInputError(\n\t\t\t\"Domain machine input must be an object with a string type.\",\n\t\t);\n\t}\n}\n\nexport function isDomainMachineInput(\n\tinput: unknown,\n): input is DomainMachineInput {\n\tif (!isRecord(input)) return false;\n\n\tconst typeDescriptor = Object.getOwnPropertyDescriptor(input, \"type\");\n\treturn (\n\t\ttypeDescriptor !== undefined &&\n\t\t\"value\" in typeDescriptor &&\n\t\ttypeof typeDescriptor.value === \"string\"\n\t);\n}\n\nexport function resolveDomainTransitionGuardResult(\n\tresult: unknown,\n):\n\t| { readonly allowed: true }\n\t| { readonly allowed: false; readonly rejection?: DomainError } {\n\tif (typeof result === \"boolean\") return { allowed: result };\n\tif (result instanceof DomainError) {\n\t\treturn { allowed: false, rejection: result };\n\t}\n\n\tthrow new InvalidDomainTransitionGuardResultError(\n\t\t\"Domain transition guard must return a boolean or DomainError.\",\n\t);\n}\n\nexport function validateDomainTransitionResult<TContext, TOutput>(\n\tresult: DomainTransitionResult<TContext, TOutput> | undefined,\n): void {\n\tif (result === undefined) return;\n\n\tif (!isPlainRecord(result)) {\n\t\tthrow new InvalidDomainTransitionResultError(\n\t\t\t\"Domain transition result must be a plain object when returned.\",\n\t\t);\n\t}\n\n\tfor (const key of Reflect.ownKeys(result)) {\n\t\tif (!DOMAIN_TRANSITION_RESULT_KEYS.has(key)) {\n\t\t\tthrow new InvalidDomainTransitionResultError(\n\t\t\t\t`Domain transition result contains unknown property \"${String(key)}\".`,\n\t\t\t);\n\t\t}\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(result, key);\n\t\tif (descriptor !== undefined && !(\"value\" in descriptor)) {\n\t\t\tthrow new InvalidDomainTransitionResultError(\n\t\t\t\t\"Domain transition result must contain data properties only.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tconst outputs = readDomainTransitionResultOutputs(result);\n\tif (outputs !== undefined && !Array.isArray(outputs)) {\n\t\tthrow new InvalidDomainTransitionResultError(\n\t\t\t\"Domain transition result outputs must be an array when provided.\",\n\t\t);\n\t}\n}\n\nexport function readDomainTransitionResultContext<TContext, TOutput>(\n\tresult: DomainTransitionResult<TContext, TOutput> | undefined,\n):\n\t| { readonly hasContext: false }\n\t| { readonly hasContext: true; readonly context: TContext } {\n\tif (result === undefined) return { hasContext: false };\n\n\tconst contextDescriptor = Object.getOwnPropertyDescriptor(result, \"context\");\n\tif (contextDescriptor === undefined) return { hasContext: false };\n\tif (!(\"value\" in contextDescriptor)) {\n\t\tthrow new InvalidDomainTransitionResultError(\n\t\t\t\"Domain transition result context must be a data property when provided.\",\n\t\t);\n\t}\n\n\treturn { hasContext: true, context: contextDescriptor.value as TContext };\n}\n\nexport function readDomainTransitionResultOutputs<TContext, TOutput>(\n\tresult: DomainTransitionResult<TContext, TOutput> | undefined,\n): readonly TOutput[] | undefined {\n\tif (result === undefined) return undefined;\n\n\tconst outputsDescriptor = Object.getOwnPropertyDescriptor(result, \"outputs\");\n\tif (outputsDescriptor === undefined) return undefined;\n\tif (!(\"value\" in outputsDescriptor)) {\n\t\tthrow new InvalidDomainTransitionResultError(\n\t\t\t\"Domain transition result outputs must be a data property when provided.\",\n\t\t);\n\t}\n\n\treturn outputsDescriptor.value as readonly TOutput[] | undefined;\n}\n","import type {\n\tDomainMachineDefinition,\n\tDomainMachineInput,\n\tDomainMachineSnapshot,\n\tDomainTransitionOutcome,\n} from \"./contracts\";\nimport {\n\tensureStableDomainMachineDefinition,\n\tgetTransition,\n} from \"./definition\";\nimport {\n\tDomainTransitionGuardRejectedError,\n\tInvalidDomainTransitionError,\n} from \"./errors\";\nimport {\n\tcopyDomainMachineInput,\n\tcopyDomainMachineOutputs,\n} from \"./machine-data\";\nimport {\n\tcreateDomainMachineSnapshot,\n\tcreateDomainMachineSnapshotFromPreparedContext,\n\tisDomainMachineInput,\n\tprepareDomainMachineSnapshot,\n\treadDomainTransitionResultContext,\n\treadDomainTransitionResultOutputs,\n\tresolveDomainTransitionGuardResult,\n\tvalidateDomainMachineInput,\n\tvalidateDomainMachineSnapshotInvariant,\n\tvalidateDomainTransitionResult,\n} from \"./snapshot\";\n\n/** Creates and validates a fresh initial snapshot from a machine definition. */\nexport function createInitialDomainMachineSnapshot<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n): DomainMachineSnapshot<TState, TContext> {\n\tconst stableDefinition = ensureStableDomainMachineDefinition(definition);\n\treturn createInitialDomainMachineSnapshotFromPrepared(stableDefinition);\n}\n\nexport function createInitialDomainMachineSnapshotFromPrepared<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n): DomainMachineSnapshot<TState, TContext> {\n\tconst snapshot = createDomainMachineSnapshot<TState, TContext>({\n\t\tstate: definition.initial,\n\t\tcontext: definition.initialContext(),\n\t});\n\tvalidateDomainMachineSnapshotInvariant(definition, snapshot);\n\treturn snapshot;\n}\n\n/**\n * Checks whether an input currently has an allowed transition.\n *\n * Returns `false` for missing transitions, terminal states, rejected guards,\n * and inputs without an own string `type` property. Invalid payload data for a\n * matching transition and broken guard code still throw structured errors.\n */\nexport function canTransitionDomainState<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tsnapshot: DomainMachineSnapshot<TState, TContext>,\n\tinput: TInput,\n): boolean {\n\tconst stableDefinition = ensureStableDomainMachineDefinition(definition);\n\tconst currentSnapshot = prepareDomainMachineSnapshot(\n\t\tstableDefinition,\n\t\tsnapshot,\n\t);\n\treturn canTransitionPreparedDomainState(\n\t\tstableDefinition,\n\t\tcurrentSnapshot,\n\t\tinput,\n\t);\n}\n\nexport function canTransitionPreparedDomainState<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tsnapshot: DomainMachineSnapshot<TState, TContext>,\n\tinput: TInput,\n): boolean {\n\tif (!isDomainMachineInput(input)) return false;\n\n\tconst stateNode = definition.states[snapshot.state];\n\tif (stateNode.terminal === true) return false;\n\n\tconst transition = getTransition(definition, snapshot.state, input);\n\tif (!transition) return false;\n\n\tconst currentInput = copyDomainMachineInput(input);\n\tif (!transition.guard) return true;\n\n\tconst guardResult = transition.guard({\n\t\tstate: snapshot.state,\n\t\tcontext: snapshot.context,\n\t\tinput: currentInput,\n\t});\n\n\treturn resolveDomainTransitionGuardResult(guardResult).allowed;\n}\n\n/**\n * Applies one input without mutating the input definition or snapshot.\n *\n * @throws {@link InvalidDomainTransitionError} when no transition is defined.\n * @throws {@link DomainTransitionGuardRejectedError} when its guard rejects.\n * @throws A concrete `DomainError` returned by a rejecting guard.\n */\nexport function transitionDomainState<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tsnapshot: DomainMachineSnapshot<TState, TContext>,\n\tinput: TInput,\n): DomainTransitionOutcome<TState, TContext, TOutput> {\n\tconst stableDefinition = ensureStableDomainMachineDefinition(definition);\n\tconst currentSnapshot = prepareDomainMachineSnapshot(\n\t\tstableDefinition,\n\t\tsnapshot,\n\t);\n\treturn transitionPreparedDomainState(\n\t\tstableDefinition,\n\t\tcurrentSnapshot,\n\t\tinput,\n\t);\n}\n\nexport function transitionPreparedDomainState<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\tsnapshot: DomainMachineSnapshot<TState, TContext>,\n\tinput: TInput,\n): DomainTransitionOutcome<TState, TContext, TOutput> {\n\tvalidateDomainMachineInput(input);\n\n\tconst from = snapshot.state;\n\tconst stateNode = definition.states[from];\n\tconst transition =\n\t\tstateNode.terminal === true\n\t\t\t? undefined\n\t\t\t: getTransition(definition, from, input);\n\n\tif (!transition) {\n\t\tthrow new InvalidDomainTransitionError(from, input.type);\n\t}\n\n\tconst currentInput = copyDomainMachineInput(input);\n\tconst guardResult =\n\t\ttransition.guard === undefined\n\t\t\t? true\n\t\t\t: transition.guard({\n\t\t\t\t\tstate: from,\n\t\t\t\t\tcontext: snapshot.context,\n\t\t\t\t\tinput: currentInput,\n\t\t\t\t});\n\tconst guardDecision = resolveDomainTransitionGuardResult(guardResult);\n\n\tif (!guardDecision.allowed) {\n\t\tif (guardDecision.rejection !== undefined) {\n\t\t\tthrow guardDecision.rejection;\n\t\t}\n\t\tthrow new DomainTransitionGuardRejectedError(from, currentInput.type);\n\t}\n\n\tconst result = transition.reduce?.({\n\t\tstate: from,\n\t\tcontext: snapshot.context,\n\t\tinput: currentInput,\n\t});\n\tvalidateDomainTransitionResult(result);\n\tconst contextResult = readDomainTransitionResultContext(result);\n\tconst nextContext = contextResult.hasContext\n\t\t? contextResult.context\n\t\t: snapshot.context;\n\tconst nextSnapshot =\n\t\tnextContext === snapshot.context\n\t\t\t? createDomainMachineSnapshotFromPreparedContext<TState, TContext>(\n\t\t\t\t\ttransition.target,\n\t\t\t\t\tsnapshot.context,\n\t\t\t\t)\n\t\t\t: createDomainMachineSnapshot<TState, TContext>({\n\t\t\t\t\tstate: transition.target,\n\t\t\t\t\tcontext: nextContext,\n\t\t\t\t});\n\tvalidateDomainMachineSnapshotInvariant(definition, nextSnapshot);\n\n\t// Frozen like every sibling return value (snapshots, outputs, the\n\t// analyzer result): the contract types the fields readonly, and the\n\t// runtime must not allow a cast to rewrite from/to.\n\treturn Object.freeze({\n\t\tfrom,\n\t\tto: transition.target,\n\t\tsnapshot: nextSnapshot,\n\t\toutputs: copyDomainMachineOutputs(\n\t\t\treadDomainTransitionResultOutputs(result),\n\t\t),\n\t});\n}\n","import type { DomainMachineDefinition, DomainMachineInput } from \"./contracts\";\nimport { ensureStableDomainMachineDefinition } from \"./definition\";\n\nexport type DomainMachineDefinitionDiagnostic<TState extends string> =\n\t| {\n\t\t\treadonly code: \"unreachable-state\";\n\t\t\treadonly state: TState;\n\t }\n\t| {\n\t\t\treadonly code: \"structural-dead-end\";\n\t\t\treadonly state: TState;\n\t }\n\t| {\n\t\t\treadonly code: \"no-terminal-path\";\n\t\t\treadonly state: TState;\n\t };\n\nexport type DomainMachineTransitionDescription<\n\tTState extends string,\n\tTInputType extends string,\n> = {\n\treadonly state: TState;\n\treadonly inputType: TInputType;\n\treadonly target: TState;\n\treadonly guarded: boolean;\n};\n\nexport type DomainMachineDefinitionAnalysis<\n\tTState extends string,\n\tTInputType extends string,\n> = {\n\treadonly diagnostics: readonly DomainMachineDefinitionDiagnostic<TState>[];\n\treadonly transitions: readonly DomainMachineTransitionDescription<\n\t\tTState,\n\t\tTInputType\n\t>[];\n\t/** States reachable when every guard is assumed to allow its transition. */\n\treadonly structurallyReachableStates: readonly TState[];\n\t/** States with a graph path to a terminal state when every guard is assumed to allow it. */\n\treadonly statesWithTerminalPath: readonly TState[];\n};\n\n/**\n * Inspects the declarative transition graph without executing definition callbacks.\n * Guarded edges are treated as possible edges, so diagnostics never claim more\n * runtime reachability than the static graph can prove.\n */\nexport function analyzeDomainMachineDefinition<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput,\n>(\n\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n): DomainMachineDefinitionAnalysis<TState, TInput[\"type\"]> {\n\t// The shared entry-point normalization: a prepared definition passes\n\t// through untouched (already validated, copied, frozen), a raw one\n\t// pays the documented per-call validate-and-copy.\n\tconst stableDefinition = ensureStableDomainMachineDefinition(definition);\n\tconst states = (Object.keys(stableDefinition.states) as TState[]).sort(\n\t\tcompareStrings,\n\t);\n\tconst outgoing = new Map<TState, TState[]>();\n\tconst incoming = new Map<TState, TState[]>();\n\tconst transitions: DomainMachineTransitionDescription<\n\t\tTState,\n\t\tTInput[\"type\"]\n\t>[] = [];\n\n\tfor (const state of states) {\n\t\toutgoing.set(state, []);\n\t\tincoming.set(state, []);\n\t}\n\n\tfor (const state of states) {\n\t\tconst stateTransitions = stableDefinition.states[state].on;\n\t\tconst inputTypes = (\n\t\t\tObject.keys(stateTransitions ?? {}) as TInput[\"type\"][]\n\t\t).sort(compareStrings);\n\n\t\tfor (const inputType of inputTypes) {\n\t\t\tconst transition = stateTransitions?.[inputType];\n\t\t\tif (transition === undefined) continue;\n\n\t\t\toutgoing.get(state)?.push(transition.target);\n\t\t\tincoming.get(transition.target)?.push(state);\n\t\t\ttransitions.push(\n\t\t\t\tObject.freeze({\n\t\t\t\t\tstate,\n\t\t\t\t\tinputType,\n\t\t\t\t\ttarget: transition.target,\n\t\t\t\t\tguarded: transition.guard !== undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tconst structurallyReachable = visitGraph(\n\t\t[stableDefinition.initial],\n\t\toutgoing,\n\t);\n\tconst terminalStates = states.filter(\n\t\t(state) => stableDefinition.states[state].terminal === true,\n\t);\n\tconst statesWithTerminalPath = visitGraph(terminalStates, incoming);\n\tconst diagnostics: DomainMachineDefinitionDiagnostic<TState>[] = [];\n\n\tfor (const state of states) {\n\t\tif (!structurallyReachable.has(state)) {\n\t\t\tdiagnostics.push(Object.freeze({ code: \"unreachable-state\", state }));\n\t\t}\n\t}\n\tfor (const state of states) {\n\t\tif (\n\t\t\tstableDefinition.states[state].terminal !== true &&\n\t\t\toutgoing.get(state)?.length === 0\n\t\t) {\n\t\t\tdiagnostics.push(Object.freeze({ code: \"structural-dead-end\", state }));\n\t\t}\n\t}\n\tfor (const state of states) {\n\t\tif (!statesWithTerminalPath.has(state)) {\n\t\t\tdiagnostics.push(Object.freeze({ code: \"no-terminal-path\", state }));\n\t\t}\n\t}\n\n\treturn Object.freeze({\n\t\tdiagnostics: Object.freeze(diagnostics),\n\t\ttransitions: Object.freeze(transitions),\n\t\tstructurallyReachableStates: Object.freeze(\n\t\t\tstates.filter((state) => structurallyReachable.has(state)),\n\t\t),\n\t\tstatesWithTerminalPath: Object.freeze(\n\t\t\tstates.filter((state) => statesWithTerminalPath.has(state)),\n\t\t),\n\t});\n}\n\nfunction visitGraph<TState extends string>(\n\tstartStates: readonly TState[],\n\tedges: ReadonlyMap<TState, readonly TState[]>,\n): ReadonlySet<TState> {\n\tconst visited = new Set<TState>();\n\tconst pending = [...startStates];\n\n\twhile (pending.length > 0) {\n\t\tconst state = pending.pop();\n\t\tif (state === undefined || visited.has(state)) continue;\n\n\t\tvisited.add(state);\n\t\tfor (const next of edges.get(state) ?? []) {\n\t\t\tif (!visited.has(next)) pending.push(next);\n\t\t}\n\t}\n\n\treturn visited;\n}\n\nfunction compareStrings(left: string, right: string): number {\n\treturn left < right ? -1 : left > right ? 1 : 0;\n}\n","import type {\n\tDomainMachineDefinition,\n\tDomainMachineInput,\n\tDomainMachineReadonly,\n\tDomainMachineSnapshot,\n\tDomainTransitionOutcome,\n} from \"./contracts\";\nimport { ensureStableDomainMachineDefinition } from \"./definition\";\nimport { ReentrantDomainStateMachineEvaluationError } from \"./errors\";\nimport {\n\tcreateDomainMachineSnapshot,\n\tprepareDomainMachineSnapshot,\n} from \"./snapshot\";\nimport {\n\tcanTransitionPreparedDomainState,\n\tcreateInitialDomainMachineSnapshotFromPrepared,\n\ttransitionPreparedDomainState,\n} from \"./transition\";\n\nexport type {\n\tDomainMachineDefinitionAnalysis,\n\tDomainMachineDefinitionDiagnostic,\n\tDomainMachineTransitionDescription,\n} from \"./analyzer\";\nexport { analyzeDomainMachineDefinition } from \"./analyzer\";\nexport type {\n\tDomainMachineDefinition,\n\tDomainMachineInput,\n\tDomainMachineReadonly,\n\tDomainMachineSnapshot,\n\tDomainStateNode,\n\tDomainTransition,\n\tDomainTransitionGuardResult,\n\tDomainTransitionOutcome,\n\tDomainTransitionResult,\n} from \"./contracts\";\nexport {\n\ttype PreparedDomainMachineDefinition,\n\tprepareDomainMachineDefinition,\n} from \"./definition\";\nexport {\n\tDomainTransitionGuardRejectedError,\n\tInvalidDomainMachineContextError,\n\tInvalidDomainMachineDefinitionError,\n\tInvalidDomainMachineInputError,\n\tInvalidDomainMachineSnapshotError,\n\tInvalidDomainTransitionError,\n\tInvalidDomainTransitionGuardResultError,\n\tInvalidDomainTransitionResultError,\n\tReentrantDomainStateMachineEvaluationError,\n} from \"./errors\";\nexport {\n\tcanTransitionDomainState,\n\tcreateInitialDomainMachineSnapshot,\n\ttransitionDomainState,\n} from \"./transition\";\n\n/**\n * Stateful convenience wrapper around the pure domain transition functions.\n *\n * Persist {@link snapshot}, not the machine instance. Pass a restored snapshot\n * to the second constructor overload to validate and reconstitute a machine.\n */\nexport class DomainStateMachine<\n\tTState extends string,\n\tTContext,\n\tTInput extends DomainMachineInput,\n\tTOutput = never,\n> {\n\tprivate readonly definition: DomainMachineDefinition<\n\t\tTState,\n\t\tTContext,\n\t\tTInput,\n\t\tTOutput\n\t>;\n\n\t#snapshot: DomainMachineSnapshot<TState, TContext>;\n\t#evaluating = false;\n\n\tconstructor(\n\t\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\t);\n\tconstructor(\n\t\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\t\tsnapshot: DomainMachineSnapshot<TState, TContext> | undefined,\n\t);\n\tconstructor(\n\t\tdefinition: DomainMachineDefinition<TState, TContext, TInput, TOutput>,\n\t\t...snapshotInput: [] | [DomainMachineSnapshot<TState, TContext> | undefined]\n\t) {\n\t\t// A prepared definition (prepareDomainMachineDefinition) passes\n\t\t// through; a raw one pays the one-time validate-and-copy here.\n\t\tthis.definition = ensureStableDomainMachineDefinition(definition);\n\t\t// Resolve the overload by the argument value, not the rest-parameter\n\t\t// arity: an explicit `undefined` snapshot (a natural result of a\n\t\t// nullable `repo.loadSnapshot(id)` or `map.get(id)` passed straight\n\t\t// through) means \"no snapshot\", so it must fall back to the initial\n\t\t// snapshot instead of failing validation.\n\t\tconst [suppliedSnapshot] = snapshotInput;\n\t\tif (suppliedSnapshot !== undefined) {\n\t\t\t// One shared implementation with the pure path (transition.ts);\n\t\t\t// hand-rolling the validate-copy-validate trio here would let\n\t\t\t// the class and pure snapshot preparation drift.\n\t\t\tthis.#snapshot = prepareDomainMachineSnapshot(\n\t\t\t\tthis.definition,\n\t\t\t\tsuppliedSnapshot,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.#snapshot = createInitialDomainMachineSnapshotFromPrepared(\n\t\t\t\tthis.definition,\n\t\t\t);\n\t\t}\n\t}\n\n\t/** Returns a defensive, deeply frozen copy of the current snapshot. */\n\tget snapshot(): DomainMachineSnapshot<TState, TContext> {\n\t\treturn createDomainMachineSnapshot<TState, TContext>(this.#snapshot);\n\t}\n\n\t/** Current named control state. */\n\tget state(): TState {\n\t\treturn this.#snapshot.state;\n\t}\n\n\t/** Current deeply readonly context. */\n\tget context(): DomainMachineReadonly<TContext> {\n\t\treturn this.#snapshot.context;\n\t}\n\n\t/** Whether the current state permanently forbids outgoing transitions. */\n\tisTerminal(): boolean {\n\t\treturn this.definition.states[this.state].terminal === true;\n\t}\n\n\t/** Checks a transition without changing the current snapshot. */\n\tcan(input: TInput): boolean {\n\t\treturn this.evaluate(() =>\n\t\t\tcanTransitionPreparedDomainState(this.definition, this.#snapshot, input),\n\t\t);\n\t}\n\n\t/** Applies an input and advances the current snapshot on success. */\n\tdispatch(input: TInput): DomainTransitionOutcome<TState, TContext, TOutput> {\n\t\treturn this.evaluate(() => {\n\t\t\tconst result = transitionPreparedDomainState(\n\t\t\t\tthis.definition,\n\t\t\t\tthis.#snapshot,\n\t\t\t\tinput,\n\t\t\t);\n\t\t\tthis.#snapshot = result.snapshot;\n\t\t\treturn result;\n\t\t});\n\t}\n\n\tprivate evaluate<TResult>(operation: () => TResult): TResult {\n\t\tif (this.#evaluating) {\n\t\t\tthrow new ReentrantDomainStateMachineEvaluationError();\n\t\t}\n\n\t\tthis.#evaluating = true;\n\t\ttry {\n\t\t\treturn operation();\n\t\t} finally {\n\t\t\tthis.#evaluating = false;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I as DeadlineStore, K as EventBus, St as AnyDomainEvent, Wt as AggregateIdentity, X as Aggregate, b as ProjectionCheckpointStore, bt as EventCommitCandidate, c as StreamReadResult, i as EventStore, k as IdempotencyStore, lt as CommandOutboxWriter, mt as Outbox, n as ReplayableStreamPages, nt as Id, pt as DispatchTrackingOutbox, qt as PublishedCommand, s as ReadStreamOptions, st as CommandOutboxCommitCandidate, t as SnapshotStore, w as IdempotencyClaimHandle, yt as CommittedDomainEvent } from "./chunks/snapshot-store.js";
|
|
2
2
|
//#region src/testing/contract-assertions.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* One entry of a contract test suite. Every suite (repository,
|
|
@@ -190,7 +190,7 @@ interface EventBusContractEnvironment<Evt extends AnyDomainEvent> {
|
|
|
190
190
|
/**
|
|
191
191
|
* What an implementation supplies to run the event-bus contract suite.
|
|
192
192
|
*
|
|
193
|
-
* The suite
|
|
193
|
+
* The suite builds no events, so it stays free of any event union. The two
|
|
194
194
|
* factories must produce DIFFERENT `type` values: the suite subscribes to
|
|
195
195
|
* both to prove that ordering holds across types and that a catch-all
|
|
196
196
|
* subscription sees every type.
|
|
@@ -242,7 +242,7 @@ interface EventStoreContractHarness<Evt extends AnyDomainEvent> {
|
|
|
242
242
|
/**
|
|
243
243
|
* Reusable proof of an EventStore adapter's portable semantics: qualified
|
|
244
244
|
* value identity, ordered reads and slicing, OCC error mapping and atomicity,
|
|
245
|
-
* no-op empty appends, and
|
|
245
|
+
* no-op empty appends, and copied return arrays. Physical-position
|
|
246
246
|
* corruption needs adapter-specific fixture support and is tested there.
|
|
247
247
|
*/
|
|
248
248
|
declare function createEventStoreContractTests<Evt extends AnyDomainEvent>(harness: EventStoreContractHarness<Evt>): EventStoreContractTest[];
|
|
@@ -629,7 +629,7 @@ interface RepositoryContractHarness<TAggregate extends Aggregate<Id<string>, TEv
|
|
|
629
629
|
mutateVersionOnly?(aggregate: TAggregate): void;
|
|
630
630
|
/** A decision that changes a nested collection. */
|
|
631
631
|
mutateChildCollection?(aggregate: TAggregate): void;
|
|
632
|
-
/** Round-trip-stable adapter persistence
|
|
632
|
+
/** Round-trip-stable adapter persistence capture. */
|
|
633
633
|
snapshotState?(aggregate: TAggregate): unknown;
|
|
634
634
|
/** Opt out only for an intentionally upserting add implementation. */
|
|
635
635
|
insertsAreDuplicateChecked?: boolean;
|
package/dist/testing.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as deepEqual, n as deepFreeze } from "./chunks/value-object.js";
|
|
2
|
+
import { a as isDispatchTrackingOutbox, c as runBoundedExecution, f as assertPositiveSafeInteger, n as readStreamPages, w as isStampedDomainEvent } from "./chunks/read-stream-pages.js";
|
|
2
3
|
|
|
3
4
|
//#region src/testing/contract-assertions.ts
|
|
4
5
|
/**
|
|
@@ -195,9 +196,9 @@ function gatedContractTest(gate, test) {
|
|
|
195
196
|
* the suite-specific rule the harness violated when an event is not
|
|
196
197
|
* recorded.
|
|
197
198
|
*/
|
|
198
|
-
function
|
|
199
|
+
function stampedPendingEventIds(events, requirement) {
|
|
199
200
|
return events.map((event) => {
|
|
200
|
-
assert(typeof event === "object" && event !== null &&
|
|
201
|
+
assert(typeof event === "object" && event !== null && isStampedDomainEvent(event), requirement);
|
|
201
202
|
return event.eventId;
|
|
202
203
|
});
|
|
203
204
|
}
|
|
@@ -1002,7 +1003,7 @@ function createEsRepositoryContractTests(harness) {
|
|
|
1002
1003
|
const overlappingCallsBoundMs = harness.overlappingCallsBoundMs ?? 1e3;
|
|
1003
1004
|
const load = (repository, id) => loadAggregateOrFail(repository, id, "the stream was not appended or replayed correctly");
|
|
1004
1005
|
const streamFor = (id) => harness.streamKeyFor(id);
|
|
1005
|
-
const recordedIds = (events) =>
|
|
1006
|
+
const recordedIds = (events) => stampedPendingEventIds(events, "pending events must be stamped before flush");
|
|
1006
1007
|
const ids = (events) => events.map((event) => {
|
|
1007
1008
|
assert(typeof event.eventId === "string" && event.eventId.length > 0, "committed events must carry their persisted eventId");
|
|
1008
1009
|
return event.eventId;
|
|
@@ -1073,7 +1074,7 @@ function createEsRepositoryContractTests(harness) {
|
|
|
1073
1074
|
});
|
|
1074
1075
|
const reloaded = await environment.run(({ repository }) => load(repository, aggregate.id));
|
|
1075
1076
|
assertEqual(reloaded.version, expectedIds.length, "event-sourced version must equal the folded event count");
|
|
1076
|
-
assertEqual(reloaded.pendingEvents.length, 0, "replay must not re-
|
|
1077
|
+
assertEqual(reloaded.pendingEvents.length, 0, "replay must not re-stamp historical events");
|
|
1077
1078
|
if (snapshotState) assert(deepEqual(snapshotState.call(harness, reloaded), snapshotState.call(harness, aggregate)), "replay must fold to the same state in emission order");
|
|
1078
1079
|
const stream = await environment.committedStreamEvents(streamFor(aggregate.id), readAll);
|
|
1079
1080
|
assert(stream.exists && deepEqual(ids(stream.events), expectedIds), "the committed stream must preserve emission order");
|
|
@@ -1615,7 +1616,7 @@ function createEventBusContractTests(harness) {
|
|
|
1615
1616
|
/**
|
|
1616
1617
|
* Reusable proof of an EventStore adapter's portable semantics: qualified
|
|
1617
1618
|
* value identity, ordered reads and slicing, OCC error mapping and atomicity,
|
|
1618
|
-
* no-op empty appends, and
|
|
1619
|
+
* no-op empty appends, and copied return arrays. Physical-position
|
|
1619
1620
|
* corruption needs adapter-specific fixture support and is tested there.
|
|
1620
1621
|
*/
|
|
1621
1622
|
function createEventStoreContractTests(harness) {
|
|
@@ -2779,7 +2780,7 @@ function createProjectionCheckpointStoreContractTests(harness) {
|
|
|
2779
2780
|
})
|
|
2780
2781
|
},
|
|
2781
2782
|
{
|
|
2782
|
-
name: "a loaded position is a
|
|
2783
|
+
name: "a loaded position is a copy; mutating it must not move the watermark",
|
|
2783
2784
|
run: inEnv(async (env) => {
|
|
2784
2785
|
await env.run((ctx) => env.store.save(ctx, "order-list", order("o-1"), checkpoint(pos(2, 0))));
|
|
2785
2786
|
const loaded = await env.run((ctx) => env.store.load(ctx, "order-list", order("o-1")));
|
|
@@ -3111,7 +3112,7 @@ function createRepositoryContractTests(harness) {
|
|
|
3111
3112
|
}
|
|
3112
3113
|
const reload = (environment, id) => environment.run(({ repository }) => load(repository, id));
|
|
3113
3114
|
const eventIds = (events) => sortedCommittedEventIds(events);
|
|
3114
|
-
const pendingEventIds = (events) =>
|
|
3115
|
+
const pendingEventIds = (events) => stampedPendingEventIds(events, "the harness must stamp pending events before persistence");
|
|
3115
3116
|
const tests = [
|
|
3116
3117
|
overlappingCallsPreflight(inEnvironment, () => harness.createAggregate().id, overlappingCallsBoundMs),
|
|
3117
3118
|
{
|
|
@@ -3125,7 +3126,7 @@ function createRepositoryContractTests(harness) {
|
|
|
3125
3126
|
});
|
|
3126
3127
|
const reloaded = await reload(environment, aggregate.id);
|
|
3127
3128
|
assertEqual(reloaded.version, aggregate.version, "add must store the version registered by the Unit of Work");
|
|
3128
|
-
if (snapshotState) assert(deepEqual(snapshotState.call(harness, reloaded), snapshotState.call(harness, aggregate)), "add must store the adapter's complete persistence
|
|
3129
|
+
if (snapshotState) assert(deepEqual(snapshotState.call(harness, reloaded), snapshotState.call(harness, aggregate)), "add must store the adapter's complete persistence capture");
|
|
3129
3130
|
const outbox = await environment.committedOutboxEvents();
|
|
3130
3131
|
assert(deepEqual(eventIds(outbox), pendingEventIds(registeredEvents).sort()), "the outbox must contain exactly the batch registered by add");
|
|
3131
3132
|
assertEqual(aggregate.pendingEvents.length, 0, "only a committed add acknowledges its registered event batch");
|
|
@@ -3458,7 +3459,7 @@ function createSnapshotStoreContractTests(harness) {
|
|
|
3458
3459
|
})
|
|
3459
3460
|
},
|
|
3460
3461
|
{
|
|
3461
|
-
name: "loads are
|
|
3462
|
+
name: "loads are copies and saves capture the input: later mutations touch nothing",
|
|
3462
3463
|
run: inEnv(async (env) => {
|
|
3463
3464
|
const input = snapshot(5, {
|
|
3464
3465
|
total: 5,
|
|
@@ -3477,7 +3478,7 @@ function createSnapshotStoreContractTests(harness) {
|
|
|
3477
3478
|
assertEqual(loaded.state.items.length, 1, "save must capture the snapshot by value, not hold the caller's reference");
|
|
3478
3479
|
loaded.state.total = 999;
|
|
3479
3480
|
const reloaded = await env.store.load(identity("Order", "o-1"));
|
|
3480
|
-
assertEqual(reloaded?.state.total, 5, "load must hand out a
|
|
3481
|
+
assertEqual(reloaded?.state.total, 5, "load must hand out a copy, never live internal state");
|
|
3481
3482
|
})
|
|
3482
3483
|
}
|
|
3483
3484
|
];
|