@shirudo/ddd-kit 3.0.0-rc.12 → 3.0.0-rc.14

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.
@@ -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 { A as IdempotencyClaimHandle, E as ProjectionCheckpointStore, Et as EventCommitCandidate, F as IdempotencyStore, H as DeadlineStore, Ot as AnyDomainEvent, Q as EventBus, Qt as AggregateIdentity, Tt as CommittedDomainEvent, bt as Outbox, c as StreamReadResult, ct as Id, ht as CommandOutboxWriter, i as EventStore, n as ReplayableStreamPages, nt as Aggregate, pt as CommandOutboxCommitCandidate, s as ReadStreamOptions, t as SnapshotStore, tn as PublishedCommand, yt as DispatchTrackingOutbox } from "./chunks/snapshot-store.js";
1
+ import { Ct as CommittedDomainEvent, Et as AnyDomainEvent, I as DeadlineStore, Jt as AggregateIdentity, X as EventBus, Zt as PublishedCommand, _t as DispatchTrackingOutbox, b as ProjectionCheckpointStore, c as StreamReadResult, dt as CommandOutboxCommitCandidate, et as Aggregate, i as EventStore, k as IdempotencyStore, n as ReplayableStreamPages, ot as Id, pt as CommandOutboxWriter, s as ReadStreamOptions, t as SnapshotStore, vt as Outbox, w as IdempotencyClaimHandle, wt as EventCommitCandidate } 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 mints no events, so it stays free of any event union. The two
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 detached return arrays. Physical-position
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 projection. */
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 { P as deepFreeze, U as deepEqual, a as isDispatchTrackingOutbox, c as runBoundedExecution, f as assertPositiveSafeInteger, n as readStreamPages, w as isRecordedDomainEvent } from "./chunks/read-stream-pages.js";
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, v as buildUnstampedDomainEvent, 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 recordedPendingEventIds(events, requirement) {
199
+ function stampedPendingEventIds(events, requirement) {
199
200
  return events.map((event) => {
200
- assert(typeof event === "object" && event !== null && isRecordedDomainEvent(event), requirement);
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) => recordedPendingEventIds(events, "pending events must be recorded before flush");
1006
+ const registeredIds = (events) => stampedPendingEventIds(events, "the unit of work must stamp the batch that add registers");
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;
@@ -1021,10 +1022,11 @@ function createEsRepositoryContractTests(harness) {
1021
1022
  name: "add appends the exact creation batch to stream and outbox",
1022
1023
  run: inEnvironment(async (environment) => {
1023
1024
  const aggregate = harness.createAggregate();
1024
- const expectedIds = recordedIds(aggregate.pendingEvents);
1025
- assertEqual(expectedIds.length, 1, "createAggregate must record exactly one creation event");
1025
+ assertEqual(aggregate.pendingEvents.length, 1, "createAggregate must record exactly one creation event");
1026
+ let expectedIds = [];
1026
1027
  await environment.run(async ({ repository }) => {
1027
1028
  repository.add(aggregate);
1029
+ expectedIds = registeredIds(aggregate.pendingEvents);
1028
1030
  });
1029
1031
  const stream = await environment.committedStreamEvents(streamFor(aggregate.id), readAll);
1030
1032
  assert(stream.exists && deepEqual(ids(stream.events), expectedIds), "the stream must contain exactly the registered creation batch");
@@ -1067,13 +1069,14 @@ function createEsRepositoryContractTests(harness) {
1067
1069
  const aggregate = harness.createAggregate();
1068
1070
  harness.mutate(aggregate);
1069
1071
  harness.mutate(aggregate);
1070
- const expectedIds = recordedIds(aggregate.pendingEvents);
1072
+ let expectedIds = [];
1071
1073
  await environment.run(async ({ repository }) => {
1072
1074
  repository.add(aggregate);
1075
+ expectedIds = registeredIds(aggregate.pendingEvents);
1073
1076
  });
1074
1077
  const reloaded = await environment.run(({ repository }) => load(repository, aggregate.id));
1075
1078
  assertEqual(reloaded.version, expectedIds.length, "event-sourced version must equal the folded event count");
1076
- assertEqual(reloaded.pendingEvents.length, 0, "replay must not re-record historical events");
1079
+ assertEqual(reloaded.pendingEvents.length, 0, "replay must not re-stamp historical events");
1077
1080
  if (snapshotState) assert(deepEqual(snapshotState.call(harness, reloaded), snapshotState.call(harness, aggregate)), "replay must fold to the same state in emission order");
1078
1081
  const stream = await environment.committedStreamEvents(streamFor(aggregate.id), readAll);
1079
1082
  assert(stream.exists && deepEqual(ids(stream.events), expectedIds), "the committed stream must preserve emission order");
@@ -1084,9 +1087,10 @@ function createEsRepositoryContractTests(harness) {
1084
1087
  run: inEnvironment(async (environment) => {
1085
1088
  const aggregate = harness.createAggregate();
1086
1089
  harness.mutate(aggregate);
1087
- const pending = [...aggregate.pendingEvents];
1090
+ let pending = [];
1088
1091
  await captureRejection(environment.run(async ({ repository }) => {
1089
1092
  repository.add(aggregate);
1093
+ pending = [...aggregate.pendingEvents];
1090
1094
  throw new Error("rollback probe");
1091
1095
  }));
1092
1096
  const stream = await environment.committedStreamEvents(streamFor(aggregate.id), readAll);
@@ -1100,9 +1104,10 @@ function createEsRepositoryContractTests(harness) {
1100
1104
  run: inEnvironment(async (environment) => {
1101
1105
  const aggregate = harness.createAggregate();
1102
1106
  harness.mutate(aggregate);
1103
- const expectedIds = recordedIds(aggregate.pendingEvents);
1107
+ let expectedIds = [];
1104
1108
  await captureRejection(environment.run(async ({ repository }) => {
1105
1109
  repository.add(aggregate);
1110
+ expectedIds = registeredIds(aggregate.pendingEvents);
1106
1111
  throw new Error("rollback probe");
1107
1112
  }));
1108
1113
  await environment.run(async ({ repository }) => {
@@ -1117,10 +1122,11 @@ function createEsRepositoryContractTests(harness) {
1117
1122
  name: "outbox failure rolls the already-appended stream batch back",
1118
1123
  run: inEnvironment(async (environment) => {
1119
1124
  const aggregate = harness.createAggregate();
1120
- const pending = [...aggregate.pendingEvents];
1125
+ let pending = [];
1121
1126
  environment.failNextOutboxWrite(/* @__PURE__ */ new Error("outbox failure probe"));
1122
1127
  const rejection = await captureRejection(environment.run(async ({ repository }) => {
1123
1128
  repository.add(aggregate);
1129
+ pending = [...aggregate.pendingEvents];
1124
1130
  }));
1125
1131
  assert(rejection !== void 0, "the outbox failure must reject");
1126
1132
  const stream = await environment.committedStreamEvents(streamFor(aggregate.id), readAll);
@@ -1615,12 +1621,18 @@ function createEventBusContractTests(harness) {
1615
1621
  /**
1616
1622
  * Reusable proof of an EventStore adapter's portable semantics: qualified
1617
1623
  * value identity, ordered reads and slicing, OCC error mapping and atomicity,
1618
- * no-op empty appends, and detached return arrays. Physical-position
1624
+ * no-op empty appends, and copied return arrays. Physical-position
1619
1625
  * corruption needs adapter-specific fixture support and is tested there.
1620
1626
  */
1621
1627
  function createEventStoreContractTests(harness) {
1622
1628
  const inEnv = bindContractEnvironment(() => harness.createEnvironment());
1623
1629
  const fixtureRead = { limit: 100 };
1630
+ /** The decision of `event` without its stamp: no event id and no time. */
1631
+ const unstampedTwin = (event) => buildUnstampedDomainEvent(event.type, event.payload, {
1632
+ aggregateId: event.aggregateId,
1633
+ aggregateType: event.aggregateType,
1634
+ schemaVersion: event.schemaVersion
1635
+ }, "createEventStoreContractTests");
1624
1636
  const hasSameEventIds = (actual, expected) => actual.length === expected.length && actual.every((event, index) => event.eventId === expected[index]?.eventId);
1625
1637
  return [
1626
1638
  {
@@ -1642,6 +1654,18 @@ function createEventStoreContractTests(harness) {
1642
1654
  assert(stored.exists && stored.lastVersion === 1 && stored.events.length === 1 && stored.events[0]?.eventId === event.eventId, "an empty append must not check OCC or create an empty stream");
1643
1655
  })
1644
1656
  },
1657
+ {
1658
+ name: "unstamped event: an append rejects an event without an eventId with TypeError and writes nothing",
1659
+ run: inEnv(async ({ store }) => {
1660
+ const [firstKey] = harness.createCollidingStreamKeys();
1661
+ const stamped = harness.createEvent(firstKey, 50);
1662
+ const unstamped = unstampedTwin(harness.createEvent(firstKey, 51));
1663
+ const rejection = await captureRejection(store.append(firstKey, [stamped, unstamped], { expectedVersion: 0 }));
1664
+ assert(rejection instanceof TypeError, "an append must reject an event without an eventId with TypeError");
1665
+ const stored = await store.readStream(firstKey, fixtureRead);
1666
+ assert(!stored.exists && stored.lastVersion === 0, "an append with an unstamped event must write none of the batch");
1667
+ })
1668
+ },
1645
1669
  {
1646
1670
  name: "qualified stream key: equal aggregate ids remain isolated by aggregate type",
1647
1671
  run: inEnv(async ({ store }) => {
@@ -2779,7 +2803,7 @@ function createProjectionCheckpointStoreContractTests(harness) {
2779
2803
  })
2780
2804
  },
2781
2805
  {
2782
- name: "a loaded position is a detached copy; mutating it must not move the watermark",
2806
+ name: "a loaded position is a copy; mutating it must not move the watermark",
2783
2807
  run: inEnv(async (env) => {
2784
2808
  await env.run((ctx) => env.store.save(ctx, "order-list", order("o-1"), checkpoint(pos(2, 0))));
2785
2809
  const loaded = await env.run((ctx) => env.store.load(ctx, "order-list", order("o-1")));
@@ -3111,7 +3135,7 @@ function createRepositoryContractTests(harness) {
3111
3135
  }
3112
3136
  const reload = (environment, id) => environment.run(({ repository }) => load(repository, id));
3113
3137
  const eventIds = (events) => sortedCommittedEventIds(events);
3114
- const pendingEventIds = (events) => recordedPendingEventIds(events, "the harness must record pending events before persistence");
3138
+ const pendingEventIds = (events) => stampedPendingEventIds(events, "the unit of work must stamp the batch that add registers");
3115
3139
  const tests = [
3116
3140
  overlappingCallsPreflight(inEnvironment, () => harness.createAggregate().id, overlappingCallsBoundMs),
3117
3141
  {
@@ -3119,13 +3143,14 @@ function createRepositoryContractTests(harness) {
3119
3143
  run: inEnvironment(async (environment) => {
3120
3144
  const aggregate = harness.createAggregate();
3121
3145
  harness.mutate(aggregate);
3122
- const registeredEvents = [...aggregate.pendingEvents];
3146
+ let registeredEvents = [];
3123
3147
  await environment.run(async ({ repository }) => {
3124
3148
  repository.add(aggregate);
3149
+ registeredEvents = [...aggregate.pendingEvents];
3125
3150
  });
3126
3151
  const reloaded = await reload(environment, aggregate.id);
3127
3152
  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 projection");
3153
+ if (snapshotState) assert(deepEqual(snapshotState.call(harness, reloaded), snapshotState.call(harness, aggregate)), "add must store the adapter's complete persistence capture");
3129
3154
  const outbox = await environment.committedOutboxEvents();
3130
3155
  assert(deepEqual(eventIds(outbox), pendingEventIds(registeredEvents).sort()), "the outbox must contain exactly the batch registered by add");
3131
3156
  assertEqual(aggregate.pendingEvents.length, 0, "only a committed add acknowledges its registered event batch");
@@ -3183,9 +3208,10 @@ function createRepositoryContractTests(harness) {
3183
3208
  run: inEnvironment(async (environment) => {
3184
3209
  const aggregate = harness.createAggregate();
3185
3210
  harness.mutate(aggregate);
3186
- const pending = [...aggregate.pendingEvents];
3211
+ let pending = [];
3187
3212
  await captureRejection(environment.run(async ({ repository }) => {
3188
3213
  repository.add(aggregate);
3214
+ pending = [...aggregate.pendingEvents];
3189
3215
  throw new Error("rollback probe");
3190
3216
  }));
3191
3217
  const absent = await environment.run(({ repository }) => repository.findById(aggregate.id));
@@ -3199,10 +3225,11 @@ function createRepositoryContractTests(harness) {
3199
3225
  run: inEnvironment(async (environment) => {
3200
3226
  const aggregate = harness.createAggregate();
3201
3227
  harness.mutate(aggregate);
3202
- const pending = [...aggregate.pendingEvents];
3228
+ let pending = [];
3203
3229
  environment.failNextOutboxWrite(/* @__PURE__ */ new Error("outbox failure probe"));
3204
3230
  const rejection = await captureRejection(environment.run(async ({ repository }) => {
3205
3231
  repository.add(aggregate);
3232
+ pending = [...aggregate.pendingEvents];
3206
3233
  }));
3207
3234
  assert(rejection !== void 0, "the outbox failure must reject");
3208
3235
  const absent = await environment.run(({ repository }) => repository.findById(aggregate.id));
@@ -3458,7 +3485,7 @@ function createSnapshotStoreContractTests(harness) {
3458
3485
  })
3459
3486
  },
3460
3487
  {
3461
- name: "loads are detached copies and saves capture the input: later mutations touch nothing",
3488
+ name: "loads are copies and saves capture the input: later mutations touch nothing",
3462
3489
  run: inEnv(async (env) => {
3463
3490
  const input = snapshot(5, {
3464
3491
  total: 5,
@@ -3477,7 +3504,7 @@ function createSnapshotStoreContractTests(harness) {
3477
3504
  assertEqual(loaded.state.items.length, 1, "save must capture the snapshot by value, not hold the caller's reference");
3478
3505
  loaded.state.total = 999;
3479
3506
  const reloaded = await env.store.load(identity("Order", "o-1"));
3480
- assertEqual(reloaded?.state.total, 5, "load must hand out a detached copy, never live internal state");
3507
+ assertEqual(reloaded?.state.total, 5, "load must hand out a copy, never live internal state");
3481
3508
  })
3482
3509
  }
3483
3510
  ];