@vielzeug/codex 3.1.0 → 26.10.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/data/catalog.json +124 -36
- package/data/llms-full.txt +2335 -679
- package/data/llms.txt +5 -3
- package/data/manifest.json +1 -1
- package/data/packages/arsenal.json +30 -6
- package/data/packages/assay.json +11 -19
- package/data/packages/clockwork.json +30 -27
- package/data/packages/codex.json +4 -4
- package/data/packages/conduit.json +33 -34
- package/data/packages/courier.json +15 -14
- package/data/packages/dnd.json +2 -2
- package/data/packages/familiar.json +24 -3
- package/data/packages/flux.json +9 -6
- package/data/packages/focus.json +16 -6
- package/data/packages/gesture.json +10 -4
- package/data/packages/herald.json +7 -8
- package/data/packages/illusionist.json +1 -1
- package/data/packages/keymap.json +11 -7
- package/data/packages/ledger.json +25 -25
- package/data/packages/lingua.json +2 -2
- package/data/packages/mesh.json +29 -31
- package/data/packages/necromancer.json +3 -2
- package/data/packages/orbit.json +4 -3
- package/data/packages/ore.json +4 -3
- package/data/packages/postmaster.json +24 -24
- package/data/packages/pulse.json +28 -28
- package/data/packages/refine.json +6 -4
- package/data/packages/ripple.json +2 -2
- package/data/packages/sandbox.json +2 -2
- package/data/packages/scout.json +13 -7
- package/data/packages/scroll.json +7 -7
- package/data/packages/sentinel.json +26 -15
- package/data/packages/sigil.json +3 -3
- package/data/packages/spell.json +25 -30
- package/data/packages/tandem.json +29 -0
- package/data/packages/tavern.json +23 -0
- package/data/packages/tempo.json +44 -42
- package/data/packages/vault.json +9 -19
- package/data/packages/ward.json +26 -29
- package/data/packages/wayfinder.json +20 -13
- package/data/refine.json +4002 -3266
- package/data/search.json +198 -163
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -12
- package/skills/vielzeug/SKILL.md +2 -0
- package/dist/advanced.d.ts +0 -12
- package/dist/advanced.js +0 -13
- package/dist/advanced.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"apiSource": "export {
|
|
2
|
+
"apiSource": "export {\n ClockworkDefinitionError,\n ClockworkError,\n ClockworkSnapshotError,\n ClockworkTransitionLimitError,\n} from './errors.js';\nexport { defineMachine } from './interpret.js';\nexport type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';\n",
|
|
3
3
|
"docs": {
|
|
4
|
-
"index": "---\ntitle: Clockwork — Typed finite state machines for TypeScript\ndescription: Framework-neutral typed state machines with pure transitions, actor-owned runtime work, timers, invokes, and explicit effects.\npackage: clockwork\ncategory: state\nkeywords: [state-machine, finite-state, typed, actor, async-tasks]\nrelated: [herald, ripple, ward]\nexports: [defineMachine, ClockworkError, Machine, Actor, MachineConfig, MachineSnapshot]\nenvironments: [browser, node, ssr, deno]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"clockwork\" />\n\n## Why Clockwork?\n\nApplication workflows often mix state changes with timers, requests, rendering, and cleanup. Clockwork keeps transition logic pure while each disposable actor owns runtime work. You can test state decisions without starting effects or invokes.\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\n// Before\nif (status === 'idle') status = 'loading';\nfetchItems().then((items) => {\n status = 'ready';\n data = items;\n});\n\n// After\ntype Event = { type: 'FETCH' } | { items: string[]; type: 'DONE' };\nconst machine = defineMachine<{ items: string[] }, Event>()({\n context: { items: [] },\n initial: 'idle',\n states: {\n idle: { on: { FETCH: { target: 'loading' } } },\n loading: {\n invoke: [{\n src: ({ signal }) => fetch('/api/items', { signal }).then((response) => response.json() as Promise<string[]>),\n onDone: ({ result }) => ({ items: result, type: 'DONE' }),\n }],\n on: { DONE: { reduce: ({ event }) => ({ items: event.items }), target: 'ready' } },\n },\n ready: {},\n },\n});\n```\n\n| Feature | Clockwork | XState | Zustand |\n| --- | --- | --- | --- |\n| Bundle size | <PackageInfo package=\"clockwork\" type=\"size\" /> | Larger actor/statechart runtime | Smaller store runtime |\n| Zero dependencies | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> |\n| Pure transition API | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"triangle-alert\" size=\"16\"></ore-icon> Statechart-focused | <ore-icon name=\"x\" size=\"16\"></ore-icon> |\n| Owned cancellation | <ore-icon name=\"check\" size=\"16\"></ore-icon> Actor disposal | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> |\n| Framework coupling | <ore-icon name=\"check\" size=\"16\"></ore-icon> None | <ore-icon name=\"check\" size=\"16\"></ore-icon> None | <ore-icon name=\"check\" size=\"16\"></ore-icon> None |\n\n<div class=\"decision-callout\">\n\n**Use Clockwork when** your feature has explicit workflow states, cancellable work, or effects that must run after a state commit.\n\n**Consider XState when** you need statecharts, visual tooling, or its broader actor ecosystem.\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/clockwork\n```\n\n```sh [npm]\nnpm install @vielzeug/clockwork\n```\n\n```sh [yarn]\nyarn add @vielzeug/clockwork\n```\n\n:::\n\n## Quick Start\n\nDefine the context and event union, create an actor, observe its snapshot, then dispose it when its owner ends.\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\ntype Event = { type: 'DEC' } | { type: 'INC' };\n\nconst counter = defineMachine<{ count: number }, Event>()({\n context: { count: 0 },\n initial: 'idle',\n states: {\n idle: {\n on: {\n DEC: { reduce: ({ context }) => ({ count: context.count - 1 }), target: 'idle' },\n INC: { reduce: ({ context }) => ({ count: context.count + 1 }), target: 'idle' },\n },\n },\n },\n});\n\nusing actor = counter.createActor();\nactor.subscribe((snapshot) => console.log(snapshot));\nactor.send({ type: 'INC' });\n// { context: { count: 1 }, state: 'idle' }\n```\n\n## Features\n\n<div class=\"features-grid\">\n\n- **`defineMachine()`** —
|
|
5
|
-
"api": "---\ntitle: Clockwork — API Reference\ndescription: Reference for Clockwork machine definitions, actors, and types.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `defineMachine()` | Compile a typed flat machine definition | Sync | Call the generic factory before supplying the definition |\n| `Machine.transition()` | Resolve a pure next snapshot | Sync | Does not run effects, invokes, or timers |\n| `Machine.createActor()` | Create a runtime owner | Sync | Fresh and restored actors have different entry behavior |\n| `Actor.send()` | Dispatch an event | Sync | Returns `void`; re-entrant events queue internally |\n| `Actor.subscribe()` | Observe committed snapshots | Sync | Observes only; it does not trace sends or errors |\n| `ClockworkError` | Report definition and snapshot validation failures | Sync | Use `code`, not message text |\n\n## Package Entry Points\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/clockwork` | Machine compiler, actor runtime, errors, and types |\n\n## Exported Surface\n\nCallback parameter types are inferred for inline definitions. Clockwork also exports reusable callback, transition, state-node, actor-option, result, and error-context types for shared helpers.\n\n| Primary export | Kind |\n| --- | --- |\n| `defineMachine` | Function |\n| `Machine` | Type |\n| `Actor` | Type |\n| `MachineSnapshot` | Type |\n| `MachineConfig` | Type |\n| `ClockworkError` | Class |\n\nAdditional exported types: `ActorErrorContext`, `ActorOptions`, `After`, `Effect`, `EffectArgs`, `EventByType`, `EventType`, `Guard`, `Invoke`, `InvokeArgs`, `MachineEvent`, `Reducer`, `StateNode`, `Transition`, `TransitionInput`, and `TransitionResult`.\n\n## Core Functions\n\n### `defineMachine()`\n\n```ts\nfunction defineMachine<\n Context extends Record<string, unknown> = Record<string, never>,\n Event extends MachineEvent = MachineEvent,\n>(): <State extends string>(definition: MachineConfig<State, Context, Event>) => Machine<State, Context, Event>;\n```\n\nReturns a factory that validates and compiles a typed flat machine definition. Definitions and their structural entries must be ordinary or null-prototype records, not arrays or class instances. Context follows the same record rule; omit it only when the context type has no keys. Compilation snapshots invoke and transition callback references.\n\nThe curried signature is required so TypeScript can infer `State` from the `states` object while you explicitly provide `Context` and `Event`. TypeScript does not support partial type argument inference, so the state-key union cannot be inferred in a single non-curried call when the context and event generics are explicit.\n\n**Returns:** A definition function that returns `Machine`.\n\n**Example:**\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\ntype Event = { type: 'START' };\n\nconst machine = defineMachine<Record<string, never>, Event>()({\n initial: 'idle',\n states: { idle: { on: { START: { target: 'running' } } }, running: {} },\n});\n```\n\nThrows `ClockworkError` when a definition has an invalid context, initial state, target, transition, effect, invoke, or timer delay.\n\n---\n\n### `Actor.subscribe()`\n\n```ts\nsubscribe(listener: (snapshot: MachineSnapshot<State, Context>) => void): () => void;\n```\n\nSubscribes to future committed actor snapshots. It does not run immediately; read `actor.snapshot` for the initial value. Returns an unsubscribe function. Subscriber failures are reported through `onError` without stopping remaining subscribers, declared effects, or the actor.\n\n**Example:**\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\nconst machine = defineMachine<Record<string, never>, { type: 'NEXT' }>()({\n initial: 'idle',\n states: { idle: { on: { NEXT: { target: 'idle' } } } },\n});\n\nconst actor = machine.createActor();\nconst stop = actor.subscribe((snapshot) => console.debug(snapshot));\nactor.send({ type: 'NEXT' });\nstop();\nactor.dispose();\n```\n\n## Machine Methods\n\n### `machine.transition()`\n\n```ts\ntransition(\n snapshot: MachineSnapshot<State, Context>,\n event: Event,\n): TransitionResult<State, Context>;\n```\n\nResolves a snapshot for one user event without actor runtime work.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `snapshot` | `MachineSnapshot<State, Context>` | Input state and context |\n| `event` | `Event` | User event to evaluate |\n\n**Returns:** A `TransitionResult` with `transition` or `ignored` type.\n\n**Example:**\n\n```ts\nconst result = machine.transition(machine.initialSnapshot, { type: 'START' });\n```\n\n---\n\n### `machine.can()`\n\n```ts\ncan(snapshot: MachineSnapshot<State, Context>, event: Event): boolean;\n```\n\nReturns whether a transition exists and its guard passes.\n\n**Returns:** `true` when the supplied snapshot accepts the event.\n\n---\n\n### `machine.createActor()`\n\n```ts\ncreateActor(options?: ActorOptions<State, Context, Event>): Actor<State, Context, Event>;\n```\n\nCreates an independent actor for event dispatch, timers, invokes, effects, subscriptions, and disposal. A fresh actor starts the initial state's entry effects and resources. An actor restored with `options.snapshot` starts only the restored state's resources: invokes and timers, not entry effects.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `options.snapshot` | `MachineSnapshot<State, Context>` | Optional restored actor snapshot |\n| `options.maxTransitions` | `number` | Positive queued-transition limit for one synchronous flush |\n| `options.onError` | `(error, context) => void` | Side-channel observation callback for runtime failures |\n\n**Returns:** Disposable `Actor`.\n\n**Example:**\n\n```ts\nconst actor = machine.createActor({\n onError(error, { phase, state }) {\n console.error(phase, state, error);\n },\n snapshot: { context: {}, state: 'idle' },\n});\n```\n\n## Actor Methods\n\n### `actor.send()`\n\n```ts\nsend(event: Event): void;\n```\n\nDispatches a user event to the current actor state. Events sent while the actor is processing queue and flush synchronously; sends to a disposed actor are ignored. For active actors, malformed events without a string `type` log a development warning and are ignored. Valid but unhandled event types are ignored without a warning. Use `actor.snapshot` after sending to read the current snapshot.\n\n**Returns:** Nothing.\n\n---\n\n### `actor.can()`\n\n```ts\ncan(event: Event): boolean;\n```\n\nReturns whether the current actor snapshot accepts an event. A guard failure is reported as a fatal transition error, disposes the actor, and returns `false`. Returns `false` after disposal.\n\n**Returns:** Boolean transition availability.\n\n---\n\n### `actor.subscribe()`\n\n```ts\nsubscribe(listener: (snapshot: MachineSnapshot<State, Context>) => void): () => void;\n```\n\nRegisters a listener for committed snapshots. The listener does not run immediately.\n\n**Returns:** An unsubscribe function.\n\n---\n\n### `actor.dispose()`\n\n```ts\ndispose(): void;\n[Symbol.dispose](): void;\n```\n\nCancels timers and invokes, clears queued events and listeners, and aborts `disposalSignal`.\n\n**Returns:** Nothing. Idempotent.\n\n## Error Handling Policy\n\nMachine-execution failures are fail-stop: guard, reducer, effect, invoke, timer, and queued-transition-limit failures dispose the actor. Subscriber failures are observational: Clockwork reports them, continues the stable subscriber snapshot and declared effects, and keeps the actor active.\n\nThe optional `onError` callback receives the error and its phase/state context but cannot control disposition. Errors thrown by this observer are swallowed so error reporting cannot change synchronous, timer, or invoke behavior.\n\n```ts\ntype ActorErrorContext<State, Event> = {\n readonly event?: Event;\n readonly phase: 'effect' | 'invoke' | 'subscriber' | 'transition';\n readonly state: State;\n};\n```\n\nSubscriber iteration uses a stable snapshot: listeners added during notification begin with the next transition.\n\n## Types\n\n### `MachineSnapshot<State, Context>`\n\n```ts\ntype MachineSnapshot<State extends string, Context extends Record<string, unknown>> = {\n readonly context: Readonly<Context>;\n readonly state: State;\n};\n```\n\nClockwork shallow-clones and freezes each snapshot and its context record. Nested context values remain caller-owned and are not deep-frozen.\n\n### `MachineConfig<State, Context, Event>`\n\n```ts\ntype MachineConfig<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> =\n (keyof Context extends never ? { readonly context?: Context } : { readonly context: Context }) & {\n readonly initial: State;\n readonly states: Record<State, StateNode<State, Context, Event>>;\n };\n```\n\nA flat machine definition. State nodes cannot contain child states. The `StateNode`, `Transition`, `After`, `Invoke`, `Effect`, `Guard`, and `Reducer` shapes are inferred inline and exported for reusable helpers. `After.delay` must be finite and between 0 and 2,147,483,647 milliseconds; delayed guards and reducers receive `event: undefined`.\n\n### `Actor<State, Context, Event>`\n\n```ts\ntype Actor<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n [Symbol.dispose](): void;\n can(event: Event): boolean;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n send(event: Event): void;\n readonly snapshot: MachineSnapshot<State, Context>;\n subscribe(listener: (snapshot: MachineSnapshot<State, Context>) => void): () => void;\n};\n```\n\nAn actor's `snapshot` is the current plain readonly snapshot.\n\n### `Machine<State, Context, Event>`\n\n```ts\ntype Machine<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n can(snapshot: MachineSnapshot<State, Context>, event: Event): boolean;\n createActor(options?: ActorOptions<State, Context, Event>): Actor<State, Context, Event>;\n readonly initialSnapshot: MachineSnapshot<State, Context>;\n transition(snapshot: MachineSnapshot<State, Context>, event: Event): TransitionResult<State, Context>;\n};\n```\n\nA compiled, reusable machine. Its transition lookup is map-based, so unknown or poison event names such as `__proto__` are safely ignored when no transition exists.\n\n## Errors\n\n### `ClockworkError`\n\n`ClockworkError` reports invalid definitions, contexts, snapshots, and actor transition limits. It has `code`, `details`, and standard `Error` fields. Use `instanceof ClockworkError` to narrow an unknown error.\n\n```ts\nif (error instanceof ClockworkError) {\n console.error(error.code, error.details);\n}\n```\n",
|
|
6
|
-
"usage": "---\ntitle: Clockwork — Usage Guide\ndescription: Build deterministic state machines with pure transitions and actor-owned runtime work.\n---\n\n[[toc]]\n\n## Basic Usage\n\nCall `defineMachine<Context, Event>()` first to bind context and event types; the returned definition function infers state labels from `states`. Context is optional only when its type has no keys. Create one actor for each independently owned workflow.\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\ntype Event = { type: 'TOGGLE' };\n\nconst machine = defineMachine<Record<string, never>, Event>()({\n initial: 'on',\n states: {\n off: { on: { TOGGLE: { target: 'on' } } },\n on: { on: { TOGGLE: { target: 'off' } } },\n },\n});\n\nconst actor = machine.createActor();\nactor.send({ type: 'TOGGLE' });\nconsole.log(actor.snapshot.state); // 'off'\nactor.dispose();\n```\n\nDispose actors when a feature, request, or test ends. You can use `using` when the surrounding runtime supports `Symbol.dispose`.\n\n```ts\nusing actor = machine.createActor();\nactor.send({ type: 'TOGGLE' });\n```\n\n## Context reducers\n\nA reducer receives readonly context and returns the next context. Clockwork shallow-clones and freezes each snapshot and context record; nested values are not deep-cloned, so make explicit nested replacements.\n\n```ts\ntype Event = { type: 'DEC' } | { type: 'INC' } | { type: 'RESET' };\n\nconst counter = defineMachine<{ count: number }, Event>()({\n context: { count: 0 },\n initial: 'idle',\n states: {\n idle: {\n on: {\n DEC: { reduce: ({ context }) => ({ count: context.count - 1 }), target: 'idle' },\n INC: { reduce: ({ context }) => ({ count: context.count + 1 }), target: 'idle' },\n RESET: { reduce: () => ({ count: 0 }), target: 'idle' },\n },\n },\n },\n});\n```\n\nKeep reducers pure. Make nested copies yourself when nested data changes.\n\n```ts\nSAVE: {\n reduce: ({ context, event }) => ({\n ...context,\n profile: { ...context.profile, name: event.name },\n }),\n target: 'editing',\n}\n```\n\n## Guards\n\nGuards decide whether a transition can run. They receive readonly context and the matching event. For several choices, use an ordered array; the first passing guard wins.\n\n```ts\nPAY: [\n {\n guard: ({ context }) => context.balance >= context.total,\n reduce: ({ context }) => ({ ...context, balance: context.balance - context.total }),\n target: 'success',\n },\n { target: 'insufficientFunds' },\n]\n```\n\nCall `actor.can(event)` for the current actor snapshot or `machine.can(snapshot, event)` for an arbitrary snapshot.\n\n## Pure transitions\n\n`machine.transition()` enables isolated unit tests and decision UIs. It returns the unchanged snapshot with `type: 'ignored'` when no transition matches; it does not expose or run effects.\n\n```ts\nconst result = counter.transition(\n { context: { count: 3 }, state: 'idle' },\n { type: 'INC' },\n);\n\nif (result.type === 'transition') {\n console.log(result.snapshot.context.count); // 4\n}\n```\n\n## Effects\n\nEntry, exit, and transition effects run only through an actor. The actor commits, establishes target-state timers and invokes, notifies a stable subscriber snapshot, then runs exit, transition, and entry effects. Subscriber failures are reported but cannot skip declared effects. Effects cannot change context; send a regular event for another state change.\n\n```ts\ntype WorkflowEvent = { type: 'SUBMIT' };\nconst workflow = defineMachine<{ orderId: string }, WorkflowEvent>()({\n context: { orderId: '' },\n initial: 'draft',\n states: {\n draft: {\n on: {\n SUBMIT: {\n effects: [({ context }) => console.debug('submitted', context)],\n target: 'submitted',\n },\n },\n },\n submitted: { entry: [({ context }) => console.log(`Submitted ${context.orderId}`)] },\n },\n});\n```\n\nEffects receive `context`, the triggering `event` (or `undefined` for initial entry), actor `send`, and the actor lifetime `signal`.\n\n## Async invokes\n\nInvokes start on state entry. `src` gets readonly entry context, the triggering event or `undefined`, and an `AbortSignal`. `onDone` or `onError` map settlement to ordinary events. All invokes are cancelled when the actor exits the state or disposes.\n\n```ts\ntype LoadEvent =\n | { type: 'FETCH' }\n | { items: string[]; type: 'SUCCESS' }\n | { message: string; type: 'FAILURE' }\n | { type: 'RETRY' };\n\nconst loader = defineMachine<{ error: string; items: string[] }, LoadEvent>()({\n context: { error: '', items: [] },\n initial: 'idle',\n states: {\n idle: { on: { FETCH: { target: 'loading' } } },\n loading: {\n invoke: [{\n src: async ({ signal }) => {\n const response = await fetch('/api/items', { signal });\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n return response.json() as Promise<string[]>;\n },\n onDone: ({ result }) => ({ items: result, type: 'SUCCESS' }),\n onError: ({ error }) => ({ message: String(error), type: 'FAILURE' }),\n }],\n on: {\n FAILURE: { reduce: ({ event }) => ({ error: event.message, items: [] }), target: 'error' },\n SUCCESS: { reduce: ({ event }) => ({ error: '', items: event.items }), target: 'ready' },\n },\n },\n ready: {},\n error: { on: { RETRY: { target: 'loading' } } },\n },\n});\n```\n\n## Delayed transitions\n\n`after` starts timers on state entry and cancels them on exit or disposal. Delay must be finite and between 0 and 2,147,483,647 milliseconds. Guards and reducers receive `event: undefined`; a user event with `type: '$after'` remains a normal user event.\n\n```ts\ntype NotificationEvent = { type: 'DISMISS' } | { message: string; type: 'SHOW' };\nconst notification = defineMachine<{ message: string }, NotificationEvent>()({\n context: { message: '' },\n initial: 'hidden',\n states: {\n hidden: { on: { SHOW: { reduce: ({ event }) => ({ message: event.message }), target: 'visible' } } },\n visible: {\n after: [{ delay: 5_000, target: 'hidden' }],\n on: { DISMISS: { target: 'hidden' } },\n },\n },\n});\n```\n\n## Snapshot observation and persistence\n\n`actor.snapshot` is the current shallow-frozen `MachineSnapshot`; read it directly rather than calling a snapshot method. Use `subscribe()` to integrate a state library or persist future committed snapshots. Fresh actors run their initial entry effects and resources; restored actors start only the restored state's invokes and timers, not its entry effects.\n\n```ts\nconst stored = sessionStorage.getItem('wizard');\nconst actor = machine.createActor({\n snapshot: stored ? JSON.parse(stored) : undefined,\n});\n\nconst stopSaving = actor.subscribe((snapshot) => {\n sessionStorage.setItem('wizard', JSON.stringify(snapshot));\n});\n\nconsole.log(actor.snapshot);\nstopSaving();\nactor.dispose();\n```\n\nValidate untrusted persisted data before passing it to `createActor()`. Clockwork validates the restored state name but cannot validate application-specific context fields.\n\n## Error handling\n\nGuard, reducer, effect, invoke, timer, and transition-limit failures dispose the actor. Subscriber failures are reported but do not dispose the actor or interrupt remaining subscribers and declared effects.\n\nUse `onError` to observe either class without controlling disposition. The callback receives the error and its `phase` and `state`; callback failures are swallowed so observation cannot alter actor behavior.\n\n```ts\nconst actor = machine.createActor({\n onError(error, { event, phase, state }) {\n console.error({ error, event, phase, state });\n },\n});\n```\n\nFor fatal machine failures, the observer runs before disposal. Without `onError`, fatal failures dispose silently.\n\n## Debugging\n\nUse `actor.subscribe()` to observe committed snapshots during development. It observes snapshots only; it does not trace dispatched events or runtime errors.\n\n```ts\nconst actor = machine.createActor();\nconst stop = actor.subscribe((snapshot) => console.debug(snapshot));\nactor.send({ type: 'NEXT' });\nstop();\nactor.dispose();\n```\n\nFor richer inspection, route snapshots to application devtools. Clockwork intentionally has no internal trace buffer.\n\n## Flat state maps\n\nClockwork has flat state IDs. Prefer explicit states such as `editingDraft` and `editingSaving`, or compose several actors when domains have independent lifecycles.\n\n## SSR\n\nReuse a compiled machine definition, but create and dispose an actor per request. Never share an actor across concurrent requests.\n\n## Testing\n\nTest deterministic state behavior through `machine.transition()`. Create actors only for timers, invokes, effects, queueing, subscriptions, or disposal behavior.\n\n```ts\nimport { expect, test } from 'vitest';\n\ntest('increments without an actor', () => {\n const result = counter.transition(\n { context: { count: 2 }, state: 'idle' },\n { type: 'INC' },\n );\n\n expect(result).toMatchObject({\n snapshot: { context: { count: 3 }, state: 'idle' },\n type: 'transition',\n });\n});\n```\n\n## Framework Integration\n\nBridge the current actor snapshot into renderer state through one subscription. Dispose that subscription with component lifecycle.\n\n::: code-group\n\n```ts [React]\nimport { useSyncExternalStore } from 'react';\n\nfunction useActor<Value>(actor: { readonly snapshot: Value; subscribe(listener: (snapshot: Value) => void): () => void }) {\n return useSyncExternalStore(\n (notify) => actor.subscribe(() => notify()),\n () => actor.snapshot,\n () => actor.snapshot,\n );\n}\n```\n\n```ts [Vue 3]\nimport { onUnmounted, shallowRef } from 'vue';\n\nconst snapshot = shallowRef(actor.snapshot);\nconst stop = actor.subscribe((next) => (snapshot.value = next));\nonUnmounted(stop);\n```\n\n```ts [Svelte]\nimport { onDestroy } from 'svelte';\n\nlet snapshot = actor.snapshot;\nconst stop = actor.subscribe((next) => (snapshot = next));\nonDestroy(stop);\n```\n\n:::\n\n## Working with Other Vielzeug Libraries\n\nUse Herald when separate actors exchange application events. Bridge Clockwork snapshots into Ripple only at a UI or application boundary.\n\n```ts\nimport { createBus } from '@vielzeug/herald';\n\nconst bus = createBus<{ REFRESH: void }>();\nbus.on('REFRESH', () => actor.send({ type: 'FETCH' }));\n```\n\n## Best Practices\n\n- Define context and event unions with `defineMachine<Context, Event>()`.\n- Return replacement context from reducers; do not rely on runtime copying or freezing.\n- Keep guards and reducers pure.\n- Use actors for effects, timers, invokes, subscriptions, and cancellation.\n- Read the current snapshot from `actor.snapshot`, not a wrapper value.\n- Validate persisted context before restoring a snapshot.\n- Dispose every actor at its ownership boundary.\n- Route runtime failures through the `onError` observer for logging and diagnostics.\n",
|
|
4
|
+
"index": "---\ntitle: Clockwork — Typed finite state machines for TypeScript\ndescription: Framework-neutral typed state machines with pure transitions, actor-owned runtime work, timers, invokes, and explicit effects.\npackage: clockwork\ncategory: state\nkeywords: [state-machine, finite-state, typed, actor, async-tasks]\nrelated: [herald, ripple, ward]\nexports: [defineMachine, ClockworkError, Machine, Actor, MachineConfig, MachineSnapshot]\nenvironments: [browser, node, ssr, deno]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"clockwork\" />\n\n## Why Clockwork?\n\nApplication workflows often mix state changes with timers, requests, rendering, and cleanup. Clockwork keeps transition logic pure while each disposable actor owns runtime work. You can test state decisions without starting effects or invokes.\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\n// Before\nif (status === 'idle') status = 'loading';\nfetchItems().then((items) => {\n status = 'ready';\n data = items;\n});\n\n// After\ntype Event = { type: 'FETCH' } | { items: string[]; type: 'DONE' };\nconst machine = defineMachine<{ items: string[] }, Event>()({\n context: { items: [] },\n initial: 'idle',\n states: {\n idle: { on: { FETCH: { target: 'loading' } } },\n loading: {\n invoke: [{\n src: ({ signal }) => fetch('/api/items', { signal }).then((response) => response.json() as Promise<string[]>),\n onDone: ({ result }) => ({ items: result, type: 'DONE' }),\n }],\n on: { DONE: { reduce: ({ event }) => ({ items: event.items }), target: 'ready' } },\n },\n ready: {},\n },\n});\n```\n\n| Feature | Clockwork | XState | Zustand |\n| --- | --- | --- | --- |\n| Bundle size | <PackageInfo package=\"clockwork\" type=\"size\" /> | Larger actor/statechart runtime | Smaller store runtime |\n| Zero dependencies | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> |\n| Pure transition API | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"triangle-alert\" size=\"16\"></ore-icon> Statechart-focused | <ore-icon name=\"x\" size=\"16\"></ore-icon> |\n| Owned cancellation | <ore-icon name=\"check\" size=\"16\"></ore-icon> Actor disposal | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> |\n| Framework coupling | <ore-icon name=\"check\" size=\"16\"></ore-icon> None | <ore-icon name=\"check\" size=\"16\"></ore-icon> None | <ore-icon name=\"check\" size=\"16\"></ore-icon> None |\n\n<div class=\"decision-callout\">\n\n**Use Clockwork when** your feature has explicit workflow states, cancellable work, or effects that must run after a state commit.\n\n**Consider XState when** you need statecharts, visual tooling, or its broader actor ecosystem.\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/clockwork\n```\n\n```sh [npm]\nnpm install @vielzeug/clockwork\n```\n\n```sh [yarn]\nyarn add @vielzeug/clockwork\n```\n\n:::\n\n## Quick Start\n\nDefine the context and event union, create an actor, observe its snapshot, then dispose it when its owner ends.\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\ntype Event = { type: 'DEC' } | { type: 'INC' };\n\nconst counter = defineMachine<{ count: number }, Event>()({\n context: { count: 0 },\n initial: 'idle',\n states: {\n idle: {\n on: {\n DEC: { reduce: ({ context }) => ({ count: context.count - 1 }), target: 'idle' },\n INC: { reduce: ({ context }) => ({ count: context.count + 1 }), target: 'idle' },\n },\n },\n },\n});\n\nusing actor = counter.createActor();\nactor.subscribe((snapshot) => console.log(snapshot));\nactor.send({ type: 'INC' });\n// { context: { count: 1 }, state: 'idle' }\n```\n\n## Features\n\n<div class=\"features-grid\">\n\n- **`defineMachine()`** — defines one flat, typed machine and rejects the footguns types cannot express.\n- **`machine.transition()`** — evaluates a transition without actor runtime work.\n- **`machine.createActor()`** — creates isolated, disposable runtime ownership.\n- **`reduce`** — returns a replacement context from a transition.\n- **`effects`** — run after commit and stable subscriber notification.\n- **`invoke`** — runs cancellable asynchronous work on state entry.\n- **`after`** — schedules cancellable delayed transitions.\n- **`actor.snapshot`** — exposes the current shallow-frozen state/context value.\n\n</div>\n\n## Documentation\n\n<div class=\"doc-links\">\n\n- [Usage Guide](./usage.md)\n- [API Reference](./api.md)\n- [Examples](./examples.md)\n- [Migration Guide](./migration.md)\n\n</div>\n\n## See Also\n\n<div class=\"see-also\">\n\n- [Herald](/herald/) — publish events between independent actors without coupling machine definitions.\n- [Ripple](/ripple/) — bridge actor snapshots into a reactive graph when you need fine-grained rendering.\n- [Ward](/ward/) — call authorization predicates from transition guards.\n\n</div>\n\n<!-- markdownlint-enable MD025 MD033 MD060 -->\n",
|
|
5
|
+
"api": "---\ntitle: Clockwork — API Reference\ndescription: Reference for Clockwork machine definitions, actors, and types.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `defineMachine()` | Define a typed flat machine | Sync | Call the generic factory before supplying the definition |\n| `Machine.transition()` | Resolve a pure next snapshot | Sync | Does not run effects, invokes, or timers |\n| `Machine.createActor()` | Create a runtime owner | Sync | Fresh and restored actors have different entry behavior |\n| `Actor.send()` | Dispatch an event | Sync | Returns `void`; re-entrant events queue internally |\n| `Actor.subscribe()` | Observe committed snapshots | Sync | Observes only; it does not trace sends or errors |\n| `Actor.tap()` | Observe transitions, ignores, errors, disposal | Sync | Handler errors are swallowed; it cannot control disposition |\n| `ClockworkError` | Report definition, snapshot, and transition-limit failures | Sync | Narrow with the error subtypes, not message text |\n\n## Package Entry Points\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/clockwork` | Machine factory, actor runtime, errors, and types |\n\n## Exported Surface\n\nCallback parameter types are inferred for inline definitions. Clockwork also exports reusable callback, transition, state-node, actor-option, result, and error-context types for shared helpers.\n\n| Primary export | Kind |\n| --- | --- |\n| `defineMachine` | Function |\n| `Machine` | Type |\n| `Actor` | Type |\n| `MachineSnapshot` | Type |\n| `MachineConfig` | Type |\n| `ClockworkError` | Class |\n| `ClockworkDefinitionError` | Class |\n| `ClockworkSnapshotError` | Class |\n| `ClockworkTransitionLimitError` | Class |\n\nAdditional exported types: `ActorErrorContext`, `ActorOptions`, `ActorTapEvent`, `After`, `Effect`, `EffectArgs`, `EventByType`, `EventType`, `Guard`, `Invoke`, `InvokeArgs`, `MachineEvent`, `Reducer`, `StateNode`, `Transition`, `TransitionInput`, and `TransitionResult`.\n\n## Core Functions\n\n### `defineMachine()`\n\n```ts\nfunction defineMachine<\n Context extends Record<string, unknown> = Record<string, never>,\n Event extends MachineEvent = MachineEvent,\n>(): <State extends string>(definition: MachineConfig<State, Context, Event>) => Machine<State, Context, Event>;\n```\n\nReturns a factory that accepts a typed flat machine definition. The definition is trusted as typed: targets, callback shapes, and state keys are compiler-checked. `defineMachine()` rejects only what types cannot express — timer delays outside `0..2,147,483,647` ms, empty transition arrays, and a context that is not a plain record (arrays, `null`, and class instances fail). Omit `context` only when the context type has no keys.\n\nThe curried signature is required so TypeScript can infer `State` from the `states` object while you explicitly provide `Context` and `Event`. TypeScript does not support partial type argument inference, so the state-key union cannot be inferred in a single non-curried call when the context and event generics are explicit.\n\n**Returns:** A definition function that returns `Machine`.\n\n**Example:**\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\ntype Event = { type: 'START' };\n\nconst machine = defineMachine<Record<string, never>, Event>()({\n initial: 'idle',\n states: { idle: { on: { START: { target: 'running' } } }, running: {} },\n});\n```\n\nThrows `ClockworkDefinitionError` when a definition carries a timer delay outside the platform range, an empty transition array, or a context that is not a plain record.\n\n---\n\n### `Actor.subscribe()`\n\n```ts\nsubscribe(listener: (snapshot: MachineSnapshot<State, Context>) => void): () => void;\n```\n\nSubscribes to future committed actor snapshots. It does not run immediately; read `actor.snapshot` for the initial value. Returns an unsubscribe function. Subscriber failures are reported through `tap()` as `error` events with `phase: 'subscriber'` without stopping remaining subscribers, declared effects, or the actor.\n\n**Example:**\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\nconst machine = defineMachine<Record<string, never>, { type: 'NEXT' }>()({\n initial: 'idle',\n states: { idle: { on: { NEXT: { target: 'idle' } } } },\n});\n\nconst actor = machine.createActor();\nconst stop = actor.subscribe((snapshot) => console.debug(snapshot));\nactor.send({ type: 'NEXT' });\nstop();\nactor.dispose();\n```\n\n## Machine Methods\n\n### `machine.transition()`\n\n```ts\ntransition(\n snapshot: MachineSnapshot<State, Context>,\n event: Event,\n): TransitionResult<State, Context>;\n```\n\nResolves a snapshot for one user event without actor runtime work.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `snapshot` | `MachineSnapshot<State, Context>` | Input state and context |\n| `event` | `Event` | User event to evaluate |\n\n**Returns:** A `TransitionResult` with `transition` or `ignored` type.\n\n**Example:**\n\n```ts\nconst result = machine.transition(machine.initialSnapshot, { type: 'START' });\n```\n\n---\n\n### `machine.can()`\n\n```ts\ncan(snapshot: MachineSnapshot<State, Context>, event: Event): boolean;\n```\n\nReturns whether a transition exists and its guard passes.\n\n**Returns:** `true` when the supplied snapshot accepts the event.\n\n---\n\n### `machine.createActor()`\n\n```ts\ncreateActor(options?: ActorOptions<State, Context>): Actor<State, Context, Event>;\n```\n\nCreates an independent actor for event dispatch, timers, invokes, effects, subscriptions, and disposal. A fresh actor starts the initial state's entry effects and resources. An actor restored with `options.snapshot` starts only the restored state's resources: invokes and timers, not entry effects.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `options.snapshot` | `MachineSnapshot<State, Context>` | Optional restored actor snapshot |\n\n**Returns:** Disposable `Actor`.\n\n**Example:**\n\n```ts\nconst actor = machine.createActor({ snapshot: { context: {}, state: 'idle' } });\n```\n\n## Actor Methods\n\n### `actor.send()`\n\n```ts\nsend(event: Event): void;\n```\n\nDispatches a user event to the current actor state. Events sent while the actor is processing queue and flush synchronously; sends to a disposed actor are ignored. For active actors, malformed events without a string `type` log a development warning and are ignored. Valid but unhandled event types are ignored without a warning. Use `actor.snapshot` after sending to read the current snapshot.\n\n**Returns:** Nothing.\n\n---\n\n### `actor.can()`\n\n```ts\ncan(event: Event): boolean;\n```\n\nReturns whether the current actor snapshot accepts an event. A guard failure is reported as a fatal transition error, disposes the actor, and returns `false`. Returns `false` after disposal.\n\n**Returns:** Boolean transition availability.\n\n---\n\n### `actor.subscribe()`\n\n```ts\nsubscribe(listener: (snapshot: MachineSnapshot<State, Context>) => void): () => void;\n```\n\nRegisters a listener for committed snapshots. The listener does not run immediately.\n\n**Returns:** An unsubscribe function.\n\n---\n\n### `actor.dispose()`\n\n```ts\ndispose(): void;\n[Symbol.dispose](): void;\n```\n\nCancels timers and invokes, clears queued events, tappers and listeners, emits a final `dispose` tap event, and aborts `disposalSignal`.\n\n**Returns:** Nothing. Idempotent.\n\n### `actor.tap()`\n\n```ts\ntap(\n handler: (event: ActorTapEvent<State, Context, Event>) => void,\n options?: { signal?: AbortSignal },\n): () => void;\n```\n\nObserves actor lifecycle without affecting machine behavior: `{ type: 'transition' | 'ignored' }` carries the event and resulting snapshot, `{ type: 'error' }` carries the error with its `phase`/`state`/`event` context, and `{ type: 'dispose' }` is the final event before tappers are cleared. Handler errors are swallowed. Returns an unsubscribe function.\n\n```ts\nactor.tap((event) => {\n if (event.type === 'error') console.error(event.phase, event.state, event.error);\n});\n```\n\n## Error Handling Policy\n\nMachine-execution failures are fail-stop: guard, reducer, effect, invoke, timer, and queued-transition-limit failures dispose the actor. The queued-transition limit is a fixed internal guard against runaway loops, not a configurable option. Subscriber failures are observational: Clockwork reports them through `tap()`, continues the stable subscriber snapshot and declared effects, and keeps the actor active. Tap handlers cannot control disposition.\n\nSubscriber iteration uses a stable snapshot: listeners added during notification begin with the next transition.\n\n## Types\n\n### `MachineSnapshot<State, Context>`\n\n```ts\ntype MachineSnapshot<State extends string, Context extends Record<string, unknown>> = {\n readonly context: Readonly<Context>;\n readonly state: State;\n};\n```\n\nClockwork shallow-clones and freezes each snapshot and its context record. Nested context values remain caller-owned and are not deep-frozen.\n\n### `MachineConfig<State, Context, Event>`\n\n```ts\ntype MachineConfig<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> =\n (keyof Context extends never ? { readonly context?: Context } : { readonly context: Context }) & {\n readonly initial: State;\n readonly states: Record<State, StateNode<State, Context, Event>>;\n };\n```\n\nA flat machine definition. State nodes cannot contain child states. The `StateNode`, `Transition`, `After`, `Invoke`, `Effect`, `Guard`, and `Reducer` shapes are inferred inline and exported for reusable helpers. `After.delay` must be finite and between 0 and 2,147,483,647 milliseconds; delayed guards and reducers receive `event: undefined`.\n\n### `Actor<State, Context, Event>`\n\n```ts\ntype Actor<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n [Symbol.dispose](): void;\n can(event: Event): boolean;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n send(event: Event): void;\n readonly snapshot: MachineSnapshot<State, Context>;\n subscribe(listener: (snapshot: MachineSnapshot<State, Context>) => void): () => void;\n tap(\n handler: (event: ActorTapEvent<State, Context, Event>) => void,\n options?: { readonly signal?: AbortSignal },\n ): () => void;\n};\n```\n\nAn actor's `snapshot` is the current plain readonly snapshot.\n\n### `ActorTapEvent<State, Context, Event>`\n\n```ts\ntype ActorTapEvent<State, Context, Event> =\n | (ActorErrorContext<State, Event> & { readonly error: unknown; readonly type: 'error' })\n | {\n readonly event: Event | undefined;\n readonly snapshot: MachineSnapshot<State, Context>;\n readonly type: 'transition' | 'ignored';\n }\n | { readonly type: 'dispose' };\n\ntype ActorErrorContext<State, Event> = {\n readonly event?: Event;\n readonly phase: 'effect' | 'invoke' | 'subscriber' | 'transition';\n readonly state: State;\n};\n```\n\n### `Machine<State, Context, Event>`\n\n```ts\ntype Machine<State extends string, Context extends Record<string, unknown>, Event extends MachineEvent> = {\n can(snapshot: MachineSnapshot<State, Context>, event: Event): boolean;\n createActor(options?: ActorOptions<State, Context>): Actor<State, Context, Event>;\n readonly initialSnapshot: MachineSnapshot<State, Context>;\n transition(snapshot: MachineSnapshot<State, Context>, event: Event): TransitionResult<State, Context>;\n};\n```\n\nA reusable machine. Its state and event lookups are own-property guarded, so unknown or prototype-colliding names such as `__proto__` or `constructor` are safely ignored when no transition exists.\n\n## Errors\n\n### `ClockworkError`\n\n`ClockworkError` is the base class for every Clockwork failure, with `details` and standard `Error` fields. Use `instanceof ClockworkError` to narrow an unknown error. Three subtypes carry the failure category:\n\n| Subtype | Raised when |\n| --- | --- |\n| `ClockworkDefinitionError` | `defineMachine()` rejects a definition footgun types cannot express: a timer delay outside `0..2,147,483,647` ms, an empty transition array, or a context that is not a plain record |\n| `ClockworkSnapshotError` | A snapshot, its context, or a reducer result is not a plain object record, or names an undeclared state |\n| `ClockworkTransitionLimitError` | An actor exceeds the fixed queued-transition limit and disposes itself |\n\n```ts\nif (error instanceof ClockworkDefinitionError) {\n console.error(error.message, error.details);\n}\n```\n",
|
|
6
|
+
"usage": "---\ntitle: Clockwork — Usage Guide\ndescription: Build deterministic state machines with pure transitions and actor-owned runtime work.\n---\n\n[[toc]]\n\n## Basic Usage\n\nCall `defineMachine<Context, Event>()` first to bind context and event types; the returned definition function infers state labels from `states`. Context is optional only when its type has no keys. Create one actor for each independently owned workflow.\n\n```ts\nimport { defineMachine } from '@vielzeug/clockwork';\n\ntype Event = { type: 'TOGGLE' };\n\nconst machine = defineMachine<Record<string, never>, Event>()({\n initial: 'on',\n states: {\n off: { on: { TOGGLE: { target: 'on' } } },\n on: { on: { TOGGLE: { target: 'off' } } },\n },\n});\n\nconst actor = machine.createActor();\nactor.send({ type: 'TOGGLE' });\nconsole.log(actor.snapshot.state); // 'off'\nactor.dispose();\n```\n\nDispose actors when a feature, request, or test ends. You can use `using` when the surrounding runtime supports `Symbol.dispose`.\n\n```ts\nusing actor = machine.createActor();\nactor.send({ type: 'TOGGLE' });\n```\n\n## Context reducers\n\nA reducer receives readonly context and returns the next context. Clockwork shallow-clones and freezes each snapshot and context record; nested values are not deep-cloned, so make explicit nested replacements.\n\n```ts\ntype Event = { type: 'DEC' } | { type: 'INC' } | { type: 'RESET' };\n\nconst counter = defineMachine<{ count: number }, Event>()({\n context: { count: 0 },\n initial: 'idle',\n states: {\n idle: {\n on: {\n DEC: { reduce: ({ context }) => ({ count: context.count - 1 }), target: 'idle' },\n INC: { reduce: ({ context }) => ({ count: context.count + 1 }), target: 'idle' },\n RESET: { reduce: () => ({ count: 0 }), target: 'idle' },\n },\n },\n },\n});\n```\n\nKeep reducers pure. Make nested copies yourself when nested data changes.\n\n```ts\nSAVE: {\n reduce: ({ context, event }) => ({\n ...context,\n profile: { ...context.profile, name: event.name },\n }),\n target: 'editing',\n}\n```\n\n## Guards\n\nGuards decide whether a transition can run. They receive readonly context and the matching event. For several choices, use an ordered array; the first passing guard wins.\n\n```ts\nPAY: [\n {\n guard: ({ context }) => context.balance >= context.total,\n reduce: ({ context }) => ({ ...context, balance: context.balance - context.total }),\n target: 'success',\n },\n { target: 'insufficientFunds' },\n]\n```\n\nCall `actor.can(event)` for the current actor snapshot or `machine.can(snapshot, event)` for an arbitrary snapshot.\n\n## Pure transitions\n\n`machine.transition()` enables isolated unit tests and decision UIs. It returns the unchanged snapshot with `type: 'ignored'` when no transition matches; it does not expose or run effects.\n\n```ts\nconst result = counter.transition(\n { context: { count: 3 }, state: 'idle' },\n { type: 'INC' },\n);\n\nif (result.type === 'transition') {\n console.log(result.snapshot.context.count); // 4\n}\n```\n\n## Effects\n\nEntry, exit, and transition effects run only through an actor. The actor commits, establishes target-state timers and invokes, notifies a stable subscriber snapshot, then runs exit, transition, and entry effects. Subscriber failures are reported but cannot skip declared effects. Effects cannot change context; send a regular event for another state change.\n\n```ts\ntype WorkflowEvent = { type: 'SUBMIT' };\nconst workflow = defineMachine<{ orderId: string }, WorkflowEvent>()({\n context: { orderId: '' },\n initial: 'draft',\n states: {\n draft: {\n on: {\n SUBMIT: {\n effects: [({ context }) => console.debug('submitted', context)],\n target: 'submitted',\n },\n },\n },\n submitted: { entry: [({ context }) => console.log(`Submitted ${context.orderId}`)] },\n },\n});\n```\n\nEffects receive `context`, the triggering `event` (or `undefined` for initial entry), actor `send`, and the actor lifetime `signal`.\n\n## Async invokes\n\nInvokes start on state entry. `src` gets readonly entry context, the triggering event or `undefined`, and an `AbortSignal`. `onDone` or `onError` map settlement to ordinary events. All invokes are cancelled when the actor exits the state or disposes.\n\n```ts\ntype LoadEvent =\n | { type: 'FETCH' }\n | { items: string[]; type: 'SUCCESS' }\n | { message: string; type: 'FAILURE' }\n | { type: 'RETRY' };\n\nconst loader = defineMachine<{ error: string; items: string[] }, LoadEvent>()({\n context: { error: '', items: [] },\n initial: 'idle',\n states: {\n idle: { on: { FETCH: { target: 'loading' } } },\n loading: {\n invoke: [{\n src: async ({ signal }) => {\n const response = await fetch('/api/items', { signal });\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n return response.json() as Promise<string[]>;\n },\n onDone: ({ result }) => ({ items: result, type: 'SUCCESS' }),\n onError: ({ error }) => ({ message: String(error), type: 'FAILURE' }),\n }],\n on: {\n FAILURE: { reduce: ({ event }) => ({ error: event.message, items: [] }), target: 'error' },\n SUCCESS: { reduce: ({ event }) => ({ error: '', items: event.items }), target: 'ready' },\n },\n },\n ready: {},\n error: { on: { RETRY: { target: 'loading' } } },\n },\n});\n```\n\n## Delayed transitions\n\n`after` starts timers on state entry and cancels them on exit or disposal. Delay must be finite and between 0 and 2,147,483,647 milliseconds. Guards and reducers receive `event: undefined`; a user event with `type: '$after'` remains a normal user event.\n\n```ts\ntype NotificationEvent = { type: 'DISMISS' } | { message: string; type: 'SHOW' };\nconst notification = defineMachine<{ message: string }, NotificationEvent>()({\n context: { message: '' },\n initial: 'hidden',\n states: {\n hidden: { on: { SHOW: { reduce: ({ event }) => ({ message: event.message }), target: 'visible' } } },\n visible: {\n after: [{ delay: 5_000, target: 'hidden' }],\n on: { DISMISS: { target: 'hidden' } },\n },\n },\n});\n```\n\n## Snapshot observation and persistence\n\n`actor.snapshot` is the current shallow-frozen `MachineSnapshot`; read it directly rather than calling a snapshot method. Use `subscribe()` to integrate a state library or persist future committed snapshots. Fresh actors run their initial entry effects and resources; restored actors start only the restored state's invokes and timers, not its entry effects.\n\n```ts\nconst stored = sessionStorage.getItem('wizard');\nconst actor = machine.createActor({\n snapshot: stored ? JSON.parse(stored) : undefined,\n});\n\nconst stopSaving = actor.subscribe((snapshot) => {\n sessionStorage.setItem('wizard', JSON.stringify(snapshot));\n});\n\nconsole.log(actor.snapshot);\nstopSaving();\nactor.dispose();\n```\n\nValidate untrusted persisted data before passing it to `createActor()`. Clockwork validates the restored state name but cannot validate application-specific context fields.\n\n## Error handling\n\nGuard, reducer, effect, invoke, timer, and transition-limit failures dispose the actor. The transition limit is a fixed internal guard against runaway loops. Subscriber failures are reported but do not dispose the actor or interrupt remaining subscribers and declared effects.\n\nUse `tap()` to observe either class without controlling disposition. The `error` event carries the error and its `phase` and `state`; handler failures are swallowed so observation cannot alter actor behavior.\n\n```ts\nconst actor = machine.createActor();\nactor.tap((event) => {\n if (event.type === 'error') console.error({ error: event.error, event: event.event, phase: event.phase, state: event.state });\n});\n```\n\nFor fatal machine failures, the `error` event is emitted before disposal. Without a tap handler, fatal failures dispose silently.\n\n## Debugging\n\nUse `actor.subscribe()` to observe committed snapshots during development. It observes snapshots only; it does not trace dispatched events or runtime errors.\n\n```ts\nconst actor = machine.createActor();\nconst stop = actor.subscribe((snapshot) => console.debug(snapshot));\nactor.send({ type: 'NEXT' });\nstop();\nactor.dispose();\n```\n\nFor richer inspection, route snapshots to application devtools. Clockwork intentionally has no internal trace buffer.\n\n## Flat state maps\n\nClockwork has flat state IDs. Prefer explicit states such as `editingDraft` and `editingSaving`, or compose several actors when domains have independent lifecycles.\n\n## SSR\n\nReuse one machine definition, but create and dispose an actor per request. Never share an actor across concurrent requests.\n\n## Testing\n\nTest deterministic state behavior through `machine.transition()`. Create actors only for timers, invokes, effects, queueing, subscriptions, or disposal behavior.\n\n```ts\nimport { expect, test } from 'vitest';\n\ntest('increments without an actor', () => {\n const result = counter.transition(\n { context: { count: 2 }, state: 'idle' },\n { type: 'INC' },\n );\n\n expect(result).toMatchObject({\n snapshot: { context: { count: 3 }, state: 'idle' },\n type: 'transition',\n });\n});\n```\n\n## Framework Integration\n\nBridge the current actor snapshot into renderer state through one subscription. Dispose that subscription with component lifecycle.\n\n::: code-group\n\n```ts [React]\nimport { useSyncExternalStore } from 'react';\n\nfunction useActor<Value>(actor: { readonly snapshot: Value; subscribe(listener: (snapshot: Value) => void): () => void }) {\n return useSyncExternalStore(\n (notify) => actor.subscribe(() => notify()),\n () => actor.snapshot,\n () => actor.snapshot,\n );\n}\n```\n\n```ts [Vue 3]\nimport { onUnmounted, shallowRef } from 'vue';\n\nconst snapshot = shallowRef(actor.snapshot);\nconst stop = actor.subscribe((next) => (snapshot.value = next));\nonUnmounted(stop);\n```\n\n```ts [Svelte]\nimport { onDestroy } from 'svelte';\n\nlet snapshot = actor.snapshot;\nconst stop = actor.subscribe((next) => (snapshot = next));\nonDestroy(stop);\n```\n\n:::\n\n## Working with Other Vielzeug Libraries\n\nUse Herald when separate actors exchange application events. Bridge Clockwork snapshots into Ripple only at a UI or application boundary.\n\n```ts\nimport { createBus } from '@vielzeug/herald';\n\nconst bus = createBus<{ REFRESH: void }>();\nbus.on('REFRESH', () => actor.send({ type: 'FETCH' }));\n```\n\n## Best Practices\n\n- Define context and event unions with `defineMachine<Context, Event>()`.\n- Return replacement context from reducers; do not rely on runtime copying or freezing.\n- Keep guards and reducers pure.\n- Use actors for effects, timers, invokes, subscriptions, and cancellation.\n- Read the current snapshot from `actor.snapshot`, not a wrapper value.\n- Validate persisted context before restoring a snapshot.\n- Dispose every actor at its ownership boundary.\n- Route runtime failures through the `tap()` observer for logging and diagnostics.\n",
|
|
7
7
|
"examples": "---\ntitle: Clockwork — Examples\ndescription: Practical state machine patterns with pure transitions and actors.\n---\n\n- [Counter with Reset](./examples/counter-with-reset.md)\n- [Form Validation](./examples/form-validation.md)\n- [Auto-Dismiss Notification](./examples/auto-dismiss-notification.md)\n- [Model Nested Workflows with Flat States](./examples/hierarchical-states.md)\n- [Pure Transition Testing](./examples/unit-testing.md)\n- [Auth Flow with Guards](./examples/auth-flow.md)\n- [Data Fetching with Error Recovery](./examples/data-fetching.md)\n- [Fetch with Retry](./examples/fetch-retry.md)\n- [Paginated Data Loading](./examples/paginated-data-loading.md)\n- [Media Player](./examples/media-player.md)\n- [Persisted Wizard](./examples/persisted-wizard.md)\n- [Multi-Step Wizard with Routing](./examples/wizard-with-routing.md)\n- [Shopping Cart Checkout](./examples/checkout.md)\n- [Permission-Based Access Control](./examples/permission-based-access.md)\n- [Event Boundaries](./examples/middleware-pipeline.md)\n- [Multi-Machine Coordination](./examples/multi-machine-coordination.md)\n- [Debugging Transitions](./examples/debugging-transitions.md)\n"
|
|
8
8
|
},
|
|
9
9
|
"examples": [
|
|
@@ -34,33 +34,36 @@
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"id": "pure-transitions-and-errors",
|
|
37
|
-
"code": "import {
|
|
37
|
+
"code": "import { ClockworkDefinitionError, defineMachine } from '@vielzeug/clockwork'\n\nconst machine = defineMachine()({\n context: { role: 'guest' },\n initial: 'locked',\n states: {\n locked: {\n on: {\n UNLOCK: {\n guard: ({ context }) => context.role === 'admin',\n target: 'unlocked',\n },\n },\n },\n unlocked: { on: { LOCK: { target: 'locked' } } },\n },\n})\n\n// Pure transition: no actor, effects, or mutation.\nconst result = machine.transition(\n { context: { role: 'guest' }, state: 'locked' },\n { type: 'UNLOCK' },\n)\nconsole.log('Guest result:', result.type)\n\nfor (const definition of [\n { initial: 'missing', states: { idle: {} } },\n { context: [], initial: 'idle', states: { idle: {} } },\n]) {\n try {\n defineMachine()(definition)\n } catch (error) {\n if (error instanceof ClockworkDefinitionError) {\n console.log('Validation failed:', error.message)\n console.log('Details:', error.details)\n }\n }\n}",
|
|
38
38
|
"name": "Pure Transitions & Errors"
|
|
39
39
|
}
|
|
40
40
|
],
|
|
41
41
|
"typeSignatures": {
|
|
42
|
-
"
|
|
43
|
-
"
|
|
42
|
+
"ClockworkDefinitionError": "export {\n ClockworkDefinitionError,\n ClockworkError,\n ClockworkSnapshotError,\n ClockworkTransitionLimitError,\n} from './errors.js';",
|
|
43
|
+
"ClockworkError": "export {\n ClockworkDefinitionError,\n ClockworkError,\n ClockworkSnapshotError,\n ClockworkTransitionLimitError,\n} from './errors.js';",
|
|
44
|
+
"ClockworkSnapshotError": "export {\n ClockworkDefinitionError,\n ClockworkError,\n ClockworkSnapshotError,\n ClockworkTransitionLimitError,\n} from './errors.js';",
|
|
45
|
+
"ClockworkTransitionLimitError": "export {\n ClockworkDefinitionError,\n ClockworkError,\n ClockworkSnapshotError,\n ClockworkTransitionLimitError,\n} from './errors.js';",
|
|
44
46
|
"defineMachine": "export { defineMachine } from './interpret.js';",
|
|
45
|
-
"Actor": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
46
|
-
"ActorErrorContext": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
47
|
-
"ActorOptions": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
47
|
+
"Actor": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
48
|
+
"ActorErrorContext": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
49
|
+
"ActorOptions": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
50
|
+
"ActorTapEvent": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
51
|
+
"After": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
52
|
+
"Effect": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
53
|
+
"EffectArgs": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
54
|
+
"EventByType": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
55
|
+
"EventType": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
56
|
+
"Guard": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
57
|
+
"Invoke": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
58
|
+
"InvokeArgs": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
59
|
+
"Machine": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
60
|
+
"MachineConfig": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
61
|
+
"MachineEvent": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
62
|
+
"MachineSnapshot": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
63
|
+
"Reducer": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
64
|
+
"StateNode": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
65
|
+
"Transition": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
66
|
+
"TransitionInput": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';",
|
|
67
|
+
"TransitionResult": "export type {\n Actor,\n ActorErrorContext,\n ActorOptions,\n ActorTapEvent,\n After,\n Effect,\n EffectArgs,\n EventByType,\n EventType,\n Guard,\n Invoke,\n InvokeArgs,\n Machine,\n MachineConfig,\n MachineEvent,\n MachineSnapshot,\n Reducer,\n StateNode,\n Transition,\n TransitionInput,\n TransitionResult,\n} from './types.js';"
|
|
65
68
|
}
|
|
66
69
|
}
|
package/data/packages/codex.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"apiSource": "/**\n * `@vielzeug/codex` — supported public contract.\n *\n * Exposes the generic catalog, snapshot loader, errors, and server hosts
|
|
2
|
+
"apiSource": "/**\n * `@vielzeug/codex` — supported public contract.\n *\n * Exposes the generic catalog, snapshot loader, errors, and server hosts.\n * Refine catalog types and tools live behind `@vielzeug/codex/refine`.\n */\nexport { StdioServerTransport } from '@modelcontextprotocol/server/stdio';\nexport { type Catalog, CatalogError, type SearchHit, SnapshotCatalog } from './catalog.js';\nexport { CodexError } from './errors.js';\nexport { type HttpHost, type HttpHostOptions, startHttpHost } from './http.js';\nexport { createMcpServer } from './server.js';\nexport { type LoadedSnapshot, loadSnapshot } from './snapshot.js';\nexport type {\n DocPage,\n Example,\n PackageContent,\n PackageMeta,\n SnapshotManifest,\n} from './types.js';\n",
|
|
3
3
|
"docs": {
|
|
4
|
-
"index": "---\ntitle: Codex\ndescription: Local MCP access to Vielzeug documentation and package metadata.\npackage: codex\ncategory: AI\nkeywords: [mcp, docs, ai]\nrelated: [refine]\nexports: [loadSnapshot, SnapshotCatalog, createMcpServer, startHttpHost, StdioServerTransport, CatalogError, CodexError]\nenvironments: [node]\n---\n\n<PackageHero package=\"codex\" />\n\n## Why Codex?\n\nCodex exposes current Vielzeug catalog data through MCP without scanning source at request time.\n\n## Installation\n\n```sh\npnpm add @vielzeug/codex\n```\n\n## Quick Start\n\n```sh\nnpx -y @vielzeug/codex\n```\n\n## Features\n\n- `loadSnapshot` validates chunked snapshot metadata.\n- `SnapshotCatalog` loads package content only when requested.\n- `createMcpServer` registers generic package tools; `/refine` adds component tools explicitly.\n- Root
|
|
5
|
-
"api": "---\ntitle: Codex API\ndescription: Snapshot, catalog, MCP server, and local HTTP host APIs.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `loadSnapshot` | Read validated snapshot metadata | Sync | Content chunks load lazily |\n| `SnapshotCatalog` | Query package corpus | Sync | Construct from loaded snapshot |\n| `createMcpServer` | MCP adapter factory (generic tools) | Sync | Requires catalog and version |\n| `startHttpHost` | Loopback Streamable HTTP host | Async | HTTP remains local-only |\n| `registerRefineTools` | Opt-in Refine tool registration | Sync | Import from `@vielzeug/codex/refine` |\n
|
|
6
|
-
"usage": "---\ntitle: Codex — Usage Guide\ndescription: Install, connect, develop, and debug the Vielzeug MCP server.\n---\n\n[[toc]]\n\n## Basic Usage\n\nRun local stdio server:\n\n```sh\nnpx -y @vielzeug/codex\n```\n\nUse shipped `mcp-setup.json` for machine-readable generic configuration. Client-specific configuration must use its documented MCP format.\n\n## HTTP Mode\n\nHTTP uses Streamable HTTP and binds loopback only:\n\n```sh\nnpx -y @vielzeug/codex --port=3100\ncurl http://127.0.0.1:3100/health\n```\n\nResponse includes snapshot version. Runtime bind validation and Host/Origin allowlists restrict access to localhost; no remote host mode exists. Programmatic `configureServer` hooks run once per MCP request server, not at host startup. Dispose the host asynchronously and observe `disposed` or `disposalSignal` when coordinating shutdown.\n\n## Agent Skill\n\nCodex ships a `vielzeug` agent skill — a `SKILL.md` that tells an AI agent working in *your* project to discover packages through the MCP tools instead of guessing, to use the owning `@vielzeug/*` package instead of hand-rolling, and to build UI from Refine components, tokens, and theme whenever `@vielzeug/refine` is installed. Install it into the project:\n\n```sh\nnpx -y @vielzeug/codex skills install\nnpx -y @vielzeug/codex skills install --target=.claude/skills\nnpx -y @vielzeug/codex skills install --force # overwrite an existing copy\n```\n\nWithout `--target`, the first existing directory among `.agents/skills`, `.github/skills`, and `.claude/skills` is used; when none exists, `.agents/skills` is created. The command refuses to overwrite an installed skill unless `--force` is passed. Rerun after upgrading codex to pick up the current package list, which is generated from the published manifests. The skill pairs with the MCP server: its lookups (`get-docs`, `refine-get-component`, `refine-validate-usage`, …) assume codex is connected, and it documents `node_modules` fallbacks for when it is not.\n\n## Local Development\n\nRequires Node 22+ and root setup:\n\n```sh\npnpm setup\ncd packages/codex\npnpm test:unit\npnpm test:integration\npnpm dev\n```\n\n`test:unit` uses fixtures only. `test:integration` regenerates a current snapshot then checks real monorepo inputs.\n\n`pnpm dev` watches documentation and package inputs, atomically publishes snapshots, then restarts server when snapshot changes.\n\n## Debugging\n\n```sh\npnpm dev\nnode src/cli.ts --port=3100 --debug\ncurl http://127.0.0.1:3100/health\n```\n\n`--debug` logs tool durations and expected catalog errors to stderr. Build `@vielzeug/refine` before generating snapshot when component metadata changes.\n\n## Programmatic Usage\n\n```ts\nimport { SnapshotCatalog, StdioServerTransport, createMcpServer, loadSnapshot } from '@vielzeug/codex';\n\nconst snapshot = loadSnapshot();\nconst catalog = new SnapshotCatalog(snapshot);\nawait createMcpServer(catalog, { version: snapshot.manifest.version }).connect(new StdioServerTransport());\n```\n\nTo include Refine component tools, upgrade the server with the `@vielzeug/codex/refine` subpath:\n\n```ts\nimport { StdioServerTransport, createMcpServer, loadSnapshot } from '@vielzeug/codex';\nimport { SnapshotRefineCatalog, registerRefineTools } from '@vielzeug/codex/refine';\n\nconst snapshot = loadSnapshot();\nconst catalog = new SnapshotRefineCatalog(snapshot);\nconst server = createMcpServer(catalog, { version: snapshot.manifest.version });\nregisterRefineTools(server, catalog);\nawait server.connect(new StdioServerTransport());\n```\n\n## Best Practices\n\n- Use `search-packages` for capability discovery before loading broad source.\n- Use `get-type-signature` before loading full source.\n- Published package snapshots are static directories; local dev snapshots are immutable generations selected by `.dev/current.json`.\n-
|
|
4
|
+
"index": "---\ntitle: Codex\ndescription: Local MCP access to Vielzeug documentation and package metadata.\npackage: codex\ncategory: AI\nkeywords: [mcp, docs, ai]\nrelated: [refine]\nexports: [loadSnapshot, SnapshotCatalog, createMcpServer, startHttpHost, StdioServerTransport, CatalogError, CodexError]\nenvironments: [node]\n---\n\n<PackageHero package=\"codex\" />\n\n## Why Codex?\n\nCodex exposes current Vielzeug catalog data through MCP without scanning source at request time.\n\n## Installation\n\n```sh\npnpm add @vielzeug/codex\n```\n\n## Quick Start\n\n```sh\nnpx -y @vielzeug/codex\n```\n\n## Features\n\n- `loadSnapshot` validates chunked snapshot metadata.\n- `SnapshotCatalog` loads package content only when requested.\n- `createMcpServer` registers generic package tools; `/refine` adds component tools explicitly.\n- Root and `/refine` entry points publish TypeScript declarations.\n- `startHttpHost` enforces loopback binding plus localhost Host and Origin validation.\n\n## Documentation\n\n- [Usage](./usage.md)\n- [API](./api.md)\n- [Examples](./examples.md)\n- [Migration Guide](./migration.md)\n\n## See Also\n\n- [Refine](../refine/) provides component metadata bundled by Codex.\n",
|
|
5
|
+
"api": "---\ntitle: Codex API\ndescription: Snapshot, catalog, MCP server, and local HTTP host APIs.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `loadSnapshot` | Read validated snapshot metadata | Sync | Content chunks load lazily |\n| `SnapshotCatalog` | Query package corpus | Sync | Construct from loaded snapshot |\n| `createMcpServer` | MCP adapter factory (generic tools) | Sync | Requires catalog and version |\n| `startHttpHost` | Loopback Streamable HTTP host | Async | HTTP remains local-only |\n| `registerRefineTools` | Opt-in Refine tool registration | Sync | Import from `@vielzeug/codex/refine` |\n\n## Package Entry Points\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/codex` | `Catalog`, `SnapshotCatalog`, `loadSnapshot`, MCP server, and HTTP host |\n| `@vielzeug/codex/refine` | Opt-in Refine component tools (`registerRefineTools`) |\n\n## Snapshot\n\n### `loadSnapshot`\n\n```ts\nloadSnapshot(snapshotRoot?: string, options?: { validateContents?: boolean }): LoadedSnapshot;\n```\n\nLoads catalog/search metadata and Refine metadata. `snapshotRoot` defaults to bundled `data/`. Package content chunks stay lazy unless `validateContents: true`, which validates every package content chunk during loading.\n\n### `SnapshotCatalog`\n\n```ts\nnew SnapshotCatalog(snapshot: LoadedSnapshot)\n```\n\nProvides generic package lookup, docs/source/example/signature access, and deterministic search. Use `SnapshotRefineCatalog` from `/refine` when component methods are needed.\n\n---\n\n## MCP\n\n### `createMcpServer`\n\n```ts\ncreateMcpServer(catalog: Catalog, options: { version: string; debug?: boolean }): Server;\n```\n\nRegisters generic package tools over `Catalog`. Refine tools are opt-in through `/refine`. The root also re-exports `StdioServerTransport` for connecting the server without a second package import.\n\n## Refine tools (`@vielzeug/codex/refine`)\n\n### `SnapshotRefineCatalog`\n\n```ts\nnew SnapshotRefineCatalog(snapshot: LoadedSnapshot)\n```\n\nExtends `SnapshotCatalog` with `getComponent()` and `listComponents()`.\n\n### `registerRefineTools`\n\n```ts\nregisterRefineTools(server: Server, catalog: RefineCatalog, debug?: boolean): void;\n```\n\nUpgrades a server created by `createMcpServer()` with the combined generic and `refine-*` tool set. `refineTools` is exported as a readonly registry.\n\n## HTTP\n\n### `startHttpHost`\n\n```ts\nstartHttpHost(options: HttpHostOptions): Promise<HttpHost>;\n```\n\nStarts Streamable HTTP on `127.0.0.1` by default. Runtime validation accepts only `127.0.0.1` or `::1`; every request must also pass localhost Host and Origin checks. `configureServer` runs once for each lazily created MCP request server and is not called during host startup.\n\n## Types\n\n```ts\ninterface SnapshotPointer {\n directory: string;\n}\n\ninterface SnapshotManifest {\n catalog: 'catalog.json';\n contentDirectory: 'packages';\n refine: 'refine.json' | null;\n schemaVersion: typeof SNAPSHOT_SCHEMA_VERSION;\n search: 'search.json';\n version: string;\n}\n```\n\nDev snapshots use `SnapshotPointer` (via `current.json`); published snapshots are static directories.\n\n```ts\ninterface LoadedSnapshot {\n catalog: CatalogFile;\n contentDirectory: string;\n manifest: SnapshotManifest;\n refineComponents: CemDeclaration[];\n search: SearchRecord[];\n}\n```\n\n```ts\ninterface CatalogFile {\n packages: PackageMeta[];\n version: string;\n}\n\ninterface SearchRecord {\n category: string;\n description: string;\n docs: Partial<Record<DocPage, string>>;\n examples: Array<{ id: string; text: string }>;\n exports: string;\n keywords: string;\n name: string;\n related: string;\n slug: string;\n source: string | null;\n}\n\ninterface PackageMeta {\n availableDocPages: DocPage[];\n category: string;\n description: string;\n exampleIds: string[];\n exports: string[];\n hasSource: boolean;\n keywords: string[];\n name: string;\n related: string[];\n slug: string;\n version: string;\n}\n\ninterface PackageContent {\n apiSource: string | null;\n docs: Partial<Record<DocPage, string>>;\n examples: Example[];\n typeSignatures: Record<string, string>;\n}\n\ninterface Example {\n code: string;\n id: string;\n name: string;\n}\n```\n\n```ts\ninterface Catalog {\n getContent(slug: string): PackageContent;\n getDocs(slug: string, page: DocPage): string;\n getExample(slug: string, exampleId: string): Example;\n getPackage(slug: string): PackageMeta;\n getSource(slug: string): string;\n getTypeSignature(slug: string, symbol: string): string;\n listExamples(slug: string): Array<Pick<Example, 'id' | 'name'>>;\n listPackages(): PackageMeta[];\n search(query: string): SearchHit[];\n}\n\ninterface RefineCatalog extends Catalog {\n getComponent(tagName: string): CemDeclaration;\n listComponents(): CemDeclaration[];\n}\n\ninterface SearchHit {\n matchedExamples?: string[];\n matchedIn: Array<'docs' | 'examples' | 'exports' | 'keywords' | 'metadata' | 'related' | 'source'>;\n matchedPages?: DocPage[];\n name: string;\n slug: string;\n}\n```\n\n```ts\ninterface HttpHost {\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n readonly host: string;\n readonly port: number;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\ninterface HttpHostOptions {\n catalog: Catalog;\n configureServer?: (server: Server) => void;\n debug?: boolean;\n host?: '127.0.0.1' | '::1';\n port: number;\n version: string;\n}\n```\n\n```ts\nconst DOC_PAGES = ['index', 'api', 'usage', 'examples'] as const;\ntype DocPage = (typeof DOC_PAGES)[number];\n\nconst SNAPSHOT_SCHEMA_VERSION = 1 as const;\n```\n\nCEM types and `RefineCatalog` are exported from `/refine`.\n\n```ts\ninterface CemDeclaration {\n attributes?: CemAttribute[];\n cssParts?: CemCssPart[];\n cssProperties?: CemCssProperty[];\n description?: string;\n events?: CemEvent[];\n members?: CemMember[];\n name?: string;\n slots?: CemSlot[];\n superclass?: { name: string; package?: string };\n tagName?: string;\n [key: string]: unknown;\n}\n\ninterface CemAttribute {\n default?: string;\n description?: string;\n fieldName?: string;\n name: string;\n type?: { text: string };\n}\n\ninterface CemCssPart {\n description?: string;\n name: string;\n}\n\ninterface CemCssProperty {\n default?: string;\n description?: string;\n name: string;\n}\n\ninterface CemEvent {\n description?: string;\n name: string;\n type?: { text: string };\n}\n\ninterface CemMember {\n description?: string;\n kind?: 'field' | 'method';\n name: string;\n type?: { text: string };\n}\n\ninterface CemSlot {\n description?: string;\n name: string;\n}\n```\n\n## Errors\n\n`CodexError` signals malformed snapshots or host failures. `CatalogError` adds `INVALID_ARG`, `NOT_FOUND`, or `UNAVAILABLE` for expected tool failures.\n",
|
|
6
|
+
"usage": "---\ntitle: Codex — Usage Guide\ndescription: Install, connect, develop, and debug the Vielzeug MCP server.\n---\n\n[[toc]]\n\n## Basic Usage\n\nRun local stdio server:\n\n```sh\nnpx -y @vielzeug/codex\n```\n\nUse shipped `mcp-setup.json` for machine-readable generic configuration. Client-specific configuration must use its documented MCP format.\n\n## HTTP Mode\n\nHTTP uses Streamable HTTP and binds loopback only:\n\n```sh\nnpx -y @vielzeug/codex --port=3100\ncurl http://127.0.0.1:3100/health\n```\n\nResponse includes snapshot version. Runtime bind validation and Host/Origin allowlists restrict access to localhost; no remote host mode exists. Programmatic `configureServer` hooks run once per MCP request server, not at host startup. Dispose the host asynchronously and observe `disposed` or `disposalSignal` when coordinating shutdown.\n\n## Agent Skill\n\nCodex ships a `vielzeug` agent skill — a `SKILL.md` that tells an AI agent working in *your* project to discover packages through the MCP tools instead of guessing, to use the owning `@vielzeug/*` package instead of hand-rolling, and to build UI from Refine components, tokens, and theme whenever `@vielzeug/refine` is installed. Install it into the project:\n\n```sh\nnpx -y @vielzeug/codex skills install\nnpx -y @vielzeug/codex skills install --target=.claude/skills\nnpx -y @vielzeug/codex skills install --force # overwrite an existing copy\n```\n\nWithout `--target`, the first existing directory among `.agents/skills`, `.github/skills`, and `.claude/skills` is used; when none exists, `.agents/skills` is created. The command refuses to overwrite an installed skill unless `--force` is passed. Rerun after upgrading codex to pick up the current package list, which is generated from the published manifests. The skill pairs with the MCP server: its lookups (`get-docs`, `refine-get-component`, `refine-validate-usage`, …) assume codex is connected, and it documents `node_modules` fallbacks for when it is not.\n\n## Local Development\n\nRequires Node 22+ and root setup:\n\n```sh\npnpm setup\ncd packages/codex\npnpm test:unit\npnpm test:integration\npnpm dev\n```\n\n`test:unit` uses fixtures only. `test:integration` regenerates a current snapshot then checks real monorepo inputs.\n\n`pnpm dev` watches documentation and package inputs, atomically publishes snapshots, then restarts server when snapshot changes.\n\n## Debugging\n\n```sh\npnpm dev\nnode src/cli.ts --port=3100 --debug\ncurl http://127.0.0.1:3100/health\n```\n\n`--debug` logs tool durations and expected catalog errors to stderr. Build `@vielzeug/refine` before generating snapshot when component metadata changes.\n\n## Programmatic Usage\n\n```ts\nimport { SnapshotCatalog, StdioServerTransport, createMcpServer, loadSnapshot } from '@vielzeug/codex';\n\nconst snapshot = loadSnapshot();\nconst catalog = new SnapshotCatalog(snapshot);\nawait createMcpServer(catalog, { version: snapshot.manifest.version }).connect(new StdioServerTransport());\n```\n\nTo include Refine component tools, upgrade the server with the `@vielzeug/codex/refine` subpath:\n\n```ts\nimport { StdioServerTransport, createMcpServer, loadSnapshot } from '@vielzeug/codex';\nimport { SnapshotRefineCatalog, registerRefineTools } from '@vielzeug/codex/refine';\n\nconst snapshot = loadSnapshot();\nconst catalog = new SnapshotRefineCatalog(snapshot);\nconst server = createMcpServer(catalog, { version: snapshot.manifest.version });\nregisterRefineTools(server, catalog);\nawait server.connect(new StdioServerTransport());\n```\n\n## Best Practices\n\n- Use `search-packages` for capability discovery before loading broad source.\n- Use `get-type-signature` before loading full source.\n- Published package snapshots are static directories; local dev snapshots are immutable generations selected by `.dev/current.json`.\n- Pass `validateContents: true` to `loadSnapshot()` for artifact verification; normal startup keeps package chunks lazy.\n- Treat `configureServer` as a per-request factory hook and avoid process-global side effects.\n- Keep HTTP local. Use stdio for normal client integration.\n- Run `pnpm test:unit` before `pnpm test:integration`.\n",
|
|
7
7
|
"examples": "---\ntitle: Codex — Examples\ndescription: Practical MCP tool-call examples for package discovery, docs lookup, and Refine component queries.\n---\n\n## Examples\n\n- [Listing Packages](./examples/listing-packages.md)\n- [Searching Packages](./examples/searching-packages.md)\n- [Package Metadata](./examples/package-metadata.md)\n- [Reading Docs](./examples/reading-docs.md)\n- [Running REPL Examples](./examples/running-repl-examples.md)\n- [Looking Up Components](./examples/looking-up-components.md)\n- [Inspector](./examples/inspector.md)\n"
|
|
8
8
|
},
|
|
9
9
|
"examples": [],
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"apiSource": "export { createContainer } from './container.js';\nexport {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n
|
|
2
|
+
"apiSource": "export { createContainer } from './container.js';\nexport {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';\nexport type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';\nexport { disposalSignalToken, factoryProvider, token, valueProvider } from './types.js';\n",
|
|
3
3
|
"docs": {
|
|
4
|
-
"index": "---\ntitle: Conduit — Dependency Injection for TypeScript\ndescription: Dependency-first asynchronous dependency injection with typed tokens,
|
|
5
|
-
"api": "---\ntitle: Conduit — API Reference\ndescription: Reference for Conduit tokens, immutable provider arrays, dependency-first factories,
|
|
6
|
-
"usage": "---\ntitle: Conduit — Usage Guide\ndescription: Register an immutable provider array, resolve a typed service object at composition roots,
|
|
7
|
-
"examples": "---\ntitle: Conduit — Examples\ndescription: Immutable provider array recipes.\n---\n\n## Examples\n\n- [Basic setup](./examples/basic-setup.md)\n- [Static async providers](./examples/async-providers.md)\n- [Singleton lifetime](./examples/lifetimes.md)\n- [
|
|
4
|
+
"index": "---\ntitle: Conduit — Dependency Injection for TypeScript\ndescription: Dependency-first asynchronous dependency injection with typed tokens, child-container scoping, startup validation, and deterministic disposal.\npackage: conduit\ncategory: infrastructure\nkeywords: [dependency injection, container, token, lifecycle, scope]\nexports: [createContainer, valueProvider, factoryProvider, disposalSignalToken, token]\nrelated: [courier, vault, rune]\nenvironments: [browser, node, ssr, deno]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"conduit\" />\n\n## Why Conduit?\n\nConduit makes service wiring explicit. Typed builders create immutable providers, static graphs are validated at construction, and dependency tuples drive creation and disposal. Resolve one root token or a typed composition map.\n\n```ts\n// Before\nconst service = createService(createApi(config), logger);\n\n// After\nconst container = createContainer([\n valueProvider(Config, config),\n factoryProvider(Api, [Config], (config) => createApi(config)),\n factoryProvider(Service, [Api, Logger], (api, logger) => createService(api, logger)),\n]);\nconst services = await container.resolve({ service: Service });\n```\n\n| Feature | Conduit | Inversify | tsyringe |\n| --- | --- | --- | --- |\n| Dependencies | Explicit token tuples | Decorators/runtime metadata | Decorators/runtime metadata |\n| Async factories | <ore-icon name=\"check\" size=\"16\"></ore-icon> | Partial | Partial |\n| Lifecycle scopes | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"check\" size=\"16\"></ore-icon> |\n| Runtime dependencies | 0 | <ore-icon name=\"x\" size=\"16\"></ore-icon> | <ore-icon name=\"x\" size=\"16\"></ore-icon> |\n\n<div class=\"decision-callout\">\n\n**Use Conduit when** application services need explicit wiring and owned lifecycle cleanup.\n\n**Consider direct imports when** dependencies are static, small, and need no replacement or disposal boundary.\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/conduit\n```\n\n```sh [npm]\nnpm install @vielzeug/conduit\n```\n\n```sh [yarn]\nyarn add @vielzeug/conduit\n```\n\n:::\n\n## Quick Start\n\n```ts\nimport { createContainer, factoryProvider, token, valueProvider } from '@vielzeug/conduit';\n\nconst Config = token<{ baseUrl: string }>('Config');\nconst Client = token<{ url: string }>('Client');\n\nconst container = createContainer([\n valueProvider(Config, { baseUrl: '/api' }),\n factoryProvider(Client, [Config], (config) => ({ url: `${config.baseUrl}/users` })),\n]);\n\nconst services = await container.resolve({ client: Client });\nconsole.log(services.client);\nawait container.dispose();\n```\n\n## Features\n\n<div class=\"features-grid\">\n\n- **`token`**: typed dependency identity\n- **`valueProvider` / `factoryProvider`**: token-safe immutable registrations\n- **`createContainer`**: validated provider graph\n- **`resolve`**: direct service or typed composition map\n- **`createScope`**: child containers for request and job ownership\n- **`dispose`**: in-flight-safe resource cleanup\n\n</div>\n\n## Documentation\n\n<div class=\"doc-links\">\n\n- [Usage Guide](./usage.md)\n- [API Reference](./api.md)\n- [Examples](./examples.md)\n- [Migration Guide](./migration.md)\n\n</div>\n\n## See Also\n\n<div class=\"see-also\">\n\n- [Courier](/courier/) — inject HTTP clients into application services.\n- [Vault](/vault/) — inject persistence adapters with scoped ownership.\n- [Rune](/rune/) — provide application logging services.\n\n</div>\n\n<!-- markdownlint-enable MD025 MD033 MD060 -->\n",
|
|
5
|
+
"api": "---\ntitle: Conduit — API Reference\ndescription: Reference for Conduit tokens, immutable provider arrays, dependency-first factories, child containers, composition-root resolution, and lifecycle disposal.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Mode | Common gotcha |\n| --- | --- | --- | --- |\n| `token` | Create typed dependency identity | Sync | Same description does not mean same token |\n| `createContainer` | Build root container from an immutable provider array | Sync | Validates the full graph at construction |\n| `valueProvider` / `factoryProvider` | Build type-safe immutable registrations | Sync | Prefer over unannotated object literals |\n| `Provider` | Value or factory registration type | Sync | One local registration per token |\n| `has` | Check registration visibility | Sync | Walks parent containers |\n| `resolve` | Resolve one token or typed composition-root map | Async | Undeclared map tokens fail at resolution |\n| `createScope` | Create child container | Sync | Child providers shadow parent registrations |\n| `dispose` | Release owned resources | Async | May throw `ConduitDisposeError` after cleanup attempts |\n\n## Package Entry Point\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/conduit` | Complete Conduit API |\n\n## Tokens\n\n```ts\ntoken<T>(description: string): Token<T>\n```\n\nTokens are unique symbols. Descriptions exist only for diagnostics. `disposalSignalToken` is a built-in `Token<AbortSignal>` that resolves to the owning container's cancellation signal.\n\n## Container\n\n```ts\ncreateContainer(providers: readonly Provider[], options?: { name?: string }): Container\n```\n\n`providers` is an immutable array of value and factory providers. Construction validates the entire graph — duplicate tokens, missing dependencies, circular factory tuples, and singletons depending on transient factories all fail fast.\n\n### Providers\n\n```ts\ntype Provider<T, Dependencies> = ValueProvider<T> | FactoryProvider<T, Dependencies>;\n\nvalueProvider<T>(token: Token<T>, value: T, options?: ValueOptions<T>): ValueProvider<T>;\nfactoryProvider<T, Dependencies>(\n token: Token<T>,\n dependencies: Dependencies,\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options?: FactoryOptions<T>,\n): FactoryProvider<T, Dependencies>;\n```\n\nUse builders for token-driven value and dependency inference:\n\n```ts\nvalueProvider(Config, { baseUrl: '/api' }, { dispose: (value) => value.close() });\nfactoryProvider(Service, [Api, Logger], (api, logger) => createService(api, logger), {\n lifetime: 'singleton',\n dispose: (value) => value.dispose(),\n});\n```\n\nExplicit `ValueProvider<T>` and `FactoryProvider<T, Dependencies>` annotations remain available for reusable provider declarations. Avoid unannotated provider object literals because TypeScript cannot contextually infer one factory parameter from another object property.\n\n`dependencies` is copied at construction and drives creation, validation, cycle detection, and teardown order. Factories may return a value or promise.\n\n`lifetime` accepts `'singleton'` (default) or `'transient'`. Singletons cannot capture transient factories.\n\n```ts\ntype FactoryProvider<T, Dependencies> = {\n token: Token<T>;\n dependencies: Dependencies;\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T;\n dispose?: (value: T) => void | Promise<void>;\n lifetime?: 'singleton' | 'transient';\n};\n```\n\n### has\n\n```ts\ncontainer.has(token): boolean\n```\n\nChecks local and parent registrations without creating a factory result.\n\n### resolve\n\n```ts\ncontainer.resolve(token: Token<T>): Promise<T>\ncontainer.resolve(map: ServiceMap): Promise<InferServices<typeof map>>\n```\n\nResolves one typed token or a service object at a composition root. Map keys are defined as own properties, including `__proto__`, without changing the result prototype. Missing top-level tokens fail during resolution.\n\n```ts\nconst services = await container.resolve({ client: Client, config: Config });\n```\n\nSingleton resolutions deduplicate concurrent callers and cache successful values. A rejected creation attempt is evicted so a later resolution can retry.\n\n### createScope\n\n```ts\ncontainer.createScope(options?: { name?: string; providers?: readonly AnyProvider[] }): Container\n```\n\nA child container inherits parent registrations. Immutable local providers may shadow parent registrations for request or test overrides — this is how request-scoped values are spelled: one child per request, disposed when the request ends. Disposing a parent also disposes active children.\n\n### dispose\n\n```ts\ncontainer.dispose(): Promise<void>\ncontainer.disposalSignal: AbortSignal\ncontainer.disposed: boolean\n```\n\nDisposal blocks new work, aborts `disposalSignal`, disposes active child containers, waits for complete in-flight creation and late-result cleanup, then disposes owned resources in reverse creation order. Cleanup failures are aggregated in the readonly `ConduitDisposeError.errors` array.\n\n## Types\n\n```ts\ntype Token<T = unknown> = symbol;\ntype Lifetime = 'singleton' | 'transient';\n\ntype InferTokens<T extends readonly Token<unknown>[]> = {\n [K in keyof T]: T[K] extends Token<infer Value> ? Value : never;\n};\n\ntype ServiceMap = { readonly [key: string]: Token<unknown> };\n\ntype InferServices<M extends ServiceMap> = {\n readonly [K in keyof M]: M[K] extends Token<infer Value> ? Value : never;\n};\n\ninterface Container {\n createScope(options?: { name?: string; providers?: readonly AnyProvider[] }): Container;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n has<T>(token: Token<T>): boolean;\n readonly name: string;\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n```\n\n## Errors\n\n- `ConduitError` — base class; use `instanceof ConduitError` to narrow package errors.\n- `ConduitProviderNotFoundError` — dependency has no registration.\n- `ConduitCircularDependencyError` — static factory tuple graph contains a cycle.\n- `ConduitDuplicateRegistrationError` — token registered twice in one container.\n- `ConduitDisposedError` — operation attempted after disposal began.\n- `ConduitDisposeError` — one or more cleanup hooks failed.\n",
|
|
6
|
+
"usage": "---\ntitle: Conduit — Usage Guide\ndescription: Register an immutable provider array, resolve a typed service object at composition roots, scope work to child containers, and dispose owned resources.\n---\n\n[[toc]]\n\n## Basic Usage\n\nCreate tokens once, build a container from an immutable provider array, then resolve a typed service object at your composition root.\n\n```ts\nimport { createContainer, factoryProvider, token, valueProvider } from '@vielzeug/conduit';\n\nconst Config = token<{ baseUrl: string }>('Config');\nconst Client = token<{ url: string }>('Client');\n\nconst container = createContainer([\n valueProvider(Config, { baseUrl: '/api' }),\n factoryProvider(Client, [Config], (config) => ({ url: `${config.baseUrl}/users` })),\n]);\n\nconst services = await container.resolve({ config: Config, client: Client });\nconsole.log(services.client);\nawait container.dispose();\n```\n\n## Define Dependencies\n\nFactory `dependencies` tuples are authoritative. Conduit resolves tuple values in order, validates every edge at construction, and disposes created services in reverse dependency order.\n\n```ts\nconst Logger = token<{ info(message: string): void }>('Logger');\nconst Api = token<{ get(path: string): Promise<unknown> }>('Api');\nconst Service = token<{ load(): Promise<unknown> }>('Service');\n\nconst container = createContainer([\n valueProvider(Logger, { info: (message) => console.log(message) }),\n factoryProvider(Api, [], () => ({ get: async (path: string) => fetch(path) })),\n factoryProvider(Service, [Api, Logger], (api, logger) => ({\n async load() {\n logger.info('Loading data');\n return api.get('/data');\n },\n })),\n]);\n```\n\n## Choose Lifetimes\n\nFactories are singletons by default and cached on the registering container. Concurrent singleton resolutions share one in-flight attempt; a rejected attempt is evicted for retry. Use `'transient'` for one value per resolution. Singletons cannot depend on transient factories.\n\n```ts\nimport { createContainer, factoryProvider, token } from '@vielzeug/conduit';\n\nconst Clock = token<{ now(): number }>('Clock');\n\nconst root = createContainer([\n factoryProvider(Clock, [], () => ({ now: () => Date.now() }), { lifetime: 'transient' }),\n]);\n```\n\nFactory dependency tuples are copied at construction, so later caller mutation cannot change Conduit's graph. Add `disposalSignalToken` to a factory tuple when work must observe its owning container's cancellation.\n\n## Scope Work to Child Containers\n\nUse a child container when a resource belongs to a request, job, or test lifecycle. Pass immutable local providers through `createScope()` options to shadow parent registrations; the child owns and disposes them.\n\n```ts\nconst Session = token<{ id: string }>('Session');\nconst TraceId = token<string>('TraceId');\n\nconst request = root.createScope({\n providers: [\n factoryProvider(Session, [], () => ({ id: crypto.randomUUID() })),\n valueProvider(TraceId, 'request-trace'),\n ],\n});\nconst services = await request.resolve({ session: Session, traceId: TraceId });\nawait request.dispose();\nawait root.dispose();\n```\n\nEach child caches its own singleton, so two request children resolve distinct `Session` values while the root never sees request-owned work unless it registers it.\n\n## Resolve at Composition Roots\n\nResolve a map at composition roots to receive an explicitly typed service object. Direct `resolve(token)` remains available for one root service and focused tests; avoid scattering service-locator calls through application code.\n\n```ts\nconst client = await container.resolve(Client);\nconst services = await container.resolve({ client: Client, config: Config });\n// Both results are fully typed.\n```\n\n## Dispose Resources\n\n`dispose()` rejects new work, aborts `disposalSignal`, disposes child containers, waits for in-flight creation, then releases services in reverse creation order. A factory that finishes after disposal starts is immediately cleaned up and its resolver receives `ConduitDisposedError`.\n\n```ts\nawait container.dispose();\n```\n\n`ConduitDisposeError.errors` contains every cleanup failure after Conduit attempts all hooks, including cleanup from in-flight factories and child containers.\n\n## Testing\n\nBuild a container per test with explicit values for external dependencies. Because the provider array is immutable and validated at construction, a misconfigured test container fails immediately.\n\n```ts\nconst Clock = token<{ now(): number }>('Clock');\nconst Service = token<{ timestamp: number }>('Service');\n\nconst container = createContainer([\n valueProvider(Clock, { now: () => 123 }),\n factoryProvider(Service, [Clock], (clock) => ({ timestamp: clock.now() })),\n]);\n\nconst services = await container.resolve({ service: Service });\nexpect(services.service).toEqual({ timestamp: 123 });\nawait container.dispose();\n```\n\n## Best Practices\n\n- Create tokens at module scope.\n- Use `valueProvider()` and `factoryProvider()` so tokens, values, dependencies, and disposers remain type-safe.\n- Declare every factory dependency in its tuple.\n- Keep factories focused on one service.\n- Use child containers for request/job-owned resources.\n- Resolve once at a composition root; pass the typed service object downstream.\n- Dispose every child container and root container.\n- Keep optional application fallback policy outside Conduit.\n- Use `await using container = createContainer([...])` when lexical async disposal fits application lifetime.\n",
|
|
7
|
+
"examples": "---\ntitle: Conduit — Examples\ndescription: Immutable provider array recipes.\n---\n\n## Examples\n\n- [Basic setup](./examples/basic-setup.md)\n- [Static async providers](./examples/async-providers.md)\n- [Singleton lifetime](./examples/lifetimes.md)\n- [Child containers](./examples/child-containers.md)\n- [Disposal lifecycle](./examples/dispose-lifecycle.md)\n- [Startup validation](./examples/startup-hardening.md)\n"
|
|
8
8
|
},
|
|
9
9
|
"examples": [
|
|
10
10
|
{
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"code": "import { createContainer, factoryProvider, token, valueProvider } from '@vielzeug/conduit'\n\nconst Config = token<{ baseUrl: string }>('Config')\nconst Client = token<{ url: string }>('Client')\n\nconst container = createContainer([\n valueProvider(Config, { baseUrl: '/api' }),\n factoryProvider(Client, [Config], config => ({ url: config.baseUrl + '/users' })),\n])\n\nconst services = await container.resolve({ client: Client })\nconsole.log(services.client)\nawait container.dispose()",
|
|
13
13
|
"name": "Immutable provider array"
|
|
14
14
|
},
|
|
15
|
+
{
|
|
16
|
+
"id": "child-containers",
|
|
17
|
+
"code": "import { createContainer, factoryProvider, token } from '@vielzeug/conduit'\n\nconst Session = token('Session')\n\nconst root = createContainer([])\n\nconst request = root.createScope({\n providers: [factoryProvider(Session, [], () => ({ id: crypto.randomUUID() }))],\n})\n\nconst services = await request.resolve({ session: Session })\nconsole.log(services.session)\nawait request.dispose()\nawait root.dispose()",
|
|
18
|
+
"name": "Child container ownership"
|
|
19
|
+
},
|
|
15
20
|
{
|
|
16
21
|
"id": "dispose-lifecycle",
|
|
17
22
|
"code": "import { createContainer, factoryProvider, token } from '@vielzeug/conduit'\n\nconst Database = token('Database')\nconst Service = token('Service')\nconst order = []\n\nconst container = createContainer([\n factoryProvider(Database, [], () => ({ close() {} }), { dispose: () => { order.push('database') } }),\n factoryProvider(Service, [Database], database => ({ database }), { dispose: () => { order.push('service') } }),\n])\n\nawait container.resolve({ service: Service })\nawait container.dispose()\nconsole.log(order)",
|
|
@@ -22,11 +27,6 @@
|
|
|
22
27
|
"code": "import { createContainer, factoryProvider, token } from '@vielzeug/conduit'\n\nconst Singleton = token('Singleton')\n\nconst container = createContainer([\n factoryProvider(Singleton, [], () => ({ id: crypto.randomUUID() })),\n])\n\nconst services = await container.resolve({ a: Singleton, b: Singleton })\nconsole.log(services.a === services.b)\nawait container.dispose()",
|
|
23
28
|
"name": "Singleton lifetime caching"
|
|
24
29
|
},
|
|
25
|
-
{
|
|
26
|
-
"id": "scoped-execution",
|
|
27
|
-
"code": "import { createContainer, factoryProvider, scope, token } from '@vielzeug/conduit'\n\nconst Request = scope('request')\nconst Session = token('Session')\n\nconst root = createContainer([\n factoryProvider(Session, [], () => ({ id: crypto.randomUUID() }), { lifetime: Request }),\n])\n\nconst request = root.createScope(Request)\nconst services = await request.resolve({ session: Session })\nconsole.log(services.session)\nawait request.dispose()\nawait root.dispose()",
|
|
28
|
-
"name": "Named scope ownership"
|
|
29
|
-
},
|
|
30
30
|
{
|
|
31
31
|
"id": "testing",
|
|
32
32
|
"code": "import { createContainer, factoryProvider, token, valueProvider } from '@vielzeug/conduit'\n\nconst Clock = token<{ now(): number }>('Clock')\nconst Service = token<{ timestamp: number }>('Service')\n\nconst container = createContainer([\n valueProvider(Clock, { now: () => 123 }),\n factoryProvider(Service, [Clock], clock => ({ timestamp: clock.now() })),\n])\n\nconst services = await container.resolve({ service: Service })\nconsole.log(services.service)\nawait container.dispose()",
|
|
@@ -40,29 +40,28 @@
|
|
|
40
40
|
],
|
|
41
41
|
"typeSignatures": {
|
|
42
42
|
"createContainer": "export { createContainer } from './container.js';",
|
|
43
|
-
"ConduitCircularDependencyError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n
|
|
44
|
-
"ConduitDisposedError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n
|
|
45
|
-
"ConduitDisposeError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n
|
|
46
|
-
"ConduitDuplicateRegistrationError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n
|
|
47
|
-
"ConduitError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n
|
|
48
|
-
"ConduitProviderNotFoundError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n
|
|
49
|
-
"
|
|
50
|
-
"Container": "export type {\n Container,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"ServiceMap": "export type {\n Container,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n
|
|
59
|
-
"Token": "export type {\n Container,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n
|
|
60
|
-
"ValueOptions": "export type {\n Container,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n
|
|
61
|
-
"ValueProvider": "export type {\n Container,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n
|
|
62
|
-
"disposalSignalToken": "export { disposalSignalToken, factoryProvider,
|
|
63
|
-
"factoryProvider": "export { disposalSignalToken, factoryProvider,
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"valueProvider": "export { disposalSignalToken, factoryProvider, scope, token, valueProvider } from './types.js';"
|
|
43
|
+
"ConduitCircularDependencyError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';",
|
|
44
|
+
"ConduitDisposedError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';",
|
|
45
|
+
"ConduitDisposeError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';",
|
|
46
|
+
"ConduitDuplicateRegistrationError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';",
|
|
47
|
+
"ConduitError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';",
|
|
48
|
+
"ConduitProviderNotFoundError": "export {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';",
|
|
49
|
+
"AnyProvider": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
50
|
+
"Container": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
51
|
+
"CreateScopeOptions": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
52
|
+
"FactoryOptions": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
53
|
+
"FactoryProvider": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
54
|
+
"InferServices": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
55
|
+
"InferTokens": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
56
|
+
"Lifetime": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
57
|
+
"Provider": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
58
|
+
"ServiceMap": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
59
|
+
"Token": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
60
|
+
"ValueOptions": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
61
|
+
"ValueProvider": "export type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryOptions,\n FactoryProvider,\n InferServices,\n InferTokens,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueOptions,\n ValueProvider,\n} from './types.js';",
|
|
62
|
+
"disposalSignalToken": "export { disposalSignalToken, factoryProvider, token, valueProvider } from './types.js';",
|
|
63
|
+
"factoryProvider": "export { disposalSignalToken, factoryProvider, token, valueProvider } from './types.js';",
|
|
64
|
+
"token": "export { disposalSignalToken, factoryProvider, token, valueProvider } from './types.js';",
|
|
65
|
+
"valueProvider": "export { disposalSignalToken, factoryProvider, token, valueProvider } from './types.js';"
|
|
67
66
|
}
|
|
68
67
|
}
|