aifsmjs 0.5.8 → 0.6.0

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.
Files changed (70) hide show
  1. package/README.md +14 -7
  2. package/README_ZHTW.md +14 -7
  3. package/dist/{chunk-ZLQ7HZCE.js → chunk-D6H64FSI.js} +66 -46
  4. package/dist/chunk-D6H64FSI.js.map +1 -0
  5. package/dist/{chunk-NEJYZAKR.js → chunk-Q45LGXHO.js} +3 -3
  6. package/dist/{chunk-NEJYZAKR.js.map → chunk-Q45LGXHO.js.map} +1 -1
  7. package/dist/{chunk-CDK25FTD.cjs → chunk-QCTA2X4J.cjs} +7 -3
  8. package/dist/chunk-QCTA2X4J.cjs.map +1 -0
  9. package/dist/{chunk-A7U7QQL5.js → chunk-SSNKGEVB.js} +7 -4
  10. package/dist/chunk-SSNKGEVB.js.map +1 -0
  11. package/dist/{chunk-I354FONA.cjs → chunk-VGLF5NQH.cjs} +69 -46
  12. package/dist/chunk-VGLF5NQH.cjs.map +1 -0
  13. package/dist/{chunk-FHTQ7LSQ.cjs → chunk-VV5TKFQO.cjs} +4 -4
  14. package/dist/{chunk-FHTQ7LSQ.cjs.map → chunk-VV5TKFQO.cjs.map} +1 -1
  15. package/dist/{chunk-VZCSHTOI.js → chunk-XA24A7VP.js} +156 -157
  16. package/dist/chunk-XA24A7VP.js.map +1 -0
  17. package/dist/{chunk-2MME5V4F.cjs → chunk-YK25NVFC.cjs} +160 -161
  18. package/dist/chunk-YK25NVFC.cjs.map +1 -0
  19. package/dist/effects/index.cjs +3 -4
  20. package/dist/effects/index.cjs.map +1 -1
  21. package/dist/effects/index.d.cts +1 -1
  22. package/dist/effects/index.d.ts +1 -1
  23. package/dist/effects/index.js +2 -3
  24. package/dist/effects/index.js.map +1 -1
  25. package/dist/guards/index.cjs +5 -6
  26. package/dist/guards/index.cjs.map +1 -1
  27. package/dist/guards/index.d.cts +1 -1
  28. package/dist/guards/index.d.ts +1 -1
  29. package/dist/guards/index.js +2 -3
  30. package/dist/guards/index.js.map +1 -1
  31. package/dist/index.cjs +31 -28
  32. package/dist/index.d.cts +66 -18
  33. package/dist/index.d.ts +66 -18
  34. package/dist/index.js +3 -4
  35. package/dist/inspect/index.cjs +0 -2
  36. package/dist/inspect/index.cjs.map +1 -1
  37. package/dist/inspect/index.d.cts +1 -1
  38. package/dist/inspect/index.d.ts +1 -1
  39. package/dist/inspect/index.js +0 -2
  40. package/dist/inspect/index.js.map +1 -1
  41. package/dist/pbt/index.cjs +69 -48
  42. package/dist/pbt/index.cjs.map +1 -1
  43. package/dist/pbt/index.d.cts +29 -16
  44. package/dist/pbt/index.d.ts +29 -16
  45. package/dist/pbt/index.js +61 -40
  46. package/dist/pbt/index.js.map +1 -1
  47. package/dist/replay/index.cjs +4 -5
  48. package/dist/replay/index.d.cts +1 -1
  49. package/dist/replay/index.d.ts +1 -1
  50. package/dist/replay/index.js +3 -4
  51. package/dist/timer/index.cjs +18 -5
  52. package/dist/timer/index.cjs.map +1 -1
  53. package/dist/timer/index.d.cts +6 -0
  54. package/dist/timer/index.d.ts +6 -0
  55. package/dist/timer/index.js +18 -5
  56. package/dist/timer/index.js.map +1 -1
  57. package/dist/{types-DIM7QTtf.d.ts → types-CrDxFfBx.d.cts} +64 -16
  58. package/dist/{types-DIM7QTtf.d.cts → types-CrDxFfBx.d.ts} +64 -16
  59. package/llms-full.txt +89 -17
  60. package/package.json +57 -22
  61. package/dist/chunk-2MME5V4F.cjs.map +0 -1
  62. package/dist/chunk-A7U7QQL5.js.map +0 -1
  63. package/dist/chunk-CDK25FTD.cjs.map +0 -1
  64. package/dist/chunk-I354FONA.cjs.map +0 -1
  65. package/dist/chunk-PZ5AY32C.js +0 -9
  66. package/dist/chunk-PZ5AY32C.js.map +0 -1
  67. package/dist/chunk-Q7SFCCGT.cjs +0 -11
  68. package/dist/chunk-Q7SFCCGT.cjs.map +0 -1
  69. package/dist/chunk-VZCSHTOI.js.map +0 -1
  70. package/dist/chunk-ZLQ7HZCE.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fsm/resolver.ts","../src/fsm/snapshot.ts","../src/fsm/lifecycle.ts","../src/fsm/updater.ts"],"names":["ownValue","IS_DEV","createEnqueuer","evalGuard"],"mappings":"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","file":"chunk-VGLF5NQH.cjs","sourcesContent":["import { ownValue } from \"./evaluator.js\";\nimport type { MachineDef, TransitionConfig, TransitionDef } from \"./types.js\";\n\n/**\n * Normalize a single transition config into its object form. The string\n * shorthand `\"targetState\"` (à la XState) becomes `{ target: \"targetState\" }`;\n * the object form is returned unchanged. Centralised here so every consumer\n * (`step`, `resolveTransitions`, `can`, validation) sees the same shape.\n *\n * @since 0.5.3\n */\nexport function normalizeTransition<Ctx, Evt, States extends string>(\n entry: TransitionConfig<Ctx, Evt, States>,\n): TransitionDef<Ctx, Evt, States> {\n return typeof entry === \"string\" ? ({ target: entry } as TransitionDef<Ctx, Evt, States>) : entry;\n}\n\n/**\n * Normalize the raw `state.on[eventType]` value (object, string shorthand, or\n * an array mixing both) into an ordered list of {@link TransitionDef} objects.\n * Declaration order is preserved.\n *\n * @since 0.5.3\n */\nexport function normalizeTransitions<Ctx, Evt, States extends string>(\n entry:\n | TransitionConfig<Ctx, Evt, States>\n | readonly TransitionConfig<Ctx, Evt, States>[]\n | undefined,\n): readonly TransitionDef<Ctx, Evt, States>[] {\n if (entry === undefined) return [];\n if (Array.isArray(entry)) {\n // Hot path (send/step/can run this per event): when no string shorthand is\n // present, return the original array instead of allocating a normalized copy.\n return entry.some((t) => typeof t === \"string\")\n ? entry.map((t) => normalizeTransition(t))\n : (entry as readonly TransitionDef<Ctx, Evt, States>[]);\n }\n return [normalizeTransition(entry as TransitionConfig<Ctx, Evt, States>)];\n}\n\n/**\n * Return all transition candidates for (state, eventType). Order is preserved\n * from the declaration so that guard fallthrough behaves predictably. String\n * shorthands are normalized to `{ target }` objects.\n *\n * If the event has no entry under the given state, an empty array is returned.\n */\nexport function resolveTransitions<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n stateValue: States,\n eventType: string,\n): readonly TransitionDef<Ctx, Evt, States>[] {\n const state = def.states[stateValue];\n if (!state || !state.on) return [];\n return normalizeTransitions(ownValue(state.on, eventType));\n}\n","import type { Snapshot } from \"./types.js\";\n\n// Written so a bundler define-replacement of `process.env.NODE_ENV` (Vite,\n// webpack 5, ...) still applies: those tools replace only the\n// `process.env.NODE_ENV` expression, not a runtime `process` global, so\n// gating on `typeof process !== \"undefined\"` first left IS_DEV permanently\n// false in a browser build even though NODE_ENV !== \"production\". A plain\n// try/catch around the read lets the replaced literal survive while still\n// falling back to false wherever `process` is entirely absent. Exported for\n// internal dev-only diagnostics (runtime.ts); not re-exported from the root.\nexport let IS_DEV = false;\ntry {\n IS_DEV = process.env.NODE_ENV !== \"production\";\n} catch {\n /* no `process` global (browser without bundler define-replacement) */\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n// Trees already deep-frozen here. Short-circuits re-walking carried-over\n// context and guards cycles; unlike `Object.isFrozen` it does not stop at a\n// shallow-frozen object (e.g. an effect descriptor) whose children are mutable.\nconst DEEP_FROZEN = new WeakSet<object>();\n\nexport function deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== \"object\") return value;\n if (DEEP_FROZEN.has(value)) return value;\n DEEP_FROZEN.add(value);\n // Object.freeze throws on a non-empty TypedArray / Buffer; binary data in\n // context or event payloads is left mutable (caller-owned) instead.\n if (ArrayBuffer.isView(value)) return value;\n Object.freeze(value);\n if (Array.isArray(value)) {\n for (const item of value) deepFreeze(item);\n } else if (isPlainObject(value)) {\n for (const key of Object.keys(value)) {\n deepFreeze((value as Record<string, unknown>)[key]);\n }\n }\n return value;\n}\n\n/**\n * Wrap a freshly built snapshot. In dev mode the whole tree is deep-frozen so\n * accidental mutation throws immediately. In production only the top object is\n * frozen, keeping the cost negligible.\n */\nexport function freezeSnapshot<C, S extends string>(snap: Snapshot<C, S>): Snapshot<C, S> {\n // IS_DEV is always true in vitest; the production branch (`Object.freeze`)\n // is exercised only when NODE_ENV === \"production\" and is intentionally\n // left out of the coverage threshold.\n return IS_DEV ? deepFreeze(snap) : Object.freeze(snap);\n}\n\nexport function createSnapshot<C, S extends string>(args: {\n value: S;\n context: C;\n status?: \"active\" | \"final\";\n}): Snapshot<C, S> {\n return freezeSnapshot({\n value: args.value,\n context: args.context,\n status: args.status ?? \"active\",\n });\n}\n","import { createEnqueuer } from \"../effects/enqueuer.js\";\nimport { evalGuard, ownValue } from \"./evaluator.js\";\nimport { resolveTransitions } from \"./resolver.js\";\nimport { freezeSnapshot } from \"./snapshot.js\";\nimport type {\n Action,\n ActionRef,\n Effect,\n Implementations,\n MachineDef,\n Snapshot,\n StepResult,\n TransitionDef,\n} from \"./types.js\";\nimport { mergeContext } from \"./updater.js\";\n\nexport class UnknownActionError extends Error {\n readonly actionName: string;\n constructor(actionName: string) {\n super(`aifsmjs: action \"${actionName}\" not found in implementations.actions`);\n this.name = \"UnknownActionError\";\n this.actionName = actionName;\n }\n}\n\n/**\n * Thrown (from `step()`, and so from `send()` before anything is committed)\n * when an action returns a non-nullish primitive (`false`, `0`, `\"\"`, ...) as\n * the patch for an object context. An object context accepts only a\n * plain-object patch or `undefined`/`null` (no change).\n *\n * `actionName` is the string ref, the inline function's name, or `\"<inline>\"`\n * for an anonymous inline action (mirrors guard naming).\n *\n * @since 0.6.0\n */\nexport class InvalidActionResultError extends Error {\n readonly actionName: string;\n constructor(actionName: string, patch: unknown) {\n super(\n `aifsmjs: action \"${actionName}\" returned ${typeof patch}; an object context accepts only a plain-object patch (or undefined)`,\n );\n this.name = \"InvalidActionResultError\";\n this.actionName = actionName;\n }\n}\n\nfunction resolveAction<Ctx, Evt>(\n ref: ActionRef<Ctx, Evt>,\n impl: Implementations<Ctx, Evt>,\n): Action<Ctx, Evt> {\n if (typeof ref === \"function\") return ref;\n const fn = ownValue(impl.actions, ref);\n if (!fn) throw new UnknownActionError(ref);\n return fn;\n}\n\nfunction runActions<Ctx, Evt>(\n refs: readonly ActionRef<Ctx, Evt>[] | undefined,\n ctx: Ctx,\n event: Evt,\n impl: Implementations<Ctx, Evt>,\n effectSink: Effect[],\n): Ctx {\n if (!refs || refs.length === 0) return ctx;\n const enqueue = createEnqueuer(effectSink as { type: string; payload?: unknown }[]);\n let current = ctx;\n for (const ref of refs) {\n const fn = resolveAction(ref, impl);\n const patch = fn({ context: current, event, enqueue });\n current = mergeContext(current, patch, typeof ref === \"string\" ? ref : fn.name || \"<inline>\");\n }\n return current;\n}\n\n/**\n * The transition `event` would fire from `snapshot`: the first candidate (in\n * declaration order) with no guard or a passing guard, or `undefined` (also\n * for a final state, which never reacts). Shared by `step()` and\n * `Runtime.can()` so both resolve candidates the same way.\n */\nexport function chooseTransition<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n snapshot: Snapshot<Ctx, States>,\n event: Evt,\n impl: Implementations<Ctx, Evt>,\n): TransitionDef<Ctx, Evt, States> | undefined {\n if (snapshot.status === \"final\") return undefined;\n for (const t of resolveTransitions(def, snapshot.value, event.type)) {\n if (!t.guard || evalGuard(t.guard, snapshot.context, event, impl, snapshot.value)) return t;\n }\n return undefined;\n}\n\nconst NO_EFFECTS: readonly Effect[] = Object.freeze([]);\n\n/**\n * Internal `step()` that also reports whether the chosen transition is\n * external (has a `target`, including a same-value self-target). The runtime\n * uses it to decide the sub-machine lifecycle from the SAME guard pass that\n * produced the snapshot, so a non-idempotent guard is evaluated exactly once\n * per event. Not re-exported from the package root.\n */\nexport function stepWithMeta<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n snapshot: Snapshot<Ctx, States>,\n event: Evt,\n impl: Implementations<Ctx, Evt>,\n): { result: StepResult<Ctx, States>; external: boolean } {\n // Nothing fires for a final state (inert), an undeclared event type, or\n // when every candidate's guard fails.\n const chosen = chooseTransition(def, snapshot, event, impl);\n if (!chosen) {\n return {\n result: Object.freeze({ snapshot, effects: NO_EFFECTS, changed: false }),\n external: false,\n };\n }\n // A chosen transition implies snapshot.value is a declared state.\n const state = def.states[snapshot.value];\n\n const isExternal = chosen.target !== undefined;\n const nextStateValue = (chosen.target ?? snapshot.value) as States;\n const nextState = def.states[nextStateValue];\n\n const effectSink: Effect[] = [];\n let ctx = snapshot.context;\n\n if (isExternal) {\n ctx = runActions(state.exit, ctx, event, impl, effectSink);\n }\n ctx = runActions(chosen.actions, ctx, event, impl, effectSink);\n if (isExternal && nextState) {\n ctx = runActions(nextState.entry, ctx, event, impl, effectSink);\n }\n\n const status: \"active\" | \"final\" = nextState?.final === true ? \"final\" : \"active\";\n const nextSnapshot = freezeSnapshot({\n value: nextStateValue,\n context: ctx,\n status,\n });\n\n return {\n result: Object.freeze({\n snapshot: nextSnapshot,\n effects: Object.freeze(effectSink.slice()) as readonly Effect[],\n changed: true,\n }),\n external: isExternal,\n };\n}\n\n/**\n * Compute the next snapshot and collected effects from a single event.\n *\n * Order is fixed and uninterruptible:\n * 1. resolve candidate transitions for (state, event.type)\n * 2. evaluate guards in declaration order; pick the first passing one\n * 3. if external (target defined), run exit actions of the old state\n * 4. run transition.actions in declaration order\n * 5. if external, run entry actions of the new state\n * 6. return { snapshot, effects, changed }\n *\n * The function is pure: it never dispatches effects and never mutates inputs.\n * Each guard on the path is evaluated at most once.\n */\nexport function step<Ctx, Evt extends { type: string }, States extends string>(\n def: MachineDef<Ctx, Evt, States>,\n snapshot: Snapshot<Ctx, States>,\n event: Evt,\n impl: Implementations<Ctx, Evt>,\n): StepResult<Ctx, States> {\n return stepWithMeta(def, snapshot, event, impl).result;\n}\n","import { InvalidActionResultError } from \"./lifecycle.js\";\nimport { isPlainObject } from \"./snapshot.js\";\nimport type { Action } from \"./types.js\";\n\n/**\n * Build an Action that returns a Partial<Ctx> from a pure updater.\n * The partial is merged into the current context by `step()`.\n */\nexport function assign<Ctx, Evt>(\n updater: (args: { context: Ctx; event: Evt }) => Partial<Ctx>,\n): Action<Ctx, Evt> {\n return ({ context, event }) => updater({ context, event });\n}\n\n/**\n * Merge an action's result into the current context. The function never\n * mutates either argument.\n *\n * - `undefined` / `null` patch: `current` is returned unchanged.\n * - Object context (not an array or `ArrayBuffer` view) + plain-object patch:\n * shallow merge into a new object that keeps `current`'s prototype, so a\n * class-instance context keeps its methods and untouched fields. Only own\n * enumerable (string and symbol) properties are carried; `#private` and\n * non-enumerable members are not, so prefer plain-object contexts.\n * - Object context + non-nullish primitive patch (`false`, `0`, `\"\"`, ...):\n * throws {@link InvalidActionResultError} (`actionName` names the action).\n * - Anything else (a primitive or array context, or a non-plain-object patch\n * such as an array or class instance): the patch replaces `current`.\n */\nexport function mergeContext<Ctx>(\n current: Ctx,\n patch: Partial<Ctx> | void,\n actionName = \"<inline>\",\n): Ctx {\n if (patch === undefined || patch === null) return current;\n if (\n current !== null &&\n typeof current === \"object\" &&\n !Array.isArray(current) &&\n !ArrayBuffer.isView(current)\n ) {\n // Spread (CreateDataProperty) rather than Object.assign ([[Set]]): an own\n // `__proto__` key in a JSON-derived patch stays a plain data property\n // instead of re-prototyping the merged context, and prototype setters\n // are never invoked. Object.setPrototypeOf is a no-op for plain contexts.\n if (isPlainObject(patch)) {\n return Object.setPrototypeOf({ ...current, ...patch }, Object.getPrototypeOf(current));\n }\n if (typeof patch !== \"object\" && typeof patch !== \"function\") {\n throw new InvalidActionResultError(actionName, patch);\n }\n }\n return patch as Ctx;\n}\n"]}
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkI354FONA_cjs = require('./chunk-I354FONA.cjs');
3
+ var chunkVGLF5NQH_cjs = require('./chunk-VGLF5NQH.cjs');
4
4
 
