@vielzeug/codex 1.0.4 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +46 -107
  2. package/data/catalog.json +1680 -0
  3. package/data/llms-full.txt +18886 -31875
  4. package/data/llms.txt +32 -114
  5. package/data/manifest.json +8 -0
  6. package/data/packages/arsenal.json +210 -0
  7. package/data/packages/assay.json +40 -0
  8. package/data/packages/clockwork.json +67 -0
  9. package/data/packages/codex.json +43 -0
  10. package/data/packages/coins.json +103 -0
  11. package/data/packages/conduit.json +60 -0
  12. package/data/packages/courier.json +58 -0
  13. package/data/packages/dnd.json +75 -0
  14. package/data/packages/familiar.json +30 -0
  15. package/data/packages/flux.json +93 -0
  16. package/data/packages/forge.json +84 -0
  17. package/data/packages/herald.json +122 -0
  18. package/data/packages/keymap.json +65 -0
  19. package/data/packages/ledger.json +54 -0
  20. package/data/packages/lingua.json +68 -0
  21. package/data/packages/orbit.json +112 -0
  22. package/data/packages/ore.json +73 -0
  23. package/data/packages/prism.json +70 -0
  24. package/data/packages/pulse.json +58 -0
  25. package/data/packages/refine.json +12 -0
  26. package/data/packages/ripple.json +79 -0
  27. package/data/packages/rune.json +81 -0
  28. package/data/packages/sandbox.json +39 -0
  29. package/data/packages/scout.json +60 -0
  30. package/data/packages/scroll.json +113 -0
  31. package/data/packages/sourcerer.json +74 -0
  32. package/data/packages/spell.json +134 -0
  33. package/data/packages/tempo.json +113 -0
  34. package/data/packages/vault.json +90 -0
  35. package/data/packages/ward.json +125 -0
  36. package/data/packages/wayfinder.json +113 -0
  37. package/data/refine.json +11752 -0
  38. package/data/search.json +1437 -0
  39. package/dist/catalog.js +149 -0
  40. package/dist/catalog.js.map +1 -0
  41. package/dist/cli.js +33 -59
  42. package/dist/cli.js.map +1 -1
  43. package/dist/errors.js +0 -14
  44. package/dist/errors.js.map +1 -1
  45. package/dist/http.js +54 -96
  46. package/dist/http.js.map +1 -1
  47. package/dist/index.js +6 -5
  48. package/dist/index.js.map +1 -1
  49. package/dist/server.js +4 -9
  50. package/dist/server.js.map +1 -1
  51. package/dist/snapshot.js +233 -0
  52. package/dist/snapshot.js.map +1 -0
  53. package/dist/tools/index.js +21 -42
  54. package/dist/tools/index.js.map +1 -1
  55. package/dist/tools/packages.js +67 -166
  56. package/dist/tools/packages.js.map +1 -1
  57. package/dist/tools/refine.js +99 -305
  58. package/dist/tools/refine.js.map +1 -1
  59. package/dist/tools/schema.js +8 -8
  60. package/dist/tools/schema.js.map +1 -1
  61. package/dist/tools/shared.js +1 -26
  62. package/dist/tools/shared.js.map +1 -1
  63. package/dist/types.js +1 -2
  64. package/dist/types.js.map +1 -1
  65. package/mcp-setup.json +10 -0
  66. package/package.json +7 -7
  67. package/data/.cache.json +0 -34
  68. package/data/vielzeug-data.json +0 -16118
