controlled-machine 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +41 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -3
- package/dist/index.d.ts +31 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
function effect(config) {
|
|
4
4
|
return config;
|
|
5
5
|
}
|
|
6
|
+
function not(guard) {
|
|
7
|
+
return { __type: "not", __guards: [guard] };
|
|
8
|
+
}
|
|
9
|
+
function and(guards) {
|
|
10
|
+
return { __type: "and", __guards: guards };
|
|
11
|
+
}
|
|
12
|
+
function or(guards) {
|
|
13
|
+
return { __type: "or", __guards: guards };
|
|
14
|
+
}
|
|
6
15
|
function toArray(value) {
|
|
7
16
|
return Array.isArray(value) ? value : [value];
|
|
8
17
|
}
|
|
@@ -16,11 +25,38 @@ function executeRuleActions(actionItems, actions, getContext, payload, assign) {
|
|
|
16
25
|
}
|
|
17
26
|
}
|
|
18
27
|
}
|
|
28
|
+
function isGuardComposer(item) {
|
|
29
|
+
return typeof item === "object" && item !== null && "__type" in item && "__guards" in item;
|
|
30
|
+
}
|
|
31
|
+
function evaluateSingleGuard(item, guards, context, payload) {
|
|
32
|
+
if (isGuardComposer(item)) {
|
|
33
|
+
switch (item.__type) {
|
|
34
|
+
case "not": {
|
|
35
|
+
const innerResult = evaluateSingleGuard(item.__guards[0], guards, context, payload);
|
|
36
|
+
return !innerResult;
|
|
37
|
+
}
|
|
38
|
+
case "and": {
|
|
39
|
+
return item.__guards.every(
|
|
40
|
+
(g) => evaluateSingleGuard(g, guards, context, payload)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
case "or": {
|
|
44
|
+
return item.__guards.some(
|
|
45
|
+
(g) => evaluateSingleGuard(g, guards, context, payload)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (typeof item === "function") {
|
|
51
|
+
return item(context, payload);
|
|
52
|
+
}
|
|
53
|
+
const guardFn = guards[item];
|
|
54
|
+
return guardFn ? guardFn(context, payload) : true;
|
|
55
|
+
}
|
|
19
56
|
function evaluateGuards(guardItems, guards, context, payload) {
|
|
20
57
|
if (!guardItems) return true;
|
|
21
58
|
for (const item of toArray(guardItems)) {
|
|
22
|
-
|
|
23
|
-
if (guardFn && !guardFn(context, payload)) {
|
|
59
|
+
if (!evaluateSingleGuard(item, guards, context, payload)) {
|
|
24
60
|
return false;
|
|
25
61
|
}
|
|
26
62
|
}
|
|
@@ -224,6 +260,7 @@ function createMachine(config) {
|
|
|
224
260
|
const cleanup = () => clearEffectStore(effectStore);
|
|
225
261
|
return Object.assign(config, { send, evaluate, getSnapshot, getInternal, setInternal, getInitialInternal, cleanup });
|
|
226
262
|
}
|
|
263
|
+
exports.and = and;
|
|
227
264
|
exports.buildContext = buildContext;
|
|
228
265
|
exports.buildSnapshot = buildSnapshot;
|
|
229
266
|
exports.clearEffectStore = clearEffectStore;
|
|
@@ -236,6 +273,8 @@ exports.evaluateGuards = evaluateGuards;
|
|
|
236
273
|
exports.executeHandler = executeHandler;
|
|
237
274
|
exports.executeRuleActions = executeRuleActions;
|
|
238
275
|
exports.isRuleArray = isRuleArray;
|
|
276
|
+
exports.not = not;
|
|
277
|
+
exports.or = or;
|
|
239
278
|
exports.processEffects = processEffects;
|
|
240
279
|
exports.shallowEqual = shallowEqual;
|
|
241
280
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["/**\n * Controlled Machine\n *\n * A controlled state machine library where external state (input) is passed in\n * and internal state is managed by the machine itself.\n *\n * Key Concepts:\n * - input: External data passed in from outside (e.g., React state, props)\n * - internal: Machine-managed state that persists across events\n * - computed: Derived values calculated from input + internal\n * - context: Flattened input + internal + computed (available in all handlers)\n * - on: Event handlers with conditional rules and actions\n * - states: FSM-style state-based event handlers\n * - effects: Watch-based side effects with enter/exit/change callbacks\n * - always: Auto-evaluated rules that run on every context change\n * - actions: Named action functions (can be overridden in useMachine)\n * - guards: Named guard functions for conditional logic\n */\n\n// ============================================\n// Types - Core Building Blocks\n// ============================================\n\n/**\n * Assign function type - updates internal state with partial updates\n * Only allows modifying keys defined in Internal type\n */\nexport type AssignFn<TInternal> = (updates: Partial<TInternal>) => void\n\n/**\n * ActionItem - can be a named action string or inline function\n * Inline functions receive (context, payload, assign)\n */\nexport type ActionItem<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TInternal = unknown,\n> = TActions | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n\n/**\n * GuardItem - can be a named guard string or inline predicate function\n */\nexport type GuardItem<\n TContext,\n TPayload = undefined,\n TGuards extends string = string,\n> = TGuards | ((context: TContext, payload: TPayload) => boolean)\n\n/**\n * Rule - conditional action with optional guard(s)\n * @property when - Guard(s) that must pass (AND logic for arrays)\n * @property do - Action(s) to execute if guards pass\n */\nexport type Rule<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n when?: GuardItem<TContext, TPayload, TGuards> | GuardItem<TContext, TPayload, TGuards>[]\n do: ActionItem<TContext, TPayload, TActions, TInternal> | ActionItem<TContext, TPayload, TActions, TInternal>[]\n}\n\n/**\n * Handler - event handler definition\n * Can be: single action, action array, rule array, inline function, or function array\n *\n * @example\n * on: { CLICK: 'handleClick' } // single action\n * on: { SUBMIT: ['validate', 'save'] } // action array\n * on: { TOGGLE: [{ when: ctx => ctx.isOpen, do: 'close' }, { do: 'open' }] } // rule array\n * on: { INCREMENT: (ctx, _, assign) => assign({ count: ctx.count + 1 }) } // inline function\n * on: { SELECT: [(ctx, p) => ctx.onSelect(p), (_, __, a) => a({ isOpen: false })] } // function array\n */\nexport type Handler<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> =\n | TActions\n | TActions[]\n | Rule<TContext, TPayload, TActions, TGuards, TInternal>[]\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[]\n\n/**\n * EffectHelpers - utilities available in effect callbacks\n */\nexport type EffectHelpers<TEvents extends EventsConfig> = {\n send: Send<TEvents>\n}\n\n/** Cleanup function returned from effect callbacks */\nexport type Cleanup = () => void\n\n/**\n * Effect - watch-based side effect with lifecycle callbacks\n * @property watch - Function that returns the value to watch (uses shallow comparison)\n * @property enter - Called when watch value becomes truthy (can return cleanup)\n * @property exit - Called when watch value becomes falsy (can return cleanup)\n * @property change - Called on any value change with (prev, curr) (can return cleanup)\n */\nexport type Effect<\n TContext,\n TEvents extends EventsConfig,\n TWatched = unknown,\n> = {\n watch: (context: TContext) => TWatched\n enter?: (\n context: TContext,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup | Promise<void>\n exit?: (context: TContext, helpers: EffectHelpers<TEvents>) => void | Cleanup\n change?: (\n context: TContext,\n prev: TWatched | undefined,\n curr: TWatched,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup\n}\n\n/**\n * Helper function for creating effects with proper type inference\n * @example\n * effects: [\n * effect({ watch: ctx => ctx.isOpen, enter: () => console.log('opened') })\n * ]\n */\nexport function effect<TContext, TEvents extends EventsConfig, TWatched>(\n config: Effect<TContext, TEvents, TWatched>,\n): Effect<TContext, TEvents, TWatched> {\n return config\n}\n\n/** Event configuration - event name to payload type mapping */\nexport type EventsConfig = Record<string, unknown>\n/** Computed configuration - computed key to value type mapping */\nexport type ComputedConfig = Record<string, unknown>\n\n// ============================================\n// Object-based Generic Types\n// ============================================\n\n/**\n * MachineTypes - object-based generic type parameter\n * Specify only the types you need, in any order\n *\n * @example\n * createMachine<{\n * input: { count: number; setCount: (c: number) => void }\n * internal: { isOpen: boolean }\n * events: { INCREMENT: undefined; SET: { value: number } }\n * computed: { doubled: number }\n * actions: 'increment' | 'set'\n * guards: 'isPositive'\n * state: 'idle' | 'loading'\n * }>({...})\n */\nexport type MachineTypes = {\n input?: unknown // External state passed in (React state, props, etc.)\n internal?: unknown // Machine-managed state\n events?: EventsConfig // Event name → payload type\n computed?: ComputedConfig // Derived values from context\n actions?: string // Named action strings\n guards?: string // Named guard strings\n state?: string // FSM state values\n}\n\n// ============================================\n// Type Extraction Helpers\n// ============================================\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Input<T extends MachineTypes> = T['input'] extends object ? T['input'] : {}\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Internal<T extends MachineTypes> = T['internal'] extends object ? T['internal'] : {}\nexport type Events<T extends MachineTypes> = T['events'] extends EventsConfig\n ? T['events']\n : Record<string, undefined>\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Computed<T extends MachineTypes> = T['computed'] extends ComputedConfig\n ? T['computed']\n : {}\nexport type Actions<T extends MachineTypes> = T['actions'] extends string\n ? T['actions']\n : string\nexport type Guards<T extends MachineTypes> = T['guards'] extends string\n ? T['guards']\n : string\nexport type State<T extends MachineTypes> = T['state'] extends string\n ? T['state']\n : string\n\n// ============================================\n// Key Overlap Detection (Compile-time Safety)\n// ============================================\n\n/**\n * Check if type has only index signature (no specific keys)\n * `string extends keyof T` is true for Record<string, K> types\n */\ntype HasOnlyIndexSignature<T> = string extends keyof T ? true : false\n\n/**\n * Detects if two types have overlapping keys\n * Returns true if any key exists in both A and B\n *\n * Types with only index signatures (like Record<string, never>) are treated as empty,\n * since they don't have specific keys that could overlap.\n */\ntype HasOverlappingKeys<A, B> =\n HasOnlyIndexSignature<A> extends true ? false :\n HasOnlyIndexSignature<B> extends true ? false :\n keyof A & keyof B extends never ? false : true\n\n/**\n * Check all combinations of key overlaps between Input, Internal, Computed\n * Uses conditional chain (not union) to ensure proper boolean result\n */\ntype HasAnyKeyOverlap<T extends MachineTypes> =\n HasOverlappingKeys<Input<T>, Internal<T>> extends true ? true :\n HasOverlappingKeys<Input<T>, Computed<T>> extends true ? true :\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true ? true :\n false\n\n/**\n * Context = Input + Internal + Computed (flat structure)\n * All properties are accessible at the same level in handlers\n *\n * If any pair has overlapping keys, Context becomes `never` (compile-time error)\n */\nexport type Context<T extends MachineTypes> =\n HasAnyKeyOverlap<T> extends true\n ? never\n : Input<T> & Internal<T> & Computed<T>\n\n// ============================================\n// State-based Handler Configuration (FSM)\n// ============================================\n\n/** Configuration for handlers within a specific state */\nexport type StateConfig<\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n on?: { [K in keyof TEvents]?: Handler<TContext, TEvents[K], TActions, TGuards, TInternal> }\n}\n\n/** Map of state names to their configurations */\nexport type StatesConfig<\n TState extends string,\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n [K in TState]?: StateConfig<TContext, TEvents, TActions, TGuards, TInternal>\n}\n\n/** Base context (input + internal) before computed values are added */\nexport type BaseContext<T extends MachineTypes> = Input<T> & Internal<T>\n\n// ============================================\n// Machine Configuration Type\n// ============================================\n\n/**\n * Machine - the configuration object for createMachine\n */\nexport type Machine<T extends MachineTypes> = {\n internal?: Internal<T> // Initial internal state values\n computed?: { // Computed value definitions\n [K in keyof Computed<T>]: (ctx: BaseContext<T>) => Computed<T>[K]\n }\n on?: { // Global event handlers\n [K in keyof Events<T>]?: Handler<Context<T>, Events<T>[K], Actions<T>, Guards<T>, Internal<T>>\n }\n states?: StatesConfig<State<T>, Context<T>, Events<T>, Actions<T>, Guards<T>, Internal<T>> // FSM state handlers\n always?: Rule<Context<T>, undefined, Actions<T>, Guards<T>, Internal<T>>[] // Auto-evaluated rules\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects?: Effect<Context<T>, Events<T>, any>[] // Watch-based side effects\n actions?: { // Named action implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Actions<T>]: (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void\n }\n guards?: { // Named guard implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Guards<T>]: (ctx: Context<T>, payload?: any) => boolean\n }\n}\n\n/**\n * Send - function type for dispatching events\n * Events with undefined payload can be called without arguments\n */\nexport type Send<TEvents extends EventsConfig> = <K extends keyof TEvents>(\n event: K,\n ...args: TEvents[K] extends undefined ? [] : [payload: TEvents[K]]\n) => void\n\n// ============================================\n// Snapshot Type (Return value from getSnapshot/useMachine)\n// ============================================\n\n/**\n * Snapshot = Internal + Computed + { state } (without Input)\n * This is the value returned from getSnapshot() and useMachine()\n *\n * If Internal/Computed have overlapping keys, Snapshot becomes `never`\n * If 'state' type param is defined and Internal/Computed already has 'state' key,\n * we don't add { state } again (existing state is already included)\n */\nexport type Snapshot<T extends MachineTypes> =\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true\n ? never\n : Internal<T> & Computed<T> & (\n T['state'] extends string\n ? 'state' extends keyof Internal<T> | keyof Computed<T>\n ? object // already has 'state', don't add duplicate\n : { state: State<T> }\n : object\n )\n\n// ============================================\n// MachineInstance Type (createMachine return value)\n// ============================================\n\n/**\n * MachineInstance - the return type of createMachine\n * Includes all configuration plus runtime methods\n */\nexport type MachineInstance<T extends MachineTypes> = Machine<T> & {\n /** Dispatch an event with input and optional payload */\n send: <K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => void\n /** Evaluate always rules and effects (called automatically in React) */\n evaluate: (input: Input<T>) => void\n /** Get current snapshot (internal + computed + state) */\n getSnapshot: (input: Input<T>) => Snapshot<T>\n /** Get current internal state */\n getInternal: () => Internal<T>\n /** Set internal state directly */\n setInternal: (internal: Internal<T>) => void\n /** Get initial internal state (for reset) */\n getInitialInternal: () => Internal<T>\n /** Clean up all effect callbacks */\n cleanup: () => void\n}\n\n// ============================================\n// Core Logic - Pure Functions\n// ============================================\n\n/** Normalize a value to an array (single value becomes [value]) */\nfunction toArray<T>(value: T | T[]): T[] {\n return Array.isArray(value) ? value : [value]\n}\n\n/**\n * Execute action items (named actions or inline functions)\n * Handles both single actions and arrays of actions\n * Each action receives fresh context (rebuilt after previous assigns)\n */\nexport function executeRuleActions<TContext, TPayload, TInternal>(\n actionItems: ActionItem<TContext, TPayload, string, TInternal> | ActionItem<TContext, TPayload, string, TInternal>[],\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n for (const item of toArray(actionItems)) {\n const context = getContext() // Fresh context for each action\n if (typeof item === 'function') {\n item(context, payload, assign)\n } else {\n actions[item]?.(context, payload, assign)\n }\n }\n}\n\n/**\n * Evaluate guard items (named guards or inline predicates)\n * Uses AND logic - all guards must pass for result to be true\n */\nexport function evaluateGuards<TContext, TPayload>(\n guardItems: GuardItem<TContext, TPayload> | GuardItem<TContext, TPayload>[] | undefined,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n context: TContext,\n payload: TPayload,\n): boolean {\n if (!guardItems) return true\n\n for (const item of toArray(guardItems)) {\n const guardFn = typeof item === 'function' ? item : guards[item]\n if (guardFn && !guardFn(context, payload)) {\n return false\n }\n }\n\n return true\n}\n\n/** Type guard to check if handler is a Rule array (has 'do' property) */\nexport function isRuleArray<TContext, TPayload, TActions extends string>(\n handler: Handler<TContext, TPayload, TActions>,\n): handler is Rule<TContext, TPayload, TActions>[] {\n return (\n Array.isArray(handler) &&\n handler.length > 0 &&\n typeof handler[0] === 'object' &&\n 'do' in handler[0]\n )\n}\n\n/** Check if handler is a function array */\nfunction isFunctionArray<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n): handler is ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[] {\n return Array.isArray(handler) && handler.length > 0 && typeof handler[0] === 'function'\n}\n\n/**\n * Execute a handler (action string, action array, rule array, inline function, or function array)\n * For rule arrays, only the first matching rule executes (short-circuit)\n * Each action/function receives fresh context (rebuilt after previous assigns)\n */\nexport function executeHandler<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n // Inline function handler\n if (typeof handler === 'function') {\n handler(getContext(), payload, assign)\n return\n }\n\n // Function array - execute all functions in order with fresh context\n if (isFunctionArray(handler)) {\n for (const fn of handler) {\n fn(getContext(), payload, assign)\n }\n return\n }\n\n // Single action or action array (strings)\n if (typeof handler === 'string' || (Array.isArray(handler) && !isRuleArray(handler))) {\n executeRuleActions(handler as string | string[], actions, getContext, payload, assign)\n return\n }\n\n // Rule array - first matching rule wins (guard uses fresh context)\n for (const rule of handler as Rule<TContext, TPayload, string, string, TInternal>[]) {\n if (evaluateGuards(rule.when, guards, getContext(), payload)) {\n executeRuleActions(rule.do, actions, getContext, payload, assign)\n break\n }\n }\n}\n\n/**\n * Compute derived values from base context\n * Each computed function receives the base context (input + internal)\n */\nexport function computeValues<TBase, TComputed extends ComputedConfig>(\n base: TBase,\n computed?: { [K in keyof TComputed]: (ctx: TBase) => TComputed[K] },\n): TBase & TComputed {\n if (!computed) return base as TBase & TComputed\n\n const values = {} as TComputed\n for (const key in computed) {\n values[key] = computed[key](base)\n }\n return { ...base, ...values }\n}\n\n/**\n * Build flat context from input + internal\n * Input takes priority if keys overlap (runtime)\n */\nexport function buildContext<TInput, TInternal>(\n input: TInput,\n internal: TInternal,\n): TInput & TInternal {\n return { ...internal, ...input } as TInput & TInternal\n}\n\n/**\n * Create assign function for updating internal state\n */\nexport function createAssign<TInternal>(\n getInternal: () => TInternal,\n setInternal: (internal: TInternal) => void,\n): AssignFn<TInternal> {\n return (updates: Partial<TInternal>) => {\n setInternal({ ...getInternal(), ...updates })\n }\n}\n\n/**\n * Build snapshot from internal state, context, and computed definitions\n * Snapshot = Internal + Computed + state (without Input)\n */\nexport function buildSnapshot<T extends MachineTypes>(\n internal: Internal<T>,\n context: Context<T>,\n computedDef: Machine<T>['computed'],\n): Snapshot<T> {\n const snapshot = { ...internal } as Snapshot<T>\n // Add computed values\n if (computedDef) {\n for (const key in computedDef) {\n (snapshot as Record<string, unknown>)[key] = context[key as keyof Context<T>]\n }\n }\n // Add state if exists in context\n const state = (context as { state?: State<T> }).state\n if (state !== undefined) {\n (snapshot as Record<string, unknown>).state = state\n }\n return snapshot\n}\n\n// ============================================\n// Effects Processing\n// ============================================\n\n/**\n * Shallow comparison for effect watch values\n * Arrays: compares length and each element with ===\n * Others: strict equality (===)\n */\nexport function shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n\n // Array comparison\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => v === b[i])\n }\n\n return false\n}\n\n/**\n * EffectStore - tracks watched values and cleanup functions for effects\n * Used by both vanilla and React implementations\n */\nexport type EffectStore = {\n watchedValues: Map<number, unknown> // Previous values by effect index\n enterCleanups: Map<number, () => void> // Cleanup from enter callbacks\n changeCleanups: Map<number, () => void> // Cleanup from change callbacks\n exitCleanups: Map<number, () => void> // Cleanup from exit callbacks\n}\n\n/** Create a new effect store */\nexport function createEffectStore(): EffectStore {\n return {\n watchedValues: new Map(),\n enterCleanups: new Map(),\n changeCleanups: new Map(),\n exitCleanups: new Map(),\n }\n}\n\n/**\n * Process all effects - detect watch value changes and call appropriate callbacks\n * Called on every context change in both vanilla (evaluate) and React (useEffect)\n */\nexport function processEffects<TContext, TEvents extends EventsConfig>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects: Effect<TContext, TEvents, any>[] | undefined,\n context: TContext,\n effectHelpers: EffectHelpers<TEvents>,\n store: EffectStore,\n): void {\n if (!effects) return\n\n effects.forEach((effect, i) => {\n const prev = store.watchedValues.get(i)\n const curr = effect.watch(context)\n\n // Only process if value changed (shallow comparison)\n if (!shallowEqual(prev, curr)) {\n // 1. Cleanup previous enter callback\n const enterCleanup = store.enterCleanups.get(i)\n if (enterCleanup) {\n enterCleanup()\n store.enterCleanups.delete(i)\n }\n\n // 2. Cleanup previous change callback\n const changeCleanup = store.changeCleanups.get(i)\n if (changeCleanup) {\n changeCleanup()\n store.changeCleanups.delete(i)\n }\n\n // 3. Call change callback (fires on any value change)\n const changeResult = effect.change?.(context, prev, curr, effectHelpers)\n if (typeof changeResult === 'function') {\n store.changeCleanups.set(i, changeResult)\n }\n\n // 4. Call enter callback (falsy → truthy transition)\n if (!prev && curr) {\n // Cleanup previous exit first\n const exitCleanup = store.exitCleanups.get(i)\n if (exitCleanup) {\n exitCleanup()\n store.exitCleanups.delete(i)\n }\n\n const enterResult = effect.enter?.(context, effectHelpers)\n if (typeof enterResult === 'function') {\n store.enterCleanups.set(i, enterResult)\n }\n }\n\n // 5. Call exit callback (truthy → falsy transition)\n if (prev && !curr) {\n const exitResult = effect.exit?.(context, effectHelpers)\n if (typeof exitResult === 'function') {\n store.exitCleanups.set(i, exitResult)\n }\n }\n\n // Update stored value for next comparison\n store.watchedValues.set(i, curr)\n }\n })\n}\n\n/** Clear all effect cleanups (called on unmount or cleanup) */\nexport function clearEffectStore(store: EffectStore): void {\n store.enterCleanups.forEach((fn) => fn())\n store.enterCleanups.clear()\n store.changeCleanups.forEach((fn) => fn())\n store.changeCleanups.clear()\n store.exitCleanups.forEach((fn) => fn())\n store.exitCleanups.clear()\n store.watchedValues.clear()\n}\n\n// ============================================\n// createMachine - Vanilla Implementation\n// ============================================\n\n/**\n * Create a controlled state machine instance\n *\n * The machine manages internal state and provides methods for:\n * - send: Dispatch events with input and payload\n * - evaluate: Run always rules and effects\n * - getSnapshot: Get current state (internal + computed + state)\n *\n * @example\n * const machine = createMachine<{\n * input: { count: number }\n * internal: { isOpen: boolean }\n * events: { TOGGLE: undefined }\n * computed: { doubled: number }\n * }>({\n * internal: { isOpen: false },\n * computed: { doubled: ctx => ctx.count * 2 },\n * on: { TOGGLE: (ctx, _, assign) => assign({ isOpen: !ctx.isOpen }) }\n * })\n */\nexport function createMachine<T extends MachineTypes>(\n config: Machine<T>,\n): MachineInstance<T> {\n const effectStore = createEffectStore()\n const initialInternal = (config.internal ?? {}) as Internal<T>\n\n // Machine-managed internal state\n let currentInternal = { ...initialInternal }\n\n // Update internal state\n const updateInternal = (newInternal: Internal<T>) => {\n currentInternal = newInternal\n }\n\n // Build full context: input + internal + computed\n const buildFullContext = (input: Input<T>): Context<T> => {\n const base = buildContext(input, currentInternal)\n return computeValues(base, config.computed) as Context<T>\n }\n\n /**\n * Send an event to the machine\n * Executes state-specific handlers first, then global handlers\n */\n const send = (<K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const payload = args[0] as Events<T>[K]\n\n // getContext rebuilds context with latest internal state\n const getContext = () => buildFullContext(input)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>, payload?: unknown) => boolean>\n\n // 1. Execute state-specific handler (if in FSM mode)\n const context = getContext()\n const state = (context as { state?: State<T> }).state\n if (state && config.states?.[state]?.on?.[event]) {\n const stateHandler = config.states[state].on![event]!\n executeHandler(\n stateHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n\n // 2. Execute global handler\n const globalHandler = config.on?.[event]\n if (globalHandler) {\n executeHandler(\n globalHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n }) as MachineInstance<T>['send']\n\n // Create effect helpers with bound send\n const createEffectHelpers = (input: Input<T>): EffectHelpers<Events<T>> => ({\n send: (<K extends keyof Events<T>>(\n event: K,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n send(event, input, ...args)\n }) as Send<Events<T>>,\n })\n\n /**\n * Evaluate the machine - runs always rules and processes effects\n * Should be called when input changes (automatic in React via useMachine)\n */\n const evaluate = (input: Input<T>) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const effectHelpers = createEffectHelpers(input)\n const getContext = () => buildFullContext(input)\n\n // Process always rules (first matching rule wins)\n if (config.always) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>) => boolean>\n for (const rule of config.always) {\n if (evaluateGuards(rule.when, guardsMap, getContext(), undefined)) {\n executeRuleActions(rule.do, actionsMap, getContext, undefined, assign)\n break\n }\n }\n }\n\n // Process effects (uses current context)\n processEffects(config.effects, getContext(), effectHelpers, effectStore)\n }\n\n /** Get current snapshot (internal + computed + state) */\n const getSnapshot = (input: Input<T>): Snapshot<T> => {\n const context = buildFullContext(input)\n return buildSnapshot(currentInternal, context, config.computed)\n }\n\n // Internal state accessors\n const getInternal = (): Internal<T> => currentInternal\n const setInternal = (internal: Internal<T>) => { currentInternal = internal }\n const getInitialInternal = (): Internal<T> => initialInternal\n\n /** Clean up all effect callbacks */\n const cleanup = () => clearEffectStore(effectStore)\n\n return Object.assign(config, { send, evaluate, getSnapshot, getInternal, setInternal, getInitialInternal, cleanup })\n}\n"],"names":["effect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["/**\n * Controlled Machine\n *\n * A controlled state machine library where external state (input) is passed in\n * and internal state is managed by the machine itself.\n *\n * Key Concepts:\n * - input: External data passed in from outside (e.g., React state, props)\n * - internal: Machine-managed state that persists across events\n * - computed: Derived values calculated from input + internal\n * - context: Flattened input + internal + computed (available in all handlers)\n * - on: Event handlers with conditional rules and actions\n * - states: FSM-style state-based event handlers\n * - effects: Watch-based side effects with enter/exit/change callbacks\n * - always: Auto-evaluated rules that run on every context change\n * - actions: Named action functions (can be overridden in useMachine)\n * - guards: Named guard functions for conditional logic\n */\n\n// ============================================\n// Types - Core Building Blocks\n// ============================================\n\n/**\n * Assign function type - updates internal state with partial updates\n * Only allows modifying keys defined in Internal type\n */\nexport type AssignFn<TInternal> = (updates: Partial<TInternal>) => void\n\n/**\n * ActionItem - can be a named action string or inline function\n * Inline functions receive (context, payload, assign)\n */\nexport type ActionItem<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TInternal = unknown,\n> = TActions | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n\n/**\n * GuardComposer - composed guard using not/and/or utilities\n */\nexport type GuardComposer<\n TContext,\n TPayload = undefined,\n TGuards extends string = string,\n> = {\n __type: 'not' | 'and' | 'or'\n __guards: GuardItem<TContext, TPayload, TGuards>[]\n}\n\n/**\n * GuardItem - can be a named guard string, inline predicate function, or composed guard\n */\nexport type GuardItem<\n TContext,\n TPayload = undefined,\n TGuards extends string = string,\n> =\n | TGuards\n | ((context: TContext, payload: TPayload) => boolean)\n | GuardComposer<TContext, TPayload, TGuards>\n\n/**\n * Rule - conditional action with optional guard(s)\n * @property when - Guard(s) that must pass (AND logic for arrays)\n * @property do - Action(s) to execute if guards pass\n */\nexport type Rule<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n when?: GuardItem<TContext, TPayload, TGuards> | GuardItem<TContext, TPayload, TGuards>[]\n do: ActionItem<TContext, TPayload, TActions, TInternal> | ActionItem<TContext, TPayload, TActions, TInternal>[]\n}\n\n/**\n * Handler - event handler definition\n * Can be: single action, action array, rule array, inline function, or function array\n *\n * @example\n * on: { CLICK: 'handleClick' } // single action\n * on: { SUBMIT: ['validate', 'save'] } // action array\n * on: { TOGGLE: [{ when: ctx => ctx.isOpen, do: 'close' }, { do: 'open' }] } // rule array\n * on: { INCREMENT: (ctx, _, assign) => assign({ count: ctx.count + 1 }) } // inline function\n * on: { SELECT: [(ctx, p) => ctx.onSelect(p), (_, __, a) => a({ isOpen: false })] } // function array\n */\nexport type Handler<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> =\n | TActions\n | TActions[]\n | Rule<TContext, TPayload, TActions, TGuards, TInternal>[]\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[]\n\n/**\n * EffectHelpers - utilities available in effect callbacks\n */\nexport type EffectHelpers<TEvents extends EventsConfig> = {\n send: Send<TEvents>\n}\n\n/** Cleanup function returned from effect callbacks */\nexport type Cleanup = () => void\n\n/**\n * Effect - watch-based side effect with lifecycle callbacks\n * @property watch - Function that returns the value to watch (uses shallow comparison)\n * @property enter - Called when watch value becomes truthy (can return cleanup)\n * @property exit - Called when watch value becomes falsy (can return cleanup)\n * @property change - Called on any value change with (prev, curr) (can return cleanup)\n */\nexport type Effect<\n TContext,\n TEvents extends EventsConfig,\n TWatched = unknown,\n> = {\n watch: (context: TContext) => TWatched\n enter?: (\n context: TContext,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup | Promise<void>\n exit?: (context: TContext, helpers: EffectHelpers<TEvents>) => void | Cleanup\n change?: (\n context: TContext,\n prev: TWatched | undefined,\n curr: TWatched,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup\n}\n\n/**\n * Helper function for creating effects with proper type inference\n * @example\n * effects: [\n * effect({ watch: ctx => ctx.isOpen, enter: () => console.log('opened') })\n * ]\n */\nexport function effect<TContext, TEvents extends EventsConfig, TWatched>(\n config: Effect<TContext, TEvents, TWatched>,\n): Effect<TContext, TEvents, TWatched> {\n return config\n}\n\n// ============================================\n// Guard Utilities - not, and, or\n// ============================================\n\n/**\n * Negate a guard - returns true when the guard returns false\n * @example\n * on: { CLICK: [{ when: not('isDisabled'), do: 'handleClick' }] }\n * on: { SUBMIT: [{ when: not(ctx => ctx.loading), do: 'submit' }] }\n */\nexport function not<\n TContext = unknown,\n TPayload = undefined,\n TGuards extends string = string,\n>(\n guard: GuardItem<TContext, TPayload, TGuards>,\n): GuardComposer<TContext, TPayload, TGuards> {\n return { __type: 'not', __guards: [guard] }\n}\n\n/**\n * Combine guards with AND logic - returns true only if ALL guards return true\n * @example\n * on: { SUBMIT: [{ when: and(['hasValue', 'isValid']), do: 'submit' }] }\n * on: { DELETE: [{ when: and(['isSelected', ctx => ctx.canDelete]), do: 'delete' }] }\n */\nexport function and<\n TContext = unknown,\n TPayload = undefined,\n TGuards extends string = string,\n>(\n guards: GuardItem<TContext, TPayload, TGuards>[],\n): GuardComposer<TContext, TPayload, TGuards> {\n return { __type: 'and', __guards: guards }\n}\n\n/**\n * Combine guards with OR logic - returns true if ANY guard returns true\n * @example\n * on: { CLOSE: [{ when: or(['isEscapeKey', 'isClickOutside']), do: 'close' }] }\n * on: { SUBMIT: [{ when: or([ctx => ctx.isAdmin, 'hasPermission']), do: 'submit' }] }\n */\nexport function or<\n TContext = unknown,\n TPayload = undefined,\n TGuards extends string = string,\n>(\n guards: GuardItem<TContext, TPayload, TGuards>[],\n): GuardComposer<TContext, TPayload, TGuards> {\n return { __type: 'or', __guards: guards }\n}\n\n/** Event configuration - event name to payload type mapping */\nexport type EventsConfig = Record<string, unknown>\n/** Computed configuration - computed key to value type mapping */\nexport type ComputedConfig = Record<string, unknown>\n\n// ============================================\n// Object-based Generic Types\n// ============================================\n\n/**\n * MachineTypes - object-based generic type parameter\n * Specify only the types you need, in any order\n *\n * @example\n * createMachine<{\n * input: { count: number; setCount: (c: number) => void }\n * internal: { isOpen: boolean }\n * events: { INCREMENT: undefined; SET: { value: number } }\n * computed: { doubled: number }\n * actions: 'increment' | 'set'\n * guards: 'isPositive'\n * state: 'idle' | 'loading'\n * }>({...})\n */\nexport type MachineTypes = {\n input?: unknown // External state passed in (React state, props, etc.)\n internal?: unknown // Machine-managed state\n events?: EventsConfig // Event name → payload type\n computed?: ComputedConfig // Derived values from context\n actions?: string // Named action strings\n guards?: string // Named guard strings\n state?: string // FSM state values\n}\n\n// ============================================\n// Type Extraction Helpers\n// ============================================\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Input<T extends MachineTypes> = T['input'] extends object ? T['input'] : {}\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Internal<T extends MachineTypes> = T['internal'] extends object ? T['internal'] : {}\nexport type Events<T extends MachineTypes> = T['events'] extends EventsConfig\n ? T['events']\n : Record<string, undefined>\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Computed<T extends MachineTypes> = T['computed'] extends ComputedConfig\n ? T['computed']\n : {}\nexport type Actions<T extends MachineTypes> = T['actions'] extends string\n ? T['actions']\n : string\nexport type Guards<T extends MachineTypes> = T['guards'] extends string\n ? T['guards']\n : string\nexport type State<T extends MachineTypes> = T['state'] extends string\n ? T['state']\n : string\n\n// ============================================\n// Key Overlap Detection (Compile-time Safety)\n// ============================================\n\n/**\n * Check if type has only index signature (no specific keys)\n * `string extends keyof T` is true for Record<string, K> types\n */\ntype HasOnlyIndexSignature<T> = string extends keyof T ? true : false\n\n/**\n * Detects if two types have overlapping keys\n * Returns true if any key exists in both A and B\n *\n * Types with only index signatures (like Record<string, never>) are treated as empty,\n * since they don't have specific keys that could overlap.\n */\ntype HasOverlappingKeys<A, B> =\n HasOnlyIndexSignature<A> extends true ? false :\n HasOnlyIndexSignature<B> extends true ? false :\n keyof A & keyof B extends never ? false : true\n\n/**\n * Check all combinations of key overlaps between Input, Internal, Computed\n * Uses conditional chain (not union) to ensure proper boolean result\n */\ntype HasAnyKeyOverlap<T extends MachineTypes> =\n HasOverlappingKeys<Input<T>, Internal<T>> extends true ? true :\n HasOverlappingKeys<Input<T>, Computed<T>> extends true ? true :\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true ? true :\n false\n\n/**\n * Context = Input + Internal + Computed (flat structure)\n * All properties are accessible at the same level in handlers\n *\n * If any pair has overlapping keys, Context becomes `never` (compile-time error)\n */\nexport type Context<T extends MachineTypes> =\n HasAnyKeyOverlap<T> extends true\n ? never\n : Input<T> & Internal<T> & Computed<T>\n\n// ============================================\n// State-based Handler Configuration (FSM)\n// ============================================\n\n/** Configuration for handlers within a specific state */\nexport type StateConfig<\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n on?: { [K in keyof TEvents]?: Handler<TContext, TEvents[K], TActions, TGuards, TInternal> }\n}\n\n/** Map of state names to their configurations */\nexport type StatesConfig<\n TState extends string,\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n [K in TState]?: StateConfig<TContext, TEvents, TActions, TGuards, TInternal>\n}\n\n/** Base context (input + internal) before computed values are added */\nexport type BaseContext<T extends MachineTypes> = Input<T> & Internal<T>\n\n// ============================================\n// Machine Configuration Type\n// ============================================\n\n/**\n * Machine - the configuration object for createMachine\n */\nexport type Machine<T extends MachineTypes> = {\n internal?: Internal<T> // Initial internal state values\n computed?: { // Computed value definitions\n [K in keyof Computed<T>]: (ctx: BaseContext<T>) => Computed<T>[K]\n }\n on?: { // Global event handlers\n [K in keyof Events<T>]?: Handler<Context<T>, Events<T>[K], Actions<T>, Guards<T>, Internal<T>>\n }\n states?: StatesConfig<State<T>, Context<T>, Events<T>, Actions<T>, Guards<T>, Internal<T>> // FSM state handlers\n always?: Rule<Context<T>, undefined, Actions<T>, Guards<T>, Internal<T>>[] // Auto-evaluated rules\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects?: Effect<Context<T>, Events<T>, any>[] // Watch-based side effects\n actions?: { // Named action implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Actions<T>]: (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void\n }\n guards?: { // Named guard implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Guards<T>]: (ctx: Context<T>, payload?: any) => boolean\n }\n}\n\n/**\n * Send - function type for dispatching events\n * Events with undefined payload can be called without arguments\n */\nexport type Send<TEvents extends EventsConfig> = <K extends keyof TEvents>(\n event: K,\n ...args: TEvents[K] extends undefined ? [] : [payload: TEvents[K]]\n) => void\n\n// ============================================\n// Snapshot Type (Return value from getSnapshot/useMachine)\n// ============================================\n\n/**\n * Snapshot = Internal + Computed + { state } (without Input)\n * This is the value returned from getSnapshot() and useMachine()\n *\n * If Internal/Computed have overlapping keys, Snapshot becomes `never`\n * If 'state' type param is defined and Internal/Computed already has 'state' key,\n * we don't add { state } again (existing state is already included)\n */\nexport type Snapshot<T extends MachineTypes> =\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true\n ? never\n : Internal<T> & Computed<T> & (\n T['state'] extends string\n ? 'state' extends keyof Internal<T> | keyof Computed<T>\n ? object // already has 'state', don't add duplicate\n : { state: State<T> }\n : object\n )\n\n// ============================================\n// MachineInstance Type (createMachine return value)\n// ============================================\n\n/**\n * MachineInstance - the return type of createMachine\n * Includes all configuration plus runtime methods\n */\nexport type MachineInstance<T extends MachineTypes> = Machine<T> & {\n /** Dispatch an event with input and optional payload */\n send: <K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => void\n /** Evaluate always rules and effects (called automatically in React) */\n evaluate: (input: Input<T>) => void\n /** Get current snapshot (internal + computed + state) */\n getSnapshot: (input: Input<T>) => Snapshot<T>\n /** Get current internal state */\n getInternal: () => Internal<T>\n /** Set internal state directly */\n setInternal: (internal: Internal<T>) => void\n /** Get initial internal state (for reset) */\n getInitialInternal: () => Internal<T>\n /** Clean up all effect callbacks */\n cleanup: () => void\n}\n\n// ============================================\n// Core Logic - Pure Functions\n// ============================================\n\n/** Normalize a value to an array (single value becomes [value]) */\nfunction toArray<T>(value: T | T[]): T[] {\n return Array.isArray(value) ? value : [value]\n}\n\n/**\n * Execute action items (named actions or inline functions)\n * Handles both single actions and arrays of actions\n * Each action receives fresh context (rebuilt after previous assigns)\n */\nexport function executeRuleActions<TContext, TPayload, TInternal>(\n actionItems: ActionItem<TContext, TPayload, string, TInternal> | ActionItem<TContext, TPayload, string, TInternal>[],\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n for (const item of toArray(actionItems)) {\n const context = getContext() // Fresh context for each action\n if (typeof item === 'function') {\n item(context, payload, assign)\n } else {\n actions[item]?.(context, payload, assign)\n }\n }\n}\n\n/**\n * Check if a value is a GuardComposer (composed guard)\n */\nfunction isGuardComposer<TContext, TPayload, TGuards extends string>(\n item: GuardItem<TContext, TPayload, TGuards>,\n): item is GuardComposer<TContext, TPayload, TGuards> {\n return (\n typeof item === 'object' &&\n item !== null &&\n '__type' in item &&\n '__guards' in item\n )\n}\n\n/**\n * Evaluate a single guard item (named guard, inline function, or composed guard)\n */\nfunction evaluateSingleGuard<TContext, TPayload>(\n item: GuardItem<TContext, TPayload>,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n context: TContext,\n payload: TPayload,\n): boolean {\n // Composed guard (not/and/or)\n if (isGuardComposer(item)) {\n switch (item.__type) {\n case 'not': {\n // not() takes a single guard, negate its result\n const innerResult = evaluateSingleGuard(item.__guards[0], guards, context, payload)\n return !innerResult\n }\n case 'and': {\n // and() - all guards must return true\n return item.__guards.every((g) =>\n evaluateSingleGuard(g, guards, context, payload),\n )\n }\n case 'or': {\n // or() - at least one guard must return true\n return item.__guards.some((g) =>\n evaluateSingleGuard(g, guards, context, payload),\n )\n }\n }\n }\n\n // Inline function guard\n if (typeof item === 'function') {\n return item(context, payload)\n }\n\n // Named guard (string)\n const guardFn = guards[item as string]\n return guardFn ? guardFn(context, payload) : true\n}\n\n/**\n * Evaluate guard items (named guards, inline predicates, or composed guards)\n * Uses AND logic - all guards must pass for result to be true\n */\nexport function evaluateGuards<TContext, TPayload>(\n guardItems: GuardItem<TContext, TPayload> | GuardItem<TContext, TPayload>[] | undefined,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n context: TContext,\n payload: TPayload,\n): boolean {\n if (!guardItems) return true\n\n for (const item of toArray(guardItems)) {\n if (!evaluateSingleGuard(item, guards, context, payload)) {\n return false\n }\n }\n\n return true\n}\n\n/** Type guard to check if handler is a Rule array (has 'do' property) */\nexport function isRuleArray<TContext, TPayload, TActions extends string>(\n handler: Handler<TContext, TPayload, TActions>,\n): handler is Rule<TContext, TPayload, TActions>[] {\n return (\n Array.isArray(handler) &&\n handler.length > 0 &&\n typeof handler[0] === 'object' &&\n 'do' in handler[0]\n )\n}\n\n/** Check if handler is a function array */\nfunction isFunctionArray<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n): handler is ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[] {\n return Array.isArray(handler) && handler.length > 0 && typeof handler[0] === 'function'\n}\n\n/**\n * Execute a handler (action string, action array, rule array, inline function, or function array)\n * For rule arrays, only the first matching rule executes (short-circuit)\n * Each action/function receives fresh context (rebuilt after previous assigns)\n */\nexport function executeHandler<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n // Inline function handler\n if (typeof handler === 'function') {\n handler(getContext(), payload, assign)\n return\n }\n\n // Function array - execute all functions in order with fresh context\n if (isFunctionArray(handler)) {\n for (const fn of handler) {\n fn(getContext(), payload, assign)\n }\n return\n }\n\n // Single action or action array (strings)\n if (typeof handler === 'string' || (Array.isArray(handler) && !isRuleArray(handler))) {\n executeRuleActions(handler as string | string[], actions, getContext, payload, assign)\n return\n }\n\n // Rule array - first matching rule wins (guard uses fresh context)\n for (const rule of handler as Rule<TContext, TPayload, string, string, TInternal>[]) {\n if (evaluateGuards(rule.when, guards, getContext(), payload)) {\n executeRuleActions(rule.do, actions, getContext, payload, assign)\n break\n }\n }\n}\n\n/**\n * Compute derived values from base context\n * Each computed function receives the base context (input + internal)\n */\nexport function computeValues<TBase, TComputed extends ComputedConfig>(\n base: TBase,\n computed?: { [K in keyof TComputed]: (ctx: TBase) => TComputed[K] },\n): TBase & TComputed {\n if (!computed) return base as TBase & TComputed\n\n const values = {} as TComputed\n for (const key in computed) {\n values[key] = computed[key](base)\n }\n return { ...base, ...values }\n}\n\n/**\n * Build flat context from input + internal\n * Input takes priority if keys overlap (runtime)\n */\nexport function buildContext<TInput, TInternal>(\n input: TInput,\n internal: TInternal,\n): TInput & TInternal {\n return { ...internal, ...input } as TInput & TInternal\n}\n\n/**\n * Create assign function for updating internal state\n */\nexport function createAssign<TInternal>(\n getInternal: () => TInternal,\n setInternal: (internal: TInternal) => void,\n): AssignFn<TInternal> {\n return (updates: Partial<TInternal>) => {\n setInternal({ ...getInternal(), ...updates })\n }\n}\n\n/**\n * Build snapshot from internal state, context, and computed definitions\n * Snapshot = Internal + Computed + state (without Input)\n */\nexport function buildSnapshot<T extends MachineTypes>(\n internal: Internal<T>,\n context: Context<T>,\n computedDef: Machine<T>['computed'],\n): Snapshot<T> {\n const snapshot = { ...internal } as Snapshot<T>\n // Add computed values\n if (computedDef) {\n for (const key in computedDef) {\n (snapshot as Record<string, unknown>)[key] = context[key as keyof Context<T>]\n }\n }\n // Add state if exists in context\n const state = (context as { state?: State<T> }).state\n if (state !== undefined) {\n (snapshot as Record<string, unknown>).state = state\n }\n return snapshot\n}\n\n// ============================================\n// Effects Processing\n// ============================================\n\n/**\n * Shallow comparison for effect watch values\n * Arrays: compares length and each element with ===\n * Others: strict equality (===)\n */\nexport function shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n\n // Array comparison\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => v === b[i])\n }\n\n return false\n}\n\n/**\n * EffectStore - tracks watched values and cleanup functions for effects\n * Used by both vanilla and React implementations\n */\nexport type EffectStore = {\n watchedValues: Map<number, unknown> // Previous values by effect index\n enterCleanups: Map<number, () => void> // Cleanup from enter callbacks\n changeCleanups: Map<number, () => void> // Cleanup from change callbacks\n exitCleanups: Map<number, () => void> // Cleanup from exit callbacks\n}\n\n/** Create a new effect store */\nexport function createEffectStore(): EffectStore {\n return {\n watchedValues: new Map(),\n enterCleanups: new Map(),\n changeCleanups: new Map(),\n exitCleanups: new Map(),\n }\n}\n\n/**\n * Process all effects - detect watch value changes and call appropriate callbacks\n * Called on every context change in both vanilla (evaluate) and React (useEffect)\n */\nexport function processEffects<TContext, TEvents extends EventsConfig>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects: Effect<TContext, TEvents, any>[] | undefined,\n context: TContext,\n effectHelpers: EffectHelpers<TEvents>,\n store: EffectStore,\n): void {\n if (!effects) return\n\n effects.forEach((effect, i) => {\n const prev = store.watchedValues.get(i)\n const curr = effect.watch(context)\n\n // Only process if value changed (shallow comparison)\n if (!shallowEqual(prev, curr)) {\n // 1. Cleanup previous enter callback\n const enterCleanup = store.enterCleanups.get(i)\n if (enterCleanup) {\n enterCleanup()\n store.enterCleanups.delete(i)\n }\n\n // 2. Cleanup previous change callback\n const changeCleanup = store.changeCleanups.get(i)\n if (changeCleanup) {\n changeCleanup()\n store.changeCleanups.delete(i)\n }\n\n // 3. Call change callback (fires on any value change)\n const changeResult = effect.change?.(context, prev, curr, effectHelpers)\n if (typeof changeResult === 'function') {\n store.changeCleanups.set(i, changeResult)\n }\n\n // 4. Call enter callback (falsy → truthy transition)\n if (!prev && curr) {\n // Cleanup previous exit first\n const exitCleanup = store.exitCleanups.get(i)\n if (exitCleanup) {\n exitCleanup()\n store.exitCleanups.delete(i)\n }\n\n const enterResult = effect.enter?.(context, effectHelpers)\n if (typeof enterResult === 'function') {\n store.enterCleanups.set(i, enterResult)\n }\n }\n\n // 5. Call exit callback (truthy → falsy transition)\n if (prev && !curr) {\n const exitResult = effect.exit?.(context, effectHelpers)\n if (typeof exitResult === 'function') {\n store.exitCleanups.set(i, exitResult)\n }\n }\n\n // Update stored value for next comparison\n store.watchedValues.set(i, curr)\n }\n })\n}\n\n/** Clear all effect cleanups (called on unmount or cleanup) */\nexport function clearEffectStore(store: EffectStore): void {\n store.enterCleanups.forEach((fn) => fn())\n store.enterCleanups.clear()\n store.changeCleanups.forEach((fn) => fn())\n store.changeCleanups.clear()\n store.exitCleanups.forEach((fn) => fn())\n store.exitCleanups.clear()\n store.watchedValues.clear()\n}\n\n// ============================================\n// createMachine - Vanilla Implementation\n// ============================================\n\n/**\n * Create a controlled state machine instance\n *\n * The machine manages internal state and provides methods for:\n * - send: Dispatch events with input and payload\n * - evaluate: Run always rules and effects\n * - getSnapshot: Get current state (internal + computed + state)\n *\n * @example\n * const machine = createMachine<{\n * input: { count: number }\n * internal: { isOpen: boolean }\n * events: { TOGGLE: undefined }\n * computed: { doubled: number }\n * }>({\n * internal: { isOpen: false },\n * computed: { doubled: ctx => ctx.count * 2 },\n * on: { TOGGLE: (ctx, _, assign) => assign({ isOpen: !ctx.isOpen }) }\n * })\n */\nexport function createMachine<T extends MachineTypes>(\n config: Machine<T>,\n): MachineInstance<T> {\n const effectStore = createEffectStore()\n const initialInternal = (config.internal ?? {}) as Internal<T>\n\n // Machine-managed internal state\n let currentInternal = { ...initialInternal }\n\n // Update internal state\n const updateInternal = (newInternal: Internal<T>) => {\n currentInternal = newInternal\n }\n\n // Build full context: input + internal + computed\n const buildFullContext = (input: Input<T>): Context<T> => {\n const base = buildContext(input, currentInternal)\n return computeValues(base, config.computed) as Context<T>\n }\n\n /**\n * Send an event to the machine\n * Executes state-specific handlers first, then global handlers\n */\n const send = (<K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const payload = args[0] as Events<T>[K]\n\n // getContext rebuilds context with latest internal state\n const getContext = () => buildFullContext(input)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>, payload?: unknown) => boolean>\n\n // 1. Execute state-specific handler (if in FSM mode)\n const context = getContext()\n const state = (context as { state?: State<T> }).state\n if (state && config.states?.[state]?.on?.[event]) {\n const stateHandler = config.states[state].on![event]!\n executeHandler(\n stateHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n\n // 2. Execute global handler\n const globalHandler = config.on?.[event]\n if (globalHandler) {\n executeHandler(\n globalHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n }) as MachineInstance<T>['send']\n\n // Create effect helpers with bound send\n const createEffectHelpers = (input: Input<T>): EffectHelpers<Events<T>> => ({\n send: (<K extends keyof Events<T>>(\n event: K,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n send(event, input, ...args)\n }) as Send<Events<T>>,\n })\n\n /**\n * Evaluate the machine - runs always rules and processes effects\n * Should be called when input changes (automatic in React via useMachine)\n */\n const evaluate = (input: Input<T>) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const effectHelpers = createEffectHelpers(input)\n const getContext = () => buildFullContext(input)\n\n // Process always rules (first matching rule wins)\n if (config.always) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>) => boolean>\n for (const rule of config.always) {\n if (evaluateGuards(rule.when, guardsMap, getContext(), undefined)) {\n executeRuleActions(rule.do, actionsMap, getContext, undefined, assign)\n break\n }\n }\n }\n\n // Process effects (uses current context)\n processEffects(config.effects, getContext(), effectHelpers, effectStore)\n }\n\n /** Get current snapshot (internal + computed + state) */\n const getSnapshot = (input: Input<T>): Snapshot<T> => {\n const context = buildFullContext(input)\n return buildSnapshot(currentInternal, context, config.computed)\n }\n\n // Internal state accessors\n const getInternal = (): Internal<T> => currentInternal\n const setInternal = (internal: Internal<T>) => { currentInternal = internal }\n const getInitialInternal = (): Internal<T> => initialInternal\n\n /** Clean up all effect callbacks */\n const cleanup = () => clearEffectStore(effectStore)\n\n return Object.assign(config, { send, evaluate, getSnapshot, getInternal, setInternal, getInitialInternal, cleanup })\n}\n"],"names":["effect"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -27,9 +27,16 @@ export type AssignFn<TInternal> = (updates: Partial<TInternal>) => void;
|
|
|
27
27
|
*/
|
|
28
28
|
export type ActionItem<TContext, TPayload = undefined, TActions extends string = string, TInternal = unknown> = TActions | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void);
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* GuardComposer - composed guard using not/and/or utilities
|
|
31
31
|
*/
|
|
32
|
-
export type
|
|
32
|
+
export type GuardComposer<TContext, TPayload = undefined, TGuards extends string = string> = {
|
|
33
|
+
__type: 'not' | 'and' | 'or';
|
|
34
|
+
__guards: GuardItem<TContext, TPayload, TGuards>[];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* GuardItem - can be a named guard string, inline predicate function, or composed guard
|
|
38
|
+
*/
|
|
39
|
+
export type GuardItem<TContext, TPayload = undefined, TGuards extends string = string> = TGuards | ((context: TContext, payload: TPayload) => boolean) | GuardComposer<TContext, TPayload, TGuards>;
|
|
33
40
|
/**
|
|
34
41
|
* Rule - conditional action with optional guard(s)
|
|
35
42
|
* @property when - Guard(s) that must pass (AND logic for arrays)
|
|
@@ -80,6 +87,27 @@ export type Effect<TContext, TEvents extends EventsConfig, TWatched = unknown> =
|
|
|
80
87
|
* ]
|
|
81
88
|
*/
|
|
82
89
|
export declare function effect<TContext, TEvents extends EventsConfig, TWatched>(config: Effect<TContext, TEvents, TWatched>): Effect<TContext, TEvents, TWatched>;
|
|
90
|
+
/**
|
|
91
|
+
* Negate a guard - returns true when the guard returns false
|
|
92
|
+
* @example
|
|
93
|
+
* on: { CLICK: [{ when: not('isDisabled'), do: 'handleClick' }] }
|
|
94
|
+
* on: { SUBMIT: [{ when: not(ctx => ctx.loading), do: 'submit' }] }
|
|
95
|
+
*/
|
|
96
|
+
export declare function not<TContext = unknown, TPayload = undefined, TGuards extends string = string>(guard: GuardItem<TContext, TPayload, TGuards>): GuardComposer<TContext, TPayload, TGuards>;
|
|
97
|
+
/**
|
|
98
|
+
* Combine guards with AND logic - returns true only if ALL guards return true
|
|
99
|
+
* @example
|
|
100
|
+
* on: { SUBMIT: [{ when: and(['hasValue', 'isValid']), do: 'submit' }] }
|
|
101
|
+
* on: { DELETE: [{ when: and(['isSelected', ctx => ctx.canDelete]), do: 'delete' }] }
|
|
102
|
+
*/
|
|
103
|
+
export declare function and<TContext = unknown, TPayload = undefined, TGuards extends string = string>(guards: GuardItem<TContext, TPayload, TGuards>[]): GuardComposer<TContext, TPayload, TGuards>;
|
|
104
|
+
/**
|
|
105
|
+
* Combine guards with OR logic - returns true if ANY guard returns true
|
|
106
|
+
* @example
|
|
107
|
+
* on: { CLOSE: [{ when: or(['isEscapeKey', 'isClickOutside']), do: 'close' }] }
|
|
108
|
+
* on: { SUBMIT: [{ when: or([ctx => ctx.isAdmin, 'hasPermission']), do: 'submit' }] }
|
|
109
|
+
*/
|
|
110
|
+
export declare function or<TContext = unknown, TPayload = undefined, TGuards extends string = string>(guards: GuardItem<TContext, TPayload, TGuards>[]): GuardComposer<TContext, TPayload, TGuards>;
|
|
83
111
|
/** Event configuration - event name to payload type mapping */
|
|
84
112
|
export type EventsConfig = Record<string, unknown>;
|
|
85
113
|
/** Computed configuration - computed key to value type mapping */
|
|
@@ -216,7 +244,7 @@ export type MachineInstance<T extends MachineTypes> = Machine<T> & {
|
|
|
216
244
|
*/
|
|
217
245
|
export declare function executeRuleActions<TContext, TPayload, TInternal>(actionItems: ActionItem<TContext, TPayload, string, TInternal> | ActionItem<TContext, TPayload, string, TInternal>[], actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>, getContext: () => TContext, payload: TPayload, assign: AssignFn<TInternal>): void;
|
|
218
246
|
/**
|
|
219
|
-
* Evaluate guard items (named guards or
|
|
247
|
+
* Evaluate guard items (named guards, inline predicates, or composed guards)
|
|
220
248
|
* Uses AND logic - all guards must pass for result to be true
|
|
221
249
|
*/
|
|
222
250
|
export declare function evaluateGuards<TContext, TPayload>(guardItems: GuardItem<TContext, TPayload> | GuardItem<TContext, TPayload>[] | undefined, guards: Record<string, (context: TContext, payload?: TPayload) => boolean>, context: TContext, payload: TPayload): boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -27,9 +27,16 @@ export type AssignFn<TInternal> = (updates: Partial<TInternal>) => void;
|
|
|
27
27
|
*/
|
|
28
28
|
export type ActionItem<TContext, TPayload = undefined, TActions extends string = string, TInternal = unknown> = TActions | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void);
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* GuardComposer - composed guard using not/and/or utilities
|
|
31
31
|
*/
|
|
32
|
-
export type
|
|
32
|
+
export type GuardComposer<TContext, TPayload = undefined, TGuards extends string = string> = {
|
|
33
|
+
__type: 'not' | 'and' | 'or';
|
|
34
|
+
__guards: GuardItem<TContext, TPayload, TGuards>[];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* GuardItem - can be a named guard string, inline predicate function, or composed guard
|
|
38
|
+
*/
|
|
39
|
+
export type GuardItem<TContext, TPayload = undefined, TGuards extends string = string> = TGuards | ((context: TContext, payload: TPayload) => boolean) | GuardComposer<TContext, TPayload, TGuards>;
|
|
33
40
|
/**
|
|
34
41
|
* Rule - conditional action with optional guard(s)
|
|
35
42
|
* @property when - Guard(s) that must pass (AND logic for arrays)
|
|
@@ -80,6 +87,27 @@ export type Effect<TContext, TEvents extends EventsConfig, TWatched = unknown> =
|
|
|
80
87
|
* ]
|
|
81
88
|
*/
|
|
82
89
|
export declare function effect<TContext, TEvents extends EventsConfig, TWatched>(config: Effect<TContext, TEvents, TWatched>): Effect<TContext, TEvents, TWatched>;
|
|
90
|
+
/**
|
|
91
|
+
* Negate a guard - returns true when the guard returns false
|
|
92
|
+
* @example
|
|
93
|
+
* on: { CLICK: [{ when: not('isDisabled'), do: 'handleClick' }] }
|
|
94
|
+
* on: { SUBMIT: [{ when: not(ctx => ctx.loading), do: 'submit' }] }
|
|
95
|
+
*/
|
|
96
|
+
export declare function not<TContext = unknown, TPayload = undefined, TGuards extends string = string>(guard: GuardItem<TContext, TPayload, TGuards>): GuardComposer<TContext, TPayload, TGuards>;
|
|
97
|
+
/**
|
|
98
|
+
* Combine guards with AND logic - returns true only if ALL guards return true
|
|
99
|
+
* @example
|
|
100
|
+
* on: { SUBMIT: [{ when: and(['hasValue', 'isValid']), do: 'submit' }] }
|
|
101
|
+
* on: { DELETE: [{ when: and(['isSelected', ctx => ctx.canDelete]), do: 'delete' }] }
|
|
102
|
+
*/
|
|
103
|
+
export declare function and<TContext = unknown, TPayload = undefined, TGuards extends string = string>(guards: GuardItem<TContext, TPayload, TGuards>[]): GuardComposer<TContext, TPayload, TGuards>;
|
|
104
|
+
/**
|
|
105
|
+
* Combine guards with OR logic - returns true if ANY guard returns true
|
|
106
|
+
* @example
|
|
107
|
+
* on: { CLOSE: [{ when: or(['isEscapeKey', 'isClickOutside']), do: 'close' }] }
|
|
108
|
+
* on: { SUBMIT: [{ when: or([ctx => ctx.isAdmin, 'hasPermission']), do: 'submit' }] }
|
|
109
|
+
*/
|
|
110
|
+
export declare function or<TContext = unknown, TPayload = undefined, TGuards extends string = string>(guards: GuardItem<TContext, TPayload, TGuards>[]): GuardComposer<TContext, TPayload, TGuards>;
|
|
83
111
|
/** Event configuration - event name to payload type mapping */
|
|
84
112
|
export type EventsConfig = Record<string, unknown>;
|
|
85
113
|
/** Computed configuration - computed key to value type mapping */
|
|
@@ -216,7 +244,7 @@ export type MachineInstance<T extends MachineTypes> = Machine<T> & {
|
|
|
216
244
|
*/
|
|
217
245
|
export declare function executeRuleActions<TContext, TPayload, TInternal>(actionItems: ActionItem<TContext, TPayload, string, TInternal> | ActionItem<TContext, TPayload, string, TInternal>[], actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>, getContext: () => TContext, payload: TPayload, assign: AssignFn<TInternal>): void;
|
|
218
246
|
/**
|
|
219
|
-
* Evaluate guard items (named guards or
|
|
247
|
+
* Evaluate guard items (named guards, inline predicates, or composed guards)
|
|
220
248
|
* Uses AND logic - all guards must pass for result to be true
|
|
221
249
|
*/
|
|
222
250
|
export declare function evaluateGuards<TContext, TPayload>(guardItems: GuardItem<TContext, TPayload> | GuardItem<TContext, TPayload>[] | undefined, guards: Record<string, (context: TContext, payload?: TPayload) => boolean>, context: TContext, payload: TPayload): boolean;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
function effect(config) {
|
|
2
2
|
return config;
|
|
3
3
|
}
|
|
4
|
+
function not(guard) {
|
|
5
|
+
return { __type: "not", __guards: [guard] };
|
|
6
|
+
}
|
|
7
|
+
function and(guards) {
|
|
8
|
+
return { __type: "and", __guards: guards };
|
|
9
|
+
}
|
|
10
|
+
function or(guards) {
|
|
11
|
+
return { __type: "or", __guards: guards };
|
|
12
|
+
}
|
|
4
13
|
function toArray(value) {
|
|
5
14
|
return Array.isArray(value) ? value : [value];
|
|
6
15
|
}
|
|
@@ -14,11 +23,38 @@ function executeRuleActions(actionItems, actions, getContext, payload, assign) {
|
|
|
14
23
|
}
|
|
15
24
|
}
|
|
16
25
|
}
|
|
26
|
+
function isGuardComposer(item) {
|
|
27
|
+
return typeof item === "object" && item !== null && "__type" in item && "__guards" in item;
|
|
28
|
+
}
|
|
29
|
+
function evaluateSingleGuard(item, guards, context, payload) {
|
|
30
|
+
if (isGuardComposer(item)) {
|
|
31
|
+
switch (item.__type) {
|
|
32
|
+
case "not": {
|
|
33
|
+
const innerResult = evaluateSingleGuard(item.__guards[0], guards, context, payload);
|
|
34
|
+
return !innerResult;
|
|
35
|
+
}
|
|
36
|
+
case "and": {
|
|
37
|
+
return item.__guards.every(
|
|
38
|
+
(g) => evaluateSingleGuard(g, guards, context, payload)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
case "or": {
|
|
42
|
+
return item.__guards.some(
|
|
43
|
+
(g) => evaluateSingleGuard(g, guards, context, payload)
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (typeof item === "function") {
|
|
49
|
+
return item(context, payload);
|
|
50
|
+
}
|
|
51
|
+
const guardFn = guards[item];
|
|
52
|
+
return guardFn ? guardFn(context, payload) : true;
|
|
53
|
+
}
|
|
17
54
|
function evaluateGuards(guardItems, guards, context, payload) {
|
|
18
55
|
if (!guardItems) return true;
|
|
19
56
|
for (const item of toArray(guardItems)) {
|
|
20
|
-
|
|
21
|
-
if (guardFn && !guardFn(context, payload)) {
|
|
57
|
+
if (!evaluateSingleGuard(item, guards, context, payload)) {
|
|
22
58
|
return false;
|
|
23
59
|
}
|
|
24
60
|
}
|
|
@@ -223,6 +259,7 @@ function createMachine(config) {
|
|
|
223
259
|
return Object.assign(config, { send, evaluate, getSnapshot, getInternal, setInternal, getInitialInternal, cleanup });
|
|
224
260
|
}
|
|
225
261
|
export {
|
|
262
|
+
and,
|
|
226
263
|
buildContext,
|
|
227
264
|
buildSnapshot,
|
|
228
265
|
clearEffectStore,
|
|
@@ -235,6 +272,8 @@ export {
|
|
|
235
272
|
executeHandler,
|
|
236
273
|
executeRuleActions,
|
|
237
274
|
isRuleArray,
|
|
275
|
+
not,
|
|
276
|
+
or,
|
|
238
277
|
processEffects,
|
|
239
278
|
shallowEqual
|
|
240
279
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Controlled Machine\n *\n * A controlled state machine library where external state (input) is passed in\n * and internal state is managed by the machine itself.\n *\n * Key Concepts:\n * - input: External data passed in from outside (e.g., React state, props)\n * - internal: Machine-managed state that persists across events\n * - computed: Derived values calculated from input + internal\n * - context: Flattened input + internal + computed (available in all handlers)\n * - on: Event handlers with conditional rules and actions\n * - states: FSM-style state-based event handlers\n * - effects: Watch-based side effects with enter/exit/change callbacks\n * - always: Auto-evaluated rules that run on every context change\n * - actions: Named action functions (can be overridden in useMachine)\n * - guards: Named guard functions for conditional logic\n */\n\n// ============================================\n// Types - Core Building Blocks\n// ============================================\n\n/**\n * Assign function type - updates internal state with partial updates\n * Only allows modifying keys defined in Internal type\n */\nexport type AssignFn<TInternal> = (updates: Partial<TInternal>) => void\n\n/**\n * ActionItem - can be a named action string or inline function\n * Inline functions receive (context, payload, assign)\n */\nexport type ActionItem<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TInternal = unknown,\n> = TActions | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n\n/**\n * GuardItem - can be a named guard string or inline predicate function\n */\nexport type GuardItem<\n TContext,\n TPayload = undefined,\n TGuards extends string = string,\n> = TGuards | ((context: TContext, payload: TPayload) => boolean)\n\n/**\n * Rule - conditional action with optional guard(s)\n * @property when - Guard(s) that must pass (AND logic for arrays)\n * @property do - Action(s) to execute if guards pass\n */\nexport type Rule<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n when?: GuardItem<TContext, TPayload, TGuards> | GuardItem<TContext, TPayload, TGuards>[]\n do: ActionItem<TContext, TPayload, TActions, TInternal> | ActionItem<TContext, TPayload, TActions, TInternal>[]\n}\n\n/**\n * Handler - event handler definition\n * Can be: single action, action array, rule array, inline function, or function array\n *\n * @example\n * on: { CLICK: 'handleClick' } // single action\n * on: { SUBMIT: ['validate', 'save'] } // action array\n * on: { TOGGLE: [{ when: ctx => ctx.isOpen, do: 'close' }, { do: 'open' }] } // rule array\n * on: { INCREMENT: (ctx, _, assign) => assign({ count: ctx.count + 1 }) } // inline function\n * on: { SELECT: [(ctx, p) => ctx.onSelect(p), (_, __, a) => a({ isOpen: false })] } // function array\n */\nexport type Handler<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> =\n | TActions\n | TActions[]\n | Rule<TContext, TPayload, TActions, TGuards, TInternal>[]\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[]\n\n/**\n * EffectHelpers - utilities available in effect callbacks\n */\nexport type EffectHelpers<TEvents extends EventsConfig> = {\n send: Send<TEvents>\n}\n\n/** Cleanup function returned from effect callbacks */\nexport type Cleanup = () => void\n\n/**\n * Effect - watch-based side effect with lifecycle callbacks\n * @property watch - Function that returns the value to watch (uses shallow comparison)\n * @property enter - Called when watch value becomes truthy (can return cleanup)\n * @property exit - Called when watch value becomes falsy (can return cleanup)\n * @property change - Called on any value change with (prev, curr) (can return cleanup)\n */\nexport type Effect<\n TContext,\n TEvents extends EventsConfig,\n TWatched = unknown,\n> = {\n watch: (context: TContext) => TWatched\n enter?: (\n context: TContext,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup | Promise<void>\n exit?: (context: TContext, helpers: EffectHelpers<TEvents>) => void | Cleanup\n change?: (\n context: TContext,\n prev: TWatched | undefined,\n curr: TWatched,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup\n}\n\n/**\n * Helper function for creating effects with proper type inference\n * @example\n * effects: [\n * effect({ watch: ctx => ctx.isOpen, enter: () => console.log('opened') })\n * ]\n */\nexport function effect<TContext, TEvents extends EventsConfig, TWatched>(\n config: Effect<TContext, TEvents, TWatched>,\n): Effect<TContext, TEvents, TWatched> {\n return config\n}\n\n/** Event configuration - event name to payload type mapping */\nexport type EventsConfig = Record<string, unknown>\n/** Computed configuration - computed key to value type mapping */\nexport type ComputedConfig = Record<string, unknown>\n\n// ============================================\n// Object-based Generic Types\n// ============================================\n\n/**\n * MachineTypes - object-based generic type parameter\n * Specify only the types you need, in any order\n *\n * @example\n * createMachine<{\n * input: { count: number; setCount: (c: number) => void }\n * internal: { isOpen: boolean }\n * events: { INCREMENT: undefined; SET: { value: number } }\n * computed: { doubled: number }\n * actions: 'increment' | 'set'\n * guards: 'isPositive'\n * state: 'idle' | 'loading'\n * }>({...})\n */\nexport type MachineTypes = {\n input?: unknown // External state passed in (React state, props, etc.)\n internal?: unknown // Machine-managed state\n events?: EventsConfig // Event name → payload type\n computed?: ComputedConfig // Derived values from context\n actions?: string // Named action strings\n guards?: string // Named guard strings\n state?: string // FSM state values\n}\n\n// ============================================\n// Type Extraction Helpers\n// ============================================\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Input<T extends MachineTypes> = T['input'] extends object ? T['input'] : {}\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Internal<T extends MachineTypes> = T['internal'] extends object ? T['internal'] : {}\nexport type Events<T extends MachineTypes> = T['events'] extends EventsConfig\n ? T['events']\n : Record<string, undefined>\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Computed<T extends MachineTypes> = T['computed'] extends ComputedConfig\n ? T['computed']\n : {}\nexport type Actions<T extends MachineTypes> = T['actions'] extends string\n ? T['actions']\n : string\nexport type Guards<T extends MachineTypes> = T['guards'] extends string\n ? T['guards']\n : string\nexport type State<T extends MachineTypes> = T['state'] extends string\n ? T['state']\n : string\n\n// ============================================\n// Key Overlap Detection (Compile-time Safety)\n// ============================================\n\n/**\n * Check if type has only index signature (no specific keys)\n * `string extends keyof T` is true for Record<string, K> types\n */\ntype HasOnlyIndexSignature<T> = string extends keyof T ? true : false\n\n/**\n * Detects if two types have overlapping keys\n * Returns true if any key exists in both A and B\n *\n * Types with only index signatures (like Record<string, never>) are treated as empty,\n * since they don't have specific keys that could overlap.\n */\ntype HasOverlappingKeys<A, B> =\n HasOnlyIndexSignature<A> extends true ? false :\n HasOnlyIndexSignature<B> extends true ? false :\n keyof A & keyof B extends never ? false : true\n\n/**\n * Check all combinations of key overlaps between Input, Internal, Computed\n * Uses conditional chain (not union) to ensure proper boolean result\n */\ntype HasAnyKeyOverlap<T extends MachineTypes> =\n HasOverlappingKeys<Input<T>, Internal<T>> extends true ? true :\n HasOverlappingKeys<Input<T>, Computed<T>> extends true ? true :\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true ? true :\n false\n\n/**\n * Context = Input + Internal + Computed (flat structure)\n * All properties are accessible at the same level in handlers\n *\n * If any pair has overlapping keys, Context becomes `never` (compile-time error)\n */\nexport type Context<T extends MachineTypes> =\n HasAnyKeyOverlap<T> extends true\n ? never\n : Input<T> & Internal<T> & Computed<T>\n\n// ============================================\n// State-based Handler Configuration (FSM)\n// ============================================\n\n/** Configuration for handlers within a specific state */\nexport type StateConfig<\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n on?: { [K in keyof TEvents]?: Handler<TContext, TEvents[K], TActions, TGuards, TInternal> }\n}\n\n/** Map of state names to their configurations */\nexport type StatesConfig<\n TState extends string,\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n [K in TState]?: StateConfig<TContext, TEvents, TActions, TGuards, TInternal>\n}\n\n/** Base context (input + internal) before computed values are added */\nexport type BaseContext<T extends MachineTypes> = Input<T> & Internal<T>\n\n// ============================================\n// Machine Configuration Type\n// ============================================\n\n/**\n * Machine - the configuration object for createMachine\n */\nexport type Machine<T extends MachineTypes> = {\n internal?: Internal<T> // Initial internal state values\n computed?: { // Computed value definitions\n [K in keyof Computed<T>]: (ctx: BaseContext<T>) => Computed<T>[K]\n }\n on?: { // Global event handlers\n [K in keyof Events<T>]?: Handler<Context<T>, Events<T>[K], Actions<T>, Guards<T>, Internal<T>>\n }\n states?: StatesConfig<State<T>, Context<T>, Events<T>, Actions<T>, Guards<T>, Internal<T>> // FSM state handlers\n always?: Rule<Context<T>, undefined, Actions<T>, Guards<T>, Internal<T>>[] // Auto-evaluated rules\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects?: Effect<Context<T>, Events<T>, any>[] // Watch-based side effects\n actions?: { // Named action implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Actions<T>]: (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void\n }\n guards?: { // Named guard implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Guards<T>]: (ctx: Context<T>, payload?: any) => boolean\n }\n}\n\n/**\n * Send - function type for dispatching events\n * Events with undefined payload can be called without arguments\n */\nexport type Send<TEvents extends EventsConfig> = <K extends keyof TEvents>(\n event: K,\n ...args: TEvents[K] extends undefined ? [] : [payload: TEvents[K]]\n) => void\n\n// ============================================\n// Snapshot Type (Return value from getSnapshot/useMachine)\n// ============================================\n\n/**\n * Snapshot = Internal + Computed + { state } (without Input)\n * This is the value returned from getSnapshot() and useMachine()\n *\n * If Internal/Computed have overlapping keys, Snapshot becomes `never`\n * If 'state' type param is defined and Internal/Computed already has 'state' key,\n * we don't add { state } again (existing state is already included)\n */\nexport type Snapshot<T extends MachineTypes> =\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true\n ? never\n : Internal<T> & Computed<T> & (\n T['state'] extends string\n ? 'state' extends keyof Internal<T> | keyof Computed<T>\n ? object // already has 'state', don't add duplicate\n : { state: State<T> }\n : object\n )\n\n// ============================================\n// MachineInstance Type (createMachine return value)\n// ============================================\n\n/**\n * MachineInstance - the return type of createMachine\n * Includes all configuration plus runtime methods\n */\nexport type MachineInstance<T extends MachineTypes> = Machine<T> & {\n /** Dispatch an event with input and optional payload */\n send: <K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => void\n /** Evaluate always rules and effects (called automatically in React) */\n evaluate: (input: Input<T>) => void\n /** Get current snapshot (internal + computed + state) */\n getSnapshot: (input: Input<T>) => Snapshot<T>\n /** Get current internal state */\n getInternal: () => Internal<T>\n /** Set internal state directly */\n setInternal: (internal: Internal<T>) => void\n /** Get initial internal state (for reset) */\n getInitialInternal: () => Internal<T>\n /** Clean up all effect callbacks */\n cleanup: () => void\n}\n\n// ============================================\n// Core Logic - Pure Functions\n// ============================================\n\n/** Normalize a value to an array (single value becomes [value]) */\nfunction toArray<T>(value: T | T[]): T[] {\n return Array.isArray(value) ? value : [value]\n}\n\n/**\n * Execute action items (named actions or inline functions)\n * Handles both single actions and arrays of actions\n * Each action receives fresh context (rebuilt after previous assigns)\n */\nexport function executeRuleActions<TContext, TPayload, TInternal>(\n actionItems: ActionItem<TContext, TPayload, string, TInternal> | ActionItem<TContext, TPayload, string, TInternal>[],\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n for (const item of toArray(actionItems)) {\n const context = getContext() // Fresh context for each action\n if (typeof item === 'function') {\n item(context, payload, assign)\n } else {\n actions[item]?.(context, payload, assign)\n }\n }\n}\n\n/**\n * Evaluate guard items (named guards or inline predicates)\n * Uses AND logic - all guards must pass for result to be true\n */\nexport function evaluateGuards<TContext, TPayload>(\n guardItems: GuardItem<TContext, TPayload> | GuardItem<TContext, TPayload>[] | undefined,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n context: TContext,\n payload: TPayload,\n): boolean {\n if (!guardItems) return true\n\n for (const item of toArray(guardItems)) {\n const guardFn = typeof item === 'function' ? item : guards[item]\n if (guardFn && !guardFn(context, payload)) {\n return false\n }\n }\n\n return true\n}\n\n/** Type guard to check if handler is a Rule array (has 'do' property) */\nexport function isRuleArray<TContext, TPayload, TActions extends string>(\n handler: Handler<TContext, TPayload, TActions>,\n): handler is Rule<TContext, TPayload, TActions>[] {\n return (\n Array.isArray(handler) &&\n handler.length > 0 &&\n typeof handler[0] === 'object' &&\n 'do' in handler[0]\n )\n}\n\n/** Check if handler is a function array */\nfunction isFunctionArray<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n): handler is ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[] {\n return Array.isArray(handler) && handler.length > 0 && typeof handler[0] === 'function'\n}\n\n/**\n * Execute a handler (action string, action array, rule array, inline function, or function array)\n * For rule arrays, only the first matching rule executes (short-circuit)\n * Each action/function receives fresh context (rebuilt after previous assigns)\n */\nexport function executeHandler<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n // Inline function handler\n if (typeof handler === 'function') {\n handler(getContext(), payload, assign)\n return\n }\n\n // Function array - execute all functions in order with fresh context\n if (isFunctionArray(handler)) {\n for (const fn of handler) {\n fn(getContext(), payload, assign)\n }\n return\n }\n\n // Single action or action array (strings)\n if (typeof handler === 'string' || (Array.isArray(handler) && !isRuleArray(handler))) {\n executeRuleActions(handler as string | string[], actions, getContext, payload, assign)\n return\n }\n\n // Rule array - first matching rule wins (guard uses fresh context)\n for (const rule of handler as Rule<TContext, TPayload, string, string, TInternal>[]) {\n if (evaluateGuards(rule.when, guards, getContext(), payload)) {\n executeRuleActions(rule.do, actions, getContext, payload, assign)\n break\n }\n }\n}\n\n/**\n * Compute derived values from base context\n * Each computed function receives the base context (input + internal)\n */\nexport function computeValues<TBase, TComputed extends ComputedConfig>(\n base: TBase,\n computed?: { [K in keyof TComputed]: (ctx: TBase) => TComputed[K] },\n): TBase & TComputed {\n if (!computed) return base as TBase & TComputed\n\n const values = {} as TComputed\n for (const key in computed) {\n values[key] = computed[key](base)\n }\n return { ...base, ...values }\n}\n\n/**\n * Build flat context from input + internal\n * Input takes priority if keys overlap (runtime)\n */\nexport function buildContext<TInput, TInternal>(\n input: TInput,\n internal: TInternal,\n): TInput & TInternal {\n return { ...internal, ...input } as TInput & TInternal\n}\n\n/**\n * Create assign function for updating internal state\n */\nexport function createAssign<TInternal>(\n getInternal: () => TInternal,\n setInternal: (internal: TInternal) => void,\n): AssignFn<TInternal> {\n return (updates: Partial<TInternal>) => {\n setInternal({ ...getInternal(), ...updates })\n }\n}\n\n/**\n * Build snapshot from internal state, context, and computed definitions\n * Snapshot = Internal + Computed + state (without Input)\n */\nexport function buildSnapshot<T extends MachineTypes>(\n internal: Internal<T>,\n context: Context<T>,\n computedDef: Machine<T>['computed'],\n): Snapshot<T> {\n const snapshot = { ...internal } as Snapshot<T>\n // Add computed values\n if (computedDef) {\n for (const key in computedDef) {\n (snapshot as Record<string, unknown>)[key] = context[key as keyof Context<T>]\n }\n }\n // Add state if exists in context\n const state = (context as { state?: State<T> }).state\n if (state !== undefined) {\n (snapshot as Record<string, unknown>).state = state\n }\n return snapshot\n}\n\n// ============================================\n// Effects Processing\n// ============================================\n\n/**\n * Shallow comparison for effect watch values\n * Arrays: compares length and each element with ===\n * Others: strict equality (===)\n */\nexport function shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n\n // Array comparison\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => v === b[i])\n }\n\n return false\n}\n\n/**\n * EffectStore - tracks watched values and cleanup functions for effects\n * Used by both vanilla and React implementations\n */\nexport type EffectStore = {\n watchedValues: Map<number, unknown> // Previous values by effect index\n enterCleanups: Map<number, () => void> // Cleanup from enter callbacks\n changeCleanups: Map<number, () => void> // Cleanup from change callbacks\n exitCleanups: Map<number, () => void> // Cleanup from exit callbacks\n}\n\n/** Create a new effect store */\nexport function createEffectStore(): EffectStore {\n return {\n watchedValues: new Map(),\n enterCleanups: new Map(),\n changeCleanups: new Map(),\n exitCleanups: new Map(),\n }\n}\n\n/**\n * Process all effects - detect watch value changes and call appropriate callbacks\n * Called on every context change in both vanilla (evaluate) and React (useEffect)\n */\nexport function processEffects<TContext, TEvents extends EventsConfig>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects: Effect<TContext, TEvents, any>[] | undefined,\n context: TContext,\n effectHelpers: EffectHelpers<TEvents>,\n store: EffectStore,\n): void {\n if (!effects) return\n\n effects.forEach((effect, i) => {\n const prev = store.watchedValues.get(i)\n const curr = effect.watch(context)\n\n // Only process if value changed (shallow comparison)\n if (!shallowEqual(prev, curr)) {\n // 1. Cleanup previous enter callback\n const enterCleanup = store.enterCleanups.get(i)\n if (enterCleanup) {\n enterCleanup()\n store.enterCleanups.delete(i)\n }\n\n // 2. Cleanup previous change callback\n const changeCleanup = store.changeCleanups.get(i)\n if (changeCleanup) {\n changeCleanup()\n store.changeCleanups.delete(i)\n }\n\n // 3. Call change callback (fires on any value change)\n const changeResult = effect.change?.(context, prev, curr, effectHelpers)\n if (typeof changeResult === 'function') {\n store.changeCleanups.set(i, changeResult)\n }\n\n // 4. Call enter callback (falsy → truthy transition)\n if (!prev && curr) {\n // Cleanup previous exit first\n const exitCleanup = store.exitCleanups.get(i)\n if (exitCleanup) {\n exitCleanup()\n store.exitCleanups.delete(i)\n }\n\n const enterResult = effect.enter?.(context, effectHelpers)\n if (typeof enterResult === 'function') {\n store.enterCleanups.set(i, enterResult)\n }\n }\n\n // 5. Call exit callback (truthy → falsy transition)\n if (prev && !curr) {\n const exitResult = effect.exit?.(context, effectHelpers)\n if (typeof exitResult === 'function') {\n store.exitCleanups.set(i, exitResult)\n }\n }\n\n // Update stored value for next comparison\n store.watchedValues.set(i, curr)\n }\n })\n}\n\n/** Clear all effect cleanups (called on unmount or cleanup) */\nexport function clearEffectStore(store: EffectStore): void {\n store.enterCleanups.forEach((fn) => fn())\n store.enterCleanups.clear()\n store.changeCleanups.forEach((fn) => fn())\n store.changeCleanups.clear()\n store.exitCleanups.forEach((fn) => fn())\n store.exitCleanups.clear()\n store.watchedValues.clear()\n}\n\n// ============================================\n// createMachine - Vanilla Implementation\n// ============================================\n\n/**\n * Create a controlled state machine instance\n *\n * The machine manages internal state and provides methods for:\n * - send: Dispatch events with input and payload\n * - evaluate: Run always rules and effects\n * - getSnapshot: Get current state (internal + computed + state)\n *\n * @example\n * const machine = createMachine<{\n * input: { count: number }\n * internal: { isOpen: boolean }\n * events: { TOGGLE: undefined }\n * computed: { doubled: number }\n * }>({\n * internal: { isOpen: false },\n * computed: { doubled: ctx => ctx.count * 2 },\n * on: { TOGGLE: (ctx, _, assign) => assign({ isOpen: !ctx.isOpen }) }\n * })\n */\nexport function createMachine<T extends MachineTypes>(\n config: Machine<T>,\n): MachineInstance<T> {\n const effectStore = createEffectStore()\n const initialInternal = (config.internal ?? {}) as Internal<T>\n\n // Machine-managed internal state\n let currentInternal = { ...initialInternal }\n\n // Update internal state\n const updateInternal = (newInternal: Internal<T>) => {\n currentInternal = newInternal\n }\n\n // Build full context: input + internal + computed\n const buildFullContext = (input: Input<T>): Context<T> => {\n const base = buildContext(input, currentInternal)\n return computeValues(base, config.computed) as Context<T>\n }\n\n /**\n * Send an event to the machine\n * Executes state-specific handlers first, then global handlers\n */\n const send = (<K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const payload = args[0] as Events<T>[K]\n\n // getContext rebuilds context with latest internal state\n const getContext = () => buildFullContext(input)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>, payload?: unknown) => boolean>\n\n // 1. Execute state-specific handler (if in FSM mode)\n const context = getContext()\n const state = (context as { state?: State<T> }).state\n if (state && config.states?.[state]?.on?.[event]) {\n const stateHandler = config.states[state].on![event]!\n executeHandler(\n stateHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n\n // 2. Execute global handler\n const globalHandler = config.on?.[event]\n if (globalHandler) {\n executeHandler(\n globalHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n }) as MachineInstance<T>['send']\n\n // Create effect helpers with bound send\n const createEffectHelpers = (input: Input<T>): EffectHelpers<Events<T>> => ({\n send: (<K extends keyof Events<T>>(\n event: K,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n send(event, input, ...args)\n }) as Send<Events<T>>,\n })\n\n /**\n * Evaluate the machine - runs always rules and processes effects\n * Should be called when input changes (automatic in React via useMachine)\n */\n const evaluate = (input: Input<T>) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const effectHelpers = createEffectHelpers(input)\n const getContext = () => buildFullContext(input)\n\n // Process always rules (first matching rule wins)\n if (config.always) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>) => boolean>\n for (const rule of config.always) {\n if (evaluateGuards(rule.when, guardsMap, getContext(), undefined)) {\n executeRuleActions(rule.do, actionsMap, getContext, undefined, assign)\n break\n }\n }\n }\n\n // Process effects (uses current context)\n processEffects(config.effects, getContext(), effectHelpers, effectStore)\n }\n\n /** Get current snapshot (internal + computed + state) */\n const getSnapshot = (input: Input<T>): Snapshot<T> => {\n const context = buildFullContext(input)\n return buildSnapshot(currentInternal, context, config.computed)\n }\n\n // Internal state accessors\n const getInternal = (): Internal<T> => currentInternal\n const setInternal = (internal: Internal<T>) => { currentInternal = internal }\n const getInitialInternal = (): Internal<T> => initialInternal\n\n /** Clean up all effect callbacks */\n const cleanup = () => clearEffectStore(effectStore)\n\n return Object.assign(config, { send, evaluate, getSnapshot, getInternal, setInternal, getInitialInternal, cleanup })\n}\n"],"names":["effect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Controlled Machine\n *\n * A controlled state machine library where external state (input) is passed in\n * and internal state is managed by the machine itself.\n *\n * Key Concepts:\n * - input: External data passed in from outside (e.g., React state, props)\n * - internal: Machine-managed state that persists across events\n * - computed: Derived values calculated from input + internal\n * - context: Flattened input + internal + computed (available in all handlers)\n * - on: Event handlers with conditional rules and actions\n * - states: FSM-style state-based event handlers\n * - effects: Watch-based side effects with enter/exit/change callbacks\n * - always: Auto-evaluated rules that run on every context change\n * - actions: Named action functions (can be overridden in useMachine)\n * - guards: Named guard functions for conditional logic\n */\n\n// ============================================\n// Types - Core Building Blocks\n// ============================================\n\n/**\n * Assign function type - updates internal state with partial updates\n * Only allows modifying keys defined in Internal type\n */\nexport type AssignFn<TInternal> = (updates: Partial<TInternal>) => void\n\n/**\n * ActionItem - can be a named action string or inline function\n * Inline functions receive (context, payload, assign)\n */\nexport type ActionItem<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TInternal = unknown,\n> = TActions | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n\n/**\n * GuardComposer - composed guard using not/and/or utilities\n */\nexport type GuardComposer<\n TContext,\n TPayload = undefined,\n TGuards extends string = string,\n> = {\n __type: 'not' | 'and' | 'or'\n __guards: GuardItem<TContext, TPayload, TGuards>[]\n}\n\n/**\n * GuardItem - can be a named guard string, inline predicate function, or composed guard\n */\nexport type GuardItem<\n TContext,\n TPayload = undefined,\n TGuards extends string = string,\n> =\n | TGuards\n | ((context: TContext, payload: TPayload) => boolean)\n | GuardComposer<TContext, TPayload, TGuards>\n\n/**\n * Rule - conditional action with optional guard(s)\n * @property when - Guard(s) that must pass (AND logic for arrays)\n * @property do - Action(s) to execute if guards pass\n */\nexport type Rule<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n when?: GuardItem<TContext, TPayload, TGuards> | GuardItem<TContext, TPayload, TGuards>[]\n do: ActionItem<TContext, TPayload, TActions, TInternal> | ActionItem<TContext, TPayload, TActions, TInternal>[]\n}\n\n/**\n * Handler - event handler definition\n * Can be: single action, action array, rule array, inline function, or function array\n *\n * @example\n * on: { CLICK: 'handleClick' } // single action\n * on: { SUBMIT: ['validate', 'save'] } // action array\n * on: { TOGGLE: [{ when: ctx => ctx.isOpen, do: 'close' }, { do: 'open' }] } // rule array\n * on: { INCREMENT: (ctx, _, assign) => assign({ count: ctx.count + 1 }) } // inline function\n * on: { SELECT: [(ctx, p) => ctx.onSelect(p), (_, __, a) => a({ isOpen: false })] } // function array\n */\nexport type Handler<\n TContext,\n TPayload = undefined,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> =\n | TActions\n | TActions[]\n | Rule<TContext, TPayload, TActions, TGuards, TInternal>[]\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)\n | ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[]\n\n/**\n * EffectHelpers - utilities available in effect callbacks\n */\nexport type EffectHelpers<TEvents extends EventsConfig> = {\n send: Send<TEvents>\n}\n\n/** Cleanup function returned from effect callbacks */\nexport type Cleanup = () => void\n\n/**\n * Effect - watch-based side effect with lifecycle callbacks\n * @property watch - Function that returns the value to watch (uses shallow comparison)\n * @property enter - Called when watch value becomes truthy (can return cleanup)\n * @property exit - Called when watch value becomes falsy (can return cleanup)\n * @property change - Called on any value change with (prev, curr) (can return cleanup)\n */\nexport type Effect<\n TContext,\n TEvents extends EventsConfig,\n TWatched = unknown,\n> = {\n watch: (context: TContext) => TWatched\n enter?: (\n context: TContext,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup | Promise<void>\n exit?: (context: TContext, helpers: EffectHelpers<TEvents>) => void | Cleanup\n change?: (\n context: TContext,\n prev: TWatched | undefined,\n curr: TWatched,\n helpers: EffectHelpers<TEvents>,\n ) => void | Cleanup\n}\n\n/**\n * Helper function for creating effects with proper type inference\n * @example\n * effects: [\n * effect({ watch: ctx => ctx.isOpen, enter: () => console.log('opened') })\n * ]\n */\nexport function effect<TContext, TEvents extends EventsConfig, TWatched>(\n config: Effect<TContext, TEvents, TWatched>,\n): Effect<TContext, TEvents, TWatched> {\n return config\n}\n\n// ============================================\n// Guard Utilities - not, and, or\n// ============================================\n\n/**\n * Negate a guard - returns true when the guard returns false\n * @example\n * on: { CLICK: [{ when: not('isDisabled'), do: 'handleClick' }] }\n * on: { SUBMIT: [{ when: not(ctx => ctx.loading), do: 'submit' }] }\n */\nexport function not<\n TContext = unknown,\n TPayload = undefined,\n TGuards extends string = string,\n>(\n guard: GuardItem<TContext, TPayload, TGuards>,\n): GuardComposer<TContext, TPayload, TGuards> {\n return { __type: 'not', __guards: [guard] }\n}\n\n/**\n * Combine guards with AND logic - returns true only if ALL guards return true\n * @example\n * on: { SUBMIT: [{ when: and(['hasValue', 'isValid']), do: 'submit' }] }\n * on: { DELETE: [{ when: and(['isSelected', ctx => ctx.canDelete]), do: 'delete' }] }\n */\nexport function and<\n TContext = unknown,\n TPayload = undefined,\n TGuards extends string = string,\n>(\n guards: GuardItem<TContext, TPayload, TGuards>[],\n): GuardComposer<TContext, TPayload, TGuards> {\n return { __type: 'and', __guards: guards }\n}\n\n/**\n * Combine guards with OR logic - returns true if ANY guard returns true\n * @example\n * on: { CLOSE: [{ when: or(['isEscapeKey', 'isClickOutside']), do: 'close' }] }\n * on: { SUBMIT: [{ when: or([ctx => ctx.isAdmin, 'hasPermission']), do: 'submit' }] }\n */\nexport function or<\n TContext = unknown,\n TPayload = undefined,\n TGuards extends string = string,\n>(\n guards: GuardItem<TContext, TPayload, TGuards>[],\n): GuardComposer<TContext, TPayload, TGuards> {\n return { __type: 'or', __guards: guards }\n}\n\n/** Event configuration - event name to payload type mapping */\nexport type EventsConfig = Record<string, unknown>\n/** Computed configuration - computed key to value type mapping */\nexport type ComputedConfig = Record<string, unknown>\n\n// ============================================\n// Object-based Generic Types\n// ============================================\n\n/**\n * MachineTypes - object-based generic type parameter\n * Specify only the types you need, in any order\n *\n * @example\n * createMachine<{\n * input: { count: number; setCount: (c: number) => void }\n * internal: { isOpen: boolean }\n * events: { INCREMENT: undefined; SET: { value: number } }\n * computed: { doubled: number }\n * actions: 'increment' | 'set'\n * guards: 'isPositive'\n * state: 'idle' | 'loading'\n * }>({...})\n */\nexport type MachineTypes = {\n input?: unknown // External state passed in (React state, props, etc.)\n internal?: unknown // Machine-managed state\n events?: EventsConfig // Event name → payload type\n computed?: ComputedConfig // Derived values from context\n actions?: string // Named action strings\n guards?: string // Named guard strings\n state?: string // FSM state values\n}\n\n// ============================================\n// Type Extraction Helpers\n// ============================================\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Input<T extends MachineTypes> = T['input'] extends object ? T['input'] : {}\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Internal<T extends MachineTypes> = T['internal'] extends object ? T['internal'] : {}\nexport type Events<T extends MachineTypes> = T['events'] extends EventsConfig\n ? T['events']\n : Record<string, undefined>\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Computed<T extends MachineTypes> = T['computed'] extends ComputedConfig\n ? T['computed']\n : {}\nexport type Actions<T extends MachineTypes> = T['actions'] extends string\n ? T['actions']\n : string\nexport type Guards<T extends MachineTypes> = T['guards'] extends string\n ? T['guards']\n : string\nexport type State<T extends MachineTypes> = T['state'] extends string\n ? T['state']\n : string\n\n// ============================================\n// Key Overlap Detection (Compile-time Safety)\n// ============================================\n\n/**\n * Check if type has only index signature (no specific keys)\n * `string extends keyof T` is true for Record<string, K> types\n */\ntype HasOnlyIndexSignature<T> = string extends keyof T ? true : false\n\n/**\n * Detects if two types have overlapping keys\n * Returns true if any key exists in both A and B\n *\n * Types with only index signatures (like Record<string, never>) are treated as empty,\n * since they don't have specific keys that could overlap.\n */\ntype HasOverlappingKeys<A, B> =\n HasOnlyIndexSignature<A> extends true ? false :\n HasOnlyIndexSignature<B> extends true ? false :\n keyof A & keyof B extends never ? false : true\n\n/**\n * Check all combinations of key overlaps between Input, Internal, Computed\n * Uses conditional chain (not union) to ensure proper boolean result\n */\ntype HasAnyKeyOverlap<T extends MachineTypes> =\n HasOverlappingKeys<Input<T>, Internal<T>> extends true ? true :\n HasOverlappingKeys<Input<T>, Computed<T>> extends true ? true :\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true ? true :\n false\n\n/**\n * Context = Input + Internal + Computed (flat structure)\n * All properties are accessible at the same level in handlers\n *\n * If any pair has overlapping keys, Context becomes `never` (compile-time error)\n */\nexport type Context<T extends MachineTypes> =\n HasAnyKeyOverlap<T> extends true\n ? never\n : Input<T> & Internal<T> & Computed<T>\n\n// ============================================\n// State-based Handler Configuration (FSM)\n// ============================================\n\n/** Configuration for handlers within a specific state */\nexport type StateConfig<\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n on?: { [K in keyof TEvents]?: Handler<TContext, TEvents[K], TActions, TGuards, TInternal> }\n}\n\n/** Map of state names to their configurations */\nexport type StatesConfig<\n TState extends string,\n TContext,\n TEvents extends EventsConfig,\n TActions extends string = string,\n TGuards extends string = string,\n TInternal = unknown,\n> = {\n [K in TState]?: StateConfig<TContext, TEvents, TActions, TGuards, TInternal>\n}\n\n/** Base context (input + internal) before computed values are added */\nexport type BaseContext<T extends MachineTypes> = Input<T> & Internal<T>\n\n// ============================================\n// Machine Configuration Type\n// ============================================\n\n/**\n * Machine - the configuration object for createMachine\n */\nexport type Machine<T extends MachineTypes> = {\n internal?: Internal<T> // Initial internal state values\n computed?: { // Computed value definitions\n [K in keyof Computed<T>]: (ctx: BaseContext<T>) => Computed<T>[K]\n }\n on?: { // Global event handlers\n [K in keyof Events<T>]?: Handler<Context<T>, Events<T>[K], Actions<T>, Guards<T>, Internal<T>>\n }\n states?: StatesConfig<State<T>, Context<T>, Events<T>, Actions<T>, Guards<T>, Internal<T>> // FSM state handlers\n always?: Rule<Context<T>, undefined, Actions<T>, Guards<T>, Internal<T>>[] // Auto-evaluated rules\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects?: Effect<Context<T>, Events<T>, any>[] // Watch-based side effects\n actions?: { // Named action implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Actions<T>]: (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void\n }\n guards?: { // Named guard implementations\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in Guards<T>]: (ctx: Context<T>, payload?: any) => boolean\n }\n}\n\n/**\n * Send - function type for dispatching events\n * Events with undefined payload can be called without arguments\n */\nexport type Send<TEvents extends EventsConfig> = <K extends keyof TEvents>(\n event: K,\n ...args: TEvents[K] extends undefined ? [] : [payload: TEvents[K]]\n) => void\n\n// ============================================\n// Snapshot Type (Return value from getSnapshot/useMachine)\n// ============================================\n\n/**\n * Snapshot = Internal + Computed + { state } (without Input)\n * This is the value returned from getSnapshot() and useMachine()\n *\n * If Internal/Computed have overlapping keys, Snapshot becomes `never`\n * If 'state' type param is defined and Internal/Computed already has 'state' key,\n * we don't add { state } again (existing state is already included)\n */\nexport type Snapshot<T extends MachineTypes> =\n HasOverlappingKeys<Internal<T>, Computed<T>> extends true\n ? never\n : Internal<T> & Computed<T> & (\n T['state'] extends string\n ? 'state' extends keyof Internal<T> | keyof Computed<T>\n ? object // already has 'state', don't add duplicate\n : { state: State<T> }\n : object\n )\n\n// ============================================\n// MachineInstance Type (createMachine return value)\n// ============================================\n\n/**\n * MachineInstance - the return type of createMachine\n * Includes all configuration plus runtime methods\n */\nexport type MachineInstance<T extends MachineTypes> = Machine<T> & {\n /** Dispatch an event with input and optional payload */\n send: <K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => void\n /** Evaluate always rules and effects (called automatically in React) */\n evaluate: (input: Input<T>) => void\n /** Get current snapshot (internal + computed + state) */\n getSnapshot: (input: Input<T>) => Snapshot<T>\n /** Get current internal state */\n getInternal: () => Internal<T>\n /** Set internal state directly */\n setInternal: (internal: Internal<T>) => void\n /** Get initial internal state (for reset) */\n getInitialInternal: () => Internal<T>\n /** Clean up all effect callbacks */\n cleanup: () => void\n}\n\n// ============================================\n// Core Logic - Pure Functions\n// ============================================\n\n/** Normalize a value to an array (single value becomes [value]) */\nfunction toArray<T>(value: T | T[]): T[] {\n return Array.isArray(value) ? value : [value]\n}\n\n/**\n * Execute action items (named actions or inline functions)\n * Handles both single actions and arrays of actions\n * Each action receives fresh context (rebuilt after previous assigns)\n */\nexport function executeRuleActions<TContext, TPayload, TInternal>(\n actionItems: ActionItem<TContext, TPayload, string, TInternal> | ActionItem<TContext, TPayload, string, TInternal>[],\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n for (const item of toArray(actionItems)) {\n const context = getContext() // Fresh context for each action\n if (typeof item === 'function') {\n item(context, payload, assign)\n } else {\n actions[item]?.(context, payload, assign)\n }\n }\n}\n\n/**\n * Check if a value is a GuardComposer (composed guard)\n */\nfunction isGuardComposer<TContext, TPayload, TGuards extends string>(\n item: GuardItem<TContext, TPayload, TGuards>,\n): item is GuardComposer<TContext, TPayload, TGuards> {\n return (\n typeof item === 'object' &&\n item !== null &&\n '__type' in item &&\n '__guards' in item\n )\n}\n\n/**\n * Evaluate a single guard item (named guard, inline function, or composed guard)\n */\nfunction evaluateSingleGuard<TContext, TPayload>(\n item: GuardItem<TContext, TPayload>,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n context: TContext,\n payload: TPayload,\n): boolean {\n // Composed guard (not/and/or)\n if (isGuardComposer(item)) {\n switch (item.__type) {\n case 'not': {\n // not() takes a single guard, negate its result\n const innerResult = evaluateSingleGuard(item.__guards[0], guards, context, payload)\n return !innerResult\n }\n case 'and': {\n // and() - all guards must return true\n return item.__guards.every((g) =>\n evaluateSingleGuard(g, guards, context, payload),\n )\n }\n case 'or': {\n // or() - at least one guard must return true\n return item.__guards.some((g) =>\n evaluateSingleGuard(g, guards, context, payload),\n )\n }\n }\n }\n\n // Inline function guard\n if (typeof item === 'function') {\n return item(context, payload)\n }\n\n // Named guard (string)\n const guardFn = guards[item as string]\n return guardFn ? guardFn(context, payload) : true\n}\n\n/**\n * Evaluate guard items (named guards, inline predicates, or composed guards)\n * Uses AND logic - all guards must pass for result to be true\n */\nexport function evaluateGuards<TContext, TPayload>(\n guardItems: GuardItem<TContext, TPayload> | GuardItem<TContext, TPayload>[] | undefined,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n context: TContext,\n payload: TPayload,\n): boolean {\n if (!guardItems) return true\n\n for (const item of toArray(guardItems)) {\n if (!evaluateSingleGuard(item, guards, context, payload)) {\n return false\n }\n }\n\n return true\n}\n\n/** Type guard to check if handler is a Rule array (has 'do' property) */\nexport function isRuleArray<TContext, TPayload, TActions extends string>(\n handler: Handler<TContext, TPayload, TActions>,\n): handler is Rule<TContext, TPayload, TActions>[] {\n return (\n Array.isArray(handler) &&\n handler.length > 0 &&\n typeof handler[0] === 'object' &&\n 'do' in handler[0]\n )\n}\n\n/** Check if handler is a function array */\nfunction isFunctionArray<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n): handler is ((context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void)[] {\n return Array.isArray(handler) && handler.length > 0 && typeof handler[0] === 'function'\n}\n\n/**\n * Execute a handler (action string, action array, rule array, inline function, or function array)\n * For rule arrays, only the first matching rule executes (short-circuit)\n * Each action/function receives fresh context (rebuilt after previous assigns)\n */\nexport function executeHandler<TContext, TPayload, TInternal>(\n handler: Handler<TContext, TPayload, string, string, TInternal>,\n actions: Record<string, (context: TContext, payload: TPayload, assign: AssignFn<TInternal>) => void>,\n guards: Record<string, (context: TContext, payload?: TPayload) => boolean>,\n getContext: () => TContext,\n payload: TPayload,\n assign: AssignFn<TInternal>,\n): void {\n // Inline function handler\n if (typeof handler === 'function') {\n handler(getContext(), payload, assign)\n return\n }\n\n // Function array - execute all functions in order with fresh context\n if (isFunctionArray(handler)) {\n for (const fn of handler) {\n fn(getContext(), payload, assign)\n }\n return\n }\n\n // Single action or action array (strings)\n if (typeof handler === 'string' || (Array.isArray(handler) && !isRuleArray(handler))) {\n executeRuleActions(handler as string | string[], actions, getContext, payload, assign)\n return\n }\n\n // Rule array - first matching rule wins (guard uses fresh context)\n for (const rule of handler as Rule<TContext, TPayload, string, string, TInternal>[]) {\n if (evaluateGuards(rule.when, guards, getContext(), payload)) {\n executeRuleActions(rule.do, actions, getContext, payload, assign)\n break\n }\n }\n}\n\n/**\n * Compute derived values from base context\n * Each computed function receives the base context (input + internal)\n */\nexport function computeValues<TBase, TComputed extends ComputedConfig>(\n base: TBase,\n computed?: { [K in keyof TComputed]: (ctx: TBase) => TComputed[K] },\n): TBase & TComputed {\n if (!computed) return base as TBase & TComputed\n\n const values = {} as TComputed\n for (const key in computed) {\n values[key] = computed[key](base)\n }\n return { ...base, ...values }\n}\n\n/**\n * Build flat context from input + internal\n * Input takes priority if keys overlap (runtime)\n */\nexport function buildContext<TInput, TInternal>(\n input: TInput,\n internal: TInternal,\n): TInput & TInternal {\n return { ...internal, ...input } as TInput & TInternal\n}\n\n/**\n * Create assign function for updating internal state\n */\nexport function createAssign<TInternal>(\n getInternal: () => TInternal,\n setInternal: (internal: TInternal) => void,\n): AssignFn<TInternal> {\n return (updates: Partial<TInternal>) => {\n setInternal({ ...getInternal(), ...updates })\n }\n}\n\n/**\n * Build snapshot from internal state, context, and computed definitions\n * Snapshot = Internal + Computed + state (without Input)\n */\nexport function buildSnapshot<T extends MachineTypes>(\n internal: Internal<T>,\n context: Context<T>,\n computedDef: Machine<T>['computed'],\n): Snapshot<T> {\n const snapshot = { ...internal } as Snapshot<T>\n // Add computed values\n if (computedDef) {\n for (const key in computedDef) {\n (snapshot as Record<string, unknown>)[key] = context[key as keyof Context<T>]\n }\n }\n // Add state if exists in context\n const state = (context as { state?: State<T> }).state\n if (state !== undefined) {\n (snapshot as Record<string, unknown>).state = state\n }\n return snapshot\n}\n\n// ============================================\n// Effects Processing\n// ============================================\n\n/**\n * Shallow comparison for effect watch values\n * Arrays: compares length and each element with ===\n * Others: strict equality (===)\n */\nexport function shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n\n // Array comparison\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => v === b[i])\n }\n\n return false\n}\n\n/**\n * EffectStore - tracks watched values and cleanup functions for effects\n * Used by both vanilla and React implementations\n */\nexport type EffectStore = {\n watchedValues: Map<number, unknown> // Previous values by effect index\n enterCleanups: Map<number, () => void> // Cleanup from enter callbacks\n changeCleanups: Map<number, () => void> // Cleanup from change callbacks\n exitCleanups: Map<number, () => void> // Cleanup from exit callbacks\n}\n\n/** Create a new effect store */\nexport function createEffectStore(): EffectStore {\n return {\n watchedValues: new Map(),\n enterCleanups: new Map(),\n changeCleanups: new Map(),\n exitCleanups: new Map(),\n }\n}\n\n/**\n * Process all effects - detect watch value changes and call appropriate callbacks\n * Called on every context change in both vanilla (evaluate) and React (useEffect)\n */\nexport function processEffects<TContext, TEvents extends EventsConfig>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n effects: Effect<TContext, TEvents, any>[] | undefined,\n context: TContext,\n effectHelpers: EffectHelpers<TEvents>,\n store: EffectStore,\n): void {\n if (!effects) return\n\n effects.forEach((effect, i) => {\n const prev = store.watchedValues.get(i)\n const curr = effect.watch(context)\n\n // Only process if value changed (shallow comparison)\n if (!shallowEqual(prev, curr)) {\n // 1. Cleanup previous enter callback\n const enterCleanup = store.enterCleanups.get(i)\n if (enterCleanup) {\n enterCleanup()\n store.enterCleanups.delete(i)\n }\n\n // 2. Cleanup previous change callback\n const changeCleanup = store.changeCleanups.get(i)\n if (changeCleanup) {\n changeCleanup()\n store.changeCleanups.delete(i)\n }\n\n // 3. Call change callback (fires on any value change)\n const changeResult = effect.change?.(context, prev, curr, effectHelpers)\n if (typeof changeResult === 'function') {\n store.changeCleanups.set(i, changeResult)\n }\n\n // 4. Call enter callback (falsy → truthy transition)\n if (!prev && curr) {\n // Cleanup previous exit first\n const exitCleanup = store.exitCleanups.get(i)\n if (exitCleanup) {\n exitCleanup()\n store.exitCleanups.delete(i)\n }\n\n const enterResult = effect.enter?.(context, effectHelpers)\n if (typeof enterResult === 'function') {\n store.enterCleanups.set(i, enterResult)\n }\n }\n\n // 5. Call exit callback (truthy → falsy transition)\n if (prev && !curr) {\n const exitResult = effect.exit?.(context, effectHelpers)\n if (typeof exitResult === 'function') {\n store.exitCleanups.set(i, exitResult)\n }\n }\n\n // Update stored value for next comparison\n store.watchedValues.set(i, curr)\n }\n })\n}\n\n/** Clear all effect cleanups (called on unmount or cleanup) */\nexport function clearEffectStore(store: EffectStore): void {\n store.enterCleanups.forEach((fn) => fn())\n store.enterCleanups.clear()\n store.changeCleanups.forEach((fn) => fn())\n store.changeCleanups.clear()\n store.exitCleanups.forEach((fn) => fn())\n store.exitCleanups.clear()\n store.watchedValues.clear()\n}\n\n// ============================================\n// createMachine - Vanilla Implementation\n// ============================================\n\n/**\n * Create a controlled state machine instance\n *\n * The machine manages internal state and provides methods for:\n * - send: Dispatch events with input and payload\n * - evaluate: Run always rules and effects\n * - getSnapshot: Get current state (internal + computed + state)\n *\n * @example\n * const machine = createMachine<{\n * input: { count: number }\n * internal: { isOpen: boolean }\n * events: { TOGGLE: undefined }\n * computed: { doubled: number }\n * }>({\n * internal: { isOpen: false },\n * computed: { doubled: ctx => ctx.count * 2 },\n * on: { TOGGLE: (ctx, _, assign) => assign({ isOpen: !ctx.isOpen }) }\n * })\n */\nexport function createMachine<T extends MachineTypes>(\n config: Machine<T>,\n): MachineInstance<T> {\n const effectStore = createEffectStore()\n const initialInternal = (config.internal ?? {}) as Internal<T>\n\n // Machine-managed internal state\n let currentInternal = { ...initialInternal }\n\n // Update internal state\n const updateInternal = (newInternal: Internal<T>) => {\n currentInternal = newInternal\n }\n\n // Build full context: input + internal + computed\n const buildFullContext = (input: Input<T>): Context<T> => {\n const base = buildContext(input, currentInternal)\n return computeValues(base, config.computed) as Context<T>\n }\n\n /**\n * Send an event to the machine\n * Executes state-specific handlers first, then global handlers\n */\n const send = (<K extends keyof Events<T>>(\n event: K,\n input: Input<T>,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const payload = args[0] as Events<T>[K]\n\n // getContext rebuilds context with latest internal state\n const getContext = () => buildFullContext(input)\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>, payload?: unknown) => boolean>\n\n // 1. Execute state-specific handler (if in FSM mode)\n const context = getContext()\n const state = (context as { state?: State<T> }).state\n if (state && config.states?.[state]?.on?.[event]) {\n const stateHandler = config.states[state].on![event]!\n executeHandler(\n stateHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n\n // 2. Execute global handler\n const globalHandler = config.on?.[event]\n if (globalHandler) {\n executeHandler(\n globalHandler,\n actionsMap,\n guardsMap,\n getContext,\n payload,\n assign,\n )\n }\n }) as MachineInstance<T>['send']\n\n // Create effect helpers with bound send\n const createEffectHelpers = (input: Input<T>): EffectHelpers<Events<T>> => ({\n send: (<K extends keyof Events<T>>(\n event: K,\n ...args: Events<T>[K] extends undefined ? [] : [payload: Events<T>[K]]\n ) => {\n send(event, input, ...args)\n }) as Send<Events<T>>,\n })\n\n /**\n * Evaluate the machine - runs always rules and processes effects\n * Should be called when input changes (automatic in React via useMachine)\n */\n const evaluate = (input: Input<T>) => {\n const assign = createAssign(() => currentInternal, updateInternal)\n const effectHelpers = createEffectHelpers(input)\n const getContext = () => buildFullContext(input)\n\n // Process always rules (first matching rule wins)\n if (config.always) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const actionsMap = (config.actions ?? {}) as Record<string, (ctx: Context<T>, payload: any, assign: AssignFn<Internal<T>>) => void>\n const guardsMap = (config.guards ?? {}) as Record<string, (ctx: Context<T>) => boolean>\n for (const rule of config.always) {\n if (evaluateGuards(rule.when, guardsMap, getContext(), undefined)) {\n executeRuleActions(rule.do, actionsMap, getContext, undefined, assign)\n break\n }\n }\n }\n\n // Process effects (uses current context)\n processEffects(config.effects, getContext(), effectHelpers, effectStore)\n }\n\n /** Get current snapshot (internal + computed + state) */\n const getSnapshot = (input: Input<T>): Snapshot<T> => {\n const context = buildFullContext(input)\n return buildSnapshot(currentInternal, context, config.computed)\n }\n\n // Internal state accessors\n const getInternal = (): Internal<T> => currentInternal\n const setInternal = (internal: Internal<T>) => { currentInternal = internal }\n const getInitialInternal = (): Internal<T> => initialInternal\n\n /** Clean up all effect callbacks */\n const cleanup = () => clearEffectStore(effectStore)\n\n return Object.assign(config, { send, evaluate, getSnapshot, getInternal, setInternal, getInitialInternal, cleanup })\n}\n"],"names":["effect"],"mappings":"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"}
|