5
5
  // src/replay/index.ts
6
6
  function replay(initial, events, def, impl) {
7
7
  let snapshot = initial;
8
8
  const effects = [];
9
9
  for (const event of events) {
10
- const r = chunkI354FONA_cjs.step(def, snapshot, event, impl);
10
+ const r = chunkVGLF5NQH_cjs.step(def, snapshot, event, impl);
11
11
  snapshot = r.snapshot;
12
12
  if (r.effects.length > 0) {
13
13
  for (const eff of r.effects) effects.push(eff);
@@ -17,5 +17,5 @@ function replay(initial, events, def, impl) {
17
17
  }
18
18
 
19
19
  exports.replay = replay;
20
- //# sourceMappingURL=chunk-FHTQ7LSQ.cjs.map
21
- //# sourceMappingURL=chunk-FHTQ7LSQ.cjs.map
20
+ //# sourceMappingURL=chunk-VV5TKFQO.cjs.map
21
+ //# sourceMappingURL=chunk-VV5TKFQO.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/replay/index.ts"],"names":["step"],"mappings":";;;;;AAiBO,SAAS,MAAA,CACd,OAAA,EACA,MAAA,EACA,GAAA,EACA,IAAA,EAC2B;AAC3B,EAAA,IAAI,QAAA,GAAW,OAAA;AACf,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,CAAA,GAAIA,sBAAA,CAAK,GAAA,EAAK,QAAA,EAAU,OAAO,IAAI,CAAA;AACzC,IAAA,QAAA,GAAW,CAAA,CAAE,QAAA;AACb,IAAA,IAAI,CAAA,CAAE,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACxB,MAAA,KAAA,MAAW,GAAA,IAAO,CAAA,CAAE,OAAA,EAAS,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,IAC/C;AAAA,EACF;AACA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,EAAE,QAAA,EAAU,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,EAAG,CAAA;AAC5E","file":"chunk-FHTQ7LSQ.cjs","sourcesContent":["import { step } from \"../fsm/lifecycle.js\";\nimport type { Effect, Implementations, MachineDef, Snapshot } from \"../fsm/types.js\";\n\nexport type ReplayResult<Ctx, States extends string> = Readonly<{\n snapshot: Snapshot<Ctx, States>;\n effects: readonly Effect[];\n}>;\n\n/**\n * Fold an event log into a final snapshot via `step()`. Effects are collected\n * but never dispatched — this is a pure function, suitable for PBT, time\n * travel, and incident reproduction.\n *\n * Equivalent to:\n * events.reduce((s, e) => step(def, s, e, impl).snapshot, initial)\n * but also accumulates the effects across all events.\n */\nexport function replay<Ctx, Evt extends { type: string }, States extends string>(\n initial: Snapshot<Ctx, States>,\n events: readonly Evt[],\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n): ReplayResult<Ctx, States> {\n let snapshot = initial;\n const effects: Effect[] = [];\n for (const event of events) {\n const r = step(def, snapshot, event, impl);\n snapshot = r.snapshot;\n if (r.effects.length > 0) {\n for (const eff of r.effects) effects.push(eff);\n }\n }\n return Object.freeze({ snapshot, effects: Object.freeze(effects.slice()) });\n}\n"]}
1
+ {"version":3,"sources":["../src/replay/index.ts"],"names":["step"],"mappings":";;;;;AAiBO,SAAS,MAAA,CACd,OAAA,EACA,MAAA,EACA,GAAA,EACA,IAAA,EAC2B;AAC3B,EAAA,IAAI,QAAA,GAAW,OAAA;AACf,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,CAAA,GAAIA,sBAAA,CAAK,GAAA,EAAK,QAAA,EAAU,OAAO,IAAI,CAAA;AACzC,IAAA,QAAA,GAAW,CAAA,CAAE,QAAA;AACb,IAAA,IAAI,CAAA,CAAE,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACxB,MAAA,KAAA,MAAW,GAAA,IAAO,CAAA,CAAE,OAAA,EAAS,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,IAC/C;AAAA,EACF;AACA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,EAAE,QAAA,EAAU,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,EAAG,CAAA;AAC5E","file":"chunk-VV5TKFQO.cjs","sourcesContent":["import { step } from \"../fsm/lifecycle.js\";\nimport type { Effect, Implementations, MachineDef, Snapshot } from \"../fsm/types.js\";\n\nexport type ReplayResult<Ctx, States extends string> = Readonly<{\n snapshot: Snapshot<Ctx, States>;\n effects: readonly Effect[];\n}>;\n\n/**\n * Fold an event log into a final snapshot via `step()`. Effects are collected\n * but never dispatched — this is a pure function, suitable for PBT, time\n * travel, and incident reproduction.\n *\n * Equivalent to:\n * events.reduce((s, e) => step(def, s, e, impl).snapshot, initial)\n * but also accumulates the effects across all events.\n */\nexport function replay<Ctx, Evt extends { type: string }, States extends string>(\n initial: Snapshot<Ctx, States>,\n events: readonly Evt[],\n def: MachineDef<Ctx, Evt, States>,\n impl: Implementations<Ctx, Evt>,\n): ReplayResult<Ctx, States> {\n let snapshot = initial;\n const effects: Effect[] = [];\n for (const event of events) {\n const r = step(def, snapshot, event, impl);\n snapshot = r.snapshot;\n if (r.effects.length > 0) {\n for (const eff of r.effects) effects.push(eff);\n }\n }\n return Object.freeze({ snapshot, effects: Object.freeze(effects.slice()) });\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { freezeSnapshot, step, normalizeTransitions, deepFreeze } from './chunk-ZLQ7HZCE.js';
2
- import { evalGuard, isAsyncGuardFn, isThenable } from './chunk-A7U7QQL5.js';
1
+ import { freezeSnapshot, chooseTransition, normalizeTransitions, stepWithMeta, deepFreeze, IS_DEV } from './chunk-D6H64FSI.js';
2
+ import { isAsyncGuardFn, ownValue, isThenable } from './chunk-SSNKGEVB.js';
3
3
 
4
4
  // src/fsm/types.ts
5
5
  var RESET_EVENT_TYPE = "@@aifsmjs/RESET";
@@ -11,13 +11,16 @@ var InvalidDefinitionError = class extends Error {
11
11
  this.name = "InvalidDefinitionError";
12
12
  }
13
13
  };
14
- function validateDefinition(def) {
14
+ function assertObject(value, subject) {
15
+ if (value === null || typeof value !== "object") {
16
+ throw new InvalidDefinitionError(`${subject} must be an object`);
17
+ }
18
+ }
19
+ function validateDefinition(def, seen = /* @__PURE__ */ new WeakSet()) {
15
20
  if (!def.id || typeof def.id !== "string") {
16
21
  throw new InvalidDefinitionError("definition must have a non-empty string `id`");
17
22
  }
18
- if (!def.states || typeof def.states !== "object") {
19
- throw new InvalidDefinitionError("definition must have a `states` object");
20
- }
23
+ assertObject(def.states, "definition states");
21
24
  const stateKeys = Object.keys(def.states);
22
25
  if (stateKeys.length === 0) {
23
26
  throw new InvalidDefinitionError("`states` must declare at least one state");
@@ -28,6 +31,7 @@ function validateDefinition(def) {
28
31
  );
29
32
  }
30
33
  for (const [stateName, stateDef] of Object.entries(def.states)) {
34
+ assertObject(stateDef, `state "${stateName}"`);
31
35
  if (stateDef.sub !== void 0) {
32
36
  const sub = stateDef.sub;
33
37
  const subStates = sub.states;
@@ -39,11 +43,16 @@ function validateDefinition(def) {
39
43
  `state "${stateName}".sub is not a valid sub-machine definition (missing states or initial)`
40
44
  );
41
45
  }
46
+ if (!seen.has(sub)) {
47
+ seen.add(sub);
48
+ validateDefinition(sub, seen);
49
+ }
42
50
  }
43
51
  if (!stateDef.on) continue;
44
52
  for (const [evtType, entry] of Object.entries(stateDef.on)) {
45
53
  const transitions = normalizeTransitions(entry);
46
54
  for (const t of transitions) {
55
+ assertObject(t, `transition ${stateName} -[${evtType}]->`);
47
56
  if (t.target !== void 0 && !stateKeys.includes(t.target)) {
48
57
  throw new InvalidDefinitionError(
49
58
  `transition ${stateName} -[${evtType}]-> "${String(t.target)}" targets an unknown state`
@@ -57,20 +66,26 @@ function validateDefinition(def) {
57
66
  }
58
67
  }
59
68
  }
69
+ const path = /* @__PURE__ */ new Set();
70
+ let d = def;
71
+ while (d) {
72
+ if (path.has(d)) {
73
+ throw new InvalidDefinitionError(
74
+ `sub-machine cycle through initial states: "${d.id}" is re-entered via initial-state subs`
75
+ );
76
+ }
77
+ path.add(d);
78
+ d = d.states[d.initial]?.sub;
79
+ }
60
80
  }
61
81
  function defineMachine(def) {
62
- const normalized = !("context" in def) ? { ...def, context: {} } : def;
82
+ assertObject(def, "definition");
83
+ const normalized = def.context === void 0 ? { ...def, context: {} } : def;
63
84
  validateDefinition(normalized);
64
85
  return normalized;
65
86
  }
66
87
  function setup() {
67
- return {
68
- defineMachine: (def) => {
69
- const cast = !("context" in def) ? { ...def, context: {} } : def;
70
- validateDefinition(cast);
71
- return cast;
72
- }
73
- };
88
+ return { defineMachine };
74
89
  }
75
90
  function initialSnapshot(def) {
76
91
  const isFinal = def.states[def.initial]?.final === true;
@@ -120,15 +135,29 @@ function composeMiddleware(middleware) {
120
135
  dispatch(0);
121
136
  };
122
137
  }
138
+ function assertListener(listener) {
139
+ if (typeof listener !== "function") {
140
+ throw new InvalidDefinitionError("listener must be a function");
141
+ }
142
+ }
123
143
  function createRuntime(def, impl, opts = {}) {
144
+ assertObject(def, "definition");
145
+ assertObject(def.states, "definition states");
146
+ assertObject(impl, "implementations");
147
+ assertObject(opts, "options");
148
+ const middleware = opts.middleware;
149
+ if (middleware !== void 0 && !(Array.isArray(middleware) && middleware.every((fn) => typeof fn === "function"))) {
150
+ throw new InvalidDefinitionError("options.middleware must be an array of functions");
151
+ }
124
152
  let snapshot = initialSnapshot(def);
125
153
  const listeners = /* @__PURE__ */ new Set();
126
- const middlewareChain = opts.middleware && opts.middleware.length > 0 ? composeMiddleware(opts.middleware) : void 0;
154
+ const middlewareChain = middleware && middleware.length > 0 ? composeMiddleware(middleware) : void 0;
127
155
  const shouldDispatch = opts.dispatchEffects !== false;
128
156
  const controller = new AbortController();
129
157
  let disposed = false;
158
+ let dispatching = false;
159
+ const mailbox = [];
130
160
  let childRuntime;
131
- let childAbortCleanup;
132
161
  const eventListeners = {
133
162
  transition: /* @__PURE__ */ new Set(),
134
163
  error: /* @__PURE__ */ new Set(),
@@ -136,162 +165,131 @@ function createRuntime(def, impl, opts = {}) {
136
165
  };
137
166
  const externalAbortCleanups = /* @__PURE__ */ new Set();
138
167
  function emit(type, payload) {
139
- for (const fn of Array.from(eventListeners[type])) fn(payload);
140
- }
141
- function notify(committed) {
142
- const captured = committed ?? snapshot;
143
- for (const l of Array.from(listeners)) l(captured);
144
- }
145
- function runMiddleware(prev, event, effects, changed) {
146
- if (!middlewareChain) return;
147
- middlewareChain(deepFreeze({ prev, next: snapshot, event, effects, changed }), () => {
148
- });
168
+ const set = eventListeners[type];
169
+ let failed = false;
170
+ let firstError;
171
+ for (const fn of Array.from(set)) {
172
+ if (!set.has(fn)) continue;
173
+ try {
174
+ fn(payload);
175
+ } catch (err) {
176
+ if (!failed) {
177
+ failed = true;
178
+ firstError = err;
179
+ }
180
+ }
181
+ }
182
+ if (failed) throw firstError;
149
183
  }
150
184
  function dispatchEffects(effects, context, event) {
151
185
  if (!impl.effects || effects.length === 0) return;
152
186
  for (const eff of effects) {
153
- const handler = impl.effects[eff.type];
187
+ const handler = ownValue(impl.effects, eff.type);
154
188
  if (!handler) continue;
155
189
  const r = handler(eff, { context, event, signal: controller.signal });
156
190
  if (isThenable(r)) {
157
191
  Promise.resolve(r).catch((err) => {
158
- emit("error", { error: err, event });
192
+ if (eventListeners.error.size > 0) emit("error", { error: err, event });
193
+ else if (IS_DEV) {
194
+ console.warn(
195
+ 'aifsmjs: unhandled async effect rejection; register runtime.on("error", ...)',
196
+ err
197
+ );
198
+ }
159
199
  });
160
200
  }
161
201
  }
162
202
  }
163
- function wireChildAbort(child) {
164
- if (controller.signal.aborted) {
165
- try {
166
- child.dispose();
167
- } catch {
168
- }
169
- return () => {
170
- };
171
- }
172
- const onAbort = () => {
203
+ function swapChild(prevValue, nextValue) {
204
+ const stateDef = def.states[nextValue];
205
+ let next;
206
+ if (stateDef?.sub) {
173
207
  try {
174
- child.dispose();
175
- } catch {
176
- }
177
- };
178
- controller.signal.addEventListener("abort", onAbort, { once: true });
179
- return () => controller.signal.removeEventListener("abort", onAbort);
180
- }
181
- function initChildFor(stateValue) {
182
- const stateDef = def.states[stateValue];
183
- const sub = stateDef?.sub;
184
- if (sub === void 0) return;
185
- let newChild;
186
- try {
187
- newChild = createRuntime(sub, stateDef.subImpl ?? {});
188
- } catch (cause) {
189
- throw new SubMachineError(stateValue, "init", cause);
190
- }
191
- childRuntime = newChild;
192
- childAbortCleanup = wireChildAbort(newChild);
193
- }
194
- function findChosenIsExternal(value, event, context) {
195
- const state = def.states[value];
196
- if (!state?.on) return false;
197
- const list = normalizeTransitions(state.on[event.type]);
198
- if (list.length === 0) return false;
199
- for (const t of list) {
200
- if (!t.guard || evalGuard(t.guard, context, event, impl, value)) {
201
- return t.target !== void 0;
208
+ next = createRuntime(stateDef.sub, stateDef.subImpl ?? {});
209
+ } catch (cause) {
210
+ throw new SubMachineError(nextValue, "init", cause);
202
211
  }
203
212
  }
204
- return false;
205
- }
206
- function applySubLifecycle(prevValue, nextValue) {
207
- const prevStateDef = def.states[prevValue];
208
- const nextStateDef = def.states[nextValue];
209
- if (prevStateDef?.sub !== void 0 && childRuntime !== void 0) {
210
- const child = childRuntime;
213
+ const old = childRuntime;
214
+ if (old) {
211
215
  childRuntime = void 0;
212
- childAbortCleanup?.();
213
- childAbortCleanup = void 0;
214
216
  try {
215
- child.dispose();
217
+ old.dispose();
216
218
  } catch (cause) {
219
+ next?.dispose();
217
220
  throw new SubMachineError(prevValue, "dispose", cause);
218
221
  }
219
222
  }
220
- if (nextStateDef?.sub !== void 0) {
221
- initChildFor(nextValue);
222
- }
223
+ if (disposed) next?.dispose();
224
+ else childRuntime = next;
223
225
  }
224
- function send(event) {
225
- if (disposed) throw new RuntimeDisposedError();
226
- const prev = snapshot;
227
- const result = step(def, prev, event, impl);
228
- const isExternal = result.changed && (prev.value !== result.snapshot.value || findChosenIsExternal(prev.value, event, prev.context));
229
- if (result.changed && isExternal) applySubLifecycle(prev.value, result.snapshot.value);
230
- snapshot = result.snapshot;
231
- const committed = result.snapshot;
232
- runMiddleware(prev, event, result.effects, result.changed);
233
- if (shouldDispatch) dispatchEffects(result.effects, committed.context, event);
234
- if (result.changed) {
235
- notify(committed);
226
+ function commit(prev, next, event, effects, changed) {
227
+ snapshot = next;
228
+ middlewareChain?.(
229
+ Object.freeze({ prev, next, event, effects: deepFreeze(effects), changed }),
230
+ () => {
231
+ }
232
+ );
233
+ if (shouldDispatch) dispatchEffects(effects, next.context, event);
234
+ if (changed) {
235
+ for (const l of Array.from(listeners)) if (listeners.has(l)) l(next);
236
236
  emit("transition", {
237
237
  prev,
238
- next: committed,
238
+ next,
239
239
  event,
240
- effects: result.effects,
240
+ effects,
241
241
  changed: true
242
242
  });
243
243
  }
244
- return snapshot;
245
244
  }
246
- function reset(event) {
247
- if (disposed) throw new RuntimeDisposedError();
245
+ function processSend(event) {
248
246
  const prev = snapshot;
249
- const nextSnap = initialSnapshot(def);
250
- const changed = prev.value !== nextSnap.value;
251
- if (childRuntime) {
252
- const child = childRuntime;
253
- childRuntime = void 0;
254
- childAbortCleanup?.();
255
- childAbortCleanup = void 0;
256
- try {
257
- child.dispose();
258
- } catch (cause) {
259
- throw new SubMachineError(prev.value, "dispose", cause);
260
- }
247
+ const { result, external } = stepWithMeta(def, prev, event, impl);
248
+ if (result.changed && (prev.value !== result.snapshot.value || external)) {
249
+ swapChild(prev.value, result.snapshot.value);
261
250
  }
262
- const initStateDef = def.states[nextSnap.value];
263
- if (initStateDef?.sub) {
264
- initChildFor(nextSnap.value);
251
+ commit(prev, result.snapshot, event, result.effects, result.changed);
252
+ }
253
+ function processReset(event) {
254
+ const prev = snapshot;
255
+ const next = initialSnapshot(def);
256
+ swapChild(prev.value, next.value);
257
+ commit(
258
+ prev,
259
+ next,
260
+ event ?? RESET_EVENT,
261
+ [],
262
+ prev.value !== next.value || prev.status !== next.status || prev.context !== next.context
263
+ );
264
+ }
265
+ function run(entry) {
266
+ if (disposed) throw new RuntimeDisposedError();
267
+ if ((entry.kind === "send" || entry.event !== void 0) && typeof entry.event?.type !== "string") {
268
+ throw new InvalidDefinitionError(
269
+ `${entry.kind}() event must be an object with a string type`
270
+ );
265
271
  }
266
- snapshot = nextSnap;
267
- const committed = nextSnap;
268
- const triggerEvent = event ?? RESET_EVENT;
269
- runMiddleware(prev, triggerEvent, [], changed);
270
- if (changed) {
271
- notify(committed);
272
- emit("transition", {
273
- prev,
274
- next: committed,
275
- event: triggerEvent,
276
- effects: [],
277
- changed: true
278
- });
272
+ if (dispatching) {
273
+ mailbox.push(entry);
274
+ return snapshot;
279
275
  }
280
- return snapshot;
281
- }
282
- function can(event) {
283
- if (disposed || snapshot.status === "final") return false;
284
- const state = def.states[snapshot.value];
285
- if (!state) return false;
286
- const list = normalizeTransitions(state.on?.[event.type]);
287
- if (list.length === 0) return false;
288
- for (const t of list) {
289
- if (!t.guard) return true;
290
- if (evalGuard(t.guard, snapshot.context, event, impl, snapshot.value)) return true;
276
+ dispatching = true;
277
+ try {
278
+ for (let m = entry; m && !disposed; m = mailbox.shift()) {
279
+ if (m.kind === "send") processSend(m.event);
280
+ else processReset(m.event);
281
+ }
282
+ } finally {
283
+ dispatching = false;
284
+ mailbox.length = 0;
291
285
  }
292
- return false;
286
+ return snapshot;
293
287
  }
294
288
  function on(type, listener, options) {
289
+ if (!Object.hasOwn(eventListeners, type)) {
290
+ throw new InvalidDefinitionError('on() type must be "transition", "error" or "dispose"');
291
+ }
292
+ assertListener(listener);
295
293
  if (disposed || options?.signal?.aborted) return () => {
296
294
  };
297
295
  const target = eventListeners[type];
@@ -323,28 +321,31 @@ function createRuntime(def, impl, opts = {}) {
323
321
  function dispose() {
324
322
  if (disposed) return;
325
323
  disposed = true;
326
- if (childRuntime) {
327
- childAbortCleanup?.();
328
- childAbortCleanup = void 0;
329
- try {
330
- childRuntime.dispose();
331
- } catch {
332
- }
333
- childRuntime = void 0;
324
+ mailbox.length = 0;
325
+ const child = childRuntime;
326
+ childRuntime = void 0;
327
+ try {
328
+ child?.dispose();
329
+ } catch {
334
330
  }
335
331
  controller.abort();
336
332
  listeners.clear();
337
- emit("dispose", void 0);
338
- for (const set of Object.values(eventListeners)) set.clear();
339
- for (const cleanup of externalAbortCleanups) cleanup();
340
- externalAbortCleanups.clear();
333
+ try {
334
+ emit("dispose", void 0);
335
+ } catch {
336
+ } finally {
337
+ for (const set of Object.values(eventListeners)) set.clear();
338
+ for (const cleanup of externalAbortCleanups) cleanup();
339
+ externalAbortCleanups.clear();
340
+ }
341
341
  }
342
342
  const runtime = {
343
343
  getSnapshot: () => snapshot,
344
344
  snapshot: () => snapshot,
345
- send,
346
- can,
347
- reset,
345
+ send: (event) => run({ kind: "send", event }),
346
+ // Same candidate resolution as step(), without running any action.
347
+ can: (event) => !disposed && chooseTransition(def, snapshot, event, impl) !== void 0,
348
+ reset: (event) => run({ kind: "reset", event }),
348
349
  dispose,
349
350
  on,
350
351
  get disposed() {
@@ -354,6 +355,7 @@ function createRuntime(def, impl, opts = {}) {
354
355
  return controller.signal;
355
356
  },
356
357
  subscribe(listener) {
358
+ assertListener(listener);
357
359
  if (disposed) return () => {
358
360
  };
359
361
  listeners.add(listener);
@@ -362,13 +364,10 @@ function createRuntime(def, impl, opts = {}) {
362
364
  subRuntime: () => childRuntime,
363
365
  onTransition: (handler, options) => on("transition", handler, options)
364
366
  };
365
- const bootStateDef = def.states[snapshot.value];
366
- if (bootStateDef?.sub) {
367
- initChildFor(snapshot.value);
368
- }
367
+ swapChild(snapshot.value, snapshot.value);
369
368
  return runtime;
370
369
  }
371
370
 
372
371
  export { InvalidDefinitionError, RESET_EVENT_TYPE, RuntimeDisposedError, SubMachineError, createMachine, createRuntime, defineMachine, initialSnapshot, setup };
373
- //# sourceMappingURL=chunk-VZCSHTOI.js.map
374
- //# sourceMappingURL=chunk-VZCSHTOI.js.map
372
+ //# sourceMappingURL=chunk-XA24A7VP.js.map
373
+ //# sourceMappingURL=chunk-XA24A7VP.js.map