@@ -0,0 +1,54 @@
1
+ {
2
+ "apiSource": "export { compose } from './compose';\nexport { LedgerDisposedError, LedgerError, LedgerExecutionError, LedgerRollbackError } from './errors';\nexport { createLedger } from './ledger';\nexport type { Command, CommandMeta, Ledger, LedgerCallOptions, LedgerOptions } from './types';\n",
3
+ "docs": {
4
+ "index": "---\ntitle: Ledger — Async undo/redo command history\ndescription: Command-pattern undo/redo with async operations, Ripple signals for reactive state, and composable commands.\npackage: ledger\ncategory: utilities\nkeywords: [undo, redo, history, command-pattern, async, reactive, ripple]\nexports: [createLedger, compose]\nrelated: [ripple, keymap, forge, vault]\nenvironments: [browser, node, ssr, deno]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"ledger\" />\n\n## Why Ledger?\n\nUndo/redo is deceptively complex: you need to handle async side-effects, prevent concurrent mutations from racing, cap history size, and keep UI buttons reactive. Ledger solves all of this with a clean command-pattern API and Ripple signals.\n\n| Feature | Roll your own | Ledger |\n| ---------------------- | ------------------------------------- | --------------------------------------------------------- |\n| Bundle size | 0 B | <PackageInfo package=\"ledger\" type=\"size\" /> |\n| Async commands | Manual promise chaining | <ore-icon name=\"check\" size=\"16\"></ore-icon> serialised queue |\n| Race prevention | Manual locks | <ore-icon name=\"check\" size=\"16\"></ore-icon> built-in queue |\n| Reactive `canUndo` | Poll or manual events | `Computed<boolean>` from Ripple |\n| Composable commands | Custom wrapper | <ore-icon name=\"check\" size=\"16\"></ore-icon> `compose()` |\n| History cap | Array slice | `maxHistory` option |\n| Disposable | Manual | `dispose()` + `using` |\n\n<div class=\"decision-callout\">\n\n**Use Ledger when** you need undo/redo for editors, design tools, form state, or any app with reversible mutations — especially with async side-effects like server persistence.\n\n**Consider a simpler approach when** you only need one synchronous client-side mutation and do not need command semantics, async sequencing, or reactive history state.\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/ledger\n```\n\n```sh [npm]\nnpm install @vielzeug/ledger\n```\n\n```sh [yarn]\nyarn add @vielzeug/ledger\n```\n\n:::\n\n## Quick Start\n\n```ts\nimport { createLedger } from '@vielzeug/ledger';\n\nconst ledger = createLedger({ maxHistory: 50 });\n\n// Execute a reversible command\nawait ledger.do({\n execute: async () => { item.name = newName; },\n rollback: async () => { item.name = oldName; },\n label: 'Rename item',\n});\n\nawait ledger.undo(); // runs rollback\nawait ledger.redo(); // runs execute again\n\nledger.dispose(); // or: using ledger = createLedger()\n```\n\n## Features\n\n<div class=\"features-grid\">\n\n- `createLedger<TData>()` — Creates an async command stack; operations are serialised to prevent races\n- Reactive state — `canUndo`, `canRedo`, `historySize`, `isProcessing`, `pendingCount`, `historySnapshot` are Ripple `Computed` values\n- `compose()` — Group multiple commands into one atomic undo step; partial failure rolls back already-executed sub-commands; sub-rollback errors reach `onRollbackError`\n- `maxHistory` — Cap the undo stack; oldest entries evicted automatically\n- Async-safe — `execute()`, `rollback()`, and `clear()` are fully serialised through the queue\n- Typed history — `Command.data` stores custom metadata; `historySnapshot.value[n].data` is typed to `TData`\n- Error-safe rollback — failed `rollback()` warns via dev console; optional `onRollbackError` callback for UI integration\n- Cancellable — `execute`/`rollback` receive an `AbortSignal`, merged from a caller-supplied signal and the ledger's own `disposalSignal`\n- Disposable — `dispose()` + `[Symbol.dispose]` for `using` declarations\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\n</div>\n\n## See Also\n\n<div class=\"see-also\">\n\n- [Ripple](/ripple/) — `canUndo`, `canRedo`, `isProcessing` are Ripple `Computed` values; use `effect()` or bind directly to templates\n- [Keymap](/keymap/) — Wire `ctrl+z` / `ctrl+shift+z` to `ledger.undo()` / `ledger.redo()` with zero boilerplate\n- [Forge](/forge/) — Combine Ledger with Forge for reversible form mutations\n- [Vault](/vault/) — Persist undo history across sessions by storing commands in IndexedDB\n\n</div>\n\n<!-- markdownlint-enable MD025 MD033 MD060 -->\n",
5
+ "api": "---\ntitle: Ledger — API Reference\ndescription: Full API reference for @vielzeug/ledger — createLedger, Ledger interface, Command, and all types.\n---\n\n[[toc]]\n\n## API Overview\n\n| Export | Kind | Execution mode | Description |\n| ------ | ---- | -------------- | ----------- |\n| `createLedger` | function | async | Creates an undo/redo command stack |\n| `compose` | function | — | Combines multiple commands into one reversible command |\n| `Ledger` | interface | — | Object returned by `createLedger` |\n| `Command` | interface | — | A command: `{ execute, rollback?, label? }` |\n| `LedgerOptions` | interface | — | Options for `createLedger` |\n| `LedgerCallOptions` | interface | — | Options for `do()`/`undo()`/`redo()` — cancellation |\n| `CommandMeta` | interface | — | Metadata entry in `historySnapshot` |\n\n## Package Entry Points\n\n```ts\nimport { compose, createLedger } from '@vielzeug/ledger';\nimport type { Command, CommandMeta, Ledger, LedgerCallOptions, LedgerOptions } from '@vielzeug/ledger';\n```\n\n## `createLedger(options?)`\n\nCreates an async undo/redo command history.\n\n```ts\nfunction createLedger<TData = unknown>(options?: LedgerOptions<TData>): Ledger<TData>\n```\n\n**Parameters**\n\n- `options.maxHistory` — Maximum number of entries in the undo stack (default: `100`). Oldest entries are evicted when exceeded.\n- `options.onRollbackError` — Optional callback invoked when `rollback()` throws. Receives the error and the `CommandMeta` of the failing command. The stack position is left unchanged regardless.\n\n**Returns** a `Ledger` object.\n\n```ts\nconst ledger = createLedger({ maxHistory: 50 });\n```\n\n## `Ledger`\n\n```ts\ninterface Ledger<TData = unknown> {\n readonly canRedo: Computed<boolean>;\n readonly canUndo: Computed<boolean>;\n readonly disposalSignal: AbortSignal;\n readonly disposed: boolean;\n readonly historySize: Computed<number>;\n readonly historySnapshot: Computed<readonly CommandMeta<TData>[]>;\n readonly isProcessing: Computed<boolean>;\n readonly pendingCount: Computed<number>;\n\n clear(): Promise<void>;\n dispose(): void;\n do(command: Command<TData>, options?: LedgerCallOptions): Promise<void>;\n redo(options?: LedgerCallOptions): Promise<void>;\n undo(options?: LedgerCallOptions): Promise<void>;\n [Symbol.dispose](): void;\n}\n```\n\n### Reactive signals\n\nAll signals are Ripple `Computed<T>` — read `.value` or call `.subscribe()`.\n\n| Signal | Type | Description |\n| ------ | ---- | ----------- |\n| `canUndo` | `Computed<boolean>` | `true` when the undo stack is non-empty |\n| `canRedo` | `Computed<boolean>` | `true` when the redo stack is non-empty |\n| `historySize` | `Computed<number>` | Number of undo steps available |\n| `historySnapshot` | `Computed<readonly CommandMeta<TData>[]>` | Metadata for each undo entry, newest first |\n| `isProcessing` | `Computed<boolean>` | `true` while a command's `execute` or `rollback` is running; `false` during a queued `clear()` |\n| `pendingCount` | `Computed<number>` | Number of operations currently in the queue (executing + waiting) |\n\n### `disposalSignal` / `disposed`\n\n```ts\nreadonly disposalSignal: AbortSignal\nreadonly disposed: boolean\n```\n\n`disposalSignal` aborts when `dispose()` runs — it's the same signal merged into the one\npassed to `execute`/`rollback` (see [`LedgerCallOptions`](#ledgercalloptions)). `disposed`\nflips to `true` at the same point.\n\n### `do(command, options?)`\n\nExecutes a command and pushes it onto the undo stack. Clears the redo stack.\n\n```ts\nledger.do(command: Command<TData>, options?: LedgerCallOptions): Promise<void>\n```\n\nIf `execute()` rejects, the command is not added to the stack. Rejects with\n`LedgerDisposedError` if the ledger is already disposed — `execute()` is never called.\n\n### `undo(options?)`\n\nPops the top entry from the undo stack and pushes it onto the redo stack. If the entry has a `rollback`, it is called first.\n\n```ts\nledger.undo(options?: LedgerCallOptions): Promise<void>\n```\n\nNo-op when `canUndo.value === false`. If `rollback()` throws, a dev warning is issued, `onRollbackError` is called with a `LedgerRollbackError` (if configured), and the stack position is left unchanged. Commands without a `rollback` are popped and moved to the redo stack without any reversal. Rejects with `LedgerDisposedError` if the ledger is already disposed.\n\n### `redo(options?)`\n\nPops the top entry from the redo stack, calls `execute()`, and pushes it back onto the undo stack.\n\n```ts\nledger.redo(options?: LedgerCallOptions): Promise<void>\n```\n\nNo-op when `canRedo.value === false`. Rejects with `LedgerExecutionError` if `execute()` throws, and with `LedgerDisposedError` if the ledger is already disposed.\n\n### `clear()`\n\nEnqueues a reset of both the undo and redo stacks. Returns a `Promise` that resolves once the reset has run (after any already-queued operations complete).\n\n```ts\nawait ledger.clear()\n```\n\nSafe to call while operations are in flight — the clear is serialised in the queue and runs after the current operation finishes. Rejects with `LedgerDisposedError` if the ledger is already disposed.\n\n### `dispose()`\n\nClears both stacks, aborts `disposalSignal`, and disposes all Ripple signals. After `dispose()`, reading `.value` on any signal returns `undefined`, and `do()`/`undo()`/`redo()`/`clear()` reject with `LedgerDisposedError`.\n\n```ts\nledger.dispose();\n// or:\nusing ledger = createLedger();\n```\n\n## `Command`\n\n```ts\ninterface Command<TData = unknown> {\n data?: TData;\n execute: (signal?: AbortSignal) => Promise<void> | void;\n rollback?: (signal?: AbortSignal) => Promise<void> | void;\n label?: string;\n}\n```\n\nBoth `execute` and `rollback` accept sync and async functions. Both receive an `AbortSignal` — see [`LedgerCallOptions`](#ledgercalloptions) — but the parameter is optional, so existing commands that ignore it (`execute: () => {...}`) still type-check.\n\n`rollback` is optional. Commands without one are still tracked in history; `undo()` moves them on the stack but performs no reversal.\n\n`label` is optional — it surfaces in `historySnapshot.value` for building undo history UI.\n\n`data` is an optional custom metadata payload, typed to the `TData` type parameter of `createLedger<TData>`. It is stored as-is in `historySnapshot.value[n].data`. Use it to attach context needed by undo-history UIs (e.g. before/after snapshots, affected IDs).\n\n## `LedgerOptions`\n\n```ts\ninterface LedgerOptions<TData = unknown> {\n maxHistory?: number; // default: 100\n onRollbackError?: (err: unknown, meta: CommandMeta<TData>) => void;\n}\n```\n\n| Option | Default | Description |\n| ------ | ------- | ----------- |\n| `maxHistory` | `100` | Maximum undo stack depth. Oldest entries evicted on overflow. |\n| `onRollbackError` | — | Called with a `LedgerRollbackError` when `rollback()` throws. Useful for surfacing undo failures to the UI without parsing console warnings. |\n\n## `LedgerCallOptions`\n\nOptions accepted by `do()`/`undo()`/`redo()`.\n\n```ts\ninterface LedgerCallOptions {\n signal?: AbortSignal;\n}\n```\n\n| Option | Default | Description |\n| ------ | ------- | ----------- |\n| `signal` | — | Merged with the ledger's own `disposalSignal` via `AbortSignal.any()` and passed to `execute`/`rollback`. Lets a long-running command observe caller-initiated cancellation, ledger disposal, or both. |\n\n`execute`/`rollback` always receive a live `AbortSignal`, even when `options.signal` is omitted — it's the ledger's own `disposalSignal` in that case, so every command can at least observe disposal.\n\n```ts\nconst controller = new AbortController();\n\nawait ledger.do(\n {\n execute: async (signal) => {\n await fetch('/api/save', { signal });\n },\n },\n { signal: controller.signal },\n);\n\ncontroller.abort(); // aborts the fetch above, if still in flight\n```\n\n## `compose(commands, label?)`\n\nCombines multiple commands into a single reversible command that counts as one undo step.\n\n```ts\nfunction compose<TData = unknown>(commands: Command<TData>[], label?: string): Command<TData>\n```\n\n`execute` runs all sub-commands in order and forwards its own `signal` argument to every sub-command's `execute`. **If any sub-command fails, already-executed sub-commands are rolled back automatically (best-effort) before the error is re-thrown** — making `compose()` atomic. `rollback` runs sub-commands in reverse (also forwarding `signal`), skipping any without a defined `rollback`. If a sub-command's `rollback` throws during `undo()`, the error is propagated to the ledger's `onRollbackError` callback (if configured). `rollback` is `undefined` when no sub-command defines one. Pass the result directly to `ledger.do()`:\n\n```ts\nawait ledger.do(compose([\n { execute: () => { node.x = newX; }, rollback: () => { node.x = oldX; } },\n { execute: () => { node.y = newY; }, rollback: () => { node.y = oldY; } },\n], 'Move node'));\n```\n\n## `CommandMeta`\n\nShape of entries in `historySnapshot.value`:\n\n```ts\ninterface CommandMeta<TData = unknown> {\n data: TData | undefined;\n label: string | undefined;\n}\n```\n\n`data` holds the value from `Command.data`. The type parameter is inferred from `createLedger<TData>()`; it defaults to `unknown` when no type argument is supplied.\n\n---\n\n## Errors\n\n### `LedgerError`\n\nBase class for all ledger errors. Use `instanceof LedgerError` or `LedgerError.is()` to catch any ledger-originated error.\n\n```ts\nclass LedgerError extends Error {\n static is(err: unknown): err is LedgerError;\n}\n```\n\n**Named subclasses**\n\n| Class | Thrown when |\n| ---------------------- | ------------------------------------------------------------------------------ |\n| `LedgerDisposedError` | `do()`/`undo()`/`redo()`/`clear()` is called on a disposed ledger instance |\n| `LedgerExecutionError` | A command's `execute()` function throws; original error available via `.cause` |\n| `LedgerRollbackError` | Passed to `onRollbackError` when a command's `rollback()` function throws during undo; original error via `.cause` |\n",
6
+ "usage": "---\ntitle: Ledger — Usage Guide\ndescription: How to use createLedger for undo/redo, async commands, batch operations, and reactive UI binding.\n---\n\n[[toc]]\n\n## Basic Usage\n\nDefine commands as `{ execute, rollback }` pairs and push them through `ledger.do()`:\n\n```ts\nimport { createLedger } from '@vielzeug/ledger';\n\nconst ledger = createLedger();\n\nconst prev = item.name;\nconst next = 'New name';\n\nawait ledger.do({\n execute: async () => { item.name = next; },\n rollback: async () => { item.name = prev; },\n label: 'Rename item',\n});\n\nawait ledger.undo(); // item.name === prev\nawait ledger.redo(); // item.name === next\n```\n\nCommands can be sync or async — both `() => void` and `() => Promise<void>` are accepted.\n\n## Reactive State\n\n`canUndo`, `canRedo`, `historySize`, `isProcessing`, and `historySnapshot` are Ripple `Computed` values. Read them directly in effects or templates:\n\n```ts\nimport { effect } from '@vielzeug/ripple';\n\neffect(() => {\n undoButton.disabled = !ledger.canUndo.value;\n redoButton.disabled = !ledger.canRedo.value;\n spinner.hidden = !ledger.isProcessing.value;\n});\n```\n\nOr read `.value` imperatively:\n\n```ts\nconsole.log(ledger.historySize.value); // number of undo steps\nconsole.log(ledger.historySnapshot.value); // readonly CommandMeta[]\n```\n\n## Composing Commands\n\nGroup multiple commands into a single undo step with `compose()`. Rollback runs all sub-commands in reverse:\n\n```ts\nimport { compose, createLedger } from '@vielzeug/ledger';\n\nawait ledger.do(compose(\n [\n { execute: () => { node.x = newX; }, rollback: () => { node.x = oldX; } },\n { execute: () => { node.y = newY; }, rollback: () => { node.y = oldY; } },\n { execute: () => { node.width = newW; }, rollback: () => { node.width = oldW; } },\n ],\n 'Move and resize',\n));\n\n// One undo step undoes all three:\nawait ledger.undo();\n```\n\n## Concurrent Safety\n\nAll operations — `do()`, `undo()`, and `redo()` — are serialised through an internal queue. Concurrent calls are queued, not rejected:\n\n```ts\n// Safe to call without awaiting each:\nledger.do(cmd1);\nledger.do(cmd2);\nledger.do(cmd3);\n// cmd1 → cmd2 → cmd3 execute in order\n```\n\n`isProcessing.value` is `true` while a command's `execute` or `rollback` is actively running. Use `pendingCount.value > 0` to check whether there are any operations in the queue (including those waiting to start).\n\n## History Cap\n\nLimit the undo stack size with `maxHistory` (default: `100`):\n\n```ts\nconst ledger = createLedger({ maxHistory: 30 });\n```\n\nWhen the limit is reached, the oldest undo entry is silently evicted. The redo stack is always cleared when a new `do()` is performed.\n\n## Custom Command Data\n\nAttach arbitrary metadata to a command with the `data` field. Use `createLedger<TData>()` to type it:\n\n```ts\ntype EditData = { before: string; after: string };\n\nconst ledger = createLedger<EditData>();\n\nawait ledger.do({\n data: { before: item.name, after: newName },\n execute: () => { item.name = newName; },\n rollback: () => { item.name = item.name; }, // captured in closure\n label: 'Rename item',\n});\n\nconst [latest] = ledger.historySnapshot.value;\nconsole.log(latest.data?.before); // string | undefined — fully typed\n```\n\n`data` is stored as-is and does not affect `execute` or `rollback` behaviour.\n\n## Error Handling\n\nIf `execute()` rejects, the command is **not** added to the undo stack:\n\n```ts\nawait ledger.do({\n execute: async () => {\n await api.save(item); // throws if server error\n },\n rollback: async () => { /* not reached */ },\n});\n// ledger.historySize.value unchanged\n```\n\nIf `rollback()` throws during `undo()`, a dev warning is issued and the stack position is left unchanged — the entry stays on the undo stack so the operation can be retried.\n\nTo receive rollback errors in your application code (for example, to show a notification), pass `onRollbackError` to `createLedger`:\n\n```ts\nconst ledger = createLedger({\n onRollbackError: (err, meta) => {\n notify(`Could not undo \"${meta.label ?? 'action'}\": ${String(err)}`);\n },\n});\n```\n\n## Cancellation\n\n`execute`/`rollback` receive an `AbortSignal` as their argument — pass your own via `{ signal }` on `do()`/`undo()`/`redo()` to cancel a specific in-flight command, or ignore it if the command has nothing to abort:\n\n```ts\nconst controller = new AbortController();\n\nconst save = ledger.do(\n {\n execute: async (signal) => {\n await fetch('/api/save', { body: JSON.stringify(item), method: 'POST', signal });\n },\n label: 'Save item',\n },\n { signal: controller.signal },\n);\n\ncancelButton.addEventListener('click', () => controller.abort());\n```\n\nThe signal you pass is merged with the ledger's own `disposalSignal`, so a command can bail out early on `dispose()` too — without you having to wire that up yourself:\n\n```ts\nconst ledger = createLedger();\n\nconst polling = ledger.do({\n execute: async (signal) => {\n while (!signal?.aborted) {\n await pollServer();\n }\n },\n});\n\n// later, e.g. when the owning component unmounts:\nledger.dispose(); // the loop above sees signal.aborted === true and exits\nawait polling;\n```\n\n## Framework Integration\n\n::: code-group\n\n```tsx [React]\nimport { useEffect, useState } from 'react';\nimport { createLedger } from '@vielzeug/ledger';\n\nconst ledger = createLedger();\n\nfunction UndoRedoButtons() {\n const [canUndo, setCanUndo] = useState(false);\n const [canRedo, setCanRedo] = useState(false);\n\n useEffect(() => {\n const unsub = ledger.canUndo.subscribe(({ newValue }) => setCanUndo(newValue));\n const unsub2 = ledger.canRedo.subscribe(({ newValue }) => setCanRedo(newValue));\n return () => { unsub(); unsub2(); };\n }, []);\n\n return (\n <>\n <button disabled={!canUndo} onClick={() => ledger.undo()}>Undo</button>\n <button disabled={!canRedo} onClick={() => ledger.redo()}>Redo</button>\n </>\n );\n}\n```\n\n```vue [Vue 3]\n<script setup lang=\"ts\">\nimport { onUnmounted, ref } from 'vue';\nimport { createLedger } from '@vielzeug/ledger';\n\nconst ledger = createLedger();\nconst canUndo = ref(false);\nconst canRedo = ref(false);\n\nconst u1 = ledger.canUndo.subscribe(({ newValue }) => { canUndo.value = newValue; });\nconst u2 = ledger.canRedo.subscribe(({ newValue }) => { canRedo.value = newValue; });\nonUnmounted(() => { u1(); u2(); });\n</script>\n\n<template>\n <button :disabled=\"!canUndo\" @click=\"ledger.undo()\">Undo</button>\n <button :disabled=\"!canRedo\" @click=\"ledger.redo()\">Redo</button>\n</template>\n```\n\n```ts [Svelte]\nimport { onMount } from 'svelte';\nimport { createLedger } from '@vielzeug/ledger';\n\nconst ledger = createLedger();\nlet canUndo = false;\nlet canRedo = false;\n\nonMount(() => {\n const u1 = ledger.canUndo.subscribe(({ newValue }) => { canUndo = newValue; });\n const u2 = ledger.canRedo.subscribe(({ newValue }) => { canRedo = newValue; });\n return () => { u1(); u2(); };\n});\n```\n\n:::\n\n## Working with Other Vielzeug Libraries\n\n### Ledger + Keymap\n\n```ts\nimport { createKeymap } from '@vielzeug/keymap';\nimport { createLedger } from '@vielzeug/ledger';\n\nconst ledger = createLedger();\nconst map = createKeymap({\n 'ctrl+z': () => ledger.undo(),\n 'ctrl+shift+z': () => ledger.redo(),\n 'ctrl+y': () => ledger.redo(), // Windows alias\n});\nmap.mount(document);\n```\n\n### Ledger + Ripple effect\n\n```ts\nimport { effect } from '@vielzeug/ripple';\n\neffect(() => {\n document.title = ledger.canUndo.value\n ? `● ${documentTitle}` // unsaved indicator\n : documentTitle;\n});\n```\n\n## Best Practices\n\n- **Capture state before mutation**: close over `prev` / `next` values at `do()` call time, not inside `execute`/`rollback`.\n- **Label meaningful operations**: `historySnapshot.value` exposes labels for undo history lists.\n- **Use `data` for rich history UIs**: store before/after snapshots or affected IDs in `Command.data`; retrieve them via `historySnapshot.value[n].data`.\n- **Await `clear()` when order matters**: `ledger.clear()` is serialised — it returns a `Promise` that resolves after any in-flight operation finishes.\n- **Dispose when done**: call `ledger.dispose()` when the owner component unmounts — it clears both stacks and disposes all signals.\n- **Avoid reading `.value` after `dispose()`**: the computed nodes are disposed; `.value` returns `undefined`.\n",
7
+ "examples": "---\ntitle: Ledger — Examples\ndescription: Worked examples for @vielzeug/ledger.\n---\n\n# Examples\n\n- [Text Editor History](./examples/text-editor.md) — Per-keystroke undo with debouncing and Keymap integration\n- [Form History](./examples/form-history.md) — Reversible form field mutations with reactive undo/redo buttons\n"
8
+ },
9
+ "examples": [
10
+ {
11
+ "id": "cancellation",
12
+ "code": "import { createLedger } from '@vielzeug/ledger'\n\n// execute()/rollback() receive an AbortSignal — pass your own via { signal }\n// to cancel a specific in-flight command\nconst ledger = createLedger()\nconst controller = new AbortController()\nconst log = []\n\nconst save = ledger.do(\n {\n execute: async (signal) => {\n log.push('save started')\n // Check signal.aborted up front — an already-aborted signal never\n // fires a future 'abort' event, so a listener alone can miss it\n if (signal.aborted) throw new Error('save aborted')\n await new Promise((resolve, reject) => {\n const timer = setTimeout(resolve, 200)\n signal.addEventListener('abort', () => {\n clearTimeout(timer)\n reject(new Error('save aborted'))\n })\n })\n log.push('save finished') // never reached below\n },\n label: 'Save document',\n },\n { signal: controller.signal },\n)\n\ncontroller.abort()\n\ntry {\n await save\n} catch (err) {\n console.log('caught:', err.message) // 'save aborted'\n}\nconsole.log('log:', log) // ['save started'] — never got to 'save finished'\n\n// The signal is also merged with the ledger's own disposalSignal — no\n// external AbortController needed to react to dispose(). Poll signal.aborted\n// rather than relying on a future 'abort' event — the signal may already be\n// aborted by the time this command actually starts running its queue turn\nconst pending = ledger.do({\n execute: async (signal) => {\n while (!signal.aborted) {\n await new Promise((resolve) => setTimeout(resolve, 10))\n }\n },\n})\n\nledger.dispose()\nawait pending\nconsole.log('ledger disposed:', ledger.disposed) // true",
13
+ "name": "Cancellation (AbortSignal)"
14
+ },
15
+ {
16
+ "id": "command-data",
17
+ "code": "import { createLedger } from '@vielzeug/ledger'\n\n// Store before/after snapshots with each command\nconst ledger = createLedger()\nconst doc = { title: 'Untitled', body: '' }\n\nasync function setTitle(next) {\n const prev = doc.title\n await ledger.do({\n data: { field: 'title', before: prev, after: next },\n execute: () => { doc.title = next },\n rollback: () => { doc.title = prev },\n label: 'Set title',\n })\n}\n\nasync function setBody(next) {\n const prev = doc.body\n await ledger.do({\n data: { field: 'body', before: prev, after: next },\n execute: () => { doc.body = next },\n rollback: () => { doc.body = prev },\n label: 'Set body',\n })\n}\n\n// Queue multiple operations (pendingCount tracks them)\nconst p1 = setTitle('Hello World')\nconst p2 = setBody('Lorem ipsum')\nconsole.log('queued ops:', ledger.pendingCount.value) // 2\n\nawait Promise.all([p1, p2])\nconsole.log('after edits — doc:', doc)\nconsole.log('pendingCount:', ledger.pendingCount.value) // 0\n\n// historySnapshot exposes data for each undo step (newest first)\nconst [latest, earlier] = ledger.historySnapshot.value\nconsole.log('latest data:', latest.data) // { field: 'body', before: '', after: 'Lorem ipsum' }\nconsole.log('earlier data:', earlier.data) // { field: 'title', before: 'Untitled', after: 'Hello World' }\n\nawait ledger.undo()\nconsole.log('after undo body:', doc.body) // ''\n\nawait ledger.undo()\nconsole.log('after undo title:', doc.title) // 'Untitled'\n\nledger.dispose()",
18
+ "name": "command data & pendingCount"
19
+ },
20
+ {
21
+ "id": "compose-commands",
22
+ "code": "import { compose, createLedger } from '@vielzeug/ledger'\n\n// compose() groups commands into one atomic undo step\nconst ledger = createLedger()\nconst node = { label: 'old', x: 0, y: 0 }\nconst original = { label: node.label, x: node.x, y: node.y }\n\nawait ledger.do(compose([\n {\n execute: () => { node.x = 100 },\n rollback: () => { node.x = original.x },\n },\n {\n execute: () => { node.y = 50 },\n rollback: () => { node.y = original.y },\n },\n {\n execute: () => { node.label = 'moved' },\n rollback: () => { node.label = original.label },\n },\n], 'Move and rename'))\n\nconsole.log('after compose:', node) // { label: 'moved', x: 100, y: 50 }\nconsole.log('historySize:', ledger.historySize.value) // 1 — one step for all three\n\nawait ledger.undo()\nconsole.log('after undo:', node) // { label: 'old', x: 0, y: 0 }\n\n// If a sub-command throws, already-executed ones roll back automatically\ntry {\n await ledger.do(compose([\n { execute: () => { node.x = 999 }, rollback: () => { node.x = 0 } },\n { execute: () => { throw new Error('server error') } },\n ]))\n} catch (err) {\n console.log('compose threw:', err.message) // 'server error'\n console.log('node.x rolled back:', node.x) // 0 — first sub-command rolled back\n}\n\nledger.dispose()",
23
+ "name": "compose() — Atomic Multi-step"
24
+ },
25
+ {
26
+ "id": "do-undo-redo",
27
+ "code": "import { createLedger } from '@vielzeug/ledger'\n\n// An undo/redo stack for any async or sync mutations\nconst ledger = createLedger()\nlet counter = 0\n\nasync function increment() {\n const prev = counter\n const next = prev + 1\n await ledger.do({\n execute: () => { counter = next },\n rollback: () => { counter = prev },\n label: 'Increment',\n })\n}\n\nawait increment()\nawait increment()\nawait increment()\nconsole.log('after 3 increments:', counter) // 3\nconsole.log('historySize:', ledger.historySize.value) // 3\nconsole.log('canUndo:', ledger.canUndo.value) // true\n\nawait ledger.undo()\nconsole.log('after undo:', counter) // 2\n\nawait ledger.undo()\nconsole.log('after undo:', counter) // 1\n\nawait ledger.redo()\nconsole.log('after redo:', counter) // 2\n\n// A new do() discards the redo stack\nawait increment()\nconsole.log('historySize after new do:', ledger.historySize.value) // 3 (not 4)\n\nledger.dispose()",
28
+ "name": "do / undo / redo"
29
+ },
30
+ {
31
+ "id": "reactive-signals",
32
+ "code": "import { createLedger } from '@vielzeug/ledger'\n\n// historySnapshot exposes command labels — useful for undo history UI panels\nconst ledger = createLedger({ maxHistory: 5 })\n\nconst ops = [\n { label: 'Rename node', execute: () => {}, rollback: () => {} },\n { label: 'Move node', execute: () => {}, rollback: () => {} },\n { label: 'Resize node', execute: () => {}, rollback: () => {} },\n]\n\nfor (const op of ops) {\n await ledger.do(op)\n}\n\n// historySnapshot is newest-first\nconsole.log('labels:', ledger.historySnapshot.value.map(e => e.label))\n// ['Resize node', 'Move node', 'Rename node']\n\nconsole.log('historySize:', ledger.historySize.value) // 3\nconsole.log('canUndo:', ledger.canUndo.value) // true\nconsole.log('canRedo:', ledger.canRedo.value) // false\n\nawait ledger.undo()\nconsole.log('canRedo after undo:', ledger.canRedo.value) // true\nconsole.log('labels after undo:', ledger.historySnapshot.value.map(e => e.label))\n// ['Move node', 'Rename node']\n\nledger.clear()\nconsole.log('historySize after clear:', ledger.historySize.value) // 0\n\nledger.dispose()",
33
+ "name": "Reactive Signals & historySnapshot"
34
+ },
35
+ {
36
+ "id": "rollback-error",
37
+ "code": "import { createLedger } from '@vielzeug/ledger'\n\n// onRollbackError surfaces undo failures without silently swallowing them\nconst errors = []\n\nconst ledger = createLedger({\n onRollbackError: (err, meta) => {\n errors.push({ label: meta.label, message: err.message })\n },\n})\n\nawait ledger.do({\n execute: async () => { console.log('executed') },\n rollback: async () => { throw new Error('server unreachable') },\n label: 'Save to server',\n})\n\nawait ledger.undo()\n// rollback threw — stack position is unchanged, onRollbackError was called\n\nconsole.log('rollback errors:', errors)\n// [{ label: 'Save to server', message: 'server unreachable' }]\n\n// The entry stays on the undo stack so the operation can be retried\nconsole.log('canUndo (still true):', ledger.canUndo.value)\n\nledger.dispose()",
38
+ "name": "onRollbackError Hook"
39
+ }
40
+ ],
41
+ "typeSignatures": {
42
+ "compose": "export { compose } from './compose';",
43
+ "LedgerDisposedError": "export { LedgerDisposedError, LedgerError, LedgerExecutionError, LedgerRollbackError } from './errors';",
44
+ "LedgerError": "export { LedgerDisposedError, LedgerError, LedgerExecutionError, LedgerRollbackError } from './errors';",
45
+ "LedgerExecutionError": "export { LedgerDisposedError, LedgerError, LedgerExecutionError, LedgerRollbackError } from './errors';",
46
+ "LedgerRollbackError": "export { LedgerDisposedError, LedgerError, LedgerExecutionError, LedgerRollbackError } from './errors';",
47
+ "createLedger": "export { createLedger } from './ledger';",
48
+ "Command": "export type { Command, CommandMeta, Ledger, LedgerCallOptions, LedgerOptions } from './types';",
49
+ "CommandMeta": "export type { Command, CommandMeta, Ledger, LedgerCallOptions, LedgerOptions } from './types';",
50
+ "Ledger": "export type { Command, CommandMeta, Ledger, LedgerCallOptions, LedgerOptions } from './types';",
51
+ "LedgerCallOptions": "export type { Command, CommandMeta, Ledger, LedgerCallOptions, LedgerOptions } from './types';",
52
+ "LedgerOptions": "export type { Command, CommandMeta, Ledger, LedgerCallOptions, LedgerOptions } from './types';"
53
+ }
54
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "apiSource": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';\nexport {\n createTranslationStore,\n hydrateTranslationStore,\n type TranslationSnapshot,\n type TranslationStore,\n} from './i18n';\nexport { createCatalogTranslator, createTranslator, type Translator } from './translator';\nexport type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';\n",
3
+ "docs": {
4
+ "index": "---\ntitle: Lingua — Explicit localization for TypeScript\ndescription: Framework-neutral locale catalogs, typed translations, and explicit plural messages.\npackage: lingua\ncategory: i18n\nkeywords: [internationalization, translations, pluralization, locale, i18n, catalog-loading]\nrelated: [ripple, wayfinder, courier]\nexports: [createCatalogTranslator, createTranslationStore, createTranslator, hydrateTranslationStore, LinguaError, LinguaDisposedError, LinguaInvalidCatalogError, LinguaInvalidLocaleError, LinguaInvalidPluralCountError, LinguaInvalidStateError, LinguaMissingCatalogError]\nenvironments: [browser, node, ssr, deno]\n---\n\n<!-- markdownlint-disable MD025 MD033 MD060 -->\n\n<PackageHero package=\"lingua\" />\n\n## Why Lingua?\n\nLingua separates immutable translation from mutable locale state. Use one catalog per locale, then select static or stateful API from whether locale can change.\n\n```ts\n// Before\nconst message = catalogs[locale]?.inbox?.[count === 1 ? 'one' : 'other'] ?? 'inbox';\n\n// After\nconst output = i18n.translate('inbox', { count });\n```\n\n| Feature | Lingua | i18next | FormatJS |\n| --- | --- | --- | --- |\n| Bundle size | <PackageInfo package=\"lingua\" type=\"size\" /> | Varies by selected modules | Varies by selected modules |\n| Zero runtime dependencies | <ore-icon name=\"check\" size=\"16\"></ore-icon> | <ore-icon name=\"triangle-alert\" size=\"16\"></ore-icon> | <ore-icon name=\"triangle-alert\" size=\"16\"></ore-icon> |\n| Explicit plural catalog nodes | <ore-icon name=\"check\" size=\"16\"></ore-icon> | Convention/config dependent | ICU-message dependent |\n| Declared lazy locale catalogs | <ore-icon name=\"check\" size=\"16\"></ore-icon> | Plugin/config dependent | Application-defined |\n| Immutable locale snapshots | <ore-icon name=\"check\" size=\"16\"></ore-icon> | Application-defined | Application-defined |\n\n<div class=\"decision-callout\">\n\n**Use Lingua when** you need a compact TypeScript runtime with explicit catalog structure, deterministic fallback, and framework-neutral subscriptions.\n\n**Consider i18next or FormatJS when** you need their plugin ecosystems, message extraction pipelines, or framework-specific integrations.\n\n</div>\n\n## Installation\n\n::: code-group\n\n```sh [pnpm]\npnpm add @vielzeug/lingua\n```\n\n```sh [npm]\nnpm install @vielzeug/lingua\n```\n\n```sh [yarn]\nyarn add @vielzeug/lingua\n```\n\n:::\n\n## Quick Start\n\nCreate locale store with static catalogs, then dispose it when owner ends.\n\n```ts\nimport { createTranslationStore } from '@vielzeug/lingua';\n\nconst i18n = createTranslationStore({\n catalogs: {\n de: { inbox: { plural: { one: 'Eine Nachricht', other: '{count} Nachrichten' } } },\n en: { inbox: { plural: { one: 'One message', other: '{count} messages' } } },\n },\n locale: 'en',\n});\n\ntry {\n console.log(i18n.translate('inbox', { count: 3 }));\n await i18n.setLocale('de');\n console.log(i18n.translate('inbox', { count: 1 }));\n} finally {\n i18n.dispose();\n}\n```\n\n## Features\n\n<div class=\"features-grid\">\n\n- `createCatalogTranslator()` compiles one immutable fixed-locale catalog.\n- `createTranslator()` compiles immutable locale-keyed catalogs.\n- `createTranslationStore()` manages locale changes and declared catalogs.\n- `translate()` renders text and plural messages through explicit catalog nodes.\n- `translateDynamic()` makes runtime-key lookup explicit.\n- `load()` deduplicates lazy catalog loading per locale.\n- `getSnapshot()` and `subscribe()` expose immutable translator revisions.\n- `serialize()` and `hydrateTranslationStore()` transfer resolved SSR catalogs.\n- `createFormatter()` and `validateCatalog()` remain isolated subpath tools.\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\n</div>\n\n## See Also\n\n<div class=\"see-also\">\n\n- [Ripple](../ripple/index.md) adapts Lingua snapshots into reactive application state.\n- [Courier](../courier/index.md) can fetch locale catalogs before passing them to Lingua loaders.\n- [Wayfinder](../wayfinder/index.md) can drive locale selection from route state.\n\n</div>\n\n<!-- markdownlint-enable MD025 MD033 MD060 -->\n",
5
+ "api": "---\ntitle: Lingua — API Reference\ndescription: Complete API reference for @vielzeug/lingua.\n---\n\n[[toc]]\n\n## API Overview\n\n| Symbol | Purpose | Execution mode | Common gotcha |\n| --- | --- | --- | --- |\n| `createCatalogTranslator()` | Compile one immutable locale catalog | Sync | No fallback locales |\n| `createTranslator()` | Compile immutable locale catalogs | Sync | Locale is fixed for translator lifetime |\n| `createTranslationStore()` | Create mutable locale and catalog store | Sync | Load lazy locale explicitly |\n| `hydrateTranslationStore()` | Create store from serialized loaded catalogs | Sync | Serialized state never includes loaders |\n| `createFormatter()` | Format Intl values from `/format` | Sync | Import from subpath |\n| `validateCatalog()` | Check explicit plural forms from `/validate` | Sync | Import from subpath |\n| `LinguaError` | Base class for Lingua errors | Sync | Use `LinguaError.is()` for broad narrowing |\n\n## Package Entry Point\n\n| Import | Purpose |\n| --- | --- |\n| `@vielzeug/lingua` | Translation factories, state types, and Lingua errors |\n| `@vielzeug/lingua/format` | `createFormatter()` and formatter types |\n| `@vielzeug/lingua/validate` | `validateCatalog()` and `ValidationIssue` |\n\n## Translation Factories\n\n### createCatalogTranslator\n\n```ts\nfunction createCatalogTranslator<C extends Catalog>(\n catalog: C,\n options?: CatalogTranslatorOptions,\n): Translator<C>;\n```\n\nCompiles one catalog and returns an immutable fixed-locale translator. Locale defaults to `en` and controls plural selection and diagnostics.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `catalog` | `C` | One catalog containing only messages and grouping objects |\n| `options` | `CatalogTranslatorOptions` | Locale and missing-message handlers; fallback is unavailable |\n\n**Returns:** `Translator<C>`.\n\n**Example:**\n\n```ts\nimport { createCatalogTranslator } from '@vielzeug/lingua';\n\nconst translator = createCatalogTranslator(\n { save: 'Enregistrer' },\n { locale: 'fr' },\n);\n\ntranslator.translate('save');\n```\n\n---\n\n### createTranslator\n\n```ts\nfunction createTranslator<C extends Catalog>(catalogs: Catalogs<C>, options?: TranslatorOptions): Translator<C>;\n```\n\nCompiles locale catalogs and returns immutable translator.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `catalogs` | `Catalogs<C>` | Locale-keyed catalog objects |\n| `options` | `TranslatorOptions` | Locale, fallback chain, and missing-message handlers |\n\n**Returns:** `Translator<C>`.\n\n**Example:**\n\n```ts\nimport { createTranslator } from '@vielzeug/lingua';\n\nconst translator = createTranslator(\n { en: { save: 'Save' }, fr: { save: 'Enregistrer' } },\n { locale: 'fr' },\n);\n\ntranslator.translate('save');\n```\n\n| Method | Signature | Returns |\n| --- | --- | --- |\n| `translate` | `(textKey, options?)` or `(pluralKey, { count, ordinal?, values? })` | Rendered string |\n| `translateDynamic` | `(key, options?)` | Rendered string for runtime key |\n| `segments` | `(textKey, { values })` or `(pluralKey, { count, ordinal?, values? })` | String and typed-value segments |\n| `segmentsDynamic` | `(key, options)` | Segments for runtime key |\n| `locale` | `Locale` | Resolved active locale |\n\n---\n\n### createTranslationStore\n\n```ts\nfunction createTranslationStore<C extends Catalog>(options: TranslationStoreOptions<C>): TranslationStore<C>;\n```\n\nCreates catalog store, current locale state, and immutable translator snapshots.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `options.catalogs` | `CatalogSources<C>` | Static catalogs or lazy locale loaders |\n| `options.locale` | `Locale` | Initial locale; defaults to `en` |\n| `options.fallback` | `Locale \\| readonly Locale[]` | Fallback locale chain |\n| `options.onMissingKey` | `(key, locale) => string` | Missing-message handler |\n| `options.onMissingValue` | `(name, key, locale) => string` | Missing-interpolation handler |\n\n**Returns:** `TranslationStore<C>`, with every `Translator<C>` method plus lifecycle methods.\n\n**Example:**\n\n```ts\nimport { createTranslationStore } from '@vielzeug/lingua';\n\nconst translations = createTranslationStore({\n catalogs: { en: { title: 'Home' }, fr: { title: 'Accueil' } },\n locale: 'en',\n});\n\nawait translations.setLocale('fr');\ntranslations.translate('title');\n```\n\n| Method or property | Signature | Returns |\n| --- | --- | --- |\n| `translate` | Translator method | Rendered string |\n| `segments` | Translator method | String and typed-value segments |\n| `load` | `({ locale? })` | `Promise<void>` after catalog resolution |\n| `setLocale` | `(locale)` | `Promise<void>` after locale commit; never loads implicitly |\n| `isLoaded` | `({ locale? })` | `boolean` |\n| `getSnapshot` | `()` | `TranslationSnapshot<C>` |\n| `subscribe` | `(listener, { immediate?, signal? })` | Unsubscribe function |\n| `serialize` | `()` | Loader-free `TranslationState<C>` |\n| `dispose` | `()` | `void` |\n| `locale` | `Locale` | Current canonical locale |\n| `disposed` | `boolean` | Disposal state |\n| `disposalSignal` | `AbortSignal` | Aborts on disposal |\n| `[Symbol.dispose]` | `()` | Delegates to `dispose()` |\n\n---\n\n### hydrateTranslationStore\n\n```ts\nfunction hydrateTranslationStore<C extends Catalog>(\n state: TranslationState<C>,\n options?: Omit<TranslationStoreOptions<C>, 'locale' | 'catalogs'>,\n): TranslationStore<C>;\n```\n\nCreates translation store from SSR state payload containing resolved raw catalogs.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `state` | `TranslationState<C>` | Version `3`, active locale, and loader-free catalogs |\n| `options` | `Omit<TranslationStoreOptions<C>, 'locale' \\| 'catalogs'>` | Fallback and missing-message handlers |\n\n**Returns:** `TranslationStore<C>`.\n\n**Example:**\n\n```ts\nimport { createTranslationStore, hydrateTranslationStore } from '@vielzeug/lingua';\n\nconst server = createTranslationStore({ catalogs: { en: { title: 'Home' } }, locale: 'en' });\nconst client = hydrateTranslationStore(server.serialize());\n\nclient.translate('title');\n```\n\n## Migration from 1.x\n\n| Before | After |\n| --- | --- |\n| `createI18n(options)` | `createTranslationStore({ catalogs, ...options })` |\n| `hydrateI18n(state)` | `hydrateTranslationStore(state)` |\n| `I18n` / `I18nSnapshot` | `TranslationStore` / `TranslationSnapshot` |\n| `I18nState` version `2` | `TranslationState` version `3` |\n| Named resources and namespaces | One catalog source per locale |\n| `LinguaMissingResourceError` | `LinguaMissingCatalogError` |\n\n## Formatting and Validation\n\n### createFormatter\n\n```ts\nfunction createFormatter(source: string | (() => string)): Formatter;\n```\n\nCreates cached Intl formatters using static locale or locale getter.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `source` | `string \\| (() => string)` | Static locale or locale getter |\n\n**Returns:** `Formatter`.\n\n**Example:**\n\n```ts\nimport { createFormatter } from '@vielzeug/lingua/format';\n\nconst formatter = createFormatter('en-US');\nformatter.currency(19.99, 'USD');\n```\n\n| Method | Signature | Returns |\n| --- | --- | --- |\n| `number` | `(value, options?)` | `string` |\n| `currency` | `(value, currency, options?)` | `string` |\n| `date` | `(value, options?)` | `string` |\n| `relative` | `(value, unit, options?)` | `string` |\n| `list` | `(value, options?)` | `string` |\n| `duration` | `(value, options?)` | `string` |\n\n### validateCatalog\n\n```ts\nfunction validateCatalog(catalog: Catalog, locale: Locale): ValidationIssue[];\n```\n\nValidates explicit plural messages against locale plural categories after catalog structural validation.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| `catalog` | `Catalog` | Explicit catalog to validate |\n| `locale` | `Locale` | BCP 47 locale tag |\n\n**Returns:** `ValidationIssue[]`.\n\n**Example:**\n\n```ts\nimport { validateCatalog } from '@vielzeug/lingua/validate';\n\nvalidateCatalog({ inbox: { plural: { one: 'One message' } } }, 'en');\n```\n\n## Types\n\n```ts\ntype Locale = string;\ntype PluralCategory = Intl.LDMLPluralRule;\ntype PluralMessage = { readonly plural: Partial<Record<PluralCategory, string>> };\ntype CatalogNode = Catalog | PluralMessage | string;\ntype Catalog = { readonly [key: string]: CatalogNode };\ntype Catalogs<C extends Catalog = Catalog> = Record<Locale, C>;\ntype CatalogTranslatorOptions = Omit<TranslatorOptions, 'fallback'>;\ntype CatalogLoader<C extends Catalog = Catalog> = () => Promise<C>;\ntype CatalogSource<C extends Catalog = Catalog> = C | CatalogLoader<C>;\ntype CatalogSources<C extends Catalog = Catalog> = Record<Locale, CatalogSource<C>>;\ntype LoadedCatalogs<C extends Catalog = Catalog> = Catalogs<C>;\n\ntype TranslationStoreOptions<C extends Catalog = Catalog> = TranslatorOptions & {\n catalogs: CatalogSources<C>;\n};\n\ntype TranslationState<C extends Catalog = Catalog> = {\n readonly catalogs: LoadedCatalogs<C>;\n readonly locale: Locale;\n readonly version: 3;\n};\n\ntype TranslationSnapshot<C extends Catalog = Catalog> = {\n readonly locale: Locale;\n readonly revision: number;\n readonly translator: Translator<C>;\n};\n\ntype TranslationStore<C extends Catalog = Catalog> = Translator<C> & {\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n readonly disposed: boolean;\n getSnapshot(): TranslationSnapshot<C>;\n isLoaded(options?: { locale?: Locale }): boolean;\n load(options?: { locale?: Locale }): Promise<void>;\n serialize(): TranslationState<C>;\n setLocale(locale: Locale): Promise<void>;\n subscribe(listener: (snapshot: TranslationSnapshot<C>) => void, options?: SubscribeOptions): () => void;\n [Symbol.dispose](): void;\n};\n```\n\n```ts\ntype Values = Record<string, unknown>;\ntype TranslateOptions = { values?: Values };\ntype PluralOptions = TranslateOptions & { count: number; ordinal?: boolean };\ntype TranslatorOptions = {\n fallback?: Locale | readonly Locale[];\n locale?: Locale;\n onMissingKey?: (key: string, locale: Locale) => string;\n onMissingValue?: (name: string, key: string, locale: Locale) => string;\n};\ntype SubscribeOptions = { immediate?: boolean; signal?: AbortSignal };\n\ntype DurationValue = Partial<Record<\n 'days' | 'hours' | 'microseconds' | 'milliseconds' | 'minutes' | 'months' | 'nanoseconds' | 'seconds' | 'weeks' | 'years',\n number\n>>;\n\ntype DurationFormatOptions = {\n hours?: '2-digit' | 'numeric';\n microseconds?: 'numeric';\n milliseconds?: 'numeric';\n minutes?: '2-digit' | 'numeric';\n nanoseconds?: 'numeric';\n seconds?: '2-digit' | 'numeric';\n style?: 'digital' | 'long' | 'narrow' | 'short';\n};\n\ntype ListFormatOptions = { style?: 'long' | 'narrow' | 'short'; type?: 'and' | 'or' };\n\ntype Formatter = {\n currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'currency' | 'style'>): string;\n date(value: Date | number, options?: Intl.DateTimeFormatOptions): string;\n duration(value: DurationValue, options?: DurationFormatOptions): string;\n list(value: Array<string | number>, options?: ListFormatOptions): string;\n number(value: number, options?: Intl.NumberFormatOptions): string;\n relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string;\n};\n\ntype ValidationIssue = { key: string; locale: Locale; missing: Intl.LDMLPluralRule };\n```\n\n## Errors\n\n| Error | Trigger |\n| --- | --- |\n| `LinguaDisposedError` | State mutation or subscription after `dispose()` |\n| `LinguaInvalidCatalogError` | Invalid catalog node or reserved key |\n| `LinguaInvalidLocaleError` | Invalid BCP 47 locale tag |\n| `LinguaInvalidPluralCountError` | Non-finite plural count |\n| `LinguaInvalidStateError` | Unsupported serialized state version |\n| `LinguaMissingCatalogError` | Catalog has no source for requested locale |\n",
6
+ "usage": "---\ntitle: Lingua — Usage Guide\ndescription: Translate explicit catalogs, load lazy locales, and connect locale snapshots to UI state.\n---\n\n[[toc]]\n\n## Basic Usage\n\nCreate i18n store from locale-keyed catalogs. Strings are text messages; plural messages use `{ plural: ... }`.\n\n```ts\nimport { createTranslationStore } from '@vielzeug/lingua';\n\nconst i18n = createTranslationStore({\n catalogs: {\n en: {\n greeting: 'Hello, {name}!',\n inbox: { plural: { one: 'One message', other: '{count} messages' } },\n },\n },\n locale: 'en',\n});\n\nconsole.log(i18n.translate('greeting', { values: { name: 'Ada' } }));\nconsole.log(i18n.translate('inbox', { count: 3 }));\n```\n\nCall `dispose()` when store belongs to temporary request, test, or route owner.\n\n## Define Explicit Catalogs\n\nUse nested objects only to group keys. A plural message always has `plural`, so regular objects containing `one` or `other` remain groups.\n\n```ts\nconst catalog = {\n account: {\n greeting: 'Hello, {name}!',\n unread: { plural: { one: 'One unread message', other: '{count} unread messages' } },\n },\n};\n```\n\nUse `{ values }` for text replacements. Pass `count` at top level for plural selection; Lingua injects it into selected template. Absent replacements render as `{name}` by default. `segments()` preserves an own `undefined` or `null` value; omit property to receive `{name}`.\n\nCatalogs contain strings, grouping objects, and explicit `{ plural: ... }` messages only. Keep application data outside catalog, then translate display labels while constructing it.\n\n```ts\nimport { createCatalogTranslator } from '@vielzeug/lingua';\n\nconst messages = {\n status: { blocked: 'Blocked', done: 'Done', inProgress: 'In progress' },\n};\nconst statusDefinitions = [\n { labelKey: 'status.inProgress', value: 'in-progress' },\n { labelKey: 'status.blocked', value: 'blocked' },\n { labelKey: 'status.done', value: 'done' },\n] as const;\nconst translator = createCatalogTranslator(messages);\nconst statusOptions = statusDefinitions.map(({ labelKey, value }) => ({ label: translator.translate(labelKey), value }));\n```\n\n## Render Framework Content\n\nUse `segments()` when replacements are framework nodes, links, or other values that must not be stringified.\n\n```ts\nimport { createCatalogTranslator } from '@vielzeug/lingua';\n\nconst translator = createCatalogTranslator({ error: 'Try {retry} or {support}.' });\n\nconst retry = { href: '/retry', label: 'retry' };\nconst support = { href: '/support', label: 'support' };\n\nconsole.log(translator.segments('error', { values: { retry, support } }));\n```\n\nRender returned array with framework fragment or list primitive. Give UI values consumer-owned keys before passing them to `segments()`; Lingua preserves value identity and never clones or mutates them.\n\n## Use Static Catalogs\n\nUse `createCatalogTranslator()` when one catalog and locale stay fixed for translator lifetime. It defaults locale to `en`; pass `locale` when plural rules or diagnostics need another locale. Lingua snapshots catalog messages during construction. Do not mutate source catalog objects afterward.\n\n```ts\nimport { createCatalogTranslator } from '@vielzeug/lingua';\n\nconst translator = createCatalogTranslator(\n { save: 'Enregistrer' },\n { locale: 'fr' },\n);\n\nconsole.log(translator.translate('save'));\n```\n\nUse `createTranslator()` when fixed translation requires locale-keyed catalogs and fallback resolution.\n\n```ts\nimport { createTranslator } from '@vielzeug/lingua';\n\nconst translator = createTranslator(\n { en: { save: 'Save' }, fr: { save: 'Enregistrer' } },\n { locale: 'fr' },\n);\n\nconsole.log(translator.translate('save'));\n```\n\n## Load Catalogs and Switch Locales\n\nDeclare one static catalog or lazy loader per locale. Switch locale, then load it explicitly when source is lazy.\n\n```ts\nimport { createTranslationStore } from '@vielzeug/lingua';\n\nconst i18n = createTranslationStore({\n catalogs: {\n en: { navigation: { settings: 'Settings' } },\n fr: async () => ({ navigation: { settings: 'Réglages' } }),\n },\n locale: 'en',\n});\n\nawait i18n.setLocale('fr');\nawait i18n.load();\nconsole.log(i18n.translate('navigation.settings'));\n```\n\nConcurrent loads for same locale share work. `setLocale()` never triggers hidden loads.\n\n## Subscribe to Immutable Snapshots\n\nSubscribe when UI state must change with locale or loaded active/fallback catalog. Every callback receives snapshot containing translator for that revision.\n\n```ts\nconst unsubscribe = i18n.subscribe(\n ({ locale, translator }) => {\n console.log(locale, translator.translate('navigation.settings'));\n },\n { immediate: true },\n);\n\nunsubscribe();\n```\n\nPass `{ signal }` when an `AbortController` owns subscription lifetime.\n\n## SSR State\n\nSerialize resolved catalogs on server, then hydrate client store from same payload. `getSnapshot()` stays referentially stable until store revision changes, so use same hydrated store throughout initial client render.\n\n```ts\nimport { createTranslationStore, hydrateTranslationStore } from '@vielzeug/lingua';\n\nconst serverTranslationStore = createTranslationStore({\n catalogs: { en: { title: 'Server title' } },\n locale: 'en',\n});\n\nconst state = serverTranslationStore.serialize();\nconst clientTranslationStore = hydrateTranslationStore(state, { fallback: 'en' });\n\nconsole.log(clientTranslationStore.translate('title'));\nserverTranslationStore.dispose();\nclientTranslationStore.dispose();\n```\n\nState contains raw loaded catalogs. It never contains loader functions.\n\n## Formatting and Validation\n\nImport formatting and catalog validation from dedicated subpaths to keep translation state focused.\n\n```ts\nimport { createFormatter } from '@vielzeug/lingua/format';\nimport { validateCatalog } from '@vielzeug/lingua/validate';\n\nconst formatter = createFormatter('en-US');\nconst catalog = { inbox: { plural: { one: 'One message', other: '{count} messages' } } };\n\nconsole.log(formatter.currency(19.99, 'USD'));\nconsole.log(validateCatalog(catalog, 'en'));\n```\n\n## Framework Integration\n\nPass stable `getSnapshot()` and `subscribe()` methods to framework state primitives. For SSR, create client store from same serialized state used by server before calling `useSyncExternalStore`.\n\n::: code-group\n\n```ts [React]\nimport { useSyncExternalStore } from 'react';\n\nimport type { TranslationStore } from '@vielzeug/lingua';\n\nexport function useTranslator(i18n: TranslationStore) {\n const snapshot = useSyncExternalStore(i18n.subscribe, i18n.getSnapshot, i18n.getSnapshot);\n\n return snapshot.translator;\n}\n```\n\n```ts [Vue 3]\nimport { onUnmounted, shallowRef } from 'vue';\n\nimport type { TranslationStore } from '@vielzeug/lingua';\n\nexport function useTranslator(i18n: TranslationStore) {\n const snapshot = shallowRef(i18n.getSnapshot());\n const unsubscribe = i18n.subscribe((next) => {\n snapshot.value = next;\n });\n\n onUnmounted(unsubscribe);\n return snapshot;\n}\n```\n\n```ts [Svelte]\nimport { readable } from 'svelte/store';\n\nimport type { TranslationStore } from '@vielzeug/lingua';\n\nexport function translatorStore(i18n: TranslationStore) {\n return readable(i18n.getSnapshot().translator, (set) => i18n.subscribe(({ translator }) => set(translator)));\n}\n```\n\n:::\n\n## Working with Other Vielzeug Libraries\n\nBridge Lingua subscriptions into Ripple through Flux when templates need reactive locale reads.\n\n```ts\nimport { stream } from '@vielzeug/flux';\nimport { toSignal } from '@vielzeug/flux/ripple';\nimport { computed } from '@vielzeug/ripple';\n\nconst localeBinding = toSignal(\n stream<string>((observer) => {\n observer.next(i18n.locale);\n return i18n.subscribe(({ locale }) => observer.next(locale));\n }),\n { initial: i18n.locale },\n);\n\nexport const locale = computed(() => localeBinding.value);\n```\n\nUse Courier loaders when locale catalogs come from HTTP rather than bundled modules; pass each loader to `catalogs`.\n\n## Best Practices\n\n- Define plural messages with `{ plural: ... }` and no sibling metadata.\n- Keep arrays and application metadata outside catalogs.\n- Treat source catalog objects as immutable after construction.\n- Use `translateDynamic()` only for runtime-generated keys.\n- Load a lazy catalog before rendering it.\n- Give UI values keys before passing them to `segments()`.\n- Keep loader functions out of SSR payloads.\n- Dispose temporary stores after requests, tests, and route lifetimes.\n",
7
+ "examples": "---\ntitle: Lingua — Examples\ndescription: Focused examples for explicit catalogs and locale resources.\n---\n\n- [Static Translator](./examples/static-translator.md)\n- [Lazy Locale Catalog](./examples/feature-resources.md)\n- [SSR Hydration](./examples/ssr-hydration.md)\n"
8
+ },
9
+ "examples": [
10
+ {
11
+ "id": "feature-resources",
12
+ "code": "import { createTranslationStore } from '@vielzeug/lingua'\n\nconst i18n = createTranslationStore({\n catalogs: {\n en: { home: 'Home' },\n fr: async () => ({ home: 'Accueil' }),\n },\n locale: 'en',\n})\n\nconsole.log(i18n.translate('home'))\nawait i18n.setLocale('fr')\nawait i18n.load()\nconsole.log(i18n.translate('home'))",
13
+ "name": "Lazy Locale Catalog"
14
+ },
15
+ {
16
+ "id": "rich-segments",
17
+ "code": "import { createCatalogTranslator } from '@vielzeug/lingua'\n\n// segments() preserves components, nodes, or other non-string replacements.\nconst translator = createCatalogTranslator({\n error: 'Try {retry} or {support}.',\n})\n\nconst retry = { label: 'retry', href: '/retry' }\nconst support = { label: 'support', href: '/support' }\nconst result = translator.segments('error', { values: { retry, support } })\n\nconsole.log(result)\nconsole.log(result.map((part) => typeof part === 'string' ? part : part.label).join(''))",
18
+ "name": "Rich Segments"
19
+ },
20
+ {
21
+ "id": "static-translator",
22
+ "code": "import { createCatalogTranslator } from '@vielzeug/lingua'\n\n// Immutable translator: explicit text and plural catalog nodes.\nconst translator = createCatalogTranslator({\n greeting: 'Bonjour, {name} !',\n inbox: { plural: { one: 'Un message', other: '{count} messages' } },\n}, { locale: 'fr' })\n\nconsole.log(translator.translate('greeting', { values: { name: 'Ada' } }))\nconsole.log(translator.translate('inbox', { count: 3 }))",
23
+ "name": "Static Translator"
24
+ },
25
+ {
26
+ "id": "store",
27
+ "code": "import { createTranslationStore } from '@vielzeug/lingua'\n\nconst i18n = createTranslationStore({\n catalogs: {\n en: { save: 'Save' },\n fr: { save: 'Enregistrer' },\n },\n locale: 'en',\n})\n\ni18n.subscribe(({ locale, translator }) => {\n console.log(locale, translator.translate('save'))\n}, { immediate: true })\n\nawait i18n.setLocale('fr')",
28
+ "name": "Reactive Locale Store"
29
+ }
30
+ ],
31
+ "typeSignatures": {
32
+ "LinguaDisposedError": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';",
33
+ "LinguaError": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';",
34
+ "LinguaInvalidCatalogError": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';",
35
+ "LinguaInvalidLocaleError": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';",
36
+ "LinguaInvalidPluralCountError": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';",
37
+ "LinguaInvalidStateError": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';",
38
+ "LinguaMissingCatalogError": "export {\n LinguaDisposedError,\n LinguaError,\n LinguaInvalidCatalogError,\n LinguaInvalidLocaleError,\n LinguaInvalidPluralCountError,\n LinguaInvalidStateError,\n LinguaMissingCatalogError,\n} from './errors';",
39
+ "createTranslationStore": "export {\n createTranslationStore,\n hydrateTranslationStore,\n type TranslationSnapshot,\n type TranslationStore,\n} from './i18n';",
40
+ "hydrateTranslationStore": "export {\n createTranslationStore,\n hydrateTranslationStore,\n type TranslationSnapshot,\n type TranslationStore,\n} from './i18n';",
41
+ "TranslationSnapshot": "export {\n createTranslationStore,\n hydrateTranslationStore,\n type TranslationSnapshot,\n type TranslationStore,\n} from './i18n';",
42
+ "TranslationStore": "export {\n createTranslationStore,\n hydrateTranslationStore,\n type TranslationSnapshot,\n type TranslationStore,\n} from './i18n';",
43
+ "createCatalogTranslator": "export { createCatalogTranslator, createTranslator, type Translator } from './translator';",
44
+ "createTranslator": "export { createCatalogTranslator, createTranslator, type Translator } from './translator';",
45
+ "Translator": "export { createCatalogTranslator, createTranslator, type Translator } from './translator';",
46
+ "Catalog": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
47
+ "CatalogLoader": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
48
+ "CatalogTranslatorOptions": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
49
+ "CatalogNode": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
50
+ "Catalogs": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
51
+ "CatalogSource": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
52
+ "CatalogSources": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
53
+ "TranslationState": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
54
+ "TranslationStoreOptions": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
55
+ "LoadedCatalogs": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
56
+ "Locale": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
57
+ "MessageKey": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
58
+ "PluralCategory": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
59
+ "PluralKey": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
60
+ "PluralMessage": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
61
+ "PluralOptions": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
62
+ "SubscribeOptions": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
63
+ "TextKey": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
64
+ "TranslateOptions": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
65
+ "TranslatorOptions": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';",
66
+ "Values": "export type {\n Catalog,\n CatalogLoader,\n CatalogTranslatorOptions,\n CatalogNode,\n Catalogs,\n CatalogSource,\n CatalogSources,\n TranslationState,\n TranslationStoreOptions,\n LoadedCatalogs,\n Locale,\n MessageKey,\n PluralCategory,\n PluralKey,\n PluralMessage,\n PluralOptions,\n SubscribeOptions,\n TextKey,\n TranslateOptions,\n TranslatorOptions,\n Values,\n} from './types';"
67
+ }
68
+ }