@vielzeug/clockwork 2.0.0 → 2.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"interpret.cjs","names":[],"sources":["../src/interpret.ts"],"sourcesContent":["import type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n Effect,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Transition,\n TransitionResult,\n} from './types.js';\n\nimport { compileDefinition, type CompiledAfter, type CompiledMachine, type CompiledState } from './definition.js';\nimport { ClockworkError } from './errors.js';\n\ntype InternalEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly after: CompiledAfter<State, Context, Event>;\n readonly kind: 'after';\n};\n\ntype RuntimeEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> =\n { readonly event: Event; readonly kind: 'event' } | InternalEvent<State, Context, Event>;\n\ntype SelectedTransition<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly transition: Transition<State, Context, Event>;\n};\n\ntype TransitionOutcome<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly result: TransitionResult<State, Context>;\n readonly transition?: Transition<State, Context, Event>;\n};\n\nconst createSnapshot = <State extends string, Context extends Record<string, unknown>>(\n state: State,\n context: Context,\n): MachineSnapshot<State, Context> => ({ context, state });\n\nconst invalidSnapshot = (state: unknown): never => {\n throw new ClockworkError('INVALID_SNAPSHOT_STATE', `snapshot state \"${String(state)}\" is not declared`, { state });\n};\n\nconst isContextRecord = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === null || prototype === Object.prototype;\n};\n\nconst isMachineEvent = (event: unknown): event is MachineEvent =>\n typeof event === 'object' && event !== null && typeof (event as { type?: unknown }).type === 'string';\n\nconst stateNode = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n state: State,\n): CompiledState<State, Context, Event> => machine.states.get(state) ?? invalidSnapshot(state);\n\nconst selectTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): SelectedTransition<State, Context, Event> | undefined => {\n const state = stateNode(machine, snapshot.state);\n\n if (runtimeEvent.kind === 'after') {\n if (!state.after.includes(runtimeEvent.after)) return undefined;\n\n const { definition } = runtimeEvent.after;\n\n if (!definition.guard || definition.guard({ context: snapshot.context, event: undefined })) {\n return { event: undefined, transition: definition };\n }\n\n return undefined;\n }\n\n const candidates = state.on.get(runtimeEvent.event.type);\n\n if (!candidates) return undefined;\n\n for (const candidate of candidates) {\n const guard = candidate.guard as\n ((args: { readonly context: Readonly<Context>; readonly event: Event }) => boolean) | undefined;\n\n if (!guard || guard({ context: snapshot.context, event: runtimeEvent.event })) {\n return { event: runtimeEvent.event, transition: candidate };\n }\n }\n\n return undefined;\n};\n\nconst transition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): TransitionOutcome<State, Context, Event> => {\n const selected = selectTransition(machine, snapshot, runtimeEvent);\n\n if (!selected) {\n return {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n result: { snapshot, type: 'ignored' },\n };\n }\n\n const reducer = selected.transition.reduce as\n ((args: { readonly context: Readonly<Context>; readonly event: Event | undefined }) => Context) | undefined;\n const nextContext = reducer ? reducer({ context: snapshot.context, event: selected.event }) : snapshot.context;\n\n if (!isContextRecord(nextContext)) {\n throw new ClockworkError('INVALID_CONTEXT', 'a reducer must return a non-array object record', {\n state: snapshot.state,\n });\n }\n\n return {\n event: selected.event,\n result: { snapshot: createSnapshot(selected.transition.target, nextContext as Context), type: 'transition' },\n transition: selected.transition,\n };\n};\n\nconst canTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n event: Event,\n): boolean => selectTransition(machine, snapshot, { event, kind: 'event' }) !== undefined;\n\nconst createActor = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n initialSnapshot: MachineSnapshot<State, Context>,\n options: ActorOptions<State, Context, Event> = {},\n): Actor<State, Context, Event> => {\n if (\n options.maxTransitions !== undefined &&\n (!Number.isInteger(options.maxTransitions) || options.maxTransitions < 1)\n ) {\n throw new ClockworkError('INVALID_MAX_TRANSITIONS', 'maxTransitions must be a positive integer', {\n maxTransitions: options.maxTransitions,\n });\n }\n\n let current = options.snapshot ?? initialSnapshot;\n\n if (!isContextRecord(current.context)) {\n throw new ClockworkError('INVALID_CONTEXT', 'snapshot context must be a non-array object record', {});\n }\n\n if (!machine.states.has(current.state)) invalidSnapshot(current.state);\n\n const listeners = new Set<(snapshot: MachineSnapshot<State, Context>) => void>();\n const disposal = new AbortController();\n const timers = new Set<ReturnType<typeof setTimeout>>();\n const invokes = new Set<AbortController>();\n const queue: RuntimeEvent<State, Context, Event>[] = [];\n const maxTransitions = options.maxTransitions ?? 1_000;\n let disposed = false;\n let processing = false;\n\n const cancelStateResources = (): void => {\n for (const timer of timers) clearTimeout(timer);\n timers.clear();\n\n for (const controller of invokes) controller.abort();\n invokes.clear();\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n queue.length = 0;\n cancelStateResources();\n listeners.clear();\n disposal.abort();\n };\n\n const report = (error: unknown, context: ActorErrorContext<State, Event>): void => {\n let disposition: unknown = 'dispose';\n\n if (options.onError) {\n try {\n disposition = options.onError(error, context);\n } catch (handlerError) {\n dispose();\n throw handlerError;\n }\n }\n\n if (disposition !== 'continue') dispose();\n };\n\n const run = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n if (disposed) return;\n\n if (processing) {\n queue.push(runtimeEvent);\n\n return;\n }\n\n processing = true;\n\n try {\n process(runtimeEvent);\n flush();\n } finally {\n processing = false;\n }\n };\n\n const send = (event: Event): void => {\n if (!isMachineEvent(event)) return;\n\n run({ event, kind: 'event' });\n };\n\n const runEffects = (effects: readonly Effect<Context, Event>[], state: State, event: Event | undefined): void => {\n for (const effect of effects) {\n if (disposed) return;\n\n try {\n effect({ context: current.context, event, send, signal: disposal.signal });\n } catch (error) {\n report(error, { event, phase: 'effect', state });\n }\n }\n };\n\n const establishStateResources = (state: State, event: Event | undefined): void => {\n const node = stateNode(machine, state);\n\n for (const after of node.after) {\n const timer = setTimeout(() => {\n timers.delete(timer);\n run({ after, kind: 'after' });\n }, after.definition.delay);\n\n timers.add(timer);\n }\n\n for (const invoke of node.invoke) {\n const controller = new AbortController();\n\n invokes.add(controller);\n\n const capturedContext = current.context;\n const capturedEvent = event;\n\n void Promise.resolve()\n .then(() => invoke.src({ context: capturedContext, event: capturedEvent, signal: controller.signal }))\n .then(\n (result) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted || !invoke.onDone) return;\n\n try {\n send(invoke.onDone({ context: capturedContext, result }));\n } catch (error) {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n (error: unknown) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted) return;\n\n try {\n if (invoke.onError) {\n send(invoke.onError({ context: capturedContext, error }));\n } else {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n } catch (callbackError) {\n report(callbackError, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n );\n }\n };\n\n const notify = (event: Event | undefined): void => {\n for (const listener of listeners) {\n if (disposed) return;\n\n try {\n listener(current);\n } catch (error) {\n report(error, { event, phase: 'subscriber', state: current.state });\n }\n }\n };\n\n const process = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n const previous = current;\n let outcome: TransitionOutcome<State, Context, Event>;\n\n try {\n outcome = transition(machine, current, runtimeEvent);\n } catch (error) {\n report(error, {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n phase: 'transition',\n state: current.state,\n });\n\n return;\n }\n\n if (outcome.result.type === 'ignored' || !outcome.transition) return;\n\n const source = stateNode(machine, previous.state);\n\n current = outcome.result.snapshot;\n cancelStateResources();\n establishStateResources(current.state, outcome.event);\n notify(outcome.event);\n runEffects(source.exit, previous.state, outcome.event);\n runEffects(outcome.transition.effects ?? [], previous.state, outcome.event);\n runEffects(stateNode(machine, current.state).entry, current.state, outcome.event);\n };\n\n const flush = (): void => {\n let transitions = 0;\n\n while (queue.length > 0 && !disposed) {\n transitions += 1;\n\n if (transitions > maxTransitions) {\n report(\n new ClockworkError('INVALID_TRANSITION_LIMIT', 'maximum queued transitions exceeded', { maxTransitions }),\n { phase: 'transition', state: current.state },\n );\n\n return;\n }\n\n const next = queue.shift();\n\n if (next) process(next);\n }\n };\n\n establishStateResources(current.state, undefined);\n\n if (!options.snapshot) {\n runEffects(stateNode(machine, current.state).entry, current.state, undefined);\n }\n\n return {\n can: (event) => !disposed && canTransition(machine, current, event),\n get disposalSignal() {\n return disposal.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n send,\n get snapshot() {\n return current;\n },\n subscribe(listener) {\n if (disposed) return () => undefined;\n\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n [Symbol.dispose]: dispose,\n };\n};\n\n/** Defines a typed flat finite-state machine. */\nexport const defineMachine =\n <Context extends Record<string, unknown> = Record<string, never>, Event extends MachineEvent = MachineEvent>() =>\n <State extends string>(definition: MachineConfig<State, Context, Event>): Machine<State, Context, Event> => {\n const compiled = compileDefinition(definition);\n const initialSnapshot = createSnapshot(compiled.initial, compiled.context);\n\n return {\n can: (snapshot, event) => canTransition(compiled, snapshot, event),\n createActor: (options) => createActor(compiled, initialSnapshot, options),\n initialSnapshot,\n transition: (snapshot, event) => transition(compiled, snapshot, { event, kind: 'event' }).result,\n };\n };\n"],"mappings":"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"}
1
+ {"version":3,"file":"interpret.cjs","names":[],"sources":["../src/interpret.ts"],"sourcesContent":["import { isContextRecord } from './_context.js';\nimport { warn } from './_dev.js';\nimport { type CompiledAfter, type CompiledMachine, type CompiledState, compileDefinition } from './definition.js';\nimport { ClockworkError } from './errors.js';\nimport type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n Effect,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Transition,\n TransitionResult,\n} from './types.js';\n\ntype InternalEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly after: CompiledAfter<State, Context, Event>;\n readonly kind: 'after';\n};\n\ntype RuntimeEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> =\n | { readonly event: Event; readonly kind: 'event' }\n | InternalEvent<State, Context, Event>;\n\ntype SelectedTransition<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly transition: Transition<State, Context, Event>;\n};\n\ntype TransitionOutcome<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly result: TransitionResult<State, Context>;\n readonly transition?: Transition<State, Context, Event>;\n};\n\nconst createSnapshot = <State extends string, Context extends Record<string, unknown>>(\n state: State,\n context: Context,\n): MachineSnapshot<State, Context> => ({ context, state });\n\nconst invalidSnapshot = (state: unknown): never => {\n throw new ClockworkError('INVALID_SNAPSHOT_STATE', `snapshot state \"${String(state)}\" is not declared`, { state });\n};\n\nconst isMachineEvent = (event: unknown): event is MachineEvent =>\n typeof event === 'object' && event !== null && typeof (event as { type?: unknown }).type === 'string';\n\nconst stateNode = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n state: State,\n): CompiledState<State, Context, Event> => machine.states.get(state) ?? invalidSnapshot(state);\n\nconst selectTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): SelectedTransition<State, Context, Event> | undefined => {\n const state = stateNode(machine, snapshot.state);\n\n if (runtimeEvent.kind === 'after') {\n if (!state.after.includes(runtimeEvent.after)) return undefined;\n\n const { definition } = runtimeEvent.after;\n\n if (!definition.guard || definition.guard({ context: snapshot.context, event: undefined })) {\n return { event: undefined, transition: definition };\n }\n\n return undefined;\n }\n\n const candidates = state.on.get(runtimeEvent.event.type);\n\n if (!candidates) return undefined;\n\n for (const candidate of candidates) {\n const guard = candidate.guard as\n | ((args: { readonly context: Readonly<Context>; readonly event: Event }) => boolean)\n | undefined;\n\n if (!guard || guard({ context: snapshot.context, event: runtimeEvent.event })) {\n return { event: runtimeEvent.event, transition: candidate };\n }\n }\n\n return undefined;\n};\n\nconst transition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): TransitionOutcome<State, Context, Event> => {\n const selected = selectTransition(machine, snapshot, runtimeEvent);\n\n if (!selected) {\n return {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n result: { snapshot, type: 'ignored' },\n };\n }\n\n const reducer = selected.transition.reduce as\n | ((args: { readonly context: Readonly<Context>; readonly event: Event | undefined }) => Context)\n | undefined;\n const nextContext = reducer ? reducer({ context: snapshot.context, event: selected.event }) : snapshot.context;\n\n if (!isContextRecord(nextContext)) {\n throw new ClockworkError('INVALID_CONTEXT', 'a reducer must return a non-array object record', {\n state: snapshot.state,\n });\n }\n\n return {\n event: selected.event,\n result: { snapshot: createSnapshot(selected.transition.target, nextContext as Context), type: 'transition' },\n transition: selected.transition,\n };\n};\n\nconst canTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n event: Event,\n): boolean => selectTransition(machine, snapshot, { event, kind: 'event' }) !== undefined;\n\nconst createActor = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n initialSnapshot: MachineSnapshot<State, Context>,\n options: ActorOptions<State, Context, Event> = {},\n): Actor<State, Context, Event> => {\n if (\n options.maxTransitions !== undefined &&\n (!Number.isInteger(options.maxTransitions) || options.maxTransitions < 1)\n ) {\n throw new ClockworkError('INVALID_MAX_TRANSITIONS', 'maxTransitions must be a positive integer', {\n maxTransitions: options.maxTransitions,\n });\n }\n\n let current = options.snapshot ?? initialSnapshot;\n\n if (!isContextRecord(current.context)) {\n throw new ClockworkError('INVALID_CONTEXT', 'snapshot context must be a non-array object record', {});\n }\n\n if (!machine.states.has(current.state)) invalidSnapshot(current.state);\n\n const listeners = new Set<(snapshot: MachineSnapshot<State, Context>) => void>();\n const disposal = new AbortController();\n const timers = new Set<ReturnType<typeof setTimeout>>();\n const invokes = new Set<AbortController>();\n const queue: RuntimeEvent<State, Context, Event>[] = [];\n const maxTransitions = options.maxTransitions ?? 1_000;\n let disposed = false;\n let processing = false;\n\n const cancelStateResources = (): void => {\n for (const timer of timers) clearTimeout(timer);\n timers.clear();\n\n for (const controller of invokes) controller.abort();\n invokes.clear();\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n queue.length = 0;\n cancelStateResources();\n listeners.clear();\n disposal.abort();\n };\n\n const report = (error: unknown, context: ActorErrorContext<State, Event>): void => {\n let disposition: unknown = 'dispose';\n\n if (options.onError) {\n try {\n disposition = options.onError(error, context);\n } catch (handlerError) {\n dispose();\n throw handlerError;\n }\n }\n\n if (disposition !== 'continue') dispose();\n };\n\n const run = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n if (disposed) return;\n\n if (processing) {\n queue.push(runtimeEvent);\n\n return;\n }\n\n processing = true;\n\n try {\n process(runtimeEvent);\n flush();\n } finally {\n processing = false;\n }\n };\n\n const send = (event: Event): void => {\n if (disposed) return;\n\n if (!isMachineEvent(event)) {\n warn('ignored malformed event; expected an object with a string `type`');\n\n return;\n }\n\n run({ event, kind: 'event' });\n };\n\n const runEffects = (effects: readonly Effect<Context, Event>[], state: State, event: Event | undefined): void => {\n for (const effect of effects) {\n if (disposed) return;\n\n try {\n effect({ context: current.context, event, send, signal: disposal.signal });\n } catch (error) {\n report(error, { event, phase: 'effect', state });\n }\n }\n };\n\n const establishStateResources = (state: State, event: Event | undefined): void => {\n const node = stateNode(machine, state);\n\n for (const after of node.after) {\n const timer = setTimeout(() => {\n timers.delete(timer);\n run({ after, kind: 'after' });\n }, after.definition.delay);\n\n timers.add(timer);\n }\n\n for (const invoke of node.invoke) {\n const controller = new AbortController();\n\n invokes.add(controller);\n\n const capturedContext = current.context;\n const capturedEvent = event;\n\n void Promise.resolve()\n .then(() => invoke.src({ context: capturedContext, event: capturedEvent, signal: controller.signal }))\n .then(\n (result) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted || !invoke.onDone) return;\n\n try {\n send(invoke.onDone({ context: capturedContext, result }));\n } catch (error) {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n (error: unknown) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted) return;\n\n try {\n if (invoke.onError) {\n send(invoke.onError({ context: capturedContext, error }));\n } else {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n } catch (callbackError) {\n report(callbackError, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n );\n }\n };\n\n const notify = (event: Event | undefined): void => {\n for (const listener of listeners) {\n if (disposed) return;\n\n try {\n listener(current);\n } catch (error) {\n report(error, { event, phase: 'subscriber', state: current.state });\n }\n }\n };\n\n const process = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n const previous = current;\n let outcome: TransitionOutcome<State, Context, Event>;\n\n try {\n outcome = transition(machine, current, runtimeEvent);\n } catch (error) {\n report(error, {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n phase: 'transition',\n state: current.state,\n });\n\n return;\n }\n\n if (outcome.result.type === 'ignored' || !outcome.transition) return;\n\n const source = stateNode(machine, previous.state);\n\n current = outcome.result.snapshot;\n cancelStateResources();\n establishStateResources(current.state, outcome.event);\n notify(outcome.event);\n runEffects(source.exit, previous.state, outcome.event);\n runEffects(outcome.transition.effects ?? [], previous.state, outcome.event);\n runEffects(stateNode(machine, current.state).entry, current.state, outcome.event);\n };\n\n const flush = (): void => {\n let transitions = 0;\n\n while (queue.length > 0 && !disposed) {\n transitions += 1;\n\n if (transitions > maxTransitions) {\n report(\n new ClockworkError('INVALID_TRANSITION_LIMIT', 'maximum queued transitions exceeded', { maxTransitions }),\n { phase: 'transition', state: current.state },\n );\n\n return;\n }\n\n const next = queue.shift();\n\n if (next) process(next);\n }\n };\n\n establishStateResources(current.state, undefined);\n\n if (!options.snapshot) {\n runEffects(stateNode(machine, current.state).entry, current.state, undefined);\n }\n\n return {\n can: (event) => !disposed && canTransition(machine, current, event),\n get disposalSignal() {\n return disposal.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n send,\n get snapshot() {\n return current;\n },\n subscribe(listener) {\n if (disposed) return () => undefined;\n\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n [Symbol.dispose]: dispose,\n };\n};\n\n/** Defines a typed flat finite-state machine. */\nexport const defineMachine =\n <Context extends Record<string, unknown> = Record<string, never>, Event extends MachineEvent = MachineEvent>() =>\n <State extends string>(definition: MachineConfig<State, Context, Event>): Machine<State, Context, Event> => {\n const compiled = compileDefinition(definition);\n const initialSnapshot = createSnapshot(compiled.initial, compiled.context);\n\n return {\n can: (snapshot, event) => canTransition(compiled, snapshot, event),\n createActor: (options) => createActor(compiled, initialSnapshot, options),\n initialSnapshot,\n transition: (snapshot, event) => transition(compiled, snapshot, { event, kind: 'event' }).result,\n };\n };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"interpret.d.ts","sourceRoot":"","sources":["../src/interpret.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,OAAO,EACP,aAAa,EACb,YAAY,EAIb,MAAM,YAAY,CAAC;AA+WpB,iDAAiD;AACjD,eAAO,MAAM,aAAa,GACvB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,SAAS,YAAY,GAAG,YAAY,QAC1G,KAAK,SAAS,MAAM,EAAE,YAAY,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,KAAG,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAUtG,CAAC"}
1
+ {"version":3,"file":"interpret.d.ts","sourceRoot":"","sources":["../src/interpret.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAKV,OAAO,EACP,aAAa,EACb,YAAY,EAIb,MAAM,YAAY,CAAC;AA6WpB,iDAAiD;AACjD,eAAO,MAAM,aAAa,GACvB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,SAAS,YAAY,GAAG,YAAY,QAC1G,KAAK,SAAS,MAAM,EAAE,YAAY,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,KAAG,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAUtG,CAAC"}
package/dist/interpret.js CHANGED
@@ -1,16 +1,14 @@
1
1
  import { ClockworkError as e } from "./errors.js";
2
- import { compileDefinition as t } from "./definition.js";
2
+ import { isContextRecord as t } from "./_context.js";
3
+ import "./_dev.js";
4
+ import { compileDefinition as n } from "./definition.js";
3
5
  //#region src/interpret.ts
4
- var n = (e, t) => ({
6
+ var r = (e, t) => ({
5
7
  context: t,
6
8
  state: e
7
- }), r = (t) => {
9
+ }), i = (t) => {
8
10
  throw new e("INVALID_SNAPSHOT_STATE", `snapshot state "${String(t)}" is not declared`, { state: t });
9
- }, i = (e) => {
10
- if (typeof e != "object" || !e || Array.isArray(e)) return !1;
11
- let t = Object.getPrototypeOf(e);
12
- return t === null || t === Object.prototype;
13
- }, a = (e) => typeof e == "object" && !!e && typeof e.type == "string", o = (e, t) => e.states.get(t) ?? r(t), s = (e, t, n) => {
11
+ }, a = (e) => typeof e == "object" && !!e && typeof e.type == "string", o = (e, t) => e.states.get(t) ?? i(t), s = (e, t, n) => {
14
12
  let r = o(e, t.state);
15
13
  if (n.kind === "after") {
16
14
  if (!r.after.includes(n.after)) return;
@@ -34,24 +32,24 @@ var n = (e, t) => ({
34
32
  transition: e
35
33
  };
36
34
  }
37
- }, c = (t, r, a) => {
38
- let o = s(t, r, a);
35
+ }, c = (n, i, a) => {
36
+ let o = s(n, i, a);
39
37
  if (!o) return {
40
38
  event: a.kind === "event" ? a.event : void 0,
41
39
  result: {
42
- snapshot: r,
40
+ snapshot: i,
43
41
  type: "ignored"
44
42
  }
45
43
  };
46
44
  let c = o.transition.reduce, l = c ? c({
47
- context: r.context,
45
+ context: i.context,
48
46
  event: o.event
49
- }) : r.context;
50
- if (!i(l)) throw new e("INVALID_CONTEXT", "a reducer must return a non-array object record", { state: r.state });
47
+ }) : i.context;
48
+ if (!t(l)) throw new e("INVALID_CONTEXT", "a reducer must return a non-array object record", { state: i.state });
51
49
  return {
52
50
  event: o.event,
53
51
  result: {
54
- snapshot: n(o.transition.target, l),
52
+ snapshot: r(o.transition.target, l),
55
53
  type: "transition"
56
54
  },
57
55
  transition: o.transition
@@ -59,11 +57,11 @@ var n = (e, t) => ({
59
57
  }, l = (e, t, n) => s(e, t, {
60
58
  event: n,
61
59
  kind: "event"
62
- }) !== void 0, u = (t, n, s = {}) => {
60
+ }) !== void 0, u = (n, r, s = {}) => {
63
61
  if (s.maxTransitions !== void 0 && (!Number.isInteger(s.maxTransitions) || s.maxTransitions < 1)) throw new e("INVALID_MAX_TRANSITIONS", "maxTransitions must be a positive integer", { maxTransitions: s.maxTransitions });
64
- let u = s.snapshot ?? n;
65
- if (!i(u.context)) throw new e("INVALID_CONTEXT", "snapshot context must be a non-array object record", {});
66
- t.states.has(u.state) || r(u.state);
62
+ let u = s.snapshot ?? r;
63
+ if (!t(u.context)) throw new e("INVALID_CONTEXT", "snapshot context must be a non-array object record", {});
64
+ n.states.has(u.state) || i(u.state);
67
65
  let d = /* @__PURE__ */ new Set(), f = new AbortController(), p = /* @__PURE__ */ new Set(), m = /* @__PURE__ */ new Set(), h = [], g = s.maxTransitions ?? 1e3, _ = !1, v = !1, y = () => {
68
66
  for (let e of p) clearTimeout(e);
69
67
  p.clear();
@@ -93,7 +91,7 @@ var n = (e, t) => ({
93
91
  }
94
92
  }
95
93
  }, C = (e) => {
96
- a(e) && S({
94
+ _ || a(e) && S({
97
95
  event: e,
98
96
  kind: "event"
99
97
  });
@@ -115,8 +113,8 @@ var n = (e, t) => ({
115
113
  });
116
114
  }
117
115
  }
118
- }, T = (e, n) => {
119
- let r = o(t, e);
116
+ }, T = (e, t) => {
117
+ let r = o(n, e);
120
118
  for (let e of r.after) {
121
119
  let t = setTimeout(() => {
122
120
  p.delete(t), S({
@@ -126,19 +124,19 @@ var n = (e, t) => ({
126
124
  }, e.definition.delay);
127
125
  p.add(t);
128
126
  }
129
- for (let t of r.invoke) {
127
+ for (let n of r.invoke) {
130
128
  let r = new AbortController();
131
129
  m.add(r);
132
- let i = u.context, a = n;
133
- Promise.resolve().then(() => t.src({
130
+ let i = u.context, a = t;
131
+ Promise.resolve().then(() => n.src({
134
132
  context: i,
135
133
  event: a,
136
134
  signal: r.signal
137
- })).then((n) => {
138
- if (m.delete(r), !(_ || r.signal.aborted || !t.onDone)) try {
139
- C(t.onDone({
135
+ })).then((t) => {
136
+ if (m.delete(r), !(_ || r.signal.aborted || !n.onDone)) try {
137
+ C(n.onDone({
140
138
  context: i,
141
- result: n
139
+ result: t
142
140
  }));
143
141
  } catch (t) {
144
142
  x(t, {
@@ -147,12 +145,12 @@ var n = (e, t) => ({
147
145
  state: e
148
146
  });
149
147
  }
150
- }, (n) => {
148
+ }, (t) => {
151
149
  if (m.delete(r), !(_ || r.signal.aborted)) try {
152
- t.onError ? C(t.onError({
150
+ n.onError ? C(n.onError({
153
151
  context: i,
154
- error: n
155
- })) : x(n, {
152
+ error: t
153
+ })) : x(t, {
156
154
  event: a,
157
155
  phase: "invoke",
158
156
  state: e
@@ -180,9 +178,9 @@ var n = (e, t) => ({
180
178
  }
181
179
  }
182
180
  }, D = (e) => {
183
- let n = u, r;
181
+ let t = u, r;
184
182
  try {
185
- r = c(t, u, e);
183
+ r = c(n, u, e);
186
184
  } catch (t) {
187
185
  x(t, {
188
186
  event: e.kind === "event" ? e.event : void 0,
@@ -192,8 +190,8 @@ var n = (e, t) => ({
192
190
  return;
193
191
  }
194
192
  if (r.result.type === "ignored" || !r.transition) return;
195
- let i = o(t, n.state);
196
- u = r.result.snapshot, y(), T(u.state, r.event), E(r.event), w(i.exit, n.state, r.event), w(r.transition.effects ?? [], n.state, r.event), w(o(t, u.state).entry, u.state, r.event);
193
+ let i = o(n, t.state);
194
+ u = r.result.snapshot, y(), T(u.state, r.event), E(r.event), w(i.exit, t.state, r.event), w(r.transition.effects ?? [], t.state, r.event), w(o(n, u.state).entry, u.state, r.event);
197
195
  }, O = () => {
198
196
  let t = 0;
199
197
  for (; h.length > 0 && !_;) {
@@ -208,8 +206,8 @@ var n = (e, t) => ({
208
206
  n && D(n);
209
207
  }
210
208
  };
211
- return T(u.state, void 0), s.snapshot || w(o(t, u.state).entry, u.state, void 0), {
212
- can: (e) => !_ && l(t, u, e),
209
+ return T(u.state, void 0), s.snapshot || w(o(n, u.state).entry, u.state, void 0), {
210
+ can: (e) => !_ && l(n, u, e),
213
211
  get disposalSignal() {
214
212
  return f.signal;
215
213
  },
@@ -227,13 +225,13 @@ var n = (e, t) => ({
227
225
  [Symbol.dispose]: b
228
226
  };
229
227
  }, d = () => (e) => {
230
- let r = t(e), i = n(r.initial, r.context);
228
+ let t = n(e), i = r(t.initial, t.context);
231
229
  return {
232
- can: (e, t) => l(r, e, t),
233
- createActor: (e) => u(r, i, e),
230
+ can: (e, n) => l(t, e, n),
231
+ createActor: (e) => u(t, i, e),
234
232
  initialSnapshot: i,
235
- transition: (e, t) => c(r, e, {
236
- event: t,
233
+ transition: (e, n) => c(t, e, {
234
+ event: n,
237
235
  kind: "event"
238
236
  }).result
239
237
  };
@@ -1 +1 @@
1
- {"version":3,"file":"interpret.js","names":[],"sources":["../src/interpret.ts"],"sourcesContent":["import type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n Effect,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Transition,\n TransitionResult,\n} from './types.js';\n\nimport { compileDefinition, type CompiledAfter, type CompiledMachine, type CompiledState } from './definition.js';\nimport { ClockworkError } from './errors.js';\n\ntype InternalEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly after: CompiledAfter<State, Context, Event>;\n readonly kind: 'after';\n};\n\ntype RuntimeEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> =\n { readonly event: Event; readonly kind: 'event' } | InternalEvent<State, Context, Event>;\n\ntype SelectedTransition<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly transition: Transition<State, Context, Event>;\n};\n\ntype TransitionOutcome<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly result: TransitionResult<State, Context>;\n readonly transition?: Transition<State, Context, Event>;\n};\n\nconst createSnapshot = <State extends string, Context extends Record<string, unknown>>(\n state: State,\n context: Context,\n): MachineSnapshot<State, Context> => ({ context, state });\n\nconst invalidSnapshot = (state: unknown): never => {\n throw new ClockworkError('INVALID_SNAPSHOT_STATE', `snapshot state \"${String(state)}\" is not declared`, { state });\n};\n\nconst isContextRecord = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === null || prototype === Object.prototype;\n};\n\nconst isMachineEvent = (event: unknown): event is MachineEvent =>\n typeof event === 'object' && event !== null && typeof (event as { type?: unknown }).type === 'string';\n\nconst stateNode = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n state: State,\n): CompiledState<State, Context, Event> => machine.states.get(state) ?? invalidSnapshot(state);\n\nconst selectTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): SelectedTransition<State, Context, Event> | undefined => {\n const state = stateNode(machine, snapshot.state);\n\n if (runtimeEvent.kind === 'after') {\n if (!state.after.includes(runtimeEvent.after)) return undefined;\n\n const { definition } = runtimeEvent.after;\n\n if (!definition.guard || definition.guard({ context: snapshot.context, event: undefined })) {\n return { event: undefined, transition: definition };\n }\n\n return undefined;\n }\n\n const candidates = state.on.get(runtimeEvent.event.type);\n\n if (!candidates) return undefined;\n\n for (const candidate of candidates) {\n const guard = candidate.guard as\n ((args: { readonly context: Readonly<Context>; readonly event: Event }) => boolean) | undefined;\n\n if (!guard || guard({ context: snapshot.context, event: runtimeEvent.event })) {\n return { event: runtimeEvent.event, transition: candidate };\n }\n }\n\n return undefined;\n};\n\nconst transition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): TransitionOutcome<State, Context, Event> => {\n const selected = selectTransition(machine, snapshot, runtimeEvent);\n\n if (!selected) {\n return {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n result: { snapshot, type: 'ignored' },\n };\n }\n\n const reducer = selected.transition.reduce as\n ((args: { readonly context: Readonly<Context>; readonly event: Event | undefined }) => Context) | undefined;\n const nextContext = reducer ? reducer({ context: snapshot.context, event: selected.event }) : snapshot.context;\n\n if (!isContextRecord(nextContext)) {\n throw new ClockworkError('INVALID_CONTEXT', 'a reducer must return a non-array object record', {\n state: snapshot.state,\n });\n }\n\n return {\n event: selected.event,\n result: { snapshot: createSnapshot(selected.transition.target, nextContext as Context), type: 'transition' },\n transition: selected.transition,\n };\n};\n\nconst canTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n event: Event,\n): boolean => selectTransition(machine, snapshot, { event, kind: 'event' }) !== undefined;\n\nconst createActor = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n initialSnapshot: MachineSnapshot<State, Context>,\n options: ActorOptions<State, Context, Event> = {},\n): Actor<State, Context, Event> => {\n if (\n options.maxTransitions !== undefined &&\n (!Number.isInteger(options.maxTransitions) || options.maxTransitions < 1)\n ) {\n throw new ClockworkError('INVALID_MAX_TRANSITIONS', 'maxTransitions must be a positive integer', {\n maxTransitions: options.maxTransitions,\n });\n }\n\n let current = options.snapshot ?? initialSnapshot;\n\n if (!isContextRecord(current.context)) {\n throw new ClockworkError('INVALID_CONTEXT', 'snapshot context must be a non-array object record', {});\n }\n\n if (!machine.states.has(current.state)) invalidSnapshot(current.state);\n\n const listeners = new Set<(snapshot: MachineSnapshot<State, Context>) => void>();\n const disposal = new AbortController();\n const timers = new Set<ReturnType<typeof setTimeout>>();\n const invokes = new Set<AbortController>();\n const queue: RuntimeEvent<State, Context, Event>[] = [];\n const maxTransitions = options.maxTransitions ?? 1_000;\n let disposed = false;\n let processing = false;\n\n const cancelStateResources = (): void => {\n for (const timer of timers) clearTimeout(timer);\n timers.clear();\n\n for (const controller of invokes) controller.abort();\n invokes.clear();\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n queue.length = 0;\n cancelStateResources();\n listeners.clear();\n disposal.abort();\n };\n\n const report = (error: unknown, context: ActorErrorContext<State, Event>): void => {\n let disposition: unknown = 'dispose';\n\n if (options.onError) {\n try {\n disposition = options.onError(error, context);\n } catch (handlerError) {\n dispose();\n throw handlerError;\n }\n }\n\n if (disposition !== 'continue') dispose();\n };\n\n const run = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n if (disposed) return;\n\n if (processing) {\n queue.push(runtimeEvent);\n\n return;\n }\n\n processing = true;\n\n try {\n process(runtimeEvent);\n flush();\n } finally {\n processing = false;\n }\n };\n\n const send = (event: Event): void => {\n if (!isMachineEvent(event)) return;\n\n run({ event, kind: 'event' });\n };\n\n const runEffects = (effects: readonly Effect<Context, Event>[], state: State, event: Event | undefined): void => {\n for (const effect of effects) {\n if (disposed) return;\n\n try {\n effect({ context: current.context, event, send, signal: disposal.signal });\n } catch (error) {\n report(error, { event, phase: 'effect', state });\n }\n }\n };\n\n const establishStateResources = (state: State, event: Event | undefined): void => {\n const node = stateNode(machine, state);\n\n for (const after of node.after) {\n const timer = setTimeout(() => {\n timers.delete(timer);\n run({ after, kind: 'after' });\n }, after.definition.delay);\n\n timers.add(timer);\n }\n\n for (const invoke of node.invoke) {\n const controller = new AbortController();\n\n invokes.add(controller);\n\n const capturedContext = current.context;\n const capturedEvent = event;\n\n void Promise.resolve()\n .then(() => invoke.src({ context: capturedContext, event: capturedEvent, signal: controller.signal }))\n .then(\n (result) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted || !invoke.onDone) return;\n\n try {\n send(invoke.onDone({ context: capturedContext, result }));\n } catch (error) {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n (error: unknown) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted) return;\n\n try {\n if (invoke.onError) {\n send(invoke.onError({ context: capturedContext, error }));\n } else {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n } catch (callbackError) {\n report(callbackError, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n );\n }\n };\n\n const notify = (event: Event | undefined): void => {\n for (const listener of listeners) {\n if (disposed) return;\n\n try {\n listener(current);\n } catch (error) {\n report(error, { event, phase: 'subscriber', state: current.state });\n }\n }\n };\n\n const process = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n const previous = current;\n let outcome: TransitionOutcome<State, Context, Event>;\n\n try {\n outcome = transition(machine, current, runtimeEvent);\n } catch (error) {\n report(error, {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n phase: 'transition',\n state: current.state,\n });\n\n return;\n }\n\n if (outcome.result.type === 'ignored' || !outcome.transition) return;\n\n const source = stateNode(machine, previous.state);\n\n current = outcome.result.snapshot;\n cancelStateResources();\n establishStateResources(current.state, outcome.event);\n notify(outcome.event);\n runEffects(source.exit, previous.state, outcome.event);\n runEffects(outcome.transition.effects ?? [], previous.state, outcome.event);\n runEffects(stateNode(machine, current.state).entry, current.state, outcome.event);\n };\n\n const flush = (): void => {\n let transitions = 0;\n\n while (queue.length > 0 && !disposed) {\n transitions += 1;\n\n if (transitions > maxTransitions) {\n report(\n new ClockworkError('INVALID_TRANSITION_LIMIT', 'maximum queued transitions exceeded', { maxTransitions }),\n { phase: 'transition', state: current.state },\n );\n\n return;\n }\n\n const next = queue.shift();\n\n if (next) process(next);\n }\n };\n\n establishStateResources(current.state, undefined);\n\n if (!options.snapshot) {\n runEffects(stateNode(machine, current.state).entry, current.state, undefined);\n }\n\n return {\n can: (event) => !disposed && canTransition(machine, current, event),\n get disposalSignal() {\n return disposal.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n send,\n get snapshot() {\n return current;\n },\n subscribe(listener) {\n if (disposed) return () => undefined;\n\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n [Symbol.dispose]: dispose,\n };\n};\n\n/** Defines a typed flat finite-state machine. */\nexport const defineMachine =\n <Context extends Record<string, unknown> = Record<string, never>, Event extends MachineEvent = MachineEvent>() =>\n <State extends string>(definition: MachineConfig<State, Context, Event>): Machine<State, Context, Event> => {\n const compiled = compileDefinition(definition);\n const initialSnapshot = createSnapshot(compiled.initial, compiled.context);\n\n return {\n can: (snapshot, event) => canTransition(compiled, snapshot, event),\n createActor: (options) => createActor(compiled, initialSnapshot, options),\n initialSnapshot,\n transition: (snapshot, event) => transition(compiled, snapshot, { event, kind: 'event' }).result,\n };\n };\n"],"mappings":"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"}
1
+ {"version":3,"file":"interpret.js","names":[],"sources":["../src/interpret.ts"],"sourcesContent":["import { isContextRecord } from './_context.js';\nimport { warn } from './_dev.js';\nimport { type CompiledAfter, type CompiledMachine, type CompiledState, compileDefinition } from './definition.js';\nimport { ClockworkError } from './errors.js';\nimport type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n Effect,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Transition,\n TransitionResult,\n} from './types.js';\n\ntype InternalEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly after: CompiledAfter<State, Context, Event>;\n readonly kind: 'after';\n};\n\ntype RuntimeEvent<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> =\n | { readonly event: Event; readonly kind: 'event' }\n | InternalEvent<State, Context, Event>;\n\ntype SelectedTransition<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly transition: Transition<State, Context, Event>;\n};\n\ntype TransitionOutcome<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n readonly event: Event | undefined;\n readonly result: TransitionResult<State, Context>;\n readonly transition?: Transition<State, Context, Event>;\n};\n\nconst createSnapshot = <State extends string, Context extends Record<string, unknown>>(\n state: State,\n context: Context,\n): MachineSnapshot<State, Context> => ({ context, state });\n\nconst invalidSnapshot = (state: unknown): never => {\n throw new ClockworkError('INVALID_SNAPSHOT_STATE', `snapshot state \"${String(state)}\" is not declared`, { state });\n};\n\nconst isMachineEvent = (event: unknown): event is MachineEvent =>\n typeof event === 'object' && event !== null && typeof (event as { type?: unknown }).type === 'string';\n\nconst stateNode = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n state: State,\n): CompiledState<State, Context, Event> => machine.states.get(state) ?? invalidSnapshot(state);\n\nconst selectTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): SelectedTransition<State, Context, Event> | undefined => {\n const state = stateNode(machine, snapshot.state);\n\n if (runtimeEvent.kind === 'after') {\n if (!state.after.includes(runtimeEvent.after)) return undefined;\n\n const { definition } = runtimeEvent.after;\n\n if (!definition.guard || definition.guard({ context: snapshot.context, event: undefined })) {\n return { event: undefined, transition: definition };\n }\n\n return undefined;\n }\n\n const candidates = state.on.get(runtimeEvent.event.type);\n\n if (!candidates) return undefined;\n\n for (const candidate of candidates) {\n const guard = candidate.guard as\n | ((args: { readonly context: Readonly<Context>; readonly event: Event }) => boolean)\n | undefined;\n\n if (!guard || guard({ context: snapshot.context, event: runtimeEvent.event })) {\n return { event: runtimeEvent.event, transition: candidate };\n }\n }\n\n return undefined;\n};\n\nconst transition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n runtimeEvent: RuntimeEvent<State, Context, Event>,\n): TransitionOutcome<State, Context, Event> => {\n const selected = selectTransition(machine, snapshot, runtimeEvent);\n\n if (!selected) {\n return {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n result: { snapshot, type: 'ignored' },\n };\n }\n\n const reducer = selected.transition.reduce as\n | ((args: { readonly context: Readonly<Context>; readonly event: Event | undefined }) => Context)\n | undefined;\n const nextContext = reducer ? reducer({ context: snapshot.context, event: selected.event }) : snapshot.context;\n\n if (!isContextRecord(nextContext)) {\n throw new ClockworkError('INVALID_CONTEXT', 'a reducer must return a non-array object record', {\n state: snapshot.state,\n });\n }\n\n return {\n event: selected.event,\n result: { snapshot: createSnapshot(selected.transition.target, nextContext as Context), type: 'transition' },\n transition: selected.transition,\n };\n};\n\nconst canTransition = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n snapshot: MachineSnapshot<State, Context>,\n event: Event,\n): boolean => selectTransition(machine, snapshot, { event, kind: 'event' }) !== undefined;\n\nconst createActor = <State extends string, Context extends Record<string, unknown>, Event extends MachineEvent>(\n machine: CompiledMachine<State, Context, Event>,\n initialSnapshot: MachineSnapshot<State, Context>,\n options: ActorOptions<State, Context, Event> = {},\n): Actor<State, Context, Event> => {\n if (\n options.maxTransitions !== undefined &&\n (!Number.isInteger(options.maxTransitions) || options.maxTransitions < 1)\n ) {\n throw new ClockworkError('INVALID_MAX_TRANSITIONS', 'maxTransitions must be a positive integer', {\n maxTransitions: options.maxTransitions,\n });\n }\n\n let current = options.snapshot ?? initialSnapshot;\n\n if (!isContextRecord(current.context)) {\n throw new ClockworkError('INVALID_CONTEXT', 'snapshot context must be a non-array object record', {});\n }\n\n if (!machine.states.has(current.state)) invalidSnapshot(current.state);\n\n const listeners = new Set<(snapshot: MachineSnapshot<State, Context>) => void>();\n const disposal = new AbortController();\n const timers = new Set<ReturnType<typeof setTimeout>>();\n const invokes = new Set<AbortController>();\n const queue: RuntimeEvent<State, Context, Event>[] = [];\n const maxTransitions = options.maxTransitions ?? 1_000;\n let disposed = false;\n let processing = false;\n\n const cancelStateResources = (): void => {\n for (const timer of timers) clearTimeout(timer);\n timers.clear();\n\n for (const controller of invokes) controller.abort();\n invokes.clear();\n };\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n queue.length = 0;\n cancelStateResources();\n listeners.clear();\n disposal.abort();\n };\n\n const report = (error: unknown, context: ActorErrorContext<State, Event>): void => {\n let disposition: unknown = 'dispose';\n\n if (options.onError) {\n try {\n disposition = options.onError(error, context);\n } catch (handlerError) {\n dispose();\n throw handlerError;\n }\n }\n\n if (disposition !== 'continue') dispose();\n };\n\n const run = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n if (disposed) return;\n\n if (processing) {\n queue.push(runtimeEvent);\n\n return;\n }\n\n processing = true;\n\n try {\n process(runtimeEvent);\n flush();\n } finally {\n processing = false;\n }\n };\n\n const send = (event: Event): void => {\n if (disposed) return;\n\n if (!isMachineEvent(event)) {\n warn('ignored malformed event; expected an object with a string `type`');\n\n return;\n }\n\n run({ event, kind: 'event' });\n };\n\n const runEffects = (effects: readonly Effect<Context, Event>[], state: State, event: Event | undefined): void => {\n for (const effect of effects) {\n if (disposed) return;\n\n try {\n effect({ context: current.context, event, send, signal: disposal.signal });\n } catch (error) {\n report(error, { event, phase: 'effect', state });\n }\n }\n };\n\n const establishStateResources = (state: State, event: Event | undefined): void => {\n const node = stateNode(machine, state);\n\n for (const after of node.after) {\n const timer = setTimeout(() => {\n timers.delete(timer);\n run({ after, kind: 'after' });\n }, after.definition.delay);\n\n timers.add(timer);\n }\n\n for (const invoke of node.invoke) {\n const controller = new AbortController();\n\n invokes.add(controller);\n\n const capturedContext = current.context;\n const capturedEvent = event;\n\n void Promise.resolve()\n .then(() => invoke.src({ context: capturedContext, event: capturedEvent, signal: controller.signal }))\n .then(\n (result) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted || !invoke.onDone) return;\n\n try {\n send(invoke.onDone({ context: capturedContext, result }));\n } catch (error) {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n (error: unknown) => {\n invokes.delete(controller);\n\n if (disposed || controller.signal.aborted) return;\n\n try {\n if (invoke.onError) {\n send(invoke.onError({ context: capturedContext, error }));\n } else {\n report(error, { event: capturedEvent, phase: 'invoke', state });\n }\n } catch (callbackError) {\n report(callbackError, { event: capturedEvent, phase: 'invoke', state });\n }\n },\n );\n }\n };\n\n const notify = (event: Event | undefined): void => {\n for (const listener of listeners) {\n if (disposed) return;\n\n try {\n listener(current);\n } catch (error) {\n report(error, { event, phase: 'subscriber', state: current.state });\n }\n }\n };\n\n const process = (runtimeEvent: RuntimeEvent<State, Context, Event>): void => {\n const previous = current;\n let outcome: TransitionOutcome<State, Context, Event>;\n\n try {\n outcome = transition(machine, current, runtimeEvent);\n } catch (error) {\n report(error, {\n event: runtimeEvent.kind === 'event' ? runtimeEvent.event : undefined,\n phase: 'transition',\n state: current.state,\n });\n\n return;\n }\n\n if (outcome.result.type === 'ignored' || !outcome.transition) return;\n\n const source = stateNode(machine, previous.state);\n\n current = outcome.result.snapshot;\n cancelStateResources();\n establishStateResources(current.state, outcome.event);\n notify(outcome.event);\n runEffects(source.exit, previous.state, outcome.event);\n runEffects(outcome.transition.effects ?? [], previous.state, outcome.event);\n runEffects(stateNode(machine, current.state).entry, current.state, outcome.event);\n };\n\n const flush = (): void => {\n let transitions = 0;\n\n while (queue.length > 0 && !disposed) {\n transitions += 1;\n\n if (transitions > maxTransitions) {\n report(\n new ClockworkError('INVALID_TRANSITION_LIMIT', 'maximum queued transitions exceeded', { maxTransitions }),\n { phase: 'transition', state: current.state },\n );\n\n return;\n }\n\n const next = queue.shift();\n\n if (next) process(next);\n }\n };\n\n establishStateResources(current.state, undefined);\n\n if (!options.snapshot) {\n runEffects(stateNode(machine, current.state).entry, current.state, undefined);\n }\n\n return {\n can: (event) => !disposed && canTransition(machine, current, event),\n get disposalSignal() {\n return disposal.signal;\n },\n dispose,\n get disposed() {\n return disposed;\n },\n send,\n get snapshot() {\n return current;\n },\n subscribe(listener) {\n if (disposed) return () => undefined;\n\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n [Symbol.dispose]: dispose,\n };\n};\n\n/** Defines a typed flat finite-state machine. */\nexport const defineMachine =\n <Context extends Record<string, unknown> = Record<string, never>, Event extends MachineEvent = MachineEvent>() =>\n <State extends string>(definition: MachineConfig<State, Context, Event>): Machine<State, Context, Event> => {\n const compiled = compileDefinition(definition);\n const initialSnapshot = createSnapshot(compiled.initial, compiled.context);\n\n return {\n can: (snapshot, event) => canTransition(compiled, snapshot, event),\n createActor: (options) => createActor(compiled, initialSnapshot, options),\n initialSnapshot,\n transition: (snapshot, event) => transition(compiled, snapshot, { event, kind: 'event' }).result,\n };\n };\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "name": "@vielzeug/clockwork",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Framework-neutral typed finite state machines with pure transitions and actors",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/helmuthdu/vielzeug",
8
+ "directory": "packages/clockwork"
9
+ },
5
10
  "type": "module",
11
+ "engines": {
12
+ "node": ">=22"
13
+ },
6
14
  "files": [
7
15
  "dist"
8
16
  ],
@@ -11,38 +19,40 @@
11
19
  "types": "dist/index.d.ts",
12
20
  "exports": {
13
21
  ".": {
14
- "source": "./src/index.ts",
15
- "types": "./dist/index.d.ts",
16
22
  "import": "./dist/index.js",
17
- "require": "./dist/index.cjs"
23
+ "require": "./dist/index.cjs",
24
+ "types": "./dist/index.d.ts"
18
25
  },
19
26
  "./devtools": {
20
- "source": "./src/devtools.ts",
21
- "types": "./dist/devtools.d.ts",
22
27
  "import": "./dist/devtools.js",
23
- "require": "./dist/devtools.cjs"
28
+ "require": "./dist/devtools.cjs",
29
+ "types": "./dist/devtools.d.ts"
24
30
  }
25
31
  },
26
- "scripts": {
27
- "build": "vite build && pnpm run build:bundle && pnpm run build:types",
28
- "build:types": "tsc -p tsconfig.declarations.json",
29
- "fix": "eslint --fix src",
30
- "lint": "eslint src",
31
- "prepublishOnly": "pnpm run build",
32
- "test": "vitest",
33
- "build:bundle": "vite build --config vite.bundle.config.ts"
32
+ "typesVersions": {
33
+ "*": {
34
+ "devtools": [
35
+ "dist/devtools.d.ts"
36
+ ]
37
+ }
34
38
  },
35
39
  "publishConfig": {
36
40
  "access": "public",
37
41
  "registry": "https://registry.npmjs.org/"
38
42
  },
39
- "engines": {
40
- "node": ">=22"
43
+ "scripts": {
44
+ "build": "vite build && pnpm run build:bundle && pnpm run build:types",
45
+ "build:bundle": "vite build --config vite.bundle.config.ts",
46
+ "build:types": "tsc -p tsconfig.declarations.json",
47
+ "fix": "biome check --write src",
48
+ "lint": "biome ci src",
49
+ "prepublishOnly": "pnpm run build",
50
+ "test": "vitest"
41
51
  },
42
52
  "devDependencies": {
43
- "@types/node": "^26.1.2",
53
+ "@types/node": "^26.2.0",
44
54
  "typescript": "^6.0.3",
45
- "vite": "^8.2.0",
55
+ "vite": "^8.2.1",
46
56
  "vitest": "^4.1.10"
47
57
  }
48
58
  }