@rytejs/react 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -286,7 +286,7 @@ function createWorkflowStore(router, initialConfig, options) {
286
286
  const dispatch = async (command, payload) => {
287
287
  isDispatching = true;
288
288
  notify();
289
- const result = await router.dispatch(workflow, { type: command, payload });
289
+ const result = await router.dispatch(workflow, command, payload);
290
290
  if (result.ok) {
291
291
  workflow = result.workflow;
292
292
  error = null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/context.ts","../src/use-workflow.ts","../src/store.ts"],"sourcesContent":["export { createWorkflowClient } from \"./client.js\";\nexport { createWorkflowContext } from \"./context.js\";\nexport { createWorkflowStore } from \"./store.js\";\nexport type {\n\tBroadcastMessage,\n\tTransport,\n\tTransportError,\n\tTransportResult,\n\tTransportSubscription,\n} from \"./transport.js\";\nexport type {\n\tUseWorkflowReturn,\n\tWorkflowStore,\n\tWorkflowStoreOptions,\n\tWorkflowStoreSnapshot,\n} from \"./types.js\";\nexport { useWorkflow } from \"./use-workflow.js\";\n","import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport type { BroadcastMessage, Transport } from \"./transport.js\";\nimport type { WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowClient(transport: Transport) {\n\t// biome-ignore lint/suspicious/noExplicitAny: cache stores keyed by string, values are type-erased WorkflowStore instances\n\tconst cache = new Map<string, WorkflowStore<any>>();\n\n\treturn {\n\t\tconnect<TConfig extends WorkflowConfig>(\n\t\t\tdefinition: WorkflowDefinition<TConfig>,\n\t\t\tid: string,\n\t\t): WorkflowStore<TConfig> {\n\t\t\tconst cacheKey = `${definition.name}:${id}`;\n\t\t\tconst existing = cache.get(cacheKey);\n\t\t\tif (existing) {\n\t\t\t\treturn existing as WorkflowStore<TConfig>;\n\t\t\t}\n\n\t\t\tconst store = createRemoteStore(transport, definition, id, () => cache.delete(cacheKey));\n\t\t\tcache.set(cacheKey, store);\n\t\t\treturn store;\n\t\t},\n\t};\n}\n\nfunction createRemoteStore<TConfig extends WorkflowConfig>(\n\ttransport: Transport,\n\tdefinition: WorkflowDefinition<TConfig>,\n\tid: string,\n\tonDispose: () => void,\n): WorkflowStore<TConfig> {\n\tlet workflow: Workflow<TConfig> | null = null;\n\tlet version = 0;\n\tlet isLoading = true;\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet disposed = false;\n\n\tconst listeners = new Set<() => void>();\n\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading,\n\t\tisDispatching,\n\t\terror,\n\t};\n\n\tfunction notify() {\n\t\tif (disposed) return;\n\t\tsnapshot = { workflow, isLoading, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\t// Eagerly load\n\ttransport\n\t\t.load(id)\n\t\t.then((result) => {\n\t\t\tif (disposed) return;\n\t\t\tif (result !== null) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t}\n\t\t\t}\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t})\n\t\t.catch((err: unknown) => {\n\t\t\tif (disposed) return;\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape for interface conformance\n\t\t\t} as any;\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t});\n\n\t// Subscribe to live broadcasts\n\tconst subscription = transport.subscribe(id, (message: BroadcastMessage) => {\n\t\tif (disposed) return;\n\t\tconst restored = definition.deserialize(message.snapshot);\n\t\tif (restored.ok) {\n\t\t\tworkflow = restored.workflow;\n\t\t\tversion = message.version;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t}\n\t});\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tif (isLoading) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Cannot dispatch while loading\"),\n\t\t\t\t\tmessage: \"Cannot dispatch while loading\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\ttry {\n\t\t\tconst result = await transport.dispatch(id, { type: command as string, payload }, version);\n\n\t\t\tif (result.ok) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t\terror = null;\n\t\t\t\t\tisDispatching = false;\n\t\t\t\t\tnotify();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\tworkflow: restored.workflow,\n\t\t\t\t\t\tevents: result.events,\n\t\t\t\t\t} as DispatchResult<TConfig>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Error path\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape\n\t\t\terror = (result.ok ? null : result.error) as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: error ?? {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Transport error\"),\n\t\t\t\t\tmessage: \"Transport error\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t} catch (err: unknown) {\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: network error mapped to PipelineError shape\n\t\t\t} as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: error is always assigned in the catch block above\n\t\t\t\terror: error!,\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {\n\t\t\tdisposed = true;\n\t\t\tsubscription.unsubscribe();\n\t\t\tonDispose();\n\t\t},\n\t};\n}\n","import type { Workflow, WorkflowConfig, WorkflowDefinition } from \"@rytejs/core\";\nimport type { ReactNode } from \"react\";\nimport { createContext, createElement, useContext } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore } from \"./types.js\";\nimport { useWorkflow } from \"./use-workflow.js\";\n\nexport function createWorkflowContext<TConfig extends WorkflowConfig>(\n\t_definition: WorkflowDefinition<TConfig>,\n): {\n\tProvider: (props: { store: WorkflowStore<TConfig>; children?: ReactNode }) => ReactNode;\n\tuseWorkflow: {\n\t\t(): UseWorkflowReturn<TConfig>;\n\t\t<R>(selector: (workflow: Workflow<TConfig>) => R, equalityFn?: (a: R, b: R) => boolean): R;\n\t};\n} {\n\tconst StoreContext = createContext<WorkflowStore<TConfig> | null>(null);\n\n\tfunction Provider({\n\t\tstore,\n\t\tchildren,\n\t}: {\n\t\tstore: WorkflowStore<TConfig>;\n\t\tchildren?: ReactNode;\n\t}): ReactNode {\n\t\treturn createElement(StoreContext.Provider, { value: store }, children);\n\t}\n\n\tfunction useWorkflowFromContext(): UseWorkflowReturn<TConfig>;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): R;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector?: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): UseWorkflowReturn<TConfig> | R {\n\t\tconst store = useContext(StoreContext);\n\t\tif (!store) {\n\t\t\tthrow new Error(\n\t\t\t\t\"useWorkflow must be used within a WorkflowProvider. \" +\n\t\t\t\t\t\"Wrap your component tree with <Provider store={...}>.\",\n\t\t\t);\n\t\t}\n\t\tif (selector) {\n\t\t\t// biome-ignore lint/correctness/useHookAtTopLevel: selector presence is stable per render — callers must not change between selector and no-selector mode\n\t\t\treturn useWorkflow(store, selector, equalityFn);\n\t\t}\n\t\t// biome-ignore lint/correctness/useHookAtTopLevel: called on the non-selector path; mutually exclusive with the branch above but stable per component lifetime\n\t\treturn useWorkflow(store);\n\t}\n\n\treturn { Provider, useWorkflow: useWorkflowFromContext };\n}\n","import type { Workflow, WorkflowConfig } from \"@rytejs/core\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nfunction createReturn<TConfig extends WorkflowConfig>(\n\tsnapshot: WorkflowStoreSnapshot<TConfig>,\n\tdispatch: WorkflowStore<TConfig>[\"dispatch\"],\n): UseWorkflowReturn<TConfig> {\n\tconst wf = snapshot.workflow;\n\treturn {\n\t\tworkflow: wf,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: state/data are undefined when workflow is null (loading) — consumers check isLoading first\n\t\tstate: wf?.state as any,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: see above\n\t\tdata: wf?.data as any,\n\t\tisLoading: snapshot.isLoading,\n\t\tisDispatching: snapshot.isDispatching,\n\t\terror: snapshot.error,\n\t\tdispatch,\n\t\tmatch(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tmatchers: Record<string, any>,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tfallback?: (workflow: Workflow<TConfig> | null) => any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t): any {\n\t\t\tif (!wf) {\n\t\t\t\tif (fallback) return fallback(wf);\n\t\t\t\tthrow new Error(\"Cannot match on a loading workflow — check isLoading first\");\n\t\t\t}\n\t\t\tconst state = wf.state as string;\n\t\t\tconst matcher = matchers[state];\n\t\t\tif (matcher) {\n\t\t\t\treturn matcher(wf.data, wf);\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\treturn fallback(wf);\n\t\t\t}\n\t\t\tthrow new Error(`No match for state \"${state}\" and no fallback provided`);\n\t\t},\n\t} as UseWorkflowReturn<TConfig>;\n}\n\nexport function useWorkflow<TConfig extends WorkflowConfig>(\n\tstore: WorkflowStore<TConfig>,\n): UseWorkflowReturn<TConfig>;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): R;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector?: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): UseWorkflowReturn<TConfig> | R {\n\t// Refs for selector caching — always allocated to maintain hook call order\n\tconst selectorRef = useRef(selector);\n\tconst equalityFnRef = useRef(equalityFn);\n\tconst cachedRef = useRef<R | undefined>(undefined);\n\tconst hasCachedRef = useRef(false);\n\tselectorRef.current = selector;\n\tequalityFnRef.current = equalityFn;\n\n\tconst selectorSnapshot = useCallback(() => {\n\t\tconst wf = store.getWorkflow();\n\t\tif (!wf) {\n\t\t\t// Workflow is loading — return cached value if available\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\t// biome-ignore lint/style/noNonNullAssertion: selectorSnapshot is only used when selector is defined (checked at call site)\n\t\tconst next = selectorRef.current!(wf);\n\t\tconst eq = equalityFnRef.current ?? Object.is;\n\t\tif (hasCachedRef.current && eq(cachedRef.current as R, next)) {\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\tcachedRef.current = next;\n\t\thasCachedRef.current = true;\n\t\treturn next;\n\t}, [store]);\n\n\t// biome-ignore lint/suspicious/noExplicitAny: return type varies by overload; TS can't narrow union of getSnapshot functions\n\tconst getSnapshot: () => any = selector ? selectorSnapshot : store.getSnapshot;\n\n\tconst result: unknown = useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n\n\tif (!selector) {\n\t\treturn createReturn(result as WorkflowStoreSnapshot<TConfig>, store.dispatch);\n\t}\n\treturn result as R;\n}\n","import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport { migrate, type WorkflowRouter } from \"@rytejs/core\";\nimport type { WorkflowStore, WorkflowStoreOptions, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowStore<\n\tTConfig extends WorkflowConfig,\n\tTDeps,\n\tS extends StateNames<TConfig>,\n>(\n\trouter: WorkflowRouter<TConfig, TDeps>,\n\tinitialConfig: {\n\t\tstate: S;\n\t\tdata: StateData<TConfig, S>;\n\t\tid?: string;\n\t},\n\toptions?: WorkflowStoreOptions<TConfig>,\n): WorkflowStore<TConfig> {\n\tconst definition = router.definition;\n\n\tlet workflow: Workflow<TConfig> = loadOrCreate(definition, initialConfig, options);\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading: false,\n\t\tisDispatching,\n\t\terror,\n\t};\n\tconst listeners = new Set<() => void>();\n\n\tfunction notify() {\n\t\tsnapshot = { workflow, isLoading: false, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\tconst result = await router.dispatch(workflow, { type: command, payload });\n\n\t\tif (result.ok) {\n\t\t\tworkflow = result.workflow;\n\t\t\terror = null;\n\t\t} else {\n\t\t\terror = result.error;\n\t\t}\n\t\tisDispatching = false;\n\t\tnotify();\n\n\t\tif (result.ok && options?.persist) {\n\t\t\tconst { key, storage } = options.persist;\n\t\t\tconst snap = definition.serialize(workflow);\n\t\t\tstorage.setItem(key, JSON.stringify(snap));\n\t\t}\n\n\t\treturn result;\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {},\n\t};\n}\n\nfunction loadOrCreate<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n\toptions?: WorkflowStoreOptions<TConfig>,\n): Workflow<TConfig> {\n\tif (options?.persist) {\n\t\tconst { key, storage, migrations } = options.persist;\n\t\ttry {\n\t\t\tconst stored = storage.getItem(key);\n\t\t\tif (stored) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown structure from storage\n\t\t\t\tlet parsed: any = JSON.parse(stored);\n\t\t\t\tif (migrations) {\n\t\t\t\t\tconst migrated = migrate(migrations, parsed);\n\t\t\t\t\tif (migrated.ok) {\n\t\t\t\t\t\tparsed = migrated.snapshot;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn createFresh(definition, initialConfig);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst restored = definition.deserialize(parsed);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\treturn restored.workflow;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Invalid JSON or deserialize failed — fall through to create fresh\n\t\t}\n\t}\n\n\treturn createFresh(definition, initialConfig);\n}\n\nfunction createFresh<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n): Workflow<TConfig> {\n\treturn definition.createWorkflow(initialConfig.id ?? crypto.randomUUID(), {\n\t\tinitialState: initialConfig.state,\n\t\tdata: initialConfig.data,\n\t});\n}\n"],"mappings":"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","names":["import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/context.ts","../src/use-workflow.ts","../src/store.ts"],"sourcesContent":["export { createWorkflowClient } from \"./client.js\";\nexport { createWorkflowContext } from \"./context.js\";\nexport { createWorkflowStore } from \"./store.js\";\nexport type {\n\tBroadcastMessage,\n\tTransport,\n\tTransportError,\n\tTransportResult,\n\tTransportSubscription,\n} from \"./transport.js\";\nexport type {\n\tUseWorkflowReturn,\n\tWorkflowStore,\n\tWorkflowStoreOptions,\n\tWorkflowStoreSnapshot,\n} from \"./types.js\";\nexport { useWorkflow } from \"./use-workflow.js\";\n","import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport type { BroadcastMessage, Transport } from \"./transport.js\";\nimport type { WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowClient(transport: Transport) {\n\t// biome-ignore lint/suspicious/noExplicitAny: cache stores keyed by string, values are type-erased WorkflowStore instances\n\tconst cache = new Map<string, WorkflowStore<any>>();\n\n\treturn {\n\t\tconnect<TConfig extends WorkflowConfig>(\n\t\t\tdefinition: WorkflowDefinition<TConfig>,\n\t\t\tid: string,\n\t\t): WorkflowStore<TConfig> {\n\t\t\tconst cacheKey = `${definition.name}:${id}`;\n\t\t\tconst existing = cache.get(cacheKey);\n\t\t\tif (existing) {\n\t\t\t\treturn existing as WorkflowStore<TConfig>;\n\t\t\t}\n\n\t\t\tconst store = createRemoteStore(transport, definition, id, () => cache.delete(cacheKey));\n\t\t\tcache.set(cacheKey, store);\n\t\t\treturn store;\n\t\t},\n\t};\n}\n\nfunction createRemoteStore<TConfig extends WorkflowConfig>(\n\ttransport: Transport,\n\tdefinition: WorkflowDefinition<TConfig>,\n\tid: string,\n\tonDispose: () => void,\n): WorkflowStore<TConfig> {\n\tlet workflow: Workflow<TConfig> | null = null;\n\tlet version = 0;\n\tlet isLoading = true;\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet disposed = false;\n\n\tconst listeners = new Set<() => void>();\n\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading,\n\t\tisDispatching,\n\t\terror,\n\t};\n\n\tfunction notify() {\n\t\tif (disposed) return;\n\t\tsnapshot = { workflow, isLoading, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\t// Eagerly load\n\ttransport\n\t\t.load(id)\n\t\t.then((result) => {\n\t\t\tif (disposed) return;\n\t\t\tif (result !== null) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t}\n\t\t\t}\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t})\n\t\t.catch((err: unknown) => {\n\t\t\tif (disposed) return;\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape for interface conformance\n\t\t\t} as any;\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t});\n\n\t// Subscribe to live broadcasts\n\tconst subscription = transport.subscribe(id, (message: BroadcastMessage) => {\n\t\tif (disposed) return;\n\t\tconst restored = definition.deserialize(message.snapshot);\n\t\tif (restored.ok) {\n\t\t\tworkflow = restored.workflow;\n\t\t\tversion = message.version;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t}\n\t});\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tif (isLoading) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Cannot dispatch while loading\"),\n\t\t\t\t\tmessage: \"Cannot dispatch while loading\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\ttry {\n\t\t\tconst result = await transport.dispatch(id, { type: command as string, payload }, version);\n\n\t\t\tif (result.ok) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t\terror = null;\n\t\t\t\t\tisDispatching = false;\n\t\t\t\t\tnotify();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\tworkflow: restored.workflow,\n\t\t\t\t\t\tevents: result.events,\n\t\t\t\t\t} as DispatchResult<TConfig>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Error path\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape\n\t\t\terror = (result.ok ? null : result.error) as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: error ?? {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Transport error\"),\n\t\t\t\t\tmessage: \"Transport error\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t} catch (err: unknown) {\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: network error mapped to PipelineError shape\n\t\t\t} as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: error is always assigned in the catch block above\n\t\t\t\terror: error!,\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {\n\t\t\tdisposed = true;\n\t\t\tsubscription.unsubscribe();\n\t\t\tonDispose();\n\t\t},\n\t};\n}\n","import type { Workflow, WorkflowConfig, WorkflowDefinition } from \"@rytejs/core\";\nimport type { ReactNode } from \"react\";\nimport { createContext, createElement, useContext } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore } from \"./types.js\";\nimport { useWorkflow } from \"./use-workflow.js\";\n\nexport function createWorkflowContext<TConfig extends WorkflowConfig>(\n\t_definition: WorkflowDefinition<TConfig>,\n): {\n\tProvider: (props: { store: WorkflowStore<TConfig>; children?: ReactNode }) => ReactNode;\n\tuseWorkflow: {\n\t\t(): UseWorkflowReturn<TConfig>;\n\t\t<R>(selector: (workflow: Workflow<TConfig>) => R, equalityFn?: (a: R, b: R) => boolean): R;\n\t};\n} {\n\tconst StoreContext = createContext<WorkflowStore<TConfig> | null>(null);\n\n\tfunction Provider({\n\t\tstore,\n\t\tchildren,\n\t}: {\n\t\tstore: WorkflowStore<TConfig>;\n\t\tchildren?: ReactNode;\n\t}): ReactNode {\n\t\treturn createElement(StoreContext.Provider, { value: store }, children);\n\t}\n\n\tfunction useWorkflowFromContext(): UseWorkflowReturn<TConfig>;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): R;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector?: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): UseWorkflowReturn<TConfig> | R {\n\t\tconst store = useContext(StoreContext);\n\t\tif (!store) {\n\t\t\tthrow new Error(\n\t\t\t\t\"useWorkflow must be used within a WorkflowProvider. \" +\n\t\t\t\t\t\"Wrap your component tree with <Provider store={...}>.\",\n\t\t\t);\n\t\t}\n\t\tif (selector) {\n\t\t\t// biome-ignore lint/correctness/useHookAtTopLevel: selector presence is stable per render — callers must not change between selector and no-selector mode\n\t\t\treturn useWorkflow(store, selector, equalityFn);\n\t\t}\n\t\t// biome-ignore lint/correctness/useHookAtTopLevel: called on the non-selector path; mutually exclusive with the branch above but stable per component lifetime\n\t\treturn useWorkflow(store);\n\t}\n\n\treturn { Provider, useWorkflow: useWorkflowFromContext };\n}\n","import type { Workflow, WorkflowConfig } from \"@rytejs/core\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nfunction createReturn<TConfig extends WorkflowConfig>(\n\tsnapshot: WorkflowStoreSnapshot<TConfig>,\n\tdispatch: WorkflowStore<TConfig>[\"dispatch\"],\n): UseWorkflowReturn<TConfig> {\n\tconst wf = snapshot.workflow;\n\treturn {\n\t\tworkflow: wf,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: state/data are undefined when workflow is null (loading) — consumers check isLoading first\n\t\tstate: wf?.state as any,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: see above\n\t\tdata: wf?.data as any,\n\t\tisLoading: snapshot.isLoading,\n\t\tisDispatching: snapshot.isDispatching,\n\t\terror: snapshot.error,\n\t\tdispatch,\n\t\tmatch(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tmatchers: Record<string, any>,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tfallback?: (workflow: Workflow<TConfig> | null) => any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t): any {\n\t\t\tif (!wf) {\n\t\t\t\tif (fallback) return fallback(wf);\n\t\t\t\tthrow new Error(\"Cannot match on a loading workflow — check isLoading first\");\n\t\t\t}\n\t\t\tconst state = wf.state as string;\n\t\t\tconst matcher = matchers[state];\n\t\t\tif (matcher) {\n\t\t\t\treturn matcher(wf.data, wf);\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\treturn fallback(wf);\n\t\t\t}\n\t\t\tthrow new Error(`No match for state \"${state}\" and no fallback provided`);\n\t\t},\n\t} as UseWorkflowReturn<TConfig>;\n}\n\nexport function useWorkflow<TConfig extends WorkflowConfig>(\n\tstore: WorkflowStore<TConfig>,\n): UseWorkflowReturn<TConfig>;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): R;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector?: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): UseWorkflowReturn<TConfig> | R {\n\t// Refs for selector caching — always allocated to maintain hook call order\n\tconst selectorRef = useRef(selector);\n\tconst equalityFnRef = useRef(equalityFn);\n\tconst cachedRef = useRef<R | undefined>(undefined);\n\tconst hasCachedRef = useRef(false);\n\tselectorRef.current = selector;\n\tequalityFnRef.current = equalityFn;\n\n\tconst selectorSnapshot = useCallback(() => {\n\t\tconst wf = store.getWorkflow();\n\t\tif (!wf) {\n\t\t\t// Workflow is loading — return cached value if available\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\t// biome-ignore lint/style/noNonNullAssertion: selectorSnapshot is only used when selector is defined (checked at call site)\n\t\tconst next = selectorRef.current!(wf);\n\t\tconst eq = equalityFnRef.current ?? Object.is;\n\t\tif (hasCachedRef.current && eq(cachedRef.current as R, next)) {\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\tcachedRef.current = next;\n\t\thasCachedRef.current = true;\n\t\treturn next;\n\t}, [store]);\n\n\t// biome-ignore lint/suspicious/noExplicitAny: return type varies by overload; TS can't narrow union of getSnapshot functions\n\tconst getSnapshot: () => any = selector ? selectorSnapshot : store.getSnapshot;\n\n\tconst result: unknown = useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n\n\tif (!selector) {\n\t\treturn createReturn(result as WorkflowStoreSnapshot<TConfig>, store.dispatch);\n\t}\n\treturn result as R;\n}\n","import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport { migrate, type WorkflowRouter } from \"@rytejs/core\";\nimport type { WorkflowStore, WorkflowStoreOptions, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowStore<\n\tTConfig extends WorkflowConfig,\n\tTDeps,\n\tS extends StateNames<TConfig>,\n>(\n\trouter: WorkflowRouter<TConfig, TDeps>,\n\tinitialConfig: {\n\t\tstate: S;\n\t\tdata: StateData<TConfig, S>;\n\t\tid?: string;\n\t},\n\toptions?: WorkflowStoreOptions<TConfig>,\n): WorkflowStore<TConfig> {\n\tconst definition = router.definition;\n\n\tlet workflow: Workflow<TConfig> = loadOrCreate(definition, initialConfig, options);\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading: false,\n\t\tisDispatching,\n\t\terror,\n\t};\n\tconst listeners = new Set<() => void>();\n\n\tfunction notify() {\n\t\tsnapshot = { workflow, isLoading: false, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\tconst result = await router.dispatch(workflow, command, payload);\n\n\t\tif (result.ok) {\n\t\t\tworkflow = result.workflow;\n\t\t\terror = null;\n\t\t} else {\n\t\t\terror = result.error;\n\t\t}\n\t\tisDispatching = false;\n\t\tnotify();\n\n\t\tif (result.ok && options?.persist) {\n\t\t\tconst { key, storage } = options.persist;\n\t\t\tconst snap = definition.serialize(workflow);\n\t\t\tstorage.setItem(key, JSON.stringify(snap));\n\t\t}\n\n\t\treturn result;\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {},\n\t};\n}\n\nfunction loadOrCreate<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n\toptions?: WorkflowStoreOptions<TConfig>,\n): Workflow<TConfig> {\n\tif (options?.persist) {\n\t\tconst { key, storage, migrations } = options.persist;\n\t\ttry {\n\t\t\tconst stored = storage.getItem(key);\n\t\t\tif (stored) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown structure from storage\n\t\t\t\tlet parsed: any = JSON.parse(stored);\n\t\t\t\tif (migrations) {\n\t\t\t\t\tconst migrated = migrate(migrations, parsed);\n\t\t\t\t\tif (migrated.ok) {\n\t\t\t\t\t\tparsed = migrated.snapshot;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn createFresh(definition, initialConfig);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst restored = definition.deserialize(parsed);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\treturn restored.workflow;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Invalid JSON or deserialize failed — fall through to create fresh\n\t\t}\n\t}\n\n\treturn createFresh(definition, initialConfig);\n}\n\nfunction createFresh<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n): Workflow<TConfig> {\n\treturn definition.createWorkflow(initialConfig.id ?? crypto.randomUUID(), {\n\t\tinitialState: initialConfig.state,\n\t\tdata: initialConfig.data,\n\t});\n}\n"],"mappings":"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","names":["import_react"]}
package/dist/index.js CHANGED
@@ -257,7 +257,7 @@ function createWorkflowStore(router, initialConfig, options) {
257
257
  const dispatch = async (command, payload) => {
258
258
  isDispatching = true;
259
259
  notify();
260
- const result = await router.dispatch(workflow, { type: command, payload });
260
+ const result = await router.dispatch(workflow, command, payload);
261
261
  if (result.ok) {
262
262
  workflow = result.workflow;
263
263
  error = null;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/context.ts","../src/use-workflow.ts","../src/store.ts"],"sourcesContent":["import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport type { BroadcastMessage, Transport } from \"./transport.js\";\nimport type { WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowClient(transport: Transport) {\n\t// biome-ignore lint/suspicious/noExplicitAny: cache stores keyed by string, values are type-erased WorkflowStore instances\n\tconst cache = new Map<string, WorkflowStore<any>>();\n\n\treturn {\n\t\tconnect<TConfig extends WorkflowConfig>(\n\t\t\tdefinition: WorkflowDefinition<TConfig>,\n\t\t\tid: string,\n\t\t): WorkflowStore<TConfig> {\n\t\t\tconst cacheKey = `${definition.name}:${id}`;\n\t\t\tconst existing = cache.get(cacheKey);\n\t\t\tif (existing) {\n\t\t\t\treturn existing as WorkflowStore<TConfig>;\n\t\t\t}\n\n\t\t\tconst store = createRemoteStore(transport, definition, id, () => cache.delete(cacheKey));\n\t\t\tcache.set(cacheKey, store);\n\t\t\treturn store;\n\t\t},\n\t};\n}\n\nfunction createRemoteStore<TConfig extends WorkflowConfig>(\n\ttransport: Transport,\n\tdefinition: WorkflowDefinition<TConfig>,\n\tid: string,\n\tonDispose: () => void,\n): WorkflowStore<TConfig> {\n\tlet workflow: Workflow<TConfig> | null = null;\n\tlet version = 0;\n\tlet isLoading = true;\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet disposed = false;\n\n\tconst listeners = new Set<() => void>();\n\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading,\n\t\tisDispatching,\n\t\terror,\n\t};\n\n\tfunction notify() {\n\t\tif (disposed) return;\n\t\tsnapshot = { workflow, isLoading, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\t// Eagerly load\n\ttransport\n\t\t.load(id)\n\t\t.then((result) => {\n\t\t\tif (disposed) return;\n\t\t\tif (result !== null) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t}\n\t\t\t}\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t})\n\t\t.catch((err: unknown) => {\n\t\t\tif (disposed) return;\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape for interface conformance\n\t\t\t} as any;\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t});\n\n\t// Subscribe to live broadcasts\n\tconst subscription = transport.subscribe(id, (message: BroadcastMessage) => {\n\t\tif (disposed) return;\n\t\tconst restored = definition.deserialize(message.snapshot);\n\t\tif (restored.ok) {\n\t\t\tworkflow = restored.workflow;\n\t\t\tversion = message.version;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t}\n\t});\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tif (isLoading) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Cannot dispatch while loading\"),\n\t\t\t\t\tmessage: \"Cannot dispatch while loading\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\ttry {\n\t\t\tconst result = await transport.dispatch(id, { type: command as string, payload }, version);\n\n\t\t\tif (result.ok) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t\terror = null;\n\t\t\t\t\tisDispatching = false;\n\t\t\t\t\tnotify();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\tworkflow: restored.workflow,\n\t\t\t\t\t\tevents: result.events,\n\t\t\t\t\t} as DispatchResult<TConfig>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Error path\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape\n\t\t\terror = (result.ok ? null : result.error) as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: error ?? {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Transport error\"),\n\t\t\t\t\tmessage: \"Transport error\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t} catch (err: unknown) {\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: network error mapped to PipelineError shape\n\t\t\t} as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: error is always assigned in the catch block above\n\t\t\t\terror: error!,\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {\n\t\t\tdisposed = true;\n\t\t\tsubscription.unsubscribe();\n\t\t\tonDispose();\n\t\t},\n\t};\n}\n","import type { Workflow, WorkflowConfig, WorkflowDefinition } from \"@rytejs/core\";\nimport type { ReactNode } from \"react\";\nimport { createContext, createElement, useContext } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore } from \"./types.js\";\nimport { useWorkflow } from \"./use-workflow.js\";\n\nexport function createWorkflowContext<TConfig extends WorkflowConfig>(\n\t_definition: WorkflowDefinition<TConfig>,\n): {\n\tProvider: (props: { store: WorkflowStore<TConfig>; children?: ReactNode }) => ReactNode;\n\tuseWorkflow: {\n\t\t(): UseWorkflowReturn<TConfig>;\n\t\t<R>(selector: (workflow: Workflow<TConfig>) => R, equalityFn?: (a: R, b: R) => boolean): R;\n\t};\n} {\n\tconst StoreContext = createContext<WorkflowStore<TConfig> | null>(null);\n\n\tfunction Provider({\n\t\tstore,\n\t\tchildren,\n\t}: {\n\t\tstore: WorkflowStore<TConfig>;\n\t\tchildren?: ReactNode;\n\t}): ReactNode {\n\t\treturn createElement(StoreContext.Provider, { value: store }, children);\n\t}\n\n\tfunction useWorkflowFromContext(): UseWorkflowReturn<TConfig>;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): R;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector?: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): UseWorkflowReturn<TConfig> | R {\n\t\tconst store = useContext(StoreContext);\n\t\tif (!store) {\n\t\t\tthrow new Error(\n\t\t\t\t\"useWorkflow must be used within a WorkflowProvider. \" +\n\t\t\t\t\t\"Wrap your component tree with <Provider store={...}>.\",\n\t\t\t);\n\t\t}\n\t\tif (selector) {\n\t\t\t// biome-ignore lint/correctness/useHookAtTopLevel: selector presence is stable per render — callers must not change between selector and no-selector mode\n\t\t\treturn useWorkflow(store, selector, equalityFn);\n\t\t}\n\t\t// biome-ignore lint/correctness/useHookAtTopLevel: called on the non-selector path; mutually exclusive with the branch above but stable per component lifetime\n\t\treturn useWorkflow(store);\n\t}\n\n\treturn { Provider, useWorkflow: useWorkflowFromContext };\n}\n","import type { Workflow, WorkflowConfig } from \"@rytejs/core\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nfunction createReturn<TConfig extends WorkflowConfig>(\n\tsnapshot: WorkflowStoreSnapshot<TConfig>,\n\tdispatch: WorkflowStore<TConfig>[\"dispatch\"],\n): UseWorkflowReturn<TConfig> {\n\tconst wf = snapshot.workflow;\n\treturn {\n\t\tworkflow: wf,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: state/data are undefined when workflow is null (loading) — consumers check isLoading first\n\t\tstate: wf?.state as any,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: see above\n\t\tdata: wf?.data as any,\n\t\tisLoading: snapshot.isLoading,\n\t\tisDispatching: snapshot.isDispatching,\n\t\terror: snapshot.error,\n\t\tdispatch,\n\t\tmatch(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tmatchers: Record<string, any>,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tfallback?: (workflow: Workflow<TConfig> | null) => any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t): any {\n\t\t\tif (!wf) {\n\t\t\t\tif (fallback) return fallback(wf);\n\t\t\t\tthrow new Error(\"Cannot match on a loading workflow — check isLoading first\");\n\t\t\t}\n\t\t\tconst state = wf.state as string;\n\t\t\tconst matcher = matchers[state];\n\t\t\tif (matcher) {\n\t\t\t\treturn matcher(wf.data, wf);\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\treturn fallback(wf);\n\t\t\t}\n\t\t\tthrow new Error(`No match for state \"${state}\" and no fallback provided`);\n\t\t},\n\t} as UseWorkflowReturn<TConfig>;\n}\n\nexport function useWorkflow<TConfig extends WorkflowConfig>(\n\tstore: WorkflowStore<TConfig>,\n): UseWorkflowReturn<TConfig>;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): R;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector?: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): UseWorkflowReturn<TConfig> | R {\n\t// Refs for selector caching — always allocated to maintain hook call order\n\tconst selectorRef = useRef(selector);\n\tconst equalityFnRef = useRef(equalityFn);\n\tconst cachedRef = useRef<R | undefined>(undefined);\n\tconst hasCachedRef = useRef(false);\n\tselectorRef.current = selector;\n\tequalityFnRef.current = equalityFn;\n\n\tconst selectorSnapshot = useCallback(() => {\n\t\tconst wf = store.getWorkflow();\n\t\tif (!wf) {\n\t\t\t// Workflow is loading — return cached value if available\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\t// biome-ignore lint/style/noNonNullAssertion: selectorSnapshot is only used when selector is defined (checked at call site)\n\t\tconst next = selectorRef.current!(wf);\n\t\tconst eq = equalityFnRef.current ?? Object.is;\n\t\tif (hasCachedRef.current && eq(cachedRef.current as R, next)) {\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\tcachedRef.current = next;\n\t\thasCachedRef.current = true;\n\t\treturn next;\n\t}, [store]);\n\n\t// biome-ignore lint/suspicious/noExplicitAny: return type varies by overload; TS can't narrow union of getSnapshot functions\n\tconst getSnapshot: () => any = selector ? selectorSnapshot : store.getSnapshot;\n\n\tconst result: unknown = useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n\n\tif (!selector) {\n\t\treturn createReturn(result as WorkflowStoreSnapshot<TConfig>, store.dispatch);\n\t}\n\treturn result as R;\n}\n","import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport { migrate, type WorkflowRouter } from \"@rytejs/core\";\nimport type { WorkflowStore, WorkflowStoreOptions, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowStore<\n\tTConfig extends WorkflowConfig,\n\tTDeps,\n\tS extends StateNames<TConfig>,\n>(\n\trouter: WorkflowRouter<TConfig, TDeps>,\n\tinitialConfig: {\n\t\tstate: S;\n\t\tdata: StateData<TConfig, S>;\n\t\tid?: string;\n\t},\n\toptions?: WorkflowStoreOptions<TConfig>,\n): WorkflowStore<TConfig> {\n\tconst definition = router.definition;\n\n\tlet workflow: Workflow<TConfig> = loadOrCreate(definition, initialConfig, options);\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading: false,\n\t\tisDispatching,\n\t\terror,\n\t};\n\tconst listeners = new Set<() => void>();\n\n\tfunction notify() {\n\t\tsnapshot = { workflow, isLoading: false, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\tconst result = await router.dispatch(workflow, { type: command, payload });\n\n\t\tif (result.ok) {\n\t\t\tworkflow = result.workflow;\n\t\t\terror = null;\n\t\t} else {\n\t\t\terror = result.error;\n\t\t}\n\t\tisDispatching = false;\n\t\tnotify();\n\n\t\tif (result.ok && options?.persist) {\n\t\t\tconst { key, storage } = options.persist;\n\t\t\tconst snap = definition.serialize(workflow);\n\t\t\tstorage.setItem(key, JSON.stringify(snap));\n\t\t}\n\n\t\treturn result;\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {},\n\t};\n}\n\nfunction loadOrCreate<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n\toptions?: WorkflowStoreOptions<TConfig>,\n): Workflow<TConfig> {\n\tif (options?.persist) {\n\t\tconst { key, storage, migrations } = options.persist;\n\t\ttry {\n\t\t\tconst stored = storage.getItem(key);\n\t\t\tif (stored) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown structure from storage\n\t\t\t\tlet parsed: any = JSON.parse(stored);\n\t\t\t\tif (migrations) {\n\t\t\t\t\tconst migrated = migrate(migrations, parsed);\n\t\t\t\t\tif (migrated.ok) {\n\t\t\t\t\t\tparsed = migrated.snapshot;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn createFresh(definition, initialConfig);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst restored = definition.deserialize(parsed);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\treturn restored.workflow;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Invalid JSON or deserialize failed — fall through to create fresh\n\t\t}\n\t}\n\n\treturn createFresh(definition, initialConfig);\n}\n\nfunction createFresh<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n): Workflow<TConfig> {\n\treturn definition.createWorkflow(initialConfig.id ?? crypto.randomUUID(), {\n\t\tinitialState: initialConfig.state,\n\t\tdata: initialConfig.data,\n\t});\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/client.ts","../src/context.ts","../src/use-workflow.ts","../src/store.ts"],"sourcesContent":["import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport type { BroadcastMessage, Transport } from \"./transport.js\";\nimport type { WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowClient(transport: Transport) {\n\t// biome-ignore lint/suspicious/noExplicitAny: cache stores keyed by string, values are type-erased WorkflowStore instances\n\tconst cache = new Map<string, WorkflowStore<any>>();\n\n\treturn {\n\t\tconnect<TConfig extends WorkflowConfig>(\n\t\t\tdefinition: WorkflowDefinition<TConfig>,\n\t\t\tid: string,\n\t\t): WorkflowStore<TConfig> {\n\t\t\tconst cacheKey = `${definition.name}:${id}`;\n\t\t\tconst existing = cache.get(cacheKey);\n\t\t\tif (existing) {\n\t\t\t\treturn existing as WorkflowStore<TConfig>;\n\t\t\t}\n\n\t\t\tconst store = createRemoteStore(transport, definition, id, () => cache.delete(cacheKey));\n\t\t\tcache.set(cacheKey, store);\n\t\t\treturn store;\n\t\t},\n\t};\n}\n\nfunction createRemoteStore<TConfig extends WorkflowConfig>(\n\ttransport: Transport,\n\tdefinition: WorkflowDefinition<TConfig>,\n\tid: string,\n\tonDispose: () => void,\n): WorkflowStore<TConfig> {\n\tlet workflow: Workflow<TConfig> | null = null;\n\tlet version = 0;\n\tlet isLoading = true;\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet disposed = false;\n\n\tconst listeners = new Set<() => void>();\n\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading,\n\t\tisDispatching,\n\t\terror,\n\t};\n\n\tfunction notify() {\n\t\tif (disposed) return;\n\t\tsnapshot = { workflow, isLoading, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\t// Eagerly load\n\ttransport\n\t\t.load(id)\n\t\t.then((result) => {\n\t\t\tif (disposed) return;\n\t\t\tif (result !== null) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t}\n\t\t\t}\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t})\n\t\t.catch((err: unknown) => {\n\t\t\tif (disposed) return;\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape for interface conformance\n\t\t\t} as any;\n\t\t\tisLoading = false;\n\t\t\tnotify();\n\t\t});\n\n\t// Subscribe to live broadcasts\n\tconst subscription = transport.subscribe(id, (message: BroadcastMessage) => {\n\t\tif (disposed) return;\n\t\tconst restored = definition.deserialize(message.snapshot);\n\t\tif (restored.ok) {\n\t\t\tworkflow = restored.workflow;\n\t\t\tversion = message.version;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t}\n\t});\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tif (isLoading) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Cannot dispatch while loading\"),\n\t\t\t\t\tmessage: \"Cannot dispatch while loading\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\ttry {\n\t\t\tconst result = await transport.dispatch(id, { type: command as string, payload }, version);\n\n\t\t\tif (result.ok) {\n\t\t\t\tconst restored = definition.deserialize(result.snapshot);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\tworkflow = restored.workflow;\n\t\t\t\t\tversion = result.version;\n\t\t\t\t\terror = null;\n\t\t\t\t\tisDispatching = false;\n\t\t\t\t\tnotify();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\tworkflow: restored.workflow,\n\t\t\t\t\t\tevents: result.events,\n\t\t\t\t\t} as DispatchResult<TConfig>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Error path\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TransportError mapped to PipelineError shape\n\t\t\terror = (result.ok ? null : result.error) as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: error ?? {\n\t\t\t\t\tcategory: \"unexpected\",\n\t\t\t\t\terror: new Error(\"Transport error\"),\n\t\t\t\t\tmessage: \"Transport error\",\n\t\t\t\t},\n\t\t\t} as DispatchResult<TConfig>;\n\t\t} catch (err: unknown) {\n\t\t\terror = {\n\t\t\t\tcategory: \"unexpected\",\n\t\t\t\terror: err,\n\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: network error mapped to PipelineError shape\n\t\t\t} as any;\n\t\t\tisDispatching = false;\n\t\t\tnotify();\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: error is always assigned in the catch block above\n\t\t\t\terror: error!,\n\t\t\t} as DispatchResult<TConfig>;\n\t\t}\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {\n\t\t\tdisposed = true;\n\t\t\tsubscription.unsubscribe();\n\t\t\tonDispose();\n\t\t},\n\t};\n}\n","import type { Workflow, WorkflowConfig, WorkflowDefinition } from \"@rytejs/core\";\nimport type { ReactNode } from \"react\";\nimport { createContext, createElement, useContext } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore } from \"./types.js\";\nimport { useWorkflow } from \"./use-workflow.js\";\n\nexport function createWorkflowContext<TConfig extends WorkflowConfig>(\n\t_definition: WorkflowDefinition<TConfig>,\n): {\n\tProvider: (props: { store: WorkflowStore<TConfig>; children?: ReactNode }) => ReactNode;\n\tuseWorkflow: {\n\t\t(): UseWorkflowReturn<TConfig>;\n\t\t<R>(selector: (workflow: Workflow<TConfig>) => R, equalityFn?: (a: R, b: R) => boolean): R;\n\t};\n} {\n\tconst StoreContext = createContext<WorkflowStore<TConfig> | null>(null);\n\n\tfunction Provider({\n\t\tstore,\n\t\tchildren,\n\t}: {\n\t\tstore: WorkflowStore<TConfig>;\n\t\tchildren?: ReactNode;\n\t}): ReactNode {\n\t\treturn createElement(StoreContext.Provider, { value: store }, children);\n\t}\n\n\tfunction useWorkflowFromContext(): UseWorkflowReturn<TConfig>;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): R;\n\tfunction useWorkflowFromContext<R>(\n\t\tselector?: (workflow: Workflow<TConfig>) => R,\n\t\tequalityFn?: (a: R, b: R) => boolean,\n\t): UseWorkflowReturn<TConfig> | R {\n\t\tconst store = useContext(StoreContext);\n\t\tif (!store) {\n\t\t\tthrow new Error(\n\t\t\t\t\"useWorkflow must be used within a WorkflowProvider. \" +\n\t\t\t\t\t\"Wrap your component tree with <Provider store={...}>.\",\n\t\t\t);\n\t\t}\n\t\tif (selector) {\n\t\t\t// biome-ignore lint/correctness/useHookAtTopLevel: selector presence is stable per render — callers must not change between selector and no-selector mode\n\t\t\treturn useWorkflow(store, selector, equalityFn);\n\t\t}\n\t\t// biome-ignore lint/correctness/useHookAtTopLevel: called on the non-selector path; mutually exclusive with the branch above but stable per component lifetime\n\t\treturn useWorkflow(store);\n\t}\n\n\treturn { Provider, useWorkflow: useWorkflowFromContext };\n}\n","import type { Workflow, WorkflowConfig } from \"@rytejs/core\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport type { UseWorkflowReturn, WorkflowStore, WorkflowStoreSnapshot } from \"./types.js\";\n\nfunction createReturn<TConfig extends WorkflowConfig>(\n\tsnapshot: WorkflowStoreSnapshot<TConfig>,\n\tdispatch: WorkflowStore<TConfig>[\"dispatch\"],\n): UseWorkflowReturn<TConfig> {\n\tconst wf = snapshot.workflow;\n\treturn {\n\t\tworkflow: wf,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: state/data are undefined when workflow is null (loading) — consumers check isLoading first\n\t\tstate: wf?.state as any,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: see above\n\t\tdata: wf?.data as any,\n\t\tisLoading: snapshot.isLoading,\n\t\tisDispatching: snapshot.isDispatching,\n\t\terror: snapshot.error,\n\t\tdispatch,\n\t\tmatch(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tmatchers: Record<string, any>,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t\tfallback?: (workflow: Workflow<TConfig> | null) => any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: match overloads handled by UseWorkflowReturn type\n\t\t): any {\n\t\t\tif (!wf) {\n\t\t\t\tif (fallback) return fallback(wf);\n\t\t\t\tthrow new Error(\"Cannot match on a loading workflow — check isLoading first\");\n\t\t\t}\n\t\t\tconst state = wf.state as string;\n\t\t\tconst matcher = matchers[state];\n\t\t\tif (matcher) {\n\t\t\t\treturn matcher(wf.data, wf);\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\treturn fallback(wf);\n\t\t\t}\n\t\t\tthrow new Error(`No match for state \"${state}\" and no fallback provided`);\n\t\t},\n\t} as UseWorkflowReturn<TConfig>;\n}\n\nexport function useWorkflow<TConfig extends WorkflowConfig>(\n\tstore: WorkflowStore<TConfig>,\n): UseWorkflowReturn<TConfig>;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): R;\nexport function useWorkflow<TConfig extends WorkflowConfig, R>(\n\tstore: WorkflowStore<TConfig>,\n\tselector?: (workflow: Workflow<TConfig>) => R,\n\tequalityFn?: (a: R, b: R) => boolean,\n): UseWorkflowReturn<TConfig> | R {\n\t// Refs for selector caching — always allocated to maintain hook call order\n\tconst selectorRef = useRef(selector);\n\tconst equalityFnRef = useRef(equalityFn);\n\tconst cachedRef = useRef<R | undefined>(undefined);\n\tconst hasCachedRef = useRef(false);\n\tselectorRef.current = selector;\n\tequalityFnRef.current = equalityFn;\n\n\tconst selectorSnapshot = useCallback(() => {\n\t\tconst wf = store.getWorkflow();\n\t\tif (!wf) {\n\t\t\t// Workflow is loading — return cached value if available\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\t// biome-ignore lint/style/noNonNullAssertion: selectorSnapshot is only used when selector is defined (checked at call site)\n\t\tconst next = selectorRef.current!(wf);\n\t\tconst eq = equalityFnRef.current ?? Object.is;\n\t\tif (hasCachedRef.current && eq(cachedRef.current as R, next)) {\n\t\t\treturn cachedRef.current;\n\t\t}\n\t\tcachedRef.current = next;\n\t\thasCachedRef.current = true;\n\t\treturn next;\n\t}, [store]);\n\n\t// biome-ignore lint/suspicious/noExplicitAny: return type varies by overload; TS can't narrow union of getSnapshot functions\n\tconst getSnapshot: () => any = selector ? selectorSnapshot : store.getSnapshot;\n\n\tconst result: unknown = useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n\n\tif (!selector) {\n\t\treturn createReturn(result as WorkflowStoreSnapshot<TConfig>, store.dispatch);\n\t}\n\treturn result as R;\n}\n","import type {\n\tCommandNames,\n\tCommandPayload,\n\tDispatchResult,\n\tPipelineError,\n\tStateData,\n\tStateNames,\n\tWorkflow,\n\tWorkflowConfig,\n\tWorkflowDefinition,\n} from \"@rytejs/core\";\nimport { migrate, type WorkflowRouter } from \"@rytejs/core\";\nimport type { WorkflowStore, WorkflowStoreOptions, WorkflowStoreSnapshot } from \"./types.js\";\n\nexport function createWorkflowStore<\n\tTConfig extends WorkflowConfig,\n\tTDeps,\n\tS extends StateNames<TConfig>,\n>(\n\trouter: WorkflowRouter<TConfig, TDeps>,\n\tinitialConfig: {\n\t\tstate: S;\n\t\tdata: StateData<TConfig, S>;\n\t\tid?: string;\n\t},\n\toptions?: WorkflowStoreOptions<TConfig>,\n): WorkflowStore<TConfig> {\n\tconst definition = router.definition;\n\n\tlet workflow: Workflow<TConfig> = loadOrCreate(definition, initialConfig, options);\n\tlet isDispatching = false;\n\tlet error: PipelineError<TConfig> | null = null;\n\tlet snapshot: WorkflowStoreSnapshot<TConfig> = {\n\t\tworkflow,\n\t\tisLoading: false,\n\t\tisDispatching,\n\t\terror,\n\t};\n\tconst listeners = new Set<() => void>();\n\n\tfunction notify() {\n\t\tsnapshot = { workflow, isLoading: false, isDispatching, error };\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t}\n\n\tconst dispatch = async <C extends CommandNames<TConfig>>(\n\t\tcommand: C,\n\t\tpayload: CommandPayload<TConfig, C>,\n\t): Promise<DispatchResult<TConfig>> => {\n\t\tisDispatching = true;\n\t\tnotify();\n\n\t\tconst result = await router.dispatch(workflow, command, payload);\n\n\t\tif (result.ok) {\n\t\t\tworkflow = result.workflow;\n\t\t\terror = null;\n\t\t} else {\n\t\t\terror = result.error;\n\t\t}\n\t\tisDispatching = false;\n\t\tnotify();\n\n\t\tif (result.ok && options?.persist) {\n\t\t\tconst { key, storage } = options.persist;\n\t\t\tconst snap = definition.serialize(workflow);\n\t\t\tstorage.setItem(key, JSON.stringify(snap));\n\t\t}\n\n\t\treturn result;\n\t};\n\n\treturn {\n\t\tgetWorkflow: () => workflow,\n\t\tgetSnapshot: () => snapshot,\n\t\tsubscribe: (listener) => {\n\t\t\tlisteners.add(listener);\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t};\n\t\t},\n\t\tdispatch,\n\t\tsetWorkflow: (newWorkflow) => {\n\t\t\tworkflow = newWorkflow;\n\t\t\terror = null;\n\t\t\tnotify();\n\t\t},\n\t\tcleanup() {},\n\t};\n}\n\nfunction loadOrCreate<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n\toptions?: WorkflowStoreOptions<TConfig>,\n): Workflow<TConfig> {\n\tif (options?.persist) {\n\t\tconst { key, storage, migrations } = options.persist;\n\t\ttry {\n\t\t\tconst stored = storage.getItem(key);\n\t\t\tif (stored) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown structure from storage\n\t\t\t\tlet parsed: any = JSON.parse(stored);\n\t\t\t\tif (migrations) {\n\t\t\t\t\tconst migrated = migrate(migrations, parsed);\n\t\t\t\t\tif (migrated.ok) {\n\t\t\t\t\t\tparsed = migrated.snapshot;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn createFresh(definition, initialConfig);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst restored = definition.deserialize(parsed);\n\t\t\t\tif (restored.ok) {\n\t\t\t\t\treturn restored.workflow;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Invalid JSON or deserialize failed — fall through to create fresh\n\t\t}\n\t}\n\n\treturn createFresh(definition, initialConfig);\n}\n\nfunction createFresh<TConfig extends WorkflowConfig, S extends StateNames<TConfig>>(\n\tdefinition: WorkflowDefinition<TConfig>,\n\tinitialConfig: { state: S; data: StateData<TConfig, S>; id?: string },\n): Workflow<TConfig> {\n\treturn definition.createWorkflow(initialConfig.id ?? crypto.randomUUID(), {\n\t\tinitialState: initialConfig.state,\n\t\tdata: initialConfig.data,\n\t});\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rytejs/react",
3
- "version": "0.7.1",
3
+ "version": "0.9.0",
4
4
  "description": "React bindings for @rytejs/core — use workflows as reactive state stores",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,7 +34,7 @@
34
34
  ],
35
35
  "peerDependencies": {
36
36
  "react": ">=18",
37
- "@rytejs/core": "^0.7.1"
37
+ "@rytejs/core": "^0.9.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@testing-library/jest-dom": "^6.9.1",
@@ -48,7 +48,7 @@
48
48
  "typescript": "^5.9.0",
49
49
  "vitest": "^4.0.0",
50
50
  "zod": "^4.3.0",
51
- "@rytejs/core": "0.7.1"
51
+ "@rytejs/core": "0.9.0"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">=20"