@embedpdf/core 3.0.0-next.13 → 3.0.0-next.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +879 -427
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +212 -292
- package/dist/index.d.ts +212 -292
- package/dist/index.js +797 -400
- package/dist/index.js.map +1 -1
- package/dist/settings-CMWFRjmQ.js +1837 -0
- package/dist/settings-CMWFRjmQ.js.map +1 -0
- package/dist/settings-maKtf237.cjs +2034 -0
- package/dist/settings-maKtf237.cjs.map +1 -0
- package/dist/testing.cjs +401 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +94 -0
- package/dist/testing.d.ts +94 -0
- package/dist/testing.js +393 -0
- package/dist/testing.js.map +1 -0
- package/dist/types-t-DaU8VK.d.cts +1162 -0
- package/dist/types-t-DaU8VK.d.ts +1162 -0
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-CMWFRjmQ.js","names":[],"sources":["../src/types.ts","../src/bursts.ts","../src/scope.ts","../src/errors.ts","../src/event-hook.ts","../src/changes.ts","../src/clock.ts","../src/store.ts","../src/env.ts","../src/guarded-handle.ts","../src/lanes.ts","../src/mirror.ts","../src/page-mirror.ts","../src/serial-queue.ts","../src/cancellable.ts","../src/page-of.ts","../src/permissions.ts","../src/context.ts","../src/settle.ts","../src/settings.ts"],"sourcesContent":["/**\n * @embedpdf/core — core contracts.\n *\n * Framework-free and serializable. The engine boundary is the real one:\n * `@embedpdf/engine-core`'s `Engine`/`DocumentHandle` — implemented identically by\n * local-wasm (`@embedpdf/engine`), cloud (`@cloudpdf/engine`), and the test fake.\n * The kernel adds *document scope*: plugins declare a scope and the kernel\n * multiplexes document-scoped plugins per document.\n */\nimport type { ChangeQueue } from './changes';\nimport type { PluginClock } from './clock';\nimport type { EventHook } from './event-hook';\nimport type { Mirror, MirrorSpec } from './mirror';\nimport type { PageMirror, PageMirrorSpec } from './page-mirror';\nimport type { SerialQueue } from './serial-queue';\nimport type { NoSettings, Settings, SettingsDeclaration } from './settings';\nimport type { PluginErrorInfo } from './errors';\nimport type {\n DocumentHandle,\n Engine,\n EngineFactory,\n OpenInput,\n OpenOptions,\n PageLayout,\n PageRef,\n PageObjectNumber,\n PdfRotation,\n PageRotateResult,\n PageReorderResult,\n PagePosition,\n PageDeleteResult,\n PageInsertResult,\n PageInsertBlankSpec,\n PdfSize,\n DocCapability,\n PdfSaveMode,\n DocumentMetadata,\n MetadataPatch,\n MetadataUpdateResult,\n CustomMetadata,\n CustomMetadataPatch,\n CustomMetadataUpdateResult,\n DocumentEvent,\n EventOrigin,\n EngineRenderPolicy,\n PageDestination,\n PdfDestination,\n Identity,\n} from '@embedpdf/engine-core/runtime';\n\n// re-export the engine contracts so consumers import them from @embedpdf/core\nexport type {\n DocumentHandle,\n Engine,\n EngineFactory,\n OpenInput,\n OpenOptions,\n PageLayout,\n PageDestination,\n PdfDestination,\n PageObjectNumber,\n PdfRotation,\n PageRotateResult,\n PageReorderResult,\n PagePosition,\n PageDeleteResult,\n PageInsertResult,\n PageInsertBlankSpec,\n PdfSize,\n DocCapability,\n PdfSaveMode,\n DocumentMetadata,\n MetadataPatch,\n MetadataUpdateResult,\n CustomMetadata,\n CustomMetadataPatch,\n CustomMetadataUpdateResult,\n DocumentEvent,\n /** Who the user is: the author of what they make, and whom `:self` and `:group` permissions are checked against. */\n Identity,\n /**\n * Where a confirmed document change came from, on every fact event a plugin\n * emits: `kind` (`'local'` for this engine instance, `'remote'` for another\n * session), `sessionId`, `sub` (the signed-in user on the cloud, null\n * locally), `ts`, `serverId` and `tx`. Always the engine event's own\n * `origin`, passed on as it is, never built by hand.\n */\n EventOrigin,\n};\n\nexport type Unsubscribe = () => void;\n\n/** The last parameter of every method that does work: cooperative cancellation. */\nexport interface OperationOptions {\n readonly signal?: AbortSignal;\n}\n\n/** Load state of a resource a plugin hydrates from the engine. `forbidden` is a permission refusal, not an empty value. */\nexport type ResourceStatus = 'idle' | 'loading' | 'ready' | 'forbidden' | 'error';\n\n/**\n * The outcome of a best-effort batch (`renderPages`, `createMany`, …): what\n * was applied, what was skipped with a reason, and what failed with its\n * error summary. `R` is the input's identity (a `PageRef`, an `AnnotationRef`).\n */\nexport interface BatchResult<T, R = unknown> {\n readonly applied: readonly T[];\n readonly skipped: readonly { readonly ref: R; readonly reason: string }[];\n readonly failed: readonly { readonly ref: R; readonly error: PluginErrorInfo }[];\n}\n\n/**\n * A permission a verb can need, named as the engine names it: a document\n * capability (`'doc.forms.fill'`), or `'annotations:create'`. Creating is the\n * one annotation action that needs no target: whether the session may change\n * or delete an annotation depends on whose it is, so the annotation plugin\n * asks that per annotation (`doc.security.allowsAnnotation`).\n */\nexport type Permission = DocCapability | 'annotations:create';\n\n/** Anything `ctx.listen` can subscribe to: an EventHook, or an object with `subscribe`. */\nexport type Subscribable<T> =\n | ((listener: (event: T) => void) => Unsubscribe)\n | { subscribe(listener: (event: T) => void): Unsubscribe };\n\n/**\n * The public name of a page-registry entry: `ref` is the durable identity,\n * `index` the display order, plus label, size, rotation, userUnit and boxes.\n * Structurally the engine's `PageLayout`; named for what it is to a developer.\n */\nexport type PageInfo = PageLayout;\n\n/** A typed handle to a capability — typed resolution, no string casts. */\nexport interface CapabilityToken<T> {\n readonly name: string;\n /**\n * Authored remedy shown when a plugin `requires` this capability and no\n * plugin provides it — the missing-dependency error should contain its own\n * fix (e.g. \"add interactionPlugin() from '@embedpdf/plugin-interaction' to\n * your plugins list\").\n */\n readonly hint?: string;\n /**\n * The members of the capability that return a promise, by path (`setValue`,\n * `comments.reply`). Without a document, a framework adapter's stand-in\n * rejects these with `not-ready`, as the capability would, instead of\n * throwing (see `standInFor`).\n */\n readonly promises?: Readonly<Record<string, true>>;\n /** phantom — never present at runtime */\n readonly __type?: T;\n}\n\n/** The members of an object that return a promise, by name. */\ntype PromiseMethodOf<Owner> = {\n [Key in keyof Owner & string]-?: Owner[Key] extends (...args: never[]) => infer Result\n ? [Result] extends [PromiseLike<unknown>]\n ? Key\n : never\n : never;\n}[keyof Owner & string];\n\n/**\n * The path of every member of `Capability` that returns a promise: its own methods\n * (`'setValue'`) and those of its namespaces (`'comments.reply'`).\n */\nexport type PromiseMemberOf<Capability> =\n | PromiseMethodOf<Capability>\n | {\n [Key in keyof Capability & string]-?: Capability[Key] extends (...args: never[]) => unknown\n ? never\n : Capability[Key] extends object\n ? `${Key}.${PromiseMethodOf<Capability[Key]>}`\n : never;\n }[keyof Capability & string];\n\n/**\n * A token's `promises`: one entry for each member of `Capability` that returns a promise. The\n * type asks for every one of them, and only them, so the list can't fall behind the contract.\n */\nexport type PromiseMembers<Capability> = { readonly [Path in PromiseMemberOf<Capability>]: true };\n\n/**\n * What the kernel knows about an open document — the page registry captured at open.\n * `pages` is the engine's own snapshot (`PageLayout`: index, ref, size,\n * rotation, label, boxes). `ref` (the page's `PageRef`) is the durable\n * per-page identity; the array index is only display order.\n */\nexport interface DocumentMeta {\n readonly id: string;\n /**\n * Unique per open of this id: closing and reopening the same document id\n * yields a new instanceId. Events, refs and leases are checked against it,\n * so nothing produced by a closed instance can be mistaken for the new one.\n */\n readonly instanceId: string;\n readonly name?: string;\n readonly pageCount: number;\n readonly pages: readonly PageLayout[];\n /**\n * Bumps every time the page registry is replaced by a document mutation\n * event (rotate/move/delete). The registry's monotonic version: anything\n * caching a derivation of `pages` (e.g. the Stage's laid-out scene) keys\n * on it so a same-`pageCount` change — like a rotation — still invalidates.\n */\n readonly revision: number;\n /**\n * The deployment render policy the document's engine advertises — a\n * document fact like `pages`, materialized by the kernel at open (before\n * publish), not plugin state. One lifecycle (here), one interpretation\n * (engine-core's pure `snap*` helpers); any plugin reads it. Engines\n * without a render service — and failed policy reads — resolve to\n * `continuous`, so consumers never branch on absence. Naming rule: the\n * domain appears exactly once — bare `policy()` on the render service,\n * `renderPolicy` on flat envelopes like this one and `/v1/access`.\n */\n readonly renderPolicy: EngineRenderPolicy;\n /**\n * Whether the document changed since it was opened or last downloaded. Only an engine whose\n * changes live in this tab sets it (the local engine); the cloud engine stores every change\n * as it's made.\n */\n readonly hasUnsavedChanges: boolean;\n}\n\n/**\n * A tab slot whose document is not (yet) real: still opening, waiting for a\n * password, or failed. Lives beside `documents`, never inside it — plugins\n * only ever see ready documents; pending slots are pure registry/UI state.\n * Request-time lifecycle: `open()` reserves the slot (id, order position,\n * activation) synchronously; only the content arrives at completion time.\n */\nexport interface PendingMeta {\n readonly id: string;\n readonly name?: string;\n readonly status: 'loading' | 'locked' | 'error';\n /** `locked` only: a password was supplied at open and rejected — the\n * prompt should show its \"incorrect password\" copy, not \"required\". */\n readonly passwordProvided?: boolean;\n /** `error` only: what the open rejected with. Never carries a password. */\n readonly error?: unknown;\n}\n\n/** The document registry — what document scope is built on. */\nexport interface CoreState {\n readonly documents: Readonly<Record<string, DocumentMeta>>;\n readonly pending: Readonly<Record<string, PendingMeta>>;\n /** The tab strip: spans ready docs and pending slots, in request order. */\n readonly order: readonly string[];\n /** May point at a pending slot (a loading or locked tab can be selected). */\n readonly activeId: string | null;\n}\n\nexport interface GlobalState {\n readonly core: CoreState;\n readonly plugins: Readonly<Record<string, unknown>>;\n}\n\nexport type PluginScope = 'workspace' | 'document';\n\n/**\n * The context a plugin's `create()` receives. Document-scoped plugins get a\n * context bound to one document; workspace plugins reach documents through\n * `forDocument`. Everything here is bound to the instance's lifetime, so a\n * controller written as plain async code is lifetime-safe by construction.\n * `S` is the plugin's session state and `T` its settings, `NoSettings` for a\n * plugin that declares none.\n */\nexport interface PluginContext<S = unknown, T extends object = NoSettings> {\n // ── identity ──\n readonly id: string;\n /** Unique per open of this document (workspace plugins: `workspace:<id>`). */\n readonly instanceId: string;\n /** The bound document (document-scoped plugins only; undefined for workspace). */\n readonly documentId?: string;\n\n // ── the document ──\n readonly engine: Engine;\n /**\n * The guarded document handle: every call rejects `instance-closed` once the\n * instance closed, is aborted at close, and throws `PluginError` instead of\n * raw engine errors. Workspace plugins have no bound document and must use\n * `forDocument()`; reading `doc` there throws.\n */\n readonly doc: DocumentHandle;\n /** Resolve a live engine handle by document id; omitted follows this context's normal active/bound rule. */\n documentHandle(documentId?: string): DocumentHandle | null;\n /** The bound document's metadata; for workspace plugins, the active document's, or null. */\n document(): DocumentMeta | null;\n /**\n * The page a `PageRef` or a zero-based index names, or null when it names\n * no page of this document. What reads use: they run while rendering, and a\n * page deleted mid-render reads as no page instead of breaking a layer.\n */\n getPage(page: PageRef | number): PageInfo | null;\n /**\n * A page argument as every verb takes it: a `PageRef`, or a zero-based\n * index into the document's page list. Throws `not-found` when neither\n * names a page of this document: a verb refuses a page that isn't there.\n */\n pageOf(page: PageRef | number): PageInfo;\n /** Throw `not-found` unless the ref names a page of this document. */\n assertPageRef(ref: PageRef): void;\n\n // ── permissions ──\n /**\n * Whether the bound document's session holds `permission`: the same answer\n * the engine enforces with. What every `can<Verb>()` reads.\n * Document-scoped plugins only: a workspace context has no bound document,\n * so this throws as reading `doc` does. A workspace plugin asks the `can<Verb>()` of the\n * document plugin it acts through (`ctx.forDocument(token, documentId)`).\n */\n allows(permission: Permission): boolean;\n /**\n * Refuse a verb the session may not run, before any engine call: throws\n * `permission-denied` (\"`operation` requires `permission`\") with\n * `error.permission` set. Document-scoped plugins only, like `allows`.\n */\n assertAllowed(permission: Permission, operation: string): void;\n /**\n * Whether the session may fill in (`fill`) or sign (`sign`) this form\n * field: a `fields:<action>` permission for its group, or `doc.forms.fill`\n * (`doc.sign`) for every field. The same answer the engine enforces with.\n * Document-scoped plugins only, like `allows`.\n */\n allowsField(action: 'fill' | 'sign', field: { readonly groupId: string | null }): boolean;\n /**\n * Refuse a write to a field the session may not fill in or sign: throws\n * `permission-denied` naming what it would take (`fields:fill:group=buyer`).\n */\n assertAllowedField(\n action: 'fill' | 'sign',\n field: { readonly groupId: string | null },\n operation: string,\n ): void;\n\n // ── capabilities ──\n get<T>(token: CapabilityToken<T>): T;\n tryGet<T>(token: CapabilityToken<T>): T | null;\n forDocument<T>(token: CapabilityToken<T>, documentId: string): T;\n /** `forDocument` for an optional dependency: null when the plugin is not\n * installed or that document is not ready, never a throw. */\n tryForDocument<T>(token: CapabilityToken<T>, documentId: string): T | null;\n\n // ── state ──\n /** This instance's session state, changed only through pure transitions. */\n readonly state: StateCell<S>;\n\n // ── settings ──\n /**\n * The plugin's settings, as its definition declares them (`definePlugin({ settings })`):\n * what the app registered over the defaults. They belong to the plugin as registered, not to\n * this instance: the kernel builds them when it plans the plugin list, before any document\n * opens, and `updateSettings()` reaches every open document and the ones opened later. Spread\n * `api` into the capability and read `get()` in the controller; the instance's\n * `onSettingsChanged` listeners go when it closes. The merge rules are in `settings.ts`.\n * A plugin whose definition declares no settings has none to read: calling it throws.\n */\n readonly settings: () => Settings<T>;\n\n // ── reactivity ──\n /**\n * Wake every reader: something this capability reads outside its state\n * (a registry, a cache, a resource) changed. A no-op once the instance closed.\n */\n notify(): void;\n /**\n * Run `handler` whenever `select()` answers differently. For reacting to\n * state this plugin does not own (the page registry, a sibling's getter);\n * this plugin's own changes are observed with `state.onChange`.\n * Unsubscribed when the instance closes.\n */\n watch<R>(\n select: () => R,\n handler: (value: R, previous: R) => void,\n isEqual?: (left: R, right: R) => boolean,\n ): Unsubscribe;\n /** Resolve when the predicate holds (checked on every store change); rejects on cancel or close. */\n waitFor(predicate: () => boolean, options?: OperationOptions): Promise<void>;\n\n // ── engine truth ──\n /**\n * A local copy of document data the engine owns, kept current from confirmed\n * document events (every origin) and reloads. Document-scoped plugins only;\n * loading starts once the plugin is connected.\n */\n mirror<V>(spec: MirrorSpec<V>): Mirror<V>;\n /** Like `mirror`, for data loaded page by page on demand. */\n pageMirror<V>(spec: PageMirrorSpec<V>): PageMirror<V>;\n /**\n * The document's change queue, shared by its plugins: a user action is one change, staged\n * here, shown by every mirror's `view()` at once, and sent after everything staged before it.\n * Document-scoped plugins only. The rules are in `docs/conventions/state-and-sync.md`.\n */\n readonly changes: ChangeQueue;\n\n // ── events ──\n /** Mint a capability event; disposed with the instance. Expose only `.on`. */\n readonly events: {\n source<T>(): { readonly on: EventHook<T>; emit(event: T): void; dispose(): void };\n };\n /** Subscribe for the instance lifetime; the unsubscribe is owned by the kernel. */\n listen<T>(source: Subscribable<T>, listener: (event: T) => void): void;\n\n // ── lifetime and async ──\n /**\n * Register a resource teardown owned by this plugin instance. Document-\n * scoped callbacks run when that document closes; workspace callbacks run\n * when the kernel is destroyed. Asynchronous teardowns are awaited.\n * Registering after the owner is already disposed runs the teardown\n * immediately instead of dropping it, so a late registration cannot leak.\n */\n cleanup(fn: () => void | Promise<void>): void;\n /**\n * Time, from the host: `after(ms, run)` and `nextFrame(run)`, each returning\n * its cancel, and `hasFrames`. What the instance schedules is cancelled when\n * it closes. Plugins never read timers or frames from the environment.\n */\n readonly clock: PluginClock;\n /**\n * Register what this plugin holds back from the engine, such as text typed a moment ago or\n * the writes in its write queue (`() => queue.idle()`). Before anything reads the whole\n * document (`documents.download()`, `downloadLayer()`), the kernel calls every plugin's `flush` and\n * waits for it: send what's held back, and resolve once the engine has it. Document-scoped\n * plugins only; unregistered when the instance closes. The rules are in\n * `docs/conventions/state-and-sync.md`.\n */\n onSettle(flush: (signal: AbortSignal) => Promise<void> | void): void;\n /**\n * Run something of the document's own around every download of its file\n * (`documents.download()`, `downloadLayer()`): `wrap` gets the read and returns its bytes,\n * doing what comes before and after it. The actions plugin runs the document's save actions\n * this way. The document has settled before `wrap` is called; the first registered wraps the\n * others. Document-scoped plugins only; unregistered when the instance closes.\n */\n aroundDownload(wrap: (read: () => Promise<Uint8Array>) => Promise<Uint8Array>): void;\n /** Acquire a resource whose disposal the instance owns; a late arrival after close is disposed, not returned. */\n acquire<R>(\n get: (lifetime: AbortSignal) => Promise<R>,\n dispose: (resource: R) => void | Promise<void>,\n ): Promise<R>;\n /**\n * Run an engine call the caller can cancel: when `signal` fires, the call is\n * aborted (if the engine can abort it) and the returned promise rejects\n * `operation-cancelled` at once. A signal that already fired rejects\n * straight away; without a signal, `task` is returned as it is.\n */\n cancellable<T>(signal: AbortSignal | undefined, task: Promise<T>): Promise<T>;\n /** Newest-wins lane for reads a newer call should cancel (visible search, validation). */\n latest(key: string): import('./lanes').LatestLane;\n /**\n * Per-key submission-order queue for multi-step writes; failures do not\n * poison later work. An operation queued with `{ signal }` whose signal\n * fired while it waited is skipped and rejects `operation-cancelled`.\n */\n serialQueue(key?: string): SerialQueue;\n}\n\n/**\n * A plugin instance's session state. The value is replaced, never mutated:\n * `update` applies a pure transition, and a transition that returns the\n * current value changes nothing.\n */\nexport interface StateCell<S> {\n get(): S;\n update<Args extends unknown[]>(transition: (state: S, ...args: Args) => S, ...args: Args): void;\n /** Fires synchronously after every committed change of this instance's state. */\n readonly onChange: EventHook<StateChange<S>>;\n}\n\n/** One committed state change: the value before and after. */\nexport interface StateChange<S> {\n readonly next: S;\n readonly previous: S;\n}\n\n/**\n * A plugin definition. `scope` decides multiplexing:\n * 'workspace' (default) — one instance; can see every document.\n * 'document' — one instance per open document; authored single-document.\n *\n * Its types come from its own fields: the state `S` from `state`, the capability\n * `C` from `token`, the settings `T` from `settings.defaults`. `create` and\n * `inScope` are checked against them and never name them (`NoInfer`), so a\n * controller that returns less than the capability is a type error, not a\n * narrower capability.\n */\nexport interface PluginDef<S = unknown, C = unknown, T extends object = NoSettings> {\n readonly id: string;\n readonly token?: CapabilityToken<C>;\n readonly scope?: PluginScope;\n readonly requires?: ReadonlyArray<CapabilityToken<unknown>>;\n readonly optional?: ReadonlyArray<CapabilityToken<unknown>>;\n /**\n * The plugin resolves capabilities for code the host supplies (the commands\n * plugin runs command definitions that act on any capability), so it cannot\n * declare them. Resolving an undeclared token is then allowed; the kernel\n * neither orders nor validates those dependencies.\n */\n readonly resolvesAnyCapability?: true;\n /** Initial session state, built fresh for every instance. Omit for stateless plugins. */\n readonly state?: () => S;\n /**\n * The plugin's settings: its defaults, and what the app registered (the factory's config).\n * The kernel builds one store per registration from it when it plans the plugin list, so the\n * settings can be read and changed before any document opens (`kernel.settingsOf(token)`).\n * The plugin reads them with `ctx.settings()`. Omit for a plugin without settings.\n */\n readonly settings?: SettingsDeclaration<T>;\n /**\n * Build the instance's API and, optionally, the connections (subscriptions\n * to engine events and sibling capabilities) that start once every\n * dependency is constructed. Runs once per instance.\n */\n readonly create: NoInfer<(ctx: PluginContext<S, T>) => { api: C; connect?: () => void }>;\n /**\n * This capability as seen from inside a document's scope: calls that leave out the document\n * use `documentId` instead of the active one. Workspace plugins only. The kernel builds the\n * view once per document and hands it out whenever that document is named\n * (`kernel.capability(token, documentId)`, `ctx.forDocument`, a `<DocumentScope>`).\n */\n readonly inScope?: NoInfer<(api: C, documentId: string) => C>;\n}\n\nexport type AnyPlugin = PluginDef<any, any, any>;\n\n// ── Built-in: the document registry, exposed as a capability ─────────────────\n\n/** Where a document is: opening, waiting for its password, open, or failed to open. */\nexport type DocumentStatus = 'loading' | 'locked' | 'ready' | 'error';\n\n/**\n * An open document, as its tab shows it. The same object until one of its fields changes, so a\n * reader that compares by reference re-renders only for its own document.\n */\nexport interface DocumentInfo {\n /** The document's id, for `close(id)`, `unlock(id, …)` and a document scope. */\n readonly id: string;\n /** The name its tab shows, from `open()` or `rename()`. */\n readonly name?: string;\n readonly status: DocumentStatus;\n /** How many pages it has; 0 until it's `ready`. */\n readonly pageCount: number;\n /**\n * Whether it has changes that weren't downloaded yet. Always false on an engine that stores\n * every change as it's made (the cloud engine).\n */\n readonly hasUnsavedChanges: boolean;\n /** `locked` only: a password was tried and was wrong. */\n readonly passwordProvided?: boolean;\n /** `error` only: why it couldn't be opened, in the plugin error vocabulary. */\n readonly error?: PluginErrorInfo;\n}\n\n/** A document waiting for its password. */\nexport interface LockedDocumentInfo extends DocumentInfo {\n readonly status: 'locked';\n readonly passwordProvided: boolean;\n}\n\n/** A document that couldn't be opened, and why. */\nexport interface FailedDocumentInfo extends DocumentInfo {\n readonly status: 'error';\n readonly error: PluginErrorInfo;\n}\n\n/** A file the viewer downloads itself, with the document's cancel signal: relative to the page, or absolute. */\nexport interface UrlSource {\n readonly kind: 'url';\n readonly url: string;\n}\n\n/** Options for opening a document: the tab (`name`, `activate`), the engine's `OpenOptions`, and a `signal`. */\nexport type OpenDocumentOptions = OpenOptions & {\n /** Make it the active document; true unless given. */\n readonly activate?: boolean;\n /** The name its tab shows. */\n readonly name?: string;\n /** Cancels the open: the document closes, and `open()` rejects `operation-cancelled`. */\n readonly signal?: AbortSignal;\n};\n\n/**\n * What `open()` accepts: an engine `OpenInput`, a URL the viewer downloads, or a function that\n * returns one of them. A function runs under the document's loading state, so the tab exists\n * while it fetches; the `signal` it receives fires when the document is closed first, so pass it\n * to `fetch()`.\n */\nexport type OpenSource =\n | OpenInput\n | UrlSource\n | ((signal: AbortSignal) => OpenInput | UrlSource | Promise<OpenInput | UrlSource>);\n\n/** What `open()` and `retry()` resolve: the document, ready or locked. */\nexport interface OpenDocumentResult {\n readonly document: DocumentInfo;\n}\n\n/** Options for `unlock()`: the password, and a `signal` that stops trying it. */\nexport interface UnlockOptions extends OperationOptions {\n readonly password: string;\n}\n\n/** Options for `download()`. */\nexport interface DownloadOptions extends OperationOptions {\n /**\n * `'incremental'` (the default) appends the changes to the original file, so existing\n * signatures stay valid; `'rewrite'` writes a fresh file without earlier revisions.\n */\n readonly mode?: PdfSaveMode;\n}\n\n/**\n * One boot document for `documents.openAll()` — the shared shape every\n * framework adapter's `initialDocuments` input uses (adapters re-export it,\n * never redefine it). `active` picks the selected tab (default: the first);\n * all other open options (name, password, scope, identity, …) pass straight\n * through to `open()`, so the declarative and imperative paths cannot drift.\n */\nexport type InitialDocument = { source: OpenSource; active?: boolean } & Omit<\n OpenDocumentOptions,\n 'activate' | 'signal'\n>;\n\n// ── document lifecycle events ─────────────────────────────────────────────\nexport interface DocumentOpenedEvent {\n readonly documentId: string;\n readonly info: DocumentInfo;\n}\nexport interface DocumentOpenFailedEvent {\n readonly documentId: string;\n readonly error: PluginErrorInfo;\n}\nexport interface DocumentLockedEvent {\n readonly documentId: string;\n readonly passwordProvided: boolean;\n}\nexport interface DocumentClosedEvent {\n readonly documentId: string;\n}\nexport interface DocumentActiveChangedEvent {\n readonly documentId: string | null;\n readonly previousDocumentId: string | null;\n}\nexport interface DocumentPagesChangedEvent {\n readonly documentId: string;\n readonly revision: number;\n readonly pages: readonly PageInfo[];\n}\nexport interface DocumentUnsavedChangesChangedEvent {\n readonly documentId: string;\n readonly hasUnsavedChanges: boolean;\n}\n\n/**\n * The document registry. A call that leaves out the document uses the document in scope when\n * the capability was resolved for one (`kernel.capability(DocumentsToken, documentId)`, a\n * `<DocumentScope>`), and the active document otherwise. Its verbs reject with `PluginError`.\n */\nexport interface DocumentsCapability {\n /**\n * Open a document and make it the active one (unless `activate: false`). Its tab exists at\n * once; the promise resolves `{ document }` once it's ready, or locked with a password.\n * The document's own `scope` and `identity` replace the viewer's. Rejects with the reason it\n * couldn't be opened (the tab then shows `error`), or `operation-cancelled` when it was closed\n * or `signal` fired first.\n */\n open(source: OpenSource, options?: OpenDocumentOptions): Promise<OpenDocumentResult>;\n /**\n * Whether `open()` can open a file from the user's computer (its bytes, or a URL the viewer\n * downloads): the engine's `canOpenFiles`. True with the local engine; false with the cloud\n * engine, whose documents come from your server.\n */\n canOpenFiles(): boolean;\n /**\n * Open a failed document (`status: 'error'`) again, with the same source and options, in its\n * own tab: it keeps its id and its place, and the active document stays the active one.\n * Resolves like `open()`. Rejects `invalid-input` for a document that didn't fail.\n */\n retry(id: string, options?: OperationOptions): Promise<OpenDocumentResult>;\n /** Change the name its tab shows; the file doesn't change. */\n rename(id: string, name: string): void;\n /**\n * Open several documents, as `initialDocuments` does: every tab appears at once, in array\n * order, and the one marked `active` (else the first) becomes the active one, decided now, so\n * a slow document never steals the focus. A failure shows in that document's `status`\n * instead of rejecting. Returns the tabs' ids.\n */\n openAll(documents: readonly InitialDocument[]): readonly string[];\n /**\n * Unlock a `locked` document with its password; it opens as it would have. Rejects\n * `permission-denied` on a wrong password, and the document stays locked so you can ask\n * again; `invalid-input` for a document that isn't locked.\n */\n unlock(id: string, options: UnlockOptions): Promise<void>;\n /** Close a document and free its memory; the next one becomes active. Closing one still opening cancels it. */\n close(id: string): Promise<void>;\n /** Close every document. */\n closeAll(): Promise<void>;\n /** Make a document the active one: the one every component talks to outside a document scope. */\n setActive(id: string): void;\n /** The active document's id, or null with none open. */\n getActiveId(): string | null;\n /** The active document's fields, or null with none open. */\n getActive(): DocumentInfo | null;\n /** Every open document in tab order, loading, locked and failed ones included; the same array until one changes. */\n list(): readonly DocumentInfo[];\n /** A document's fields (the one in scope without an id), or null when it isn't open. */\n get(id?: string): DocumentInfo | null;\n /** Whether a document is open. */\n has(id: string): boolean;\n /** How many documents are open. */\n getCount(): number;\n /** The open documents' ids, in tab order. */\n getOrder(): readonly string[];\n /** Put every document in a new order at once; `ids` holds the id of every open document. */\n setOrder(ids: readonly string[]): void;\n /** Move a document to another place in the tab order. */\n move(id: string, toIndex: number): void;\n /** Swap two documents in the tab order. */\n swap(id: string, otherId: string): void;\n /**\n * The PDF with every change, as bytes. It first waits for changes still on their way (text\n * typed a moment ago, writes queued), and runs the document's own save actions around the\n * read when the actions plugin is installed. Afterwards `hasUnsavedChanges` is false, unless\n * something changed meanwhile. Rejects `permission-denied` without `doc.download`,\n * `not-ready` with no open document, `operation-cancelled` when `signal` fires.\n */\n download(id?: string, options?: DownloadOptions): Promise<Uint8Array>;\n /**\n * Only the changes, as a layer artifact you open again over the original\n * (`{ kind: 'layerBytes', baseBytes, layer: { kind: 'artifact', bytes } }`). Waits and runs the\n * save actions like `download()`. Rejects `unsupported` when the document wasn't opened with a\n * layer or the engine keeps layers itself (the cloud engine), and as `download()` does.\n */\n downloadLayer(id?: string, options?: OperationOptions): Promise<Uint8Array>;\n /** Whether the document (the one in scope without an id) may be downloaded: `doc.download`. */\n canDownload(id?: string): boolean;\n /** Whether the document (the one in scope without an id) may be printed: `doc.print`. */\n canPrint(id?: string): boolean;\n /**\n * The document's pages, in order (the one in scope without an id). The same array until a\n * page is added, removed, moved or rotated.\n */\n listPages(id?: string): readonly PageInfo[];\n /** One page, by its `PageRef` or its zero-based index, or null when the document doesn't have it. */\n getPage(page: PageRef | number, id?: string): PageInfo | null;\n /** A page's position, from 0, or `-1` when the document doesn't have it. */\n getPageIndex(ref: PageRef, id?: string): number;\n /** A number that goes up each time pages are added, removed, moved or rotated; `-1` with no document. */\n getRevision(id?: string): number;\n\n /** A document is open and ready. */\n readonly onOpened: EventHook<DocumentOpenedEvent>;\n /** A document couldn't be opened; its tab shows `error`. */\n readonly onOpenFailed: EventHook<DocumentOpenFailedEvent>;\n /** A document needs its password. */\n readonly onLocked: EventHook<DocumentLockedEvent>;\n /** A document was closed, after its resources were released. */\n readonly onClosed: EventHook<DocumentClosedEvent>;\n /** Another document became the active one. */\n readonly onActiveChanged: EventHook<DocumentActiveChangedEvent>;\n /** Pages were added, removed, moved or rotated. */\n readonly onPagesChanged: EventHook<DocumentPagesChangedEvent>;\n /** A document got its first unsaved change, or was downloaded. */\n readonly onUnsavedChangesChanged: EventHook<DocumentUnsavedChangesChangedEvent>;\n}\n\n/** Built-in token for the document registry capability (provided by the kernel). */\nexport const DocumentsToken: CapabilityToken<DocumentsCapability> = { name: 'documents' };\n","/**\n * One change, one store update. Both engines publish a change's events in one\n * synchronous burst that shares `origin.tx`. While a burst of several events\n * arrives, the store holds its notifications, so readers hear of the whole\n * change once, after its last event, whoever made it.\n */\nimport type { DocumentEvent } from '@embedpdf/engine-core/runtime';\n\nimport type { Store } from './store';\n\nconst txOf = (event: DocumentEvent) => ('origin' in event ? event.origin.tx : undefined);\n\nexport interface BurstGate {\n /** Run before every other listener: opens at a burst's first event. */\n first(event: DocumentEvent): void;\n /** Run after every other listener: closes at the burst's last event. */\n last(event: DocumentEvent): void;\n /** Close a burst left open. */\n close(): void;\n}\n\nexport function createBurstGate(store: Pick<Store, 'hold'>): BurstGate {\n let open: { id: string; release: () => void } | null = null;\n const close = (): void => {\n const held = open;\n open = null;\n held?.release();\n };\n return {\n first(event) {\n const tx = txOf(event);\n // A burst that never reached its last event ends when another event arrives.\n if (open && open.id !== tx?.id) close();\n if (!open && tx && tx.index === 0 && tx.count > 1)\n open = { id: tx.id, release: store.hold() };\n },\n last(event) {\n const tx = txOf(event);\n if (open && tx?.id === open.id && tx.index === tx.count - 1) close();\n },\n close,\n };\n}\n","/**\n * Resource scope — the ownership half of the lifecycle model.\n *\n * Every resource acquisition registers its release into the owning scope at\n * the acquisition site (`scope.defer(release)` on the line after acquiring),\n * so no exit path can forget it. `dispose()` unwinds the stack LIFO, awaits\n * asynchronous teardowns, and is idempotent — every call returns the same\n * promise.\n *\n * The rule that deletes the silent-leak bug class: a disposed scope never\n * swallows a teardown. Registering against a scope that is already disposing\n * runs the teardown as soon as the in-flight disposal finishes, instead of\n * dropping it. (Producers are still expected to stop at their next\n * cancellation checkpoint; this rule is the safety net, not the primary\n * synchronization — that's the session's operation join.)\n */\n\nexport type Teardown = () => void | Promise<void>;\n\n/**\n * A lifecycle operation was cancelled — the tab was closed mid-open, or the\n * kernel was destroyed mid-start. Not a failure: callers that race `open()`\n * against `close()` should treat this rejection as \"the close won\".\n */\nexport class CancelledError extends Error {\n constructor(what: string) {\n super(`[kernel] cancelled: ${what}`);\n this.name = 'CancelledError';\n }\n}\n\nexport const isCancelled = (error: unknown): error is CancelledError =>\n error instanceof CancelledError;\n\nexport interface Scope {\n readonly disposed: boolean;\n defer(teardown: Teardown): void;\n dispose(): Promise<void>;\n}\n\nexport function createScope(report: (error: unknown) => void): Scope {\n const teardowns: Teardown[] = [];\n let disposal: Promise<void> | null = null;\n\n return {\n get disposed() {\n return disposal !== null;\n },\n defer(teardown) {\n if (disposal) void disposal.then(() => Promise.resolve().then(teardown).catch(report));\n else teardowns.push(teardown);\n },\n dispose() {\n return (disposal ??= (async () => {\n while (teardowns.length) {\n try {\n await teardowns.pop()!();\n } catch (error) {\n report(error); // one failing teardown never strands the rest\n }\n }\n })());\n },\n };\n}\n","import { EngineError } from '@embedpdf/engine-core/runtime';\nimport { isCancelled } from './scope';\n\n/**\n * The one error vocabulary a plugin capability rejects with. Stable codes so\n * callers match on `code`, never on message text; the engine's error stays\n * reachable as `cause`.\n */\nexport type PluginErrorCode =\n | 'permission-denied'\n | 'unsupported'\n | 'not-found'\n | 'not-ready'\n | 'invalid-input'\n | 'conflict'\n | 'instance-closed'\n | 'operation-cancelled'\n | 'operation-failed';\n\nexport class PluginError extends Error {\n override readonly name = 'PluginError';\n readonly code: PluginErrorCode;\n /** The capability (plugin id) that produced the error. */\n readonly capability: string;\n /**\n * The permission the session lacks, named as the engine names it: a document capability\n * (`'doc.forms.fill'`) or an annotation action (`'annotations:update'`). Set on\n * `permission-denied` when the refusal names one, whether a plugin's own check refused\n * (`ctx.assertAllowed`) or the engine did; null otherwise.\n */\n readonly permission: string | null;\n readonly details: unknown;\n\n constructor(\n code: PluginErrorCode,\n capability: string,\n message: string,\n options: { cause?: unknown; details?: unknown; permission?: string | null } = {},\n ) {\n super(message);\n if (options.cause !== undefined) (this as { cause?: unknown }).cause = options.cause;\n this.code = code;\n this.capability = capability;\n this.permission = options.permission ?? null;\n this.details = options.details;\n }\n}\n\n/** The serializable summary of a PluginError, for state and event payloads. */\nexport interface PluginErrorInfo {\n readonly code: PluginErrorCode;\n readonly message: string;\n readonly capability: string;\n /** The permission the session lacks (see `PluginError.permission`), or null. */\n readonly permission: string | null;\n}\n\nexport function toPluginErrorInfo(error: PluginError): PluginErrorInfo {\n return {\n code: error.code,\n message: error.message,\n capability: error.capability,\n permission: error.permission,\n };\n}\n\nexport function isPluginError(value: unknown, code?: PluginErrorCode): value is PluginError {\n if (!(value instanceof PluginError)) return false;\n return code === undefined || value.code === code;\n}\n\nconst ENGINE_CODE_MAP: Readonly<Record<string, PluginErrorCode>> = {\n InvalidArg: 'invalid-input',\n MalformedPdf: 'invalid-input',\n PayloadTooLarge: 'invalid-input',\n // An answer of a shape the engine doesn't know, from its worker or its server (a version\n // apart): the engine failed, not the input, so a document's tab doesn't call the file damaged.\n WireFormat: 'operation-failed',\n DocNotOpen: 'not-ready',\n DocPasswordRequired: 'permission-denied',\n DocPasswordIncorrect: 'permission-denied',\n SharePasswordRequired: 'permission-denied',\n Unauthenticated: 'permission-denied',\n Forbidden: 'permission-denied',\n ProtectedDocument: 'permission-denied',\n NotFound: 'not-found',\n NotImplemented: 'unsupported',\n Aborted: 'operation-cancelled',\n LayerVersionConflict: 'conflict',\n StaleBase: 'conflict',\n SigningPending: 'conflict',\n SigningExpired: 'conflict',\n SigningVersionMismatch: 'conflict',\n ObjectNumberUnavailable: 'conflict',\n LayerFull: 'conflict',\n ChangeConflict: 'conflict',\n UndoUnavailable: 'conflict',\n IdempotencyKeyReused: 'invalid-input',\n};\n\n/**\n * The permission an engine refusal names. `PermissionDenied` puts it in `details.required`\n * (the first of `details.anyOf` when any of several would have done), and `details` is what\n * survives the trip from a worker or the server, where the refusal arrives as a plain\n * `EngineError` with code `Forbidden`.\n */\nfunction requiredPermissionOf(error: EngineError): string | null {\n const required = error.details?.required;\n return typeof required === 'string' ? required : null;\n}\n\n/**\n * The one boundary mapping from whatever an engine call threw to a\n * `PluginError`. Idempotent: an existing PluginError passes through.\n * Cancellation (the kernel's CancelledError, a DOM AbortError, or an engine\n * abort) is `operation-cancelled`, never `operation-failed`, so callers can\n * tell \"nobody wanted this anymore\" from \"this broke\". A refusal names the\n * missing permission in `permission`; `details` keeps the rest of what the\n * engine sent (`anyOf`, `context`).\n */\nexport function toPluginError(capability: string, error: unknown): PluginError {\n if (error instanceof PluginError) return error;\n if (isCancelled(error) || (error instanceof Error && error.name === 'AbortError')) {\n return new PluginError('operation-cancelled', capability, 'operation cancelled', {\n cause: error,\n });\n }\n if (EngineError.is(error)) {\n const code = ENGINE_CODE_MAP[String(error.code)] ?? 'operation-failed';\n return new PluginError(code, capability, error.message, {\n cause: error,\n details: error.details,\n permission: code === 'permission-denied' ? requiredPermissionOf(error) : null,\n });\n }\n const message = error instanceof Error ? error.message : String(error);\n return new PluginError('operation-failed', capability, message, { cause: error });\n}\n","import type { Unsubscribe } from './types';\n\n/**\n * Subscribe-only face of a plugin event — the one event shape a capability\n * exposes (`onX: EventHook<XEvent>`). Events carry occurrences, never state:\n * a late subscriber that needs the current value uses a query + selector\n * instead. Payloads are plain serializable objects.\n */\nexport type EventHook<T> = (\n listener: (event: T) => void,\n options?: { signal?: AbortSignal },\n) => Unsubscribe;\n\n/**\n * The plugin-private pair behind one capability event. Expose `.on` on the\n * capability; keep `emit`/`dispose` inside the plugin. Because the capability\n * member is the bare function type, the emitting half is unreachable through\n * the public contract by construction.\n */\nexport interface EventHookSource<T> {\n readonly on: EventHook<T>;\n emit(event: T): void;\n dispose(): void;\n}\n\n/**\n * Create one capability event.\n *\n * Subscribe with `{ signal }` to tie the subscription to an AbortSignal; a\n * pre-aborted signal never registers.\n *\n * Delivery contract: synchronous fan-out over a snapshot of the listener set\n * (listeners added or removed during an emit don't affect that emit); a\n * throwing listener is isolated — reported through `onListenerError`, never\n * allowed to break the emitting operation or its sibling listeners. After\n * `dispose()`, `on` returns an inert unsubscribe (teardown races never throw).\n * No value cache, no replay, no equality — state belongs to the store.\n */\nexport function createEventHook<T = void>(\n onListenerError?: (error: unknown) => void,\n): EventHookSource<T> {\n let listeners: Set<(event: T) => void> | null = new Set();\n return {\n on(listener, options) {\n if (!listeners || options?.signal?.aborted) return () => {};\n listeners.add(listener);\n const off = () => void listeners?.delete(listener);\n // An AbortSignal is the framework-neutral lifetime: one controller can\n // end many subscriptions (rule 8 of the contract).\n options?.signal?.addEventListener('abort', off, { once: true });\n return off;\n },\n emit(event) {\n if (!listeners) return;\n for (const listener of [...listeners]) {\n try {\n listener(event);\n } catch (error) {\n onListenerError?.(error);\n }\n }\n },\n dispose() {\n listeners = null;\n },\n };\n}\n","/**\n * The change queue (`ctx.changes`): one per open document, shared by every\n * plugin of it.\n *\n * A user action is one change: a list of the engine's ops, applied all or\n * nothing by `doc.apply`, sent as one request and undone as one step. A plugin\n * stages it; every mirror's `view()` shows it at once (`predict`, mirror.ts),\n * and the queue sends it after everything staged before it. The engine keeps\n * that order, and publishes a change's events before it answers.\n *\n * A change leaves the views once the engine answered:\n * - applied: once each mirror holds the answer. A mirror that folded the\n * events already does; one that asked to read again keeps showing the\n * change until that read lands (mirror.ts).\n * - refused: at once, together with the changes that name an object only it\n * would have created (its dependents), which can't apply either.\n *\n * Two ways a change is put together over time:\n * - a hold can still be amended before it is sent (typing, a form commit\n * waiting for its scripts). Any later stage sends the open holds first, so\n * send order is always staging order;\n * - a group makes everything staged inside it, by any plugin, one change.\n */\nimport {\n generateUuidV7,\n objectNumbersNamedBy,\n objectNumbersReferencedBy,\n type Annotation,\n type Change,\n type ChangeOp,\n type ChangeResult,\n type DocumentHandle,\n type FormFieldDTO,\n type WidgetAnnotation,\n} from '@embedpdf/engine-core/runtime';\n\nimport { PluginError, toPluginError } from './errors';\nimport { createEventHook, type EventHook } from './event-hook';\n\n/** What a change is called in history and refusals: an i18n key and its values. */\nexport interface ChangeLabel {\n readonly key: string;\n readonly [value: string]: string | number;\n}\n\n/** An op a view can predict: the engine's ops, and the ones only an undo brings back. */\nexport type PredictedOp =\n | ChangeOp\n | {\n readonly type: 'annotations.restore';\n readonly annotation: Annotation;\n /** Its place among the page's annotations. */\n readonly index: number;\n }\n | {\n readonly type: 'forms.restore';\n readonly field: FormFieldDTO;\n /** The rows of its widgets, as they were. */\n readonly widgets: readonly WidgetAnnotation[];\n }\n | {\n readonly type: 'forms.restoreWidget';\n /** The widget's row, as it was. */\n readonly widget: WidgetAnnotation;\n /** Its field as the restore leaves it, with the widget back; `null` when it had none. */\n readonly field: FormFieldDTO | null;\n };\n\n/** One user action, as a plugin stages it. */\nexport type StagedChange =\n | {\n readonly label: ChangeLabel;\n /** The engine's ops, sent as they are. */\n readonly ops: readonly ChangeOp[];\n /** What undoing it looks like, as ops the views can predict. Drawing only; never sent. */\n readonly undo?: readonly PredictedOp[];\n /** `false`: not a step of the history, such as a recalculation another session caused. */\n readonly history?: false;\n }\n | {\n readonly label: ChangeLabel;\n /** Undo the change with this `opId`: the engine applies the reverse it recorded. */\n readonly undoOf: string;\n /** What the views show until the engine answers. */\n readonly shows: readonly PredictedOp[];\n };\n\n/** A change of this session the engine hasn't answered yet. */\nexport interface PendingChange {\n /** Its name: what the engine's events carry as `origin.tx.id`, and what `undoOf` names. */\n readonly opId: string;\n readonly label: ChangeLabel;\n /** For an undo: the `opId` of the change it undoes. `null` for a change of ops. */\n readonly undoOf: string | null;\n /**\n * A held change's `merge` key: consecutive changes with the same key are one step of the\n * history (the pauses of one typing session). `null` for every other change.\n */\n readonly merge: string | null;\n /** What the views show until the engine answers: its ops, or an undo's prediction. */\n readonly shows: readonly PredictedOp[];\n /** What undoing it looks like (drawing only); empty when the stager gave none. */\n readonly undo: readonly PredictedOp[];\n /** Whether it is a step of the history. An undo isn't: it moves along the history. */\n readonly history: boolean;\n /** An open hold: shown, not sent yet. */\n readonly held: boolean;\n /** The engine's answer: resolves with what the change did, rejects with why it was refused. */\n readonly result: Promise<ChangeResult>;\n}\n\n/** A change the engine answered. */\nexport type SettledChange =\n | { readonly change: PendingChange; readonly status: 'applied'; readonly result: ChangeResult }\n | { readonly change: PendingChange; readonly status: 'refused'; readonly error: PluginError };\n\n/** How a held change is put in the history. */\nexport interface HoldOptions {\n /** Consecutive changes with the same key are one step of the history: typing into one text box. */\n readonly merge?: string;\n}\n\n/** A change that can still be amended until it is sent. */\nexport interface HeldChange {\n /**\n * Whether it can still be amended: false once it was sent (by `send`, by a later stage, or\n * before a download) or cancelled. What comes after goes into a new change.\n */\n readonly open: boolean;\n /** The change it is, once it has ops (its `opId`, its answer); `null` before. */\n readonly change: PendingChange | null;\n /** Its ops from now on, and what undoing them looks like. The views show the latest. */\n set(ops: readonly ChangeOp[], undo?: readonly PredictedOp[]): void;\n /**\n * Send it now, after any hold staged before it. A hold is also sent when another change is\n * staged, and before a download. `null` when nothing was ever set.\n */\n send(): PendingChange | null;\n /** Drop it: the views show the truth again, and nothing is sent. */\n cancel(): void;\n}\n\n/** The document's change queue, as a plugin uses it (`ctx.changes`). */\nexport interface ChangeQueue {\n /**\n * Stage one user action. Every mirror's view shows it before this returns, and it is sent\n * after everything staged before it; an open hold is sent first. Inside a group it joins the\n * group's change, and the group's change is what it returns.\n */\n stage(change: StagedChange): PendingChange;\n /**\n * A change that can still be amended until it is sent: typing, or a form commit waiting for\n * its scripts. It keeps its place in the order from its first `set`. Refused inside a group.\n */\n hold(label: ChangeLabel, options?: HoldOptions): HeldChange;\n /** Send every open hold now, in staging order: what an undo does first, as a download does. */\n sendHolds(): void;\n /**\n * Everything staged while `run` runs, by any plugin, becomes one change: one request, one\n * undo step. Only what is staged before `run` returns joins; nested groups join the outer\n * one. When `run` throws, nothing of it is sent.\n */\n group<T>(label: ChangeLabel, run: () => T): T;\n /** A final name for an object this session creates, or `null` when none is held (then `reserve`). */\n takeObjectNumber(): number | null;\n /** Resolves once at least `count` names are held. */\n reserveObjectNumbers(count: number): Promise<void>;\n /** This session's changes the engine hasn't answered, open holds included, in staging order. */\n pending(): readonly PendingChange[];\n hasPending(): boolean;\n /** Resolves once every change sent so far is answered; open holds aren't waited for. Never rejects. */\n whenSettled(): Promise<void>;\n /** A change was staged, or a hold was sent. */\n readonly onStaged: EventHook<PendingChange>;\n /** The engine answered a change, or refused it with one it depended on. */\n readonly onSettled: EventHook<SettledChange>;\n}\n\n/** A change in the queue, with the order it was staged in. */\nexport interface QueuedChange extends PendingChange {\n readonly seq: number;\n}\n\n/** What the mirrors read from the queue to show the pending changes. */\nexport interface ChangeViews {\n /** The changes the views show, in staging order: every one not answered yet. */\n shown(): readonly QueuedChange[];\n /** Moves every time `shown()` does. */\n version(): number;\n /** A change still waiting for its answer, by its `opId`. */\n find(opId: string): QueuedChange | undefined;\n}\n\n/** The kernel's side of a document's queue. */\nexport interface DocumentChanges extends ChangeViews {\n /** The queue as one plugin uses it: its refusals name that plugin. */\n forPlugin(capability: string): ChangeQueue;\n /** Send every open hold, then wait for every answer: what a download waits for. */\n settle(): Promise<void>;\n /** The document closed: every change still waiting rejects `instance-closed`. */\n close(): void;\n}\n\ninterface Entry {\n readonly seq: number;\n readonly opId: string;\n readonly label: ChangeLabel;\n /** The engine's ops; `null` for an undo. */\n ops: readonly ChangeOp[] | null;\n readonly undoOf: string | null;\n readonly merge: string | null;\n shows: readonly PredictedOp[];\n undo: readonly PredictedOp[];\n history: boolean;\n held: boolean;\n /** The plugin that staged it: its refusal names it. */\n readonly capability: string;\n readonly result: Promise<ChangeResult>;\n answered: boolean;\n abort: ((reason?: unknown) => void) | null;\n resolve(result: ChangeResult): void;\n reject(error: PluginError): void;\n}\n\n/** What a group collects while its `run` runs. */\ninterface Grouping {\n readonly label: ChangeLabel;\n readonly capability: string;\n entry: Entry | null;\n}\n\nconst changeOf = (entry: Entry): Change =>\n entry.undoOf !== null ? { undoOf: entry.undoOf } : { ops: entry.ops ?? [] };\n\nexport function createDocumentChanges(options: {\n /** The document's engine handle; `null` until it opened. */\n handle: () => DocumentHandle | null;\n /** Wake the store's readers: the views changed. */\n notify: () => void;\n report: (error: unknown) => void;\n}): DocumentChanges {\n let entries: Entry[] = [];\n let version = 0;\n let nextSeq = 0;\n let grouping: Grouping | null = null;\n let closed = false;\n const staged = createEventHook<PendingChange>(options.report);\n const settled = createEventHook<SettledChange>(options.report);\n\n const handleFor = (capability: string): DocumentHandle => {\n const handle = options.handle();\n if (!handle) throw new PluginError('not-ready', capability, 'the document has not opened yet');\n return handle;\n };\n\n const assertOpen = (capability: string): void => {\n if (closed) throw new PluginError('instance-closed', capability, 'the document closed');\n };\n\n const changed = (): void => {\n version += 1;\n options.notify();\n };\n\n const createEntry = (init: {\n label: ChangeLabel;\n ops: readonly ChangeOp[] | null;\n undoOf: string | null;\n merge?: string | null;\n shows: readonly PredictedOp[];\n undo: readonly PredictedOp[];\n history: boolean;\n held: boolean;\n capability: string;\n }): Entry => {\n let resolve!: (result: ChangeResult) => void;\n let reject!: (error: PluginError) => void;\n const result = new Promise<ChangeResult>((onResolve, onReject) => {\n resolve = onResolve;\n reject = onReject;\n });\n // Whoever staged it may never await the answer: a refusal is reported through `onSettled`.\n result.catch(() => {});\n return {\n ...init,\n merge: init.merge ?? null,\n seq: nextSeq++,\n opId: generateUuidV7(),\n result,\n answered: false,\n abort: null,\n resolve,\n reject,\n };\n };\n\n const remove = (entry: Entry): void => {\n entries = entries.filter((candidate) => candidate !== entry);\n };\n\n const applied = (entry: Entry, result: ChangeResult): void => {\n if (entry.answered) return;\n entry.answered = true;\n remove(entry);\n changed();\n entry.resolve(result);\n settled.emit({ change: entry, status: 'applied', result });\n };\n\n const refused = (entry: Entry, error: PluginError): void => {\n if (entry.answered) return;\n entry.answered = true;\n remove(entry);\n entry.reject(error);\n settled.emit({ change: entry, status: 'refused', error });\n refuseDependents(entry);\n changed();\n };\n\n /** The changes staged after `entry` that name an object only it would have created. */\n const refuseDependents = (entry: Entry): void => {\n const created = new Set(objectNumbersNamedBy(changeOf(entry)));\n if (created.size === 0) return;\n for (const later of entries) {\n if (later.seq < entry.seq || later.answered) continue;\n if (!objectNumbersReferencedBy(changeOf(later)).some((number) => created.has(number))) {\n continue;\n }\n later.abort?.();\n refused(\n later,\n new PluginError(\n 'conflict',\n later.capability,\n `a change it depends on (${entry.label.key}) was refused`,\n { details: { reason: 'dependency-refused', dependsOn: entry.opId } },\n ),\n );\n }\n };\n\n const send = (entry: Entry): void => {\n entry.held = false;\n let answer: PromiseLike<ChangeResult> & { abort?: (reason?: unknown) => void };\n try {\n answer = handleFor(entry.capability).apply(changeOf(entry), { opId: entry.opId });\n } catch (error) {\n refused(entry, toPluginError(entry.capability, error));\n return;\n }\n if (typeof answer.abort === 'function') entry.abort = (reason) => answer.abort!(reason);\n answer.then(\n (result) => applied(entry, result),\n (error: unknown) => refused(entry, toPluginError(entry.capability, error)),\n );\n };\n\n const cancel = (entry: Entry, capability: string): void => {\n if (entry.answered) return;\n entry.answered = true;\n remove(entry);\n entry.reject(new PluginError('operation-cancelled', capability, 'the change was cancelled'));\n changed();\n };\n\n /** Send the open holds staged before `before`, in staging order. */\n const sendHolds = (before = Infinity): void => {\n for (const entry of entries) {\n if (!entry.held || entry.seq >= before) continue;\n if ((entry.ops ?? []).length === 0) {\n cancel(entry, entry.capability);\n continue;\n }\n staged.emit(entry);\n send(entry);\n }\n };\n\n const invalid = (capability: string, message: string): PluginError =>\n new PluginError('invalid-input', capability, message);\n\n /** One stage inside a group: its ops join the group's change. */\n const join = (group: Grouping, change: Extract<StagedChange, { ops: unknown }>): Entry => {\n const entry = group.entry;\n if (!entry) {\n group.entry = createEntry({\n label: group.label,\n ops: change.ops,\n undoOf: null,\n shows: change.ops,\n undo: change.undo ?? [],\n history: change.history !== false,\n held: false,\n capability: group.capability,\n });\n entries.push(group.entry);\n changed();\n return group.entry;\n }\n entry.ops = [...(entry.ops ?? []), ...change.ops];\n entry.shows = entry.ops;\n // Undoing the group undoes its parts last first.\n entry.undo = [...(change.undo ?? []), ...entry.undo];\n entry.history = entry.history || change.history !== false;\n changed();\n return entry;\n };\n\n const forPlugin = (capability: string): ChangeQueue => ({\n stage(change) {\n assertOpen(capability);\n if ('undoOf' in change) {\n if (grouping) throw invalid(capability, 'an undo can not join a group');\n } else if (change.ops.length === 0) {\n throw invalid(capability, 'a change needs at least one op');\n } else if (grouping) {\n return join(grouping, change);\n }\n sendHolds();\n const entry =\n 'undoOf' in change\n ? createEntry({\n label: change.label,\n ops: null,\n undoOf: change.undoOf,\n shows: change.shows,\n undo: [],\n history: false,\n held: false,\n capability,\n })\n : createEntry({\n label: change.label,\n ops: change.ops,\n undoOf: null,\n shows: change.ops,\n undo: change.undo ?? [],\n history: change.history !== false,\n held: false,\n capability,\n });\n entries.push(entry);\n changed();\n staged.emit(entry);\n send(entry);\n return entry;\n },\n\n hold(label, options = {}) {\n assertOpen(capability);\n if (grouping) throw invalid(capability, 'a change can not be held inside a group');\n let entry: Entry | null = null;\n let cancelled = false;\n const open = (): boolean =>\n !closed && !cancelled && (entry === null || (entry.held && !entry.answered));\n return {\n get open() {\n return open();\n },\n get change() {\n return entry;\n },\n set(ops, undo = []) {\n if (!open()) return;\n if (!entry) {\n entry = createEntry({\n label,\n ops,\n undoOf: null,\n merge: options.merge ?? null,\n shows: ops,\n undo,\n history: true,\n held: true,\n capability,\n });\n entries.push(entry);\n } else {\n entry.ops = ops;\n entry.shows = ops;\n entry.undo = undo;\n }\n changed();\n },\n send() {\n if (entry?.held) sendHolds(entry.seq + 1);\n return entry;\n },\n cancel() {\n cancelled = true;\n if (entry?.held) cancel(entry, capability);\n },\n };\n },\n\n group(label, run) {\n assertOpen(capability);\n if (grouping) return run();\n sendHolds();\n const group: Grouping = { label, capability, entry: null };\n grouping = group;\n let value: ReturnType<typeof run>;\n try {\n value = run();\n } catch (error) {\n grouping = null;\n if (group.entry) cancel(group.entry, capability);\n throw error;\n }\n grouping = null;\n if (group.entry) {\n staged.emit(group.entry);\n send(group.entry);\n }\n return value;\n },\n\n sendHolds: () => sendHolds(),\n takeObjectNumber: () => handleFor(capability).objectNumbers.take(),\n async reserveObjectNumbers(count) {\n try {\n await handleFor(capability).objectNumbers.reserve(count);\n } catch (error) {\n throw toPluginError(capability, error);\n }\n },\n pending: () => entries,\n hasPending: () => entries.length > 0,\n whenSettled: () => whenSettled(),\n onStaged: staged.on,\n onSettled: settled.on,\n });\n\n const whenSettled = async (): Promise<void> => {\n await Promise.allSettled(entries.filter((entry) => !entry.held).map((entry) => entry.result));\n };\n\n return {\n shown: () => entries,\n version: () => version,\n find: (opId) => entries.find((entry) => entry.opId === opId),\n forPlugin,\n settle() {\n sendHolds();\n return whenSettled();\n },\n close() {\n if (closed) return;\n closed = true;\n const open = entries;\n entries = [];\n version += 1;\n for (const entry of open) {\n entry.answered = true;\n entry.reject(new PluginError('instance-closed', entry.capability, 'the document closed'));\n }\n staged.dispose();\n settled.dispose();\n },\n };\n}\n","/**\n * Time, as the host keeps it. Plugins never read timers or frames from the\n * environment: they ask their context (`ctx.clock`), and the host that built\n * the kernel says what a timer and a frame are (`createKernel({ clock })`).\n *\n * - A browser host passes `browserClock()` from `@embedpdf/web`: timers, and\n * frames from `requestAnimationFrame`. The framework viewers do this.\n * - Without one, the kernel uses {@link timerClock}: timers only, no frames.\n * Every JavaScript runtime has timers, so a kernel in Node, a worker or a\n * test needs no setup.\n * - Tests that step time pass `manualClock()` from `@embedpdf/core/testing`.\n *\n * What an instance schedules belongs to it ({@link instanceClock}): it is\n * cancelled when the instance closes, and nothing runs after that.\n *\n * This file is the one place in the kernel and the plugins that touches the\n * environment's timers (the lint rule in `eslint.config.js` says so).\n */\n\n/** Cancels what a clock call scheduled. Does nothing once it ran or was cancelled. */\nexport type Cancel = () => void;\n\n/** What a host provides: the kernel's only source of time. */\nexport interface HostClock {\n /** Milliseconds on a clock that only goes forward. */\n now(): number;\n /** Run `run` once, `ms` milliseconds from now. */\n after(ms: number, run: () => void): Cancel;\n /**\n * Run `run` once, just before the host next paints, with the frame's time\n * on the `now()` clock. Absent on a host that never paints.\n */\n nextFrame?(run: (timeMs: number) => void): Cancel;\n}\n\n/** A plugin instance's clock: `ctx.clock`. */\nexport interface PluginClock {\n /** Run `run` once, `ms` milliseconds from now. */\n after(ms: number, run: () => void): Cancel;\n /**\n * Run `run` once, just before the host next paints, with the frame's time in\n * milliseconds. On a host that never paints: as soon as possible.\n */\n nextFrame(run: (timeMs: number) => void): Cancel;\n /** False on a host that never paints (Node, a worker, most tests): animations jump to their end. */\n readonly hasFrames: boolean;\n}\n\n/** Timers only, no frames: the kernel's default. */\nexport const timerClock: HostClock = {\n now: () => performance.now(),\n after(ms, run) {\n const timer = setTimeout(run, ms);\n return () => clearTimeout(timer);\n },\n};\n\n/**\n * The clock of one plugin instance, over the host's. What it schedules is\n * cancelled when `lifetime` aborts (the instance closes), and nothing it\n * schedules after that runs.\n */\nexport function instanceClock(host: HostClock, lifetime: AbortSignal): PluginClock {\n const pending = new Set<Cancel>();\n lifetime.addEventListener(\n 'abort',\n () => {\n for (const cancel of [...pending]) cancel();\n },\n { once: true },\n );\n\n /** Schedules `run` with the host and keeps it until it runs or is cancelled. */\n const own = <Args extends unknown[]>(\n schedule: (fire: (...args: Args) => void) => Cancel,\n run: (...args: Args) => void,\n ): Cancel => {\n if (lifetime.aborted) return () => {};\n let done = false;\n let cancelWithHost: Cancel = () => {};\n const cancel: Cancel = () => {\n if (done) return;\n done = true;\n pending.delete(cancel);\n cancelWithHost();\n };\n pending.add(cancel);\n cancelWithHost = schedule((...args) => {\n if (done) return;\n done = true;\n pending.delete(cancel);\n run(...args);\n });\n return cancel;\n };\n\n // A host that never paints has no frame to wait for: the callback runs as\n // soon as the current work is done.\n const nextFrameOfHost = (run: (timeMs: number) => void): Cancel =>\n host.nextFrame ? host.nextFrame(run) : host.after(0, () => run(host.now()));\n\n return {\n after: (ms, run) => own((fire) => host.after(ms, fire), run),\n nextFrame: (run) => own(nextFrameOfHost, run),\n hasFrames: host.nextFrame !== undefined,\n };\n}\n","import { createEventHook, type EventHook } from './event-hook';\nimport type { CoreState, GlobalState, Unsubscribe } from './types';\n\n/** One committed change of a slice: the value before and after. */\nexport interface SliceChange<S> {\n readonly next: S;\n readonly previous: S;\n}\n\n/**\n * A plugin instance's authority over its state slice. Unique per instance:\n * closing and reopening the same document id yields a new lease, and the old\n * one is revoked synchronously at the start of close, so a callback retained\n * by the old instance can never read or write the new instance's state.\n * Writes return false (and are dropped) once the lease is revoked.\n */\nexport interface SliceLease<S = unknown> {\n readonly key: string;\n readonly instanceId: string;\n readonly live: boolean;\n read(): S;\n /** Replace the slice's value. Writing the current value is a no-op that returns true. */\n write(next: S): boolean;\n /** Fires after every committed change of this slice, once the store's subscribers ran. */\n readonly onChange: EventHook<SliceChange<S>>;\n revoke(): void;\n}\n\n/**\n * The store: one state tree ({ core, plugins }), keyed plugin slices held by\n * leases, and one change stream (`subscribe`) that adapters and `watch` read\n * through. Slice keys are opaque strings; the kernel uses `pluginId` for\n * workspace plugins and `pluginId::docId` for document-scoped ones.\n *\n * Change notification is non-re-entrant: a change made by a listener finishes\n * the current pass and runs another, keeping listener order deterministic.\n */\nexport interface Store {\n /** Acquire the lease for a slice. Replaces any earlier lease under the same key (revoking it). */\n lease<S>(key: string, initial: S, instanceId?: string): SliceLease<S>;\n getCore(): CoreState;\n getState(): GlobalState;\n /** The kernel's own registry writes. */\n setCore(patch: Partial<CoreState>): void;\n /** Wake every subscriber without a state change: a resource read through a capability changed. */\n notify(): void;\n /**\n * Hold the change stream until the returned release is called: state still\n * changes at once, and subscribers hear of everything held in one pass at\n * the last release. One change's events land as one update this way.\n */\n hold(): () => void;\n subscribe(listener: () => void): Unsubscribe;\n /** Kernel-destroy teardown: reset core, drop every slice and listener.\n * Reads stay legal afterwards (empty state); writes become no-ops. */\n destroy(): void;\n}\n\nexport function createStore(report: (error: unknown) => void = console.error): Store {\n let core: CoreState = { documents: {}, pending: {}, order: [], activeId: null };\n /** Live slice states, as adapters read them (`getState().plugins`). */\n const states: Record<string, unknown> = {};\n const leases = new Map<string, SliceLease<unknown>>();\n const changeListeners = new Set<() => void>();\n let leaseCounter = 0;\n\n // Per-listener isolation: one throwing subscriber (a plugin reaction, a\n // React read) must never halt the pass for its siblings, and must never\n // unwind a kernel lifecycle transition out of setCore mid-update.\n const guarded = (fn: () => void) => {\n try {\n fn();\n } catch (error) {\n report(error);\n }\n };\n\n let emitting = false;\n let pending = false;\n let holds = 0;\n let missed = false;\n const emitChange = () => {\n if (holds > 0) {\n missed = true;\n return;\n }\n if (emitting) {\n pending = true;\n return;\n }\n emitting = true;\n try {\n do {\n pending = false;\n changeListeners.forEach((listener) => guarded(listener));\n } while (pending);\n } finally {\n emitting = false;\n }\n };\n\n function lease<S>(\n key: string,\n initial: S,\n instanceId = `${key}#${++leaseCounter}`,\n ): SliceLease<S> {\n leases.get(key)?.revoke();\n const cell = { live: true, state: initial };\n const changed = createEventHook<SliceChange<S>>(report);\n states[key] = initial;\n const handle: SliceLease<S> = {\n key,\n instanceId,\n get live() {\n return cell.live;\n },\n read: () => cell.state,\n write(next) {\n if (!cell.live) return false;\n if (next === cell.state) return true;\n const previous = cell.state;\n cell.state = next;\n states[key] = next;\n emitChange();\n changed.emit({ next, previous });\n return true;\n },\n onChange: changed.on,\n revoke() {\n if (!cell.live) return;\n cell.live = false;\n changed.dispose();\n if (leases.get(key) === (handle as SliceLease<unknown>)) {\n leases.delete(key);\n delete states[key];\n emitChange();\n }\n },\n };\n leases.set(key, handle as SliceLease<unknown>);\n return handle;\n }\n\n return {\n lease,\n getCore: () => core,\n getState: () => ({ core, plugins: states }),\n setCore(patch) {\n core = { ...core, ...patch };\n emitChange();\n },\n notify: () => emitChange(),\n hold() {\n holds += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n holds -= 1;\n if (holds > 0 || !missed) return;\n missed = false;\n emitChange();\n };\n },\n subscribe(listener) {\n changeListeners.add(listener);\n return () => void changeListeners.delete(listener);\n },\n destroy() {\n core = { documents: {}, pending: {}, order: [], activeId: null };\n for (const held of [...leases.values()]) held.revoke();\n for (const key of Object.keys(states)) delete states[key];\n changeListeners.clear();\n },\n };\n}\n","/**\n * Development-mode switch for checks that are worth their cost while\n * developing (undeclared dependency resolution, frozen snapshots) and free\n * in production. Bundlers replace `process.env.NODE_ENV`; a plain browser\n * without one reports production, so the checks never throw in a page\n * that has no build step.\n */\n// Module-scoped so the check compiles without Node's ambient types; bundlers\n// still see the literal `process.env.NODE_ENV` and replace it.\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\nexport function isDev(): boolean {\n try {\n return typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n } catch {\n return false;\n }\n}\n","import type { DocumentHandle } from '@embedpdf/engine-core/runtime';\nimport { PluginError, toPluginError } from './errors';\n\n/** What the guard needs to know about the instance it protects. */\nexport interface GuardedLifetime {\n /** Aborted when the instance closes (a document session) or the kernel is destroyed. */\n readonly signal: AbortSignal;\n readonly instanceId: string;\n}\n\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n typeof (value as { then?: unknown }).then === 'function';\n\nconst isPlainWrappable = (value: unknown): value is object =>\n value !== null &&\n typeof value === 'object' &&\n !isPromiseLike(value) &&\n !(value instanceof ArrayBuffer) &&\n !ArrayBuffer.isView(value) &&\n !(value instanceof Date) &&\n !(value instanceof RegExp) &&\n !(value instanceof Map) &&\n !(value instanceof Set) &&\n !Array.isArray(value);\n\n/**\n * The guarded document handle a controller sees as `ctx.doc`. Every call made\n * through it is:\n *\n * - refused (rejected `instance-closed`) once the instance has closed,\n * - raced against the instance lifetime: a call that is still pending when\n * the instance closes rejects `instance-closed`, its late value is dropped,\n * and an abortable engine call is aborted so worker-side work stops,\n * - mapped through `toPluginError`, so a controller sees one error vocabulary.\n *\n * Nested service objects (`doc.annotations`, `doc.page(ref).render`) are\n * wrapped lazily and cached; synchronous reads (`doc.security.allows`) pass\n * straight through. Methods run with the raw target as `this`, so classes\n * with private fields keep working. The returned promises keep an `abort()`\n * when the engine's promise had one, so caller-side cancellation still works.\n */\nexport function guardHandle(\n handle: DocumentHandle,\n lifetime: GuardedLifetime,\n capability: string,\n): DocumentHandle {\n const cache = new WeakMap<object, object>();\n\n const closedError = () =>\n new PluginError(\n 'instance-closed',\n capability,\n `document instance ${lifetime.instanceId} was closed`,\n );\n\n const guardPromise = <T>(pending: PromiseLike<T>): Promise<T> => {\n const abortable = pending as PromiseLike<T> & { abort?: (reason?: unknown) => void };\n const guarded = new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n abortable.abort?.(lifetime.signal.reason);\n reject(closedError());\n };\n if (lifetime.signal.aborted) {\n onAbort();\n } else {\n lifetime.signal.addEventListener('abort', onAbort, { once: true });\n }\n Promise.resolve(pending).then(\n (value) => {\n lifetime.signal.removeEventListener('abort', onAbort);\n if (!lifetime.signal.aborted) resolve(value);\n },\n (error) => {\n lifetime.signal.removeEventListener('abort', onAbort);\n if (!lifetime.signal.aborted) reject(toPluginError(capability, error));\n },\n );\n });\n if (typeof abortable.abort === 'function') {\n Object.defineProperty(guarded, 'abort', {\n value: (reason?: unknown) => abortable.abort!(reason),\n enumerable: false,\n });\n }\n return guarded;\n };\n\n const wrapFunction = (fn: (...args: unknown[]) => unknown, target: object) =>\n function guardedCall(...args: unknown[]): unknown {\n let result: unknown;\n try {\n result = fn.apply(target, args);\n } catch (error) {\n throw toPluginError(capability, error);\n }\n if (isPromiseLike(result)) return guardPromise(result);\n return wrapValue(result, target);\n };\n\n const wrapValue = (value: unknown, target: object): unknown => {\n if (typeof value === 'function')\n return wrapFunction(value as (...args: unknown[]) => unknown, target);\n if (isPlainWrappable(value)) return wrapObject(value);\n return value;\n };\n\n const wrapObject = (target: object): object => {\n let proxy = cache.get(target);\n if (!proxy) {\n proxy = new Proxy(target, {\n get(proxyTarget, property) {\n return wrapValue(Reflect.get(proxyTarget, property, proxyTarget), proxyTarget);\n },\n });\n cache.set(target, proxy);\n }\n return proxy;\n };\n\n return wrapObject(handle) as DocumentHandle;\n}\n","import { PluginError, toPluginError } from './errors';\nimport type { OperationOptions } from './types';\n\n/** One execution inside a `latest` lane. */\n/** `details` of the `operation-cancelled` error a superseded or cancelled run rejects with. */\nexport interface LatestCancellation {\n readonly runId: string;\n /** `'superseded'`, `'cancelled'`, the caller's abort reason, or `'instance-closed'`. */\n readonly reason: string;\n}\n\nexport interface LatestRun {\n /** `${lane}#${n}`, unique per run; surfaces in cancellation errors and events. */\n readonly id: string;\n /** Aborts when a newer run starts, the caller's signal aborts, or the instance closes. */\n readonly signal: AbortSignal;\n /** True once a newer run has started. */\n readonly superseded: boolean;\n /** Run `fn` only while this run is still the newest and alive; returns whether it ran. */\n commit(fn: () => void): boolean;\n}\n\n/**\n * Newest wins. Starting a run aborts the previous one; a superseded run cannot\n * publish (`commit` returns false) and its promise rejects\n * `operation-cancelled`, whatever its engine call later does.\n */\nexport interface LatestLane {\n readonly running: boolean;\n run<T>(fn: (run: LatestRun) => Promise<T>, options?: OperationOptions): Promise<T>;\n /** Cancel the current run, if any. */\n cancel(reason?: unknown): void;\n}\n\nexport function createLatestLane(\n lifetime: AbortSignal,\n capability: string,\n name: string,\n): LatestLane {\n let generation = 0;\n let active: AbortController | null = null;\n\n const closed = () => new PluginError('instance-closed', capability, `${name}: instance closed`);\n const cancelled = (id: string, why: string) =>\n new PluginError('operation-cancelled', capability, `${name}: ${why}`, {\n details: { runId: id, reason: why },\n });\n\n return {\n get running() {\n return active !== null;\n },\n cancel(reason) {\n active?.abort(reason ?? 'cancelled');\n active = null;\n },\n async run(fn, options) {\n if (lifetime.aborted) throw closed();\n if (options?.signal?.aborted)\n throw cancelled(`${name}#${generation + 1}`, 'cancelled before start');\n\n const mine = ++generation;\n const id = `${name}#${mine}`;\n const controller = new AbortController();\n const previous = active;\n active = controller; // install before aborting: abort listeners run synchronously\n const onLifetime = () => controller.abort('instance-closed');\n const onCaller = () => controller.abort('cancelled');\n lifetime.addEventListener('abort', onLifetime, { once: true });\n options?.signal?.addEventListener('abort', onCaller, { once: true });\n\n const current = () => mine === generation && !controller.signal.aborted;\n const run: LatestRun = {\n id,\n signal: controller.signal,\n get superseded() {\n return mine !== generation;\n },\n commit(commitFn) {\n if (!current()) return false;\n commitFn();\n return true;\n },\n };\n\n try {\n previous?.abort('superseded');\n if (!current()) throw cancelled(id, 'superseded');\n const value = await fn(run);\n if (!current()) throw cancelled(id, String(controller.signal.reason ?? 'superseded'));\n return value;\n } catch (error) {\n if (lifetime.aborted) throw closed();\n if (!current()) throw cancelled(id, String(controller.signal.reason ?? 'superseded'));\n throw toPluginError(capability, error);\n } finally {\n lifetime.removeEventListener('abort', onLifetime);\n options?.signal?.removeEventListener('abort', onCaller);\n if (active === controller) active = null;\n }\n },\n };\n}\n","/**\n * Mirrors: local copies of data the engine owns, kept current from the\n * document event stream.\n *\n * A mirror changes in exactly two ways: a load (the whole value, or some\n * pages of it) and a fold (one confirmed event applied by a pure function).\n * Plugin verbs never write a mirror. Both engines publish the event for a\n * session's own mutation before the mutation's promise resolves, so a verb\n * that awaits its engine call already sees its own write in the mirror.\n *\n * What the user sees is `view()`: the mirror's value with this session's\n * pending changes (changes.ts) replayed on top, op by op, through the spec's\n * `predict`. A change leaves the view once the mirror holds its answer: when\n * the last of its events folded (even before the answer itself arrives), or,\n * when a fold asked to read again, once that read (or a later full load)\n * lands.\n *\n * The load protocol:\n * 1. The mirror subscribes to the event stream when it is created.\n * 2. The first load starts once the plugin is connected, or, for a mirror\n * `onDemand`, when something asks for it (`ensureLoaded()`, `refresh()`).\n * 3. Events that arrive while a load runs are queued, then replayed after\n * the loaded value lands, skipping events the snapshot already contains\n * (`origin.serverId <= cursor`). Replaying confirmed records in arrival\n * order is idempotent, so engines without a cursor replay everything.\n * 4. A failed load keeps the previous value, applies the queued events to\n * it, and reports `error` (or `forbidden`) through `getStatus()`. So\n * does a failed page reload: the value is stale for those pages until\n * a full load succeeds.\n * 5. `stream.desynced` and `document.versioned` reload; `fold` never sees\n * them. A `fold` that throws is reported and also reloads.\n * 6. A reload requested while one runs schedules exactly one more after it.\n * 7. The value lives in a leased store cell, revoked when the instance\n * closes, so it is reactive and a closed instance cannot write it.\n */\nimport type { DocumentEvent, DocumentHandle, PageRef } from '@embedpdf/engine-core/runtime';\nimport type { ChangeViews, PredictedOp, QueuedChange } from './changes';\nimport { isPluginError } from './errors';\nimport type { SliceLease } from './store';\nimport type { ResourceStatus } from './types';\n\nconst RELOAD = Symbol('mirror.reload');\n\n/** What `fold` returns when an event is too coarse to apply: reload everything, or some pages. */\nexport interface MirrorReload {\n readonly [RELOAD]: 'all' | readonly PageRef[];\n}\n\n/** Ask the mirror to reload instead of applying the event. */\nexport function reload(options?: { pages?: readonly PageRef[] }): MirrorReload {\n return { [RELOAD]: options?.pages ?? 'all' };\n}\n\nconst isReload = (value: unknown): value is MirrorReload =>\n typeof value === 'object' && value !== null && RELOAD in value;\n\n/** One applied change of a mirror, handed to the spec's `changed` callback. */\nexport interface MirrorChange<V> {\n /** `load` for loads and reloads, `event` for a folded event. */\n readonly cause: 'load' | 'event';\n /** The folded event; null for loads. */\n readonly event: DocumentEvent | null;\n /** For loads: every page (`'all'`) or the pages that were reloaded. Null for events. */\n readonly pages: 'all' | readonly PageRef[] | null;\n readonly previous: V;\n readonly next: V;\n}\n\nexport interface MirrorSpec<V> {\n /** Unique within the plugin; names the store cell and appears in errors. */\n readonly name: string;\n /** The value before the first load lands. */\n readonly initial: () => V;\n /** False: status `forbidden` and no engine read. Asked before every load. */\n readonly readable?: () => boolean;\n /**\n * Load only when asked: the mirror stays `idle`, folding confirmed events into its value,\n * until `ensureLoaded()` or `refresh()` runs. For data nothing needs when a document opens.\n * Without it, the first load starts once the plugin is connected.\n */\n readonly onDemand?: true;\n /**\n * Read the whole value. `cursor` is the newest server event the snapshot\n * already contains (cloud engines); omit it when the engine has none.\n */\n load(doc: DocumentHandle, signal: AbortSignal): Promise<{ value: V; cursor?: number | null }>;\n /**\n * Apply one confirmed event. Pure, and the same for every origin. Return\n * `value` itself when the event does not apply, or `reload(...)` when the\n * event does not carry enough to apply.\n */\n fold(value: V, event: DocumentEvent): V | MirrorReload;\n /**\n * Apply one op of a change this session staged and the engine hasn't\n * answered, as the engine will: the same rules, and absolute, so an op the\n * value already holds changes nothing. Pure. Return `value` itself for an op\n * it doesn't concern. Without it, `view()` is `get()`.\n */\n predict?(value: V, op: PredictedOp): V;\n /**\n * Read some pages and return how to merge them into the value. Required\n * when `fold` asks for a page-scoped reload; without it such a request\n * reloads everything.\n */\n loadPages?(\n doc: DocumentHandle,\n pages: readonly PageRef[],\n signal: AbortSignal,\n ): Promise<(value: V) => V>;\n /**\n * Runs after every load (even one that changed nothing) and every event\n * that changed the value: the one place a plugin emits the events this\n * data drives.\n */\n readonly changed?: (change: MirrorChange<V>) => void;\n}\n\nexport interface Mirror<V> {\n /** What the engine confirmed. */\n get(): V;\n /** What the user sees: `get()` with this session's pending changes on top (`predict`). */\n view(): V;\n /** `idle` until the first load starts; stays `ready` while a reload runs. */\n getStatus(): ResourceStatus;\n /**\n * Load unless it is loaded or loading: a load in flight is shared, and a loaded mirror\n * resolves at once. After a failed load it tries again. Rejects when the load fails.\n */\n ensureLoaded(): Promise<void>;\n /** Reload everything. Joins a running load; rejects when the load fails. */\n refresh(): Promise<void>;\n /**\n * Resolves once no load or page reload is running, including reloads\n * started by events that arrive while it waits. Never rejects.\n */\n settled(): Promise<void>;\n}\n\n/** What the kernel hands a mirror: the instance's document, lifetime and store access. */\nexport interface MirrorEnvironment {\n readonly doc: DocumentHandle;\n readonly lifetime: AbortSignal;\n /** A store cell owned by this instance, revoked when it closes. */\n cell<T>(name: string, initial: T): SliceLease<T>;\n /** Subscribe to the document's confirmed events for the instance's lifetime. */\n onDocumentEvent(listener: (event: DocumentEvent) => void): void;\n /** The document's pending changes, which `view()` shows. */\n readonly changes: ChangeViews;\n /** Wake the store's readers: what `view()` shows changed outside a store write. */\n notify(): void;\n report(error: unknown): void;\n}\n\ninterface MirrorCell<V> {\n readonly value: V;\n readonly status: ResourceStatus;\n}\n\n/** Events that invalidate every mirror: the stream skipped events, or the document moved to new bytes. */\nexport const isResync = (event: DocumentEvent): boolean =>\n event.type === 'stream.desynced' || event.type === 'document.versioned';\n\nexport const statusOfFailure = (error: unknown): ResourceStatus =>\n isPluginError(error, 'permission-denied') ? 'forbidden' : 'error';\n\n/** The `opId` of the change an event belongs to, or null for an event of none. */\nexport const changeIdOf = (event: DocumentEvent): string | null =>\n 'origin' in event ? (event.origin.tx?.id ?? null) : null;\n\n/** The `opId` of the change whose last event this is, or null. */\nexport const lastEventOf = (event: DocumentEvent): string | null => {\n const tx = 'origin' in event ? event.origin.tx : undefined;\n return tx && tx.index === tx.count - 1 ? tx.id : null;\n};\n\n/**\n * The changes of this session whose events a mirror folded, every one of\n * them: the mirror holds their answer, so its view stops replaying them, even\n * before the answer itself arrives. An entry goes once its change left the\n * queue.\n */\nexport function createFoldedChanges(changes: ChangeViews) {\n const folded = new Set<string>();\n return {\n has: (opId: string) => folded.has(opId),\n /** The event folded: when it was a change's last, the change is held. True when that's new. */\n add(event: DocumentEvent): boolean {\n const opId = lastEventOf(event);\n if (opId === null || folded.has(opId) || !changes.find(opId)) return false;\n for (const each of folded) if (!changes.find(each)) folded.delete(each);\n folded.add(opId);\n return true;\n },\n };\n}\n\n/**\n * The changes a view shows: the queue's, but those whose events the mirror\n * folded already, and the answered ones a mirror keeps (it asked to read\n * again), each once.\n */\nexport function showingWith(\n changes: ChangeViews,\n kept: Iterable<{ readonly change: QueuedChange }>,\n folded: { has(opId: string): boolean },\n): QueuedChange[] {\n const shown = new Map(\n changes\n .shown()\n .filter((change) => !folded.has(change.opId))\n .map((change) => [change.opId, change]),\n );\n for (const { change } of kept) shown.set(change.opId, change);\n return [...shown.values()];\n}\n\n/**\n * Replay changes over a value, in staging order: the shown ones and the\n * answered ones a mirror still shows. A `predict` that throws is reported,\n * and the value shows the truth.\n */\nexport function replay<V>(\n value: V,\n changes: readonly QueuedChange[],\n predict: (value: V, op: PredictedOp) => V,\n report: (error: unknown) => void,\n): V {\n const ordered = [...changes].sort((left, right) => left.seq - right.seq);\n let next = value;\n try {\n for (const change of ordered) for (const op of change.shows) next = predict(next, op);\n } catch (error) {\n report(error);\n return value;\n }\n return next;\n}\n\n/** A mirror plus the kernel-side `start`, called once the plugin is connected. */\nexport interface MirrorController<V> {\n readonly mirror: Mirror<V>;\n start(): void;\n}\n\nexport function createMirror<V>(spec: MirrorSpec<V>, env: MirrorEnvironment): MirrorController<V> {\n const cell = env.cell<MirrorCell<V>>(`mirror/${spec.name}`, {\n value: spec.initial(),\n status: 'idle',\n });\n let started = false;\n let running: Promise<void> | null = null;\n const pageReloads = new Set<Promise<void>>();\n let loadAgain = false;\n /** Non-null while a full load runs: the events to replay after it lands. */\n let queued: DocumentEvent[] | null = null;\n /** How many full loads have started: a load clears what was kept before it started. */\n let fullLoads = 0;\n\n /**\n * Changes this mirror still shows though the engine may have answered them: a\n * fold asked to read again, and the read hasn't landed. `after`: the full\n * loads started before; a later full load that lands holds the change too.\n */\n const kept = new Map<string, { change: QueuedChange; after: number }>();\n let keptVersion = 0;\n const folded = createFoldedChanges(env.changes);\n\n /** Keep the change an event belongs to until a read lands, when it's one of ours. */\n const keepUntilRead = (event: DocumentEvent, after: number): string | null => {\n const opId = changeIdOf(event);\n const change = opId !== null && spec.predict ? env.changes.find(opId) : undefined;\n if (!change) return null;\n kept.set(change.opId, { change, after });\n keptVersion += 1;\n return change.opId;\n };\n\n const release = (opIds: readonly string[]): void => {\n let any = false;\n for (const opId of opIds) any = kept.delete(opId) || any;\n if (!any) return;\n keptVersion += 1;\n env.notify();\n };\n\n const releaseLoadedBy = (load: number): void =>\n release([...kept].filter(([, entry]) => entry.after < load).map(([opId]) => opId));\n\n let viewMemo: { value: V; version: number; kept: number; view: V } | null = null;\n const view = (): V => {\n const value = cell.read().value;\n if (!spec.predict) return value;\n const version = env.changes.version();\n if (\n viewMemo &&\n viewMemo.value === value &&\n viewMemo.version === version &&\n viewMemo.kept === keptVersion\n ) {\n return viewMemo.view;\n }\n const next = replay(\n value,\n showingWith(env.changes, kept.values(), folded),\n spec.predict,\n env.report,\n );\n viewMemo = { value, version, kept: keptVersion, view: next };\n return next;\n };\n\n const announce = (change: MirrorChange<V>): void => {\n try {\n spec.changed?.(change);\n } catch (error) {\n env.report(error);\n }\n };\n\n const commit = (next: V, change: Omit<MirrorChange<V>, 'previous' | 'next'>): void => {\n const previous = cell.read().value;\n if (next === previous) return;\n if (!cell.write({ ...cell.read(), value: next })) return;\n announce({ ...change, previous, next });\n };\n\n const reloadInBackground = (): void => {\n void refresh().catch(() => {\n /* the failure is reported through getStatus() */\n });\n };\n\n const reloadPages = async (pages: readonly PageRef[], keptFor: string | null): Promise<void> => {\n try {\n const merge = await spec.loadPages!(env.doc, pages, env.lifetime);\n if (!cell.live) return;\n const previous = cell.read().value;\n const next = merge(previous);\n cell.write({ ...cell.read(), value: next });\n announce({ cause: 'load', event: null, pages, previous, next });\n if (keptFor !== null) release([keptFor]);\n } catch (error) {\n if (isPluginError(error, 'instance-closed') || !cell.live) return;\n // The value is stale for these pages: say so until a full load succeeds.\n cell.write({ ...cell.read(), status: statusOfFailure(error) });\n env.report(error);\n }\n };\n\n const applyEvent = (event: DocumentEvent): void => {\n let result: V | MirrorReload;\n try {\n result = spec.fold(cell.read().value, event);\n } catch (error) {\n env.report(error);\n if (!spec.onDemand || started) reloadInBackground();\n return;\n }\n if (isReload(result)) {\n // An on-demand mirror nobody has asked for reads everything fresh when someone does.\n if (spec.onDemand && !started) return;\n const pages = result[RELOAD];\n const keptFor = keepUntilRead(event, fullLoads);\n if (pages === 'all' || !spec.loadPages) {\n reloadInBackground();\n } else {\n const reloading = reloadPages(pages, keptFor).finally(() => pageReloads.delete(reloading));\n pageReloads.add(reloading);\n }\n return;\n }\n if (spec.predict && folded.add(event)) keptVersion += 1;\n commit(result, { cause: 'event', event, pages: null });\n };\n\n env.onDocumentEvent((event) => {\n if (!cell.live) return;\n if (isResync(event)) {\n if (started) reloadInBackground();\n return;\n }\n if (queued) {\n // Folded once the running load lands: shown until then.\n queued.push(event);\n keepUntilRead(event, fullLoads - 1);\n } else {\n applyEvent(event);\n }\n });\n\n const loadOnce = async (): Promise<void> => {\n if (spec.readable && !spec.readable()) {\n cell.write({ ...cell.read(), status: 'forbidden' });\n return;\n }\n if (cell.read().status !== 'ready') cell.write({ ...cell.read(), status: 'loading' });\n const load = ++fullLoads;\n queued = [];\n let loaded: { value: V; cursor?: number | null };\n try {\n loaded = await spec.load(env.doc, env.lifetime);\n } catch (error) {\n const pending = queued ?? [];\n queued = null;\n if (!cell.live || isPluginError(error, 'instance-closed')) return;\n cell.write({ ...cell.read(), status: statusOfFailure(error) });\n for (const event of pending) applyEvent(event);\n throw error;\n }\n const pending = queued ?? [];\n queued = null;\n if (!cell.live) return;\n const previous = cell.read().value;\n cell.write({ value: loaded.value, status: 'ready' });\n announce({ cause: 'load', event: null, pages: 'all', previous, next: loaded.value });\n const cursor = loaded.cursor ?? null;\n for (const event of pending) {\n const serverId = 'origin' in event ? event.origin.serverId : null;\n if (cursor !== null && serverId !== null && serverId <= cursor) continue;\n applyEvent(event);\n }\n releaseLoadedBy(load);\n };\n\n function refresh(): Promise<void> {\n started = true;\n if (running) {\n loadAgain = true;\n return running;\n }\n running = (async () => {\n let failure: unknown = null;\n do {\n loadAgain = false;\n try {\n await loadOnce();\n failure = null;\n } catch (error) {\n failure = error;\n }\n } while (loadAgain && cell.live);\n if (failure !== null) throw failure;\n })().finally(() => {\n running = null;\n });\n return running;\n }\n\n return {\n mirror: {\n get: () => cell.read().value,\n view,\n getStatus: () => cell.read().status,\n ensureLoaded: () => {\n if (running) return running;\n if (cell.read().status === 'ready') return Promise.resolve();\n return refresh();\n },\n refresh,\n async settled() {\n while (running || pageReloads.size > 0) {\n await Promise.allSettled([running, ...pageReloads]);\n }\n },\n },\n start() {\n if (!started && !spec.onDemand) reloadInBackground();\n },\n };\n}\n","/**\n * Page mirrors: engine data that is loaded page by page, on demand, and kept\n * current from the document event stream.\n *\n * A page is `idle` until something calls `ensureLoaded(page)`. Once loaded it\n * stays current: an event the spec maps to that page either folds into the\n * page's value or re-reads it. Every read carries a per-page epoch, so a read\n * that started before a newer one can never overwrite it. Loads for the same\n * page are shared while in flight. Deleted pages are dropped, and\n * `stream.desynced` / `document.versioned` re-read every loaded page.\n *\n * `view(page)` is the page's value with this session's pending changes on\n * top (`predict`), as for whole-document mirrors (mirror.ts): an answered\n * change that made a page read again stays in that page's view until the\n * read lands.\n */\nimport {\n encodePageKey,\n type DocumentEvent,\n type DocumentHandle,\n type PageRef,\n} from '@embedpdf/engine-core/runtime';\nimport type { PredictedOp, QueuedChange } from './changes';\nimport { isPluginError } from './errors';\nimport {\n changeIdOf,\n createFoldedChanges,\n isResync,\n replay,\n showingWith,\n statusOfFailure,\n type MirrorEnvironment,\n} from './mirror';\nimport type { OperationOptions, ResourceStatus } from './types';\n\n/** One applied change of one page, handed to the spec's `changed` callback. */\nexport interface PageMirrorChange<V> {\n readonly page: PageRef;\n /** `load` for reads, `event` for a folded event, `drop` when the page was deleted. */\n readonly cause: 'load' | 'event' | 'drop';\n readonly event: DocumentEvent | null;\n readonly previous: V | undefined;\n readonly next: V | undefined;\n}\n\nexport interface PageMirrorSpec<V> {\n /** Unique within the plugin; names the store cell and appears in errors. */\n readonly name: string;\n /** Read one page's value. */\n load(doc: DocumentHandle, page: PageRef, signal: AbortSignal): Promise<V>;\n /**\n * Which pages an event makes stale: those pages, every loaded page\n * (`'all'`), or none (`null`). Only pages that are loaded are affected.\n */\n affected(event: DocumentEvent): readonly PageRef[] | 'all' | null;\n /**\n * Apply an event to an affected page's value instead of re-reading it.\n * Return `'reload'` to re-read. Without `fold`, affected pages are re-read.\n */\n fold?(value: V, event: DocumentEvent, page: PageRef): V | 'reload';\n /**\n * Apply one op of a pending change of this session to a loaded page's\n * value, as the engine will. Pure and absolute, like a mirror's `predict`;\n * return `value` itself for an op that doesn't concern the page. Without\n * it, `view(page)` is `get(page)`.\n */\n predict?(value: V, op: PredictedOp, page: PageRef): V;\n /** Runs after every load of a page (even one that changed nothing) and every applied change. */\n readonly changed?: (change: PageMirrorChange<V>) => void;\n}\n\nexport interface PageMirror<V> {\n /** The page's value, or undefined when it has not loaded. */\n get(page: PageRef): V | undefined;\n /** What the user sees on the page: `get(page)` with this session's pending changes on top. */\n view(page: PageRef): V | undefined;\n getStatus(page: PageRef): ResourceStatus;\n /** Load the page unless it is loaded or loading. */\n ensureLoaded(page: PageRef, options?: OperationOptions): Promise<void>;\n /** Re-read one page, or every loaded page. */\n refresh(page?: PageRef): Promise<void>;\n}\n\ninterface PageEntry<V> {\n readonly page: PageRef;\n readonly status: ResourceStatus;\n readonly value?: V;\n}\n\ntype PageCells<V> = Readonly<Record<string, PageEntry<V>>>;\n\nconst IDLE = 'idle' as const;\n\nexport function createPageMirror<V>(\n spec: PageMirrorSpec<V>,\n env: MirrorEnvironment,\n): PageMirror<V> {\n const cell = env.cell<PageCells<V>>(`page-mirror/${spec.name}`, {});\n const epochs = new Map<string, number>();\n const inFlight = new Map<string, Promise<void>>();\n\n /**\n * Per page: answered changes the page still shows, because an event of\n * theirs made it read again. `epoch`: the page's epoch then; a later read\n * that lands clears them.\n */\n const kept = new Map<string, Map<string, { change: QueuedChange; epoch: number }>>();\n let keptVersion = 0;\n /** Changes every event of which reached the pages: each page holds its part, or keeps the change. */\n const folded = createFoldedChanges(env.changes);\n\n const keepUntilRead = (key: string, event: DocumentEvent): void => {\n const opId = changeIdOf(event);\n const change = opId !== null && spec.predict ? env.changes.find(opId) : undefined;\n if (!change) return;\n let page = kept.get(key);\n if (!page) kept.set(key, (page = new Map()));\n page.set(change.opId, { change, epoch: epochs.get(key) ?? 0 });\n keptVersion += 1;\n };\n\n const releasePage = (key: string, epoch: number): void => {\n const page = kept.get(key);\n if (!page) return;\n const before = page.size;\n for (const [opId, entry] of page) if (entry.epoch < epoch) page.delete(opId);\n if (page.size === 0) kept.delete(key);\n if (page.size === before) return;\n keptVersion += 1;\n env.notify();\n };\n\n const views = new Map<string, { value: V; version: number; kept: number; view: V }>();\n const view = (page: PageRef): V | undefined => {\n const key = encodePageKey(page);\n const value = entryOf(key)?.value;\n if (value === undefined || !spec.predict) return value;\n const version = env.changes.version();\n const memo = views.get(key);\n if (memo && memo.value === value && memo.version === version && memo.kept === keptVersion) {\n return memo.view;\n }\n const predict = spec.predict;\n const next = replay(\n value,\n showingWith(env.changes, kept.get(key)?.values() ?? [], folded),\n (current: V, op: PredictedOp) => predict(current, op, page),\n env.report,\n );\n views.set(key, { value, version, kept: keptVersion, view: next });\n return next;\n };\n\n const entryOf = (key: string): PageEntry<V> | undefined => cell.read()[key];\n\n const setEntry = (key: string, entry: PageEntry<V> | null): boolean => {\n const { [key]: _replaced, ...rest } = cell.read();\n return cell.write(entry ? { ...rest, [key]: entry } : rest);\n };\n\n const announce = (change: PageMirrorChange<V>): void => {\n if (change.cause !== 'load' && change.previous === change.next) return;\n try {\n spec.changed?.(change);\n } catch (error) {\n env.report(error);\n }\n };\n\n const load = (page: PageRef): Promise<void> => {\n const key = encodePageKey(page);\n const epoch = (epochs.get(key) ?? 0) + 1;\n epochs.set(key, epoch);\n const before = entryOf(key);\n if (before?.status !== 'ready')\n setEntry(key, { page, status: 'loading', value: before?.value });\n const isCurrent = () => cell.live && epochs.get(key) === epoch;\n const request = spec\n .load(env.doc, page, env.lifetime)\n .then(\n (value) => {\n if (!isCurrent()) return;\n const previous = entryOf(key)?.value;\n setEntry(key, { page, status: 'ready', value });\n announce({ page, cause: 'load', event: null, previous, next: value });\n if (kept.has(key)) releasePage(key, epoch);\n },\n (error: unknown) => {\n if (!isCurrent() || isPluginError(error, 'instance-closed')) return;\n setEntry(key, { page, status: statusOfFailure(error), value: entryOf(key)?.value });\n throw error;\n },\n )\n .finally(() => {\n if (inFlight.get(key) === request) inFlight.delete(key);\n });\n inFlight.set(key, request);\n return request;\n };\n\n const reloadInBackground = (page: PageRef): void => {\n void load(page).catch(() => {\n /* the failure is reported through getStatus(page) */\n });\n };\n\n const loadedPages = (): PageRef[] =>\n Object.values(cell.read())\n .filter((entry) => entry.status !== IDLE)\n .map((entry) => entry.page);\n\n env.onDocumentEvent((event) => {\n if (!cell.live) return;\n foldEvent(event);\n if (spec.predict && folded.add(event)) keptVersion += 1;\n });\n\n /** One event, into every loaded page it concerns. */\n function foldEvent(event: DocumentEvent): void {\n if (isResync(event)) {\n for (const page of loadedPages()) reloadInBackground(page);\n return;\n }\n if (event.type === 'pages.deleted') {\n for (const page of event.pages) {\n const key = encodePageKey(page);\n const before = entryOf(key);\n if (!before) continue;\n epochs.set(key, (epochs.get(key) ?? 0) + 1);\n kept.delete(key);\n views.delete(key);\n setEntry(key, null);\n announce({ page, cause: 'drop', event, previous: before.value, next: undefined });\n }\n return;\n }\n const affected = spec.affected(event);\n if (affected === null) return;\n const pages = affected === 'all' ? loadedPages() : affected;\n for (const page of pages) {\n const key = encodePageKey(page);\n const entry = entryOf(key);\n if (!entry || entry.status === IDLE) continue;\n if (!spec.fold || entry.status !== 'ready') {\n keepUntilRead(key, event);\n reloadInBackground(page);\n continue;\n }\n let next: V | 'reload';\n try {\n next = spec.fold(entry.value as V, event, page);\n } catch (error) {\n env.report(error);\n next = 'reload';\n }\n if (next === 'reload') {\n keepUntilRead(key, event);\n reloadInBackground(page);\n continue;\n }\n if (next === entry.value) continue;\n epochs.set(key, (epochs.get(key) ?? 0) + 1);\n setEntry(key, { page, status: 'ready', value: next });\n announce({ page, cause: 'event', event, previous: entry.value, next });\n }\n }\n\n return {\n get: (page) => entryOf(encodePageKey(page))?.value,\n view,\n getStatus: (page) => entryOf(encodePageKey(page))?.status ?? IDLE,\n ensureLoaded(page) {\n const key = encodePageKey(page);\n const running = inFlight.get(key);\n if (running) return running;\n if (entryOf(key)?.status === 'ready') return Promise.resolve();\n return load(page);\n },\n refresh(page) {\n if (page) return load(page);\n return Promise.all(loadedPages().map((loaded) => load(loaded))).then(() => undefined);\n },\n };\n}\n","import { PluginError } from './errors';\nimport type { OperationOptions } from './types';\n\n/**\n * Small promise-tail queue: operations run strictly one at a time, in\n * submission order, and failures never poison later operations. The shared\n * serializer for per-document mutation/dispatch pipelines.\n *\n * Direction law for nested queues: an operation running on queue A may\n * enqueue into queue B and await it, but never the reverse on the same pair —\n * a B-operation enqueueing back into A self-deadlocks behind its caller.\n */\nexport interface SerialQueue {\n /**\n * Run `operation` once everything queued before it has finished. With\n * `{ signal }`, an operation whose signal fired while it waited never\n * starts: it rejects `operation-cancelled`. Once it has started, cancelling\n * is up to the operation (`ctx.cancellable`).\n */\n <T>(operation: () => Promise<T>, options?: OperationOptions): Promise<T>;\n /** Resolves once every operation queued so far has finished, however it ended. */\n idle(): Promise<void>;\n}\n\n/** `capability` names the plugin in the error a skipped operation rejects with. */\nexport function createSerialQueue(capability: string): SerialQueue {\n let tail: Promise<void> = Promise.resolve();\n const queue = <T>(operation: () => Promise<T>, options?: OperationOptions): Promise<T> => {\n const start = (): Promise<T> =>\n options?.signal?.aborted\n ? Promise.reject(\n new PluginError('operation-cancelled', capability, 'cancelled before it started', {\n cause: options.signal.reason,\n }),\n )\n : operation();\n const result = tail.then(start, start);\n tail = result.then(\n () => undefined,\n () => undefined,\n );\n return result;\n };\n return Object.assign(queue, { idle: () => tail });\n}\n","import { PluginError, toPluginError } from './errors';\n\n/**\n * What `ctx.cancellable` does: race an engine call against the caller's\n * signal. When the signal fires, the call is aborted, so the worker or the\n * server stops working on it (an `AbortablePromise`, and a call made through\n * the guarded `ctx.doc`, carry `abort()`), and the returned promise rejects\n * `operation-cancelled` at once instead of waiting for the engine to notice.\n * The guarded handle does the same for the instance's lifetime\n * (guarded-handle.ts). A signal that fires after the call settled changes\n * nothing.\n */\nexport function cancellable<T>(\n capability: string,\n signal: AbortSignal | undefined,\n task: Promise<T>,\n): Promise<T> {\n if (!signal) return task;\n const abortable = task as Promise<T> & { abort?: (reason?: unknown) => void };\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n abortable.abort?.(signal.reason);\n reject(\n new PluginError('operation-cancelled', capability, 'operation cancelled', {\n cause: signal.reason,\n }),\n );\n };\n // Listened to even after a cancel: settling a settled promise changes\n // nothing, and the call's late rejection is then never left unhandled.\n task.then(\n (value) => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n (error) => {\n signal.removeEventListener('abort', onAbort);\n reject(toPluginError(capability, error));\n },\n );\n if (signal.aborted) onAbort();\n else signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n","/**\n * A page argument as plugins take it, a `PageRef` or a zero-based index into\n * the document's page list (display order), looked up two ways. A read asks\n * {@link findPage} and gets null for a page that isn't there: reads run while\n * rendering, and a page deleted mid-render must not break a layer. A verb asks\n * {@link pageOf}, which refuses with `not-found`.\n */\nimport { pageRefsEqual, type PageRef } from '@embedpdf/engine-core/runtime';\n\nimport { PluginError } from './errors';\nimport type { PageInfo } from './types';\n\n/** What `ctx.getPage` reads: the page `page` names in `pages`, or null. */\nexport function findPage(pages: readonly PageInfo[], page: PageRef | number): PageInfo | null {\n if (typeof page === 'number') return pages[page] ?? null;\n return pages.find((pageInfo) => pageRefsEqual(pageInfo.ref, page)) ?? null;\n}\n\n/** What `ctx.pageOf` resolves: the page `page` names in `pages`. Throws `not-found` when there is none. */\nexport function pageOf(\n pages: readonly PageInfo[],\n page: PageRef | number,\n capability: string,\n): PageInfo {\n const found = findPage(pages, page);\n if (found) return found;\n throw new PluginError(\n 'not-found',\n capability,\n typeof page === 'number'\n ? `there is no page ${page} in this document`\n : `page ${page.objectNumber} is not in this document`,\n );\n}\n","import type { DocumentHandle } from '@embedpdf/engine-core/runtime';\n\nimport { PluginError } from './errors';\nimport type { Permission } from './types';\n\n/**\n * What `ctx.allows` reads: the document session's own predicates, the ones the\n * engine enforces with, so a control gated on the answer never disagrees with\n * what the verb then does.\n */\nexport function sessionAllows(\n security: DocumentHandle['security'],\n permission: Permission,\n): boolean {\n return permission === 'annotations:create'\n ? security.allowsAnnotation('create')\n : security.allows(permission);\n}\n\n/** What `ctx.assertAllowed` throws: a refusal that names what was missing. */\nexport function permissionDenied(\n capability: string,\n permission: Permission,\n operation: string,\n): PluginError {\n return new PluginError('permission-denied', capability, `${operation} requires ${permission}`, {\n permission,\n });\n}\n\n/**\n * What a plugin throws for a form field the session may not fill in or sign:\n * a refusal that names the permission it would take, as the engine's does\n * (`fields:<action>:group=<group>`, or the broad one for a field in no group).\n */\nexport function fieldPermissionDenied(\n capability: string,\n action: 'fill' | 'sign',\n field: { readonly groupId: string | null },\n operation: string,\n): PluginError {\n const permission =\n field.groupId !== null\n ? `fields:${action}:group=${field.groupId}`\n : action === 'fill'\n ? 'doc.forms.fill'\n : 'doc.sign';\n return new PluginError('permission-denied', capability, `${operation} requires ${permission}`, {\n permission,\n });\n}\n","import { pageRefsEqual, type DocumentHandle, type PageRef } from '@embedpdf/engine-core/runtime';\n\nimport type { ChangeQueue, DocumentChanges } from './changes';\nimport { instanceClock, type HostClock } from './clock';\nimport { isDev } from './env';\nimport { PluginError } from './errors';\nimport { createEventHook, type EventHookSource } from './event-hook';\nimport { guardHandle } from './guarded-handle';\nimport { createLatestLane, type LatestLane } from './lanes';\nimport { createMirror, type MirrorEnvironment } from './mirror';\nimport { createPageMirror } from './page-mirror';\nimport type { Scope } from './scope';\nimport { createSerialQueue, type SerialQueue } from './serial-queue';\nimport { cancellable } from './cancellable';\nimport { findPage, pageOf } from './page-of';\nimport { fieldPermissionDenied, permissionDenied, sessionAllows } from './permissions';\nimport type { Settings, SettingsStore } from './settings';\nimport type { SettleFlush } from './settle';\nimport type { SliceLease, Store } from './store';\nimport type {\n AnyPlugin,\n CapabilityToken,\n DocumentMeta,\n Engine,\n OperationOptions,\n PluginContext,\n} from './types';\nimport { DocumentsToken } from './types';\n\n/** A plugin's slice key. Workspace plugins use their id; document-scoped plugins are per-document. */\nexport const sliceKey = (pluginId: string, documentId?: string): string =>\n documentId ? `${pluginId}::${documentId}` : pluginId;\n\n/**\n * The slice of a DocumentSession a context needs — structural, so this module\n * has no cycle with the kernel. Holding the session object (not its id) is\n * what makes late teardown registration safe: a context created for a session\n * can always reach that session's scope, even after the session has been\n * closed and removed from the kernel's map.\n */\nexport interface SessionRef {\n id: string;\n /** Unique per open; a reopened id gets a new one. */\n readonly instanceId: string;\n handle: DocumentHandle | null;\n /** Meta staged during bring-up, before the document is published. */\n stagedMeta: DocumentMeta | null;\n readonly scope: Scope;\n /** Aborted when close() begins. */\n readonly signal: AbortSignal;\n readonly leases: Map<AnyPlugin, SliceLease<unknown>>;\n /** The flushes to run before the document's file is read (settle.ts). */\n readonly settleFlushes: Set<SettleFlush>;\n /** What runs around each read of the document's file, first registered outermost. */\n readonly downloadWraps: DownloadWrap[];\n /** The document's change queue, shared by its plugins (`ctx.changes`). */\n readonly changes: DocumentChanges;\n}\n\n/** Something of the document's own that runs around a download: it gets the read and returns its bytes. */\nexport type DownloadWrap = (read: () => Promise<Uint8Array>) => Promise<Uint8Array>;\n\n/** `read`, inside every wrap: the first registered is the outermost. */\nexport const readWrapped = (\n wraps: readonly DownloadWrap[],\n read: () => Promise<Uint8Array>,\n): Promise<Uint8Array> =>\n wraps.reduceRight<() => Promise<Uint8Array>>((inner, wrap) => () => wrap(inner), read)();\n\n/**\n * Everything a context needs from the kernel, injected so this module has no cycles\n * with the capability resolver or the document lifecycle.\n */\nexport interface ContextServices {\n readonly engine: Engine;\n readonly store: Store;\n readonly workspaceScope: Scope;\n /** Aborted when destroy() begins. */\n readonly workspaceSignal: AbortSignal;\n readonly workspaceLeases: Map<AnyPlugin, SliceLease<unknown>>;\n readonly report: (error: unknown) => void;\n /** The host's time, which each instance's `ctx.clock` schedules on. */\n readonly clock: HostClock;\n resolveCapability<T>(token: CapabilityToken<T>, documentId?: string): T;\n /** Total resolution (the kernel's internal rule: bring-up or ready) — what\n * `ctx.tryGet` delegates to. Never exception-driven: a throwing capability\n * constructor is a bug and propagates. */\n tryResolveCapability<T>(token: CapabilityToken<T>, documentId?: string): T | null;\n documentHandle(documentId?: string): DocumentHandle | null;\n /** The plugin registration's settings store, built when the plugin list was planned; undefined when it declares none. */\n settingsStoreOf(plugin: AnyPlugin): SettingsStore<object> | undefined;\n}\n\n/**\n * The tokens a plugin may resolve: its declared `requires` and `optional`, its\n * own token, and the always-available documents token. Resolving anything else\n * is a lie in the dependency graph (the kernel cannot order or validate what it\n * does not know about), so in development it throws with the remedy.\n */\nfunction declaredTokens(plugin: AnyPlugin): Set<CapabilityToken<unknown>> {\n const declared = new Set<CapabilityToken<unknown>>([\n DocumentsToken,\n ...(plugin.requires ?? []),\n ...(plugin.optional ?? []),\n ]);\n if (plugin.token) declared.add(plugin.token);\n return declared;\n}\n\nconst connectedHooks = new WeakMap<object, () => void>();\n\n/** Kernel-side: the plugin's `connect` ran; start what waits for it (mirror loads). */\nexport function markConnected(context: object): void {\n connectedHooks.get(context)?.();\n}\n\n/**\n * Build the context a plugin's `create()` receives. With a `session` the\n * context is bound to that document: its state slice, `document()`, the\n * guarded `doc`, and `get()` resolving document-scoped capabilities for it.\n * `lifetime` aborts and `scope` disposes when the instance closes. One kind of\n * context serves every plugin, so `settings()` is always there and throws for\n * a plugin that declares none; the plugin's own types hide it (`definePlugin`).\n */\nexport function createPluginContext(\n services: ContextServices,\n plugin: AnyPlugin,\n session: SessionRef | undefined,\n lifetime: AbortSignal,\n scope: Scope,\n): PluginContext<unknown, object> {\n const { engine, store } = services;\n const documentId = session?.id;\n const instanceId = session?.instanceId ?? `workspace:${plugin.id}`;\n const capability = plugin.id;\n const lease = (session?.leases ?? services.workspaceLeases).get(plugin);\n if (!lease) {\n throw new Error(\n `[kernel] no state lease for plugin \"${plugin.id}\" (${documentId ?? 'workspace'})`,\n );\n }\n\n const declared = declaredTokens(plugin);\n const guard = (token: CapabilityToken<unknown>) => {\n if (isDev() && !plugin.resolvesAnyCapability && !declared.has(token)) {\n throw new Error(\n `[kernel] plugin \"${plugin.id}\" resolved capability \"${token.name}\" without declaring it; ` +\n `add the token to its \\`requires\\` or \\`optional\\` list.`,\n );\n }\n };\n\n // Reported once per context: a retained callback writing into a closed\n // instance is a bug worth surfacing, not a storm worth logging.\n let reportedClosed = false;\n const reportClosed = (what: string): void => {\n if (reportedClosed) return;\n reportedClosed = true;\n services.report(\n new PluginError(\n 'instance-closed',\n plugin.id,\n `${what} after the instance closed (${lease.instanceId}); dropped`,\n ),\n );\n };\n\n let guarded: DocumentHandle | null = null;\n const doc = (): DocumentHandle => {\n if (!session) {\n throw new Error(\n `[kernel] workspace plugin \"${plugin.id}\" has no bound document; use ctx.forDocument(token, documentId).`,\n );\n }\n if (!session.handle) {\n throw new PluginError(\n 'not-ready',\n capability,\n `document ${session.id} has no engine handle yet`,\n );\n }\n return (guarded ??= guardHandle(session.handle, { signal: lifetime, instanceId }, capability));\n };\n\n const metaOf = (): DocumentMeta | null =>\n session ? (store.getCore().documents[session.id] ?? session.stagedMeta) : null;\n\n const notFound = (ref: PageRef) =>\n new PluginError('not-found', capability, `page ${ref.objectNumber} is not in this document`);\n\n const queues = new Map<string, SerialQueue>();\n const lanes = new Map<string, LatestLane>();\n let instanceSettings: Settings<object> | null = null;\n let changeQueue: ChangeQueue | null = null;\n\n // Mirrors hold their values in store cells of their own, revoked with the\n // instance; their first load waits until the plugin is connected.\n const pendingStarts: (() => void)[] = [];\n const mirrorEnvironment = (): MirrorEnvironment => ({\n doc: doc(),\n changes: session!.changes,\n notify: () => {\n if (lease.live) store.notify();\n },\n lifetime,\n cell(name, initial) {\n const cell = store.lease(`${sliceKey(plugin.id, session?.id)}/${name}`, initial, instanceId);\n if (lifetime.aborted) cell.revoke();\n else lifetime.addEventListener('abort', () => cell.revoke(), { once: true });\n return cell;\n },\n onDocumentEvent(listener) {\n const off = doc().events.subscribe(listener);\n scope.defer(off);\n },\n report: services.report,\n });\n\n const context: PluginContext<unknown, object> = {\n id: plugin.id,\n instanceId,\n documentId,\n engine,\n get doc() {\n return doc();\n },\n documentHandle: (requestedDocumentId) =>\n requestedDocumentId\n ? services.documentHandle(requestedDocumentId)\n : session\n ? session.handle\n : services.documentHandle(undefined),\n document: () => {\n if (session) return metaOf();\n const id = store.getCore().activeId;\n return id ? (store.getCore().documents[id] ?? null) : null;\n },\n getPage: (page) => findPage(metaOf()?.pages ?? [], page),\n pageOf: (page) => pageOf(metaOf()?.pages ?? [], page, capability),\n assertPageRef: (ref) => {\n if (!metaOf()?.pages.some((pageInfo) => pageRefsEqual(pageInfo.ref, ref)))\n throw notFound(ref);\n },\n\n // Both read the bound document through `doc()`, so a workspace context\n // throws here exactly as reading `ctx.doc` does.\n allows: (permission) => sessionAllows(doc().security, permission),\n assertAllowed: (permission, operation) => {\n if (!sessionAllows(doc().security, permission)) {\n throw permissionDenied(capability, permission, operation);\n }\n },\n allowsField: (action, field) => doc().security.allowsField(action, { groupId: field.groupId }),\n assertAllowedField: (action, field, operation) => {\n if (!doc().security.allowsField(action, { groupId: field.groupId })) {\n throw fieldPermissionDenied(capability, action, field, operation);\n }\n },\n\n get: <T>(token: CapabilityToken<T>): T => (\n guard(token),\n services.resolveCapability(token, documentId)\n ),\n tryGet: <T>(token: CapabilityToken<T>): T | null => (\n guard(token),\n services.tryResolveCapability(token, documentId)\n ),\n forDocument: <T>(token: CapabilityToken<T>, otherDocumentId: string): T => (\n guard(token),\n services.resolveCapability(token, otherDocumentId)\n ),\n tryForDocument: <T>(token: CapabilityToken<T>, otherDocumentId: string): T | null => (\n guard(token),\n services.tryResolveCapability(token, otherDocumentId)\n ),\n\n state: {\n get: () => lease.read(),\n update: (transition, ...args) => {\n if (!lease.write(transition(lease.read(), ...args))) reportClosed('a state update');\n },\n onChange: lease.onChange,\n },\n\n settings: () => {\n if (instanceSettings) return instanceSettings;\n const registration = services.settingsStoreOf(plugin);\n if (!registration) {\n throw new Error(\n `[kernel] plugin \"${plugin.id}\" read ctx.settings() but declares no settings; ` +\n `add \\`settings: { defaults, registered }\\` to its definition.`,\n );\n }\n // The instance's own view, so its listeners go when it closes.\n return (instanceSettings = registration.forInstance((teardown) => scope.defer(teardown)));\n },\n\n notify: () => {\n if (lease.live) store.notify();\n },\n watch: (select, handler, isEqual = Object.is) => {\n let previous = select();\n const unsubscribe = store.subscribe(() => {\n const next = select();\n if (isEqual(previous, next)) return;\n const prior = previous;\n previous = next;\n handler(next, prior);\n });\n scope.defer(unsubscribe);\n return unsubscribe;\n },\n waitFor(predicate, options?: OperationOptions) {\n return new Promise<void>((resolve, reject) => {\n let done = false;\n const finish = (fn: () => void) => {\n if (done) return;\n done = true;\n unsubscribe();\n lifetime.removeEventListener('abort', onClose);\n options?.signal?.removeEventListener('abort', onCancel);\n fn();\n };\n const onClose = () =>\n finish(() =>\n reject(new PluginError('instance-closed', capability, 'closed while waiting')),\n );\n const onCancel = () =>\n finish(() =>\n reject(new PluginError('operation-cancelled', capability, 'cancelled while waiting')),\n );\n const check = () => {\n let holds = false;\n try {\n holds = predicate();\n } catch (error) {\n finish(() => reject(error));\n return;\n }\n if (holds) finish(resolve);\n };\n const unsubscribe = store.subscribe(check);\n if (lifetime.aborted) return onClose();\n if (options?.signal?.aborted) return onCancel();\n lifetime.addEventListener('abort', onClose, { once: true });\n options?.signal?.addEventListener('abort', onCancel, { once: true });\n check();\n });\n },\n\n mirror(spec) {\n const controller = createMirror(spec, mirrorEnvironment());\n pendingStarts.push(controller.start);\n return controller.mirror;\n },\n pageMirror: (spec) => createPageMirror(spec, mirrorEnvironment()),\n\n events: {\n source<T>(): EventHookSource<T> {\n const hook = createEventHook<T>(services.report);\n scope.defer(() => hook.dispose());\n return hook;\n },\n },\n listen(source, listener) {\n const off = typeof source === 'function' ? source(listener) : source.subscribe(listener);\n scope.defer(off);\n },\n\n get changes() {\n if (!session) {\n throw new Error(\n `[kernel] workspace plugin \"${plugin.id}\" has no document to change; ctx.changes is for document-scoped plugins.`,\n );\n }\n return (changeQueue ??= session.changes.forPlugin(plugin.id));\n },\n cleanup: (teardown) => scope.defer(teardown),\n clock: instanceClock(services.clock, lifetime),\n onSettle(flush) {\n if (!session) {\n throw new Error(\n `[kernel] workspace plugin \"${plugin.id}\" has no document to settle; ctx.onSettle() is for document-scoped plugins.`,\n );\n }\n session.settleFlushes.add(flush);\n scope.defer(() => {\n session.settleFlushes.delete(flush);\n });\n },\n aroundDownload(wrap) {\n if (!session) {\n throw new Error(\n `[kernel] workspace plugin \"${plugin.id}\" has no document to download; ctx.aroundDownload() is for document-scoped plugins.`,\n );\n }\n session.downloadWraps.push(wrap);\n scope.defer(() => {\n const index = session.downloadWraps.indexOf(wrap);\n if (index >= 0) session.downloadWraps.splice(index, 1);\n });\n },\n async acquire(get, dispose) {\n const value = await get(lifetime);\n if (lifetime.aborted) {\n await dispose(value);\n throw new PluginError('instance-closed', capability, 'closed while acquiring a resource');\n }\n scope.defer(() => dispose(value));\n return value;\n },\n cancellable: (signal, task) => cancellable(capability, signal, task),\n latest(key) {\n let lane = lanes.get(key);\n if (!lane) {\n lane = createLatestLane(lifetime, capability, key);\n lanes.set(key, lane);\n }\n return lane;\n },\n serialQueue(key = 'default') {\n let queue = queues.get(key);\n if (!queue) {\n queue = createSerialQueue(capability);\n queues.set(key, queue);\n }\n return queue;\n },\n };\n connectedHooks.set(context, () => {\n for (const start of pendingStarts.splice(0)) start();\n });\n return context;\n}\n","/**\n * Settling a document: before something reads the whole file (a download), everything its\n * plugins hold back from the engine is sent, and the engine has answered. Each plugin registers\n * a flush with `ctx.onSettle()` for what it holds back: text typed a moment ago, a drawing waiting\n * for its next stroke, the writes on their way in its write queue. The rules are in\n * `docs/conventions/state-and-sync.md`.\n *\n * A flush that fails doesn't stop the read: the file is then what the engine has, and the plugin\n * reports its own failure.\n */\nimport { PluginError } from './errors';\n\n/** Sends what a plugin holds back; resolves once the engine has it. */\nexport type SettleFlush = (signal: AbortSignal) => Promise<void> | void;\n\n/**\n * Run every flush and wait for all of them. Rejects with `operation-cancelled` as soon as one of\n * `signals` aborts, such as the caller's or the document's own (it aborts when the document\n * closes).\n */\nexport async function settle(\n flushes: ReadonlySet<SettleFlush>,\n signals: readonly (AbortSignal | undefined)[],\n report: (error: unknown) => void,\n): Promise<void> {\n const stop = new AbortController();\n const listening = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n const abort = () => stop.abort();\n for (const signal of listening) {\n if (signal.aborted) abort();\n else signal.addEventListener('abort', abort, { once: true });\n }\n try {\n const work = (async () => {\n const running = [...flushes].map(async (flush) => flush(stop.signal));\n for (const outcome of await Promise.allSettled(running)) {\n if (outcome.status === 'rejected') report(outcome.reason);\n }\n })();\n await whileNotAborted(work, stop.signal);\n } finally {\n for (const signal of listening) signal.removeEventListener('abort', abort);\n }\n}\n\n/** `work`, or `operation-cancelled` as soon as `signal` aborts. */\nasync function whileNotAborted(work: Promise<void>, signal: AbortSignal): Promise<void> {\n let onAbort: (() => void) | undefined;\n const aborted = new Promise<never>((_, reject) => {\n onAbort = () =>\n reject(new PluginError('operation-cancelled', 'documents', 'settling was cancelled'));\n if (signal.aborted) onAbort();\n else signal.addEventListener('abort', onAbort, { once: true });\n });\n try {\n await Promise.race([work, aborted]);\n } finally {\n if (onAbort) signal.removeEventListener('abort', onAbort);\n }\n}\n","/**\n * A plugin's settings: what the app registered over the plugin's defaults, changed at runtime\n * with `updateSettings()`. A plugin declares them in its definition\n * (`definePlugin({ settings: { defaults, registered } })`), and the kernel builds one store per\n * plugin registration when it plans the plugin list. The store belongs to the registration, not\n * to a document: it exists before the first document opens, every instance of the plugin shares\n * it, and a change reaches every open document and the ones opened later. A plugin reads its\n * store with `ctx.settings()`; an adapter reads it with `kernel.settingsOf(token)`.\n *\n * Changes merge into the settings the same way everywhere (`registered` over the defaults, and\n * every `updateSettings()`): plain objects merge key by key, arrays and every other value\n * replace, and `undefined` leaves a setting as it is.\n */\nimport { createEventHook, type EventHook } from './event-hook';\n\n/** A change to one setting: plain objects go deeper, arrays and functions are given whole. */\ntype DeepPartialValue<V> = V extends readonly unknown[] | ((...args: never[]) => unknown)\n ? V\n : V extends object\n ? DeepPartial<V>\n : V;\n\n/** Every field optional, down through the plain objects. */\nexport type DeepPartial<T> = { readonly [K in keyof T]?: DeepPartialValue<T[K]> };\n\ndeclare const noSettings: unique symbol;\n\n/**\n * The settings of a plugin whose definition declares none. A type of its own rather than `never`:\n * a plugin list mixes plugins with and without settings, and `any` stands in for every type but\n * `never`.\n */\nexport interface NoSettings {\n readonly [noSettings]: true;\n}\n\n/** A plugin's settings as its definition declares them: `definePlugin({ settings })`. */\nexport interface SettingsDeclaration<T> {\n /** Every setting's value when the app registers none. */\n readonly defaults: T;\n /** What the app registered, usually the plugin factory's config: merged over `defaults`. */\n readonly registered?: DeepPartial<T> | undefined;\n /**\n * Top-level settings that are one value each, such as a person: a change replaces them\n * whole instead of merging into them, so nothing of the previous value stays.\n */\n readonly whole?: readonly (keyof T & string)[];\n}\n\n/** What `onSettingsChanged` carries: the settings after the change, and which of them changed. */\nexport interface SettingsChangedEvent<T> {\n readonly settings: T;\n /** The top-level settings whose value changed (`['highlight']` when only a highlight color did). */\n readonly changed: readonly (keyof T)[];\n}\n\n/** The four settings calls, spread into a plugin's capability. */\nexport interface SettingsApi<T> {\n /** The settings in effect: the same object until a setting changes. */\n getSettings(): T;\n /**\n * Merge `changes` into the settings, for every document: plain objects merge key by key,\n * arrays and other values replace, and `undefined` leaves a setting as it is. Fires\n * `onSettingsChanged` once when a setting changed.\n */\n updateSettings(changes: DeepPartial<T>): void;\n /** Go back to what the app registered (not to the plugin's defaults). Fires `onSettingsChanged` when a setting changed. */\n resetSettings(): void;\n /** Fires once for each call that changed a setting. */\n readonly onSettingsChanged: EventHook<SettingsChangedEvent<T>>;\n}\n\n/** The settings type of a capability that has the settings calls, else `never`. */\nexport type SettingsOf<Capability> = Capability extends { getSettings(): infer T } ? T : never;\n\n/** What `ctx.settings()` returns: `get()` for the plugin's own code, `api` for its capability. */\nexport interface Settings<T> {\n /** The settings in effect. */\n get(): T;\n readonly api: SettingsApi<T>;\n}\n\n/** One registration's settings, kept by the kernel. */\nexport interface SettingsStore<T> {\n /** The calls themselves, bound to no instance: what `kernel.settingsOf(token)` hands out. */\n readonly api: SettingsApi<T>;\n /**\n * The store as one plugin instance sees it: the same settings, with an `onSettingsChanged`\n * of the instance's own. `cleanup` receives the teardown that ends it, so the instance's\n * listeners go when the instance closes; the settings stay.\n */\n forInstance(cleanup: (teardown: () => void) => void): Settings<T>;\n dispose(): void;\n}\n\n/**\n * Build a registration's store. `wake` runs after every change, before the event, so readers\n * that poll the capability (selectors over `getSettings()`) read again.\n */\nexport function createSettingsStore<T extends object>(\n { defaults, registered, whole = [] }: SettingsDeclaration<T>,\n wake: () => void,\n report: (error: unknown) => void,\n): SettingsStore<T> {\n const initial = mergeSettings(defaults, registered, whole);\n let current = initial;\n const changedHook = createEventHook<SettingsChangedEvent<T>>(report);\n\n const commit = (next: T): void => {\n const changed = changedKeys(current, next);\n // A call that changes no value changes nothing: no wake, no event, the same object.\n if (changed.length === 0) return;\n current = next;\n wake();\n changedHook.emit({ settings: next, changed });\n };\n\n const api: SettingsApi<T> = {\n getSettings: () => current,\n updateSettings: (changes) => commit(mergeSettings(current, changes, whole)),\n resetSettings: () => commit(initial),\n onSettingsChanged: changedHook.on,\n };\n\n return {\n api,\n forInstance(cleanup) {\n const instanceChanged = createEventHook<SettingsChangedEvent<T>>(report);\n cleanup(changedHook.on((event) => instanceChanged.emit(event)));\n cleanup(() => instanceChanged.dispose());\n return {\n get: api.getSettings,\n api: { ...api, onSettingsChanged: instanceChanged.on },\n };\n },\n dispose: () => changedHook.dispose(),\n };\n}\n\n/**\n * `changes` merged into `settings`, the `whole` ones replaced instead: the merge every settings\n * store applies, for code that keeps changes before a store exists (an adapter whose engine is\n * still loading). What a change leaves as it was keeps its object, so a reader that compares by\n * reference sees only what really changed.\n */\nexport function mergeSettings<T>(\n settings: T,\n changes: DeepPartial<T> | undefined,\n whole: readonly string[] = [],\n): T {\n if (whole.length === 0 || !isPlainObject(changes)) return mergeValue(settings, changes) as T;\n const merged = mergeValue(settings, omit(changes, whole)) as Record<string, unknown>;\n let replaced: Record<string, unknown> | null = null;\n for (const key of whole) {\n const change = (changes as Record<string, unknown>)[key];\n if (change === undefined || sameValue(merged[key], change)) continue;\n replaced ??= { ...merged };\n replaced[key] = change;\n }\n return (replaced ?? merged) as T;\n}\n\n/** `object` without `keys`. */\nfunction omit(object: Record<string, unknown>, keys: readonly string[]): Record<string, unknown> {\n const rest: Record<string, unknown> = {};\n for (const key of Object.keys(object)) if (!keys.includes(key)) rest[key] = object[key];\n return rest;\n}\n\nfunction mergeValue(base: unknown, change: unknown): unknown {\n if (change === undefined) return base;\n // Arrays and other values replace; an equal one keeps the object already there.\n if (!isPlainObject(change)) return sameValue(base, change) ? base : change;\n const into = isPlainObject(base) ? base : {};\n let merged: Record<string, unknown> | null = null;\n for (const key of Object.keys(change)) {\n const current = hasOwn(into, key) ? into[key] : undefined;\n const next = mergeValue(current, change[key]);\n if (next === current) continue;\n merged ??= { ...into };\n merged[key] = next;\n }\n return merged ?? base;\n}\n\n/** The top-level settings whose value differs between `previous` and `next`. */\nfunction changedKeys<T extends object>(previous: T, next: T): (keyof T)[] {\n const before = previous as Record<string, unknown>;\n const after = next as Record<string, unknown>;\n const keys = new Set([...Object.keys(before), ...Object.keys(after)]);\n return [...keys].filter((key) => !sameValue(before[key], after[key])) as (keyof T)[];\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst hasOwn = (object: object, key: string): boolean =>\n Object.prototype.hasOwnProperty.call(object, key);\n\n/** Equal by value: the same primitive or object, or arrays and plain objects with equal entries. */\nfunction sameValue(left: unknown, right: unknown): boolean {\n if (Object.is(left, right)) return true;\n if (Array.isArray(left) && Array.isArray(right)) {\n return (\n left.length === right.length && left.every((item, index) => sameValue(item, right[index]))\n );\n }\n if (isPlainObject(left) && isPlainObject(right)) {\n const keys = Object.keys(left);\n return (\n keys.length === Object.keys(right).length &&\n keys.every((key) => hasOwn(right, key) && sameValue(left[key], right[key]))\n );\n }\n return false;\n}\n"],"mappings":"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"}
|