@embedpdf/core 2.14.4 → 3.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +192 -21
  2. package/dist/index.cjs +864 -2
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +313 -0
  5. package/dist/index.d.ts +313 -1
  6. package/dist/index.js +816 -2124
  7. package/dist/index.js.map +1 -1
  8. package/package.json +22 -52
  9. package/README.md +0 -40
  10. package/dist/lib/base/base-plugin.d.ts +0 -190
  11. package/dist/lib/index.d.ts +0 -17
  12. package/dist/lib/plugin/builder.d.ts +0 -11
  13. package/dist/lib/registry/plugin-registry.d.ts +0 -104
  14. package/dist/lib/store/actions.d.ts +0 -154
  15. package/dist/lib/store/index.d.ts +0 -6
  16. package/dist/lib/store/initial-state.d.ts +0 -31
  17. package/dist/lib/store/plugin-store.d.ts +0 -48
  18. package/dist/lib/store/reducer-helpers.d.ts +0 -11
  19. package/dist/lib/store/reducer.d.ts +0 -4
  20. package/dist/lib/store/selectors.d.ts +0 -41
  21. package/dist/lib/store/store.d.ts +0 -106
  22. package/dist/lib/store/types.d.ts +0 -28
  23. package/dist/lib/types/errors.d.ts +0 -21
  24. package/dist/lib/types/permissions.d.ts +0 -55
  25. package/dist/lib/types/plugin.d.ts +0 -75
  26. package/dist/lib/utils/dependency-resolver.d.ts +0 -6
  27. package/dist/lib/utils/event-control.d.ts +0 -58
  28. package/dist/lib/utils/eventing.d.ts +0 -19
  29. package/dist/lib/utils/math.d.ts +0 -22
  30. package/dist/lib/utils/plugin-helpers.d.ts +0 -6
  31. package/dist/lib/utils/scoped-eventing.d.ts +0 -71
  32. package/dist/lib/utils/typed-object.d.ts +0 -12
  33. package/dist/preact/adapter.d.ts +0 -11
  34. package/dist/preact/index.cjs +0 -2
  35. package/dist/preact/index.cjs.map +0 -1
  36. package/dist/preact/index.d.ts +0 -1
  37. package/dist/preact/index.js +0 -323
  38. package/dist/preact/index.js.map +0 -1
  39. package/dist/react/adapter.d.ts +0 -2
  40. package/dist/react/index.cjs +0 -2
  41. package/dist/react/index.cjs.map +0 -1
  42. package/dist/react/index.d.ts +0 -1
  43. package/dist/react/index.js +0 -322
  44. package/dist/react/index.js.map +0 -1
  45. package/dist/shared/components/auto-mount.d.ts +0 -8
  46. package/dist/shared/components/embed-pdf.d.ts +0 -37
  47. package/dist/shared/components/index.d.ts +0 -1
  48. package/dist/shared/context.d.ts +0 -12
  49. package/dist/shared/hooks/index.d.ts +0 -7
  50. package/dist/shared/hooks/use-capability.d.ts +0 -16
  51. package/dist/shared/hooks/use-core-state.d.ts +0 -8
  52. package/dist/shared/hooks/use-document-permissions.d.ts +0 -35
  53. package/dist/shared/hooks/use-document-state.d.ts +0 -8
  54. package/dist/shared/hooks/use-plugin.d.ts +0 -16
  55. package/dist/shared/hooks/use-registry.d.ts +0 -6
  56. package/dist/shared/hooks/use-store-state.d.ts +0 -6
  57. package/dist/shared/index.d.ts +0 -3
  58. package/dist/shared-preact/components/auto-mount.d.ts +0 -8
  59. package/dist/shared-preact/components/embed-pdf.d.ts +0 -37
  60. package/dist/shared-preact/components/index.d.ts +0 -1
  61. package/dist/shared-preact/context.d.ts +0 -12
  62. package/dist/shared-preact/hooks/index.d.ts +0 -7
  63. package/dist/shared-preact/hooks/use-capability.d.ts +0 -16
  64. package/dist/shared-preact/hooks/use-core-state.d.ts +0 -8
  65. package/dist/shared-preact/hooks/use-document-permissions.d.ts +0 -35
  66. package/dist/shared-preact/hooks/use-document-state.d.ts +0 -8
  67. package/dist/shared-preact/hooks/use-plugin.d.ts +0 -16
  68. package/dist/shared-preact/hooks/use-registry.d.ts +0 -6
  69. package/dist/shared-preact/hooks/use-store-state.d.ts +0 -6
  70. package/dist/shared-preact/index.d.ts +0 -3
  71. package/dist/shared-react/components/auto-mount.d.ts +0 -8
  72. package/dist/shared-react/components/embed-pdf.d.ts +0 -37
  73. package/dist/shared-react/components/index.d.ts +0 -1
  74. package/dist/shared-react/context.d.ts +0 -12
  75. package/dist/shared-react/hooks/index.d.ts +0 -7
  76. package/dist/shared-react/hooks/use-capability.d.ts +0 -16
  77. package/dist/shared-react/hooks/use-core-state.d.ts +0 -8
  78. package/dist/shared-react/hooks/use-document-permissions.d.ts +0 -35
  79. package/dist/shared-react/hooks/use-document-state.d.ts +0 -8
  80. package/dist/shared-react/hooks/use-plugin.d.ts +0 -16
  81. package/dist/shared-react/hooks/use-registry.d.ts +0 -6
  82. package/dist/shared-react/hooks/use-store-state.d.ts +0 -6
  83. package/dist/shared-react/index.d.ts +0 -3
  84. package/dist/svelte/components/AutoMount.svelte.d.ts +0 -9
  85. package/dist/svelte/components/EmbedPDF.svelte.d.ts +0 -40
  86. package/dist/svelte/components/NestedWrapper.svelte.d.ts +0 -10
  87. package/dist/svelte/components/index.d.ts +0 -1
  88. package/dist/svelte/hooks/index.d.ts +0 -6
  89. package/dist/svelte/hooks/use-capability.svelte.d.ts +0 -14
  90. package/dist/svelte/hooks/use-core-state.svelte.d.ts +0 -9
  91. package/dist/svelte/hooks/use-document-permissions.svelte.d.ts +0 -35
  92. package/dist/svelte/hooks/use-document-state.svelte.d.ts +0 -9
  93. package/dist/svelte/hooks/use-plugin.svelte.d.ts +0 -14
  94. package/dist/svelte/hooks/use-registry.svelte.d.ts +0 -17
  95. package/dist/svelte/index.cjs +0 -2
  96. package/dist/svelte/index.cjs.map +0 -1
  97. package/dist/svelte/index.d.ts +0 -2
  98. package/dist/svelte/index.js +0 -430
  99. package/dist/svelte/index.js.map +0 -1
  100. package/dist/vue/components/auto-mount.vue.d.ts +0 -19
  101. package/dist/vue/components/embed-pdf.vue.d.ts +0 -104
  102. package/dist/vue/components/index.d.ts +0 -1
  103. package/dist/vue/components/nested-wrapper.vue.d.ts +0 -19
  104. package/dist/vue/composables/index.d.ts +0 -7
  105. package/dist/vue/composables/use-capability.d.ts +0 -15
  106. package/dist/vue/composables/use-core-state.d.ts +0 -9
  107. package/dist/vue/composables/use-document-permissions.d.ts +0 -36
  108. package/dist/vue/composables/use-document-state.d.ts +0 -8
  109. package/dist/vue/composables/use-plugin.d.ts +0 -8
  110. package/dist/vue/composables/use-registry.d.ts +0 -1
  111. package/dist/vue/composables/use-store-state.d.ts +0 -10
  112. package/dist/vue/context.d.ts +0 -13
  113. package/dist/vue/index.cjs +0 -2
  114. package/dist/vue/index.cjs.map +0 -1
  115. package/dist/vue/index.d.ts +0 -2
  116. package/dist/vue/index.js +0 -384
  117. package/dist/vue/index.js.map +0 -1
@@ -0,0 +1,313 @@
1
+ import { AbortablePromise, CONTINUOUS_RENDER_POLICY, DocCapability, DocumentEvent, DocumentHandle, DocumentMetadata, Engine, EngineFactory, EngineRenderPolicy, EngineRenderPolicy as EngineRenderPolicy$1, MetadataPatch, MetadataUpdateResult, OpenInput, OpenOptions, PageDeleteResult, PageHandle, PageImageHandle, PageImageObjectUrl, PageImageOptions, PageLayout, PageMoveResult, PageObjectNumber, PageRaster, PageRenderOptions, PageRenderTarget, PageRenderViewport, PageRotateResult, PageRotation, PdfDestination, PdfRect, PdfSaveMode, snapAppearanceScale, snapFullPageViewport, snapTileScale } from "@embedpdf/engine-core/runtime";
2
+ //#region src/types.d.ts
3
+ type Unsubscribe = () => void;
4
+ /** Every state transition is a plain, serializable action. */
5
+ interface Action {
6
+ readonly type: string;
7
+ }
8
+ /** Kernel-emitted document-lifecycle actions; plugins may react via `onAction`. */
9
+ declare const CORE_DOCUMENT_ADDED = "@@core/document-added";
10
+ declare const CORE_DOCUMENT_REMOVED = "@@core/document-removed";
11
+ declare const CORE_ACTIVE_CHANGED = "@@core/active-changed";
12
+ declare const CORE_ORDER_CHANGED = "@@core/order-changed";
13
+ /** A document's page registry was replaced by a mutation event (rotate/move/delete). */
14
+ declare const CORE_DOCUMENT_PAGES_UPDATED = "@@core/document-pages-updated";
15
+ /** A tab slot was reserved: `open()` was called; the document is loading. */
16
+ declare const CORE_DOCUMENT_OPENING = "@@core/document-opening";
17
+ /** The engine reports the document needs a password (`documents.unlock`). */
18
+ declare const CORE_DOCUMENT_LOCKED = "@@core/document-locked";
19
+ /** The open failed; the tab stays with `status: 'error'` until closed. */
20
+ declare const CORE_DOCUMENT_OPEN_FAILED = "@@core/document-open-failed";
21
+ /** A typed handle to a capability — typed resolution, no string casts. */
22
+ interface CapabilityToken<T> {
23
+ readonly name: string;
24
+ /** phantom — never present at runtime */
25
+ readonly __type?: T;
26
+ }
27
+ /**
28
+ * What the kernel knows about an open document — the page registry captured at open.
29
+ * `pages` is the engine's own snapshot (`PageLayout`: index, pageObjectNumber, size,
30
+ * rotation, label, boxes). The `pageObjectNumber` (pon) is the durable per-page
31
+ * identity; the array index is only display order.
32
+ */
33
+ interface DocumentMeta {
34
+ readonly id: string;
35
+ readonly name?: string;
36
+ readonly pageCount: number;
37
+ readonly pages: readonly PageLayout[];
38
+ /**
39
+ * Bumps every time the page registry is replaced by a document mutation
40
+ * event (rotate/move/delete). The registry's monotonic version: anything
41
+ * caching a derivation of `pages` (e.g. the Stage's laid-out scene) keys
42
+ * on it so a same-`pageCount` change — like a rotation — still invalidates.
43
+ */
44
+ readonly revision: number;
45
+ /**
46
+ * The deployment render policy the document's engine advertises — a
47
+ * document FACT like `pages`, materialized by the kernel at open (before
48
+ * publish), NOT plugin state. One lifecycle (here), one interpretation
49
+ * (engine-core's pure `snap*` helpers); any plugin reads it. Engines
50
+ * without a render service — and failed policy reads — resolve to
51
+ * `continuous`, so consumers never branch on absence. Naming rule: the
52
+ * domain appears exactly once — bare `policy()` on the render SERVICE,
53
+ * `renderPolicy` on flat envelopes like this one and `/v1/access`.
54
+ */
55
+ readonly renderPolicy: EngineRenderPolicy$1;
56
+ }
57
+ /**
58
+ * A tab slot whose document is not (yet) real: still opening, waiting for a
59
+ * password, or failed. Lives beside `documents`, never inside it — plugins
60
+ * only ever see READY documents; pending slots are pure registry/UI state.
61
+ * Request-time lifecycle: `open()` reserves the slot (id, order position,
62
+ * activation) synchronously; only the content arrives at completion time.
63
+ */
64
+ interface PendingMeta {
65
+ readonly id: string;
66
+ readonly name?: string;
67
+ readonly status: 'loading' | 'locked' | 'error';
68
+ /** `locked` only: a password was supplied at open and rejected — the
69
+ * prompt should show its "incorrect password" copy, not "required". */
70
+ readonly passwordProvided?: boolean;
71
+ /** `error` only: what the open rejected with. Never carries a password. */
72
+ readonly error?: unknown;
73
+ }
74
+ /** The document registry — what document scope is built on. */
75
+ interface CoreState {
76
+ readonly documents: Readonly<Record<string, DocumentMeta>>;
77
+ readonly pending: Readonly<Record<string, PendingMeta>>;
78
+ /** THE tab strip: spans ready docs and pending slots, in request order. */
79
+ readonly order: readonly string[];
80
+ /** May point at a pending slot (a loading or locked tab can be selected). */
81
+ readonly activeId: string | null;
82
+ }
83
+ interface GlobalState {
84
+ readonly core: CoreState;
85
+ readonly plugins: Readonly<Record<string, unknown>>;
86
+ }
87
+ type PluginScope = 'workspace' | 'document';
88
+ /**
89
+ * The context a plugin receives. Document-scoped plugins get a context bound to a
90
+ * single document — `documentId`, `document()` (metadata), `doc` (the engine handle),
91
+ * and `get()` resolving document-scoped capabilities for it.
92
+ */
93
+ interface PluginContext<S, A extends Action = Action> {
94
+ readonly id: string;
95
+ readonly engine: Engine;
96
+ /** The bound document (document-scoped plugins only; undefined for workspace). */
97
+ readonly documentId?: string;
98
+ /** The bound document's engine handle; for workspace plugins, the active doc's handle, or null. */
99
+ readonly doc: DocumentHandle | null;
100
+ /** Resolve a live engine handle by document id; omitted follows this context's normal active/bound rule. */
101
+ documentHandle(documentId?: string): DocumentHandle | null;
102
+ getState(): S;
103
+ dispatch(action: A): void;
104
+ subscribe(listener: () => void): Unsubscribe;
105
+ core(): CoreState;
106
+ /** The bound document's metadata; for workspace plugins, the active doc's, or null. */
107
+ document(): DocumentMeta | null;
108
+ get<T>(token: CapabilityToken<T>): T;
109
+ forDocument<T>(token: CapabilityToken<T>, documentId: string): T;
110
+ tryGet<T>(token: CapabilityToken<T>): T | null;
111
+ /**
112
+ * Register a resource teardown owned by this plugin instance. Document-
113
+ * scoped callbacks run when that document closes; workspace callbacks run
114
+ * when the kernel is destroyed. Asynchronous teardowns are awaited.
115
+ * Registering after the owner is already disposed runs the teardown
116
+ * immediately instead of dropping it — a late registration cannot leak.
117
+ * Safe for capability-held timers, runtimes, subscriptions, object URLs,
118
+ * and binary caches.
119
+ */
120
+ cleanup(fn: () => void | Promise<void>): void;
121
+ }
122
+ /** Side-effect context: the only place async/IO/cross-plugin reactions live. */
123
+ interface EffectContext<S, A extends Action = Action> extends PluginContext<S, A> {
124
+ watch<R>(select: () => R, handler: (value: R, previous: R) => void, isEqual?: (a: R, b: R) => boolean): Unsubscribe;
125
+ onAction(type: string, handler: (action: Action) => void): Unsubscribe;
126
+ }
127
+ /**
128
+ * A plugin definition. `scope` decides multiplexing:
129
+ * 'workspace' (default) — one instance; can see every document.
130
+ * 'document' — one instance PER open document; authored single-document.
131
+ */
132
+ interface PluginDef<S = unknown, A extends Action = Action, C = unknown> {
133
+ readonly id: string;
134
+ readonly token?: CapabilityToken<C>;
135
+ readonly scope?: PluginScope;
136
+ readonly requires?: ReadonlyArray<CapabilityToken<unknown>>;
137
+ readonly optional?: ReadonlyArray<CapabilityToken<unknown>>;
138
+ readonly initialState?: S | (() => S);
139
+ readonly reduce?: (state: S, action: A) => S;
140
+ readonly capability?: (ctx: PluginContext<S, A>) => C;
141
+ readonly init?: (ctx: PluginContext<S, A>) => void | Promise<void>;
142
+ readonly effects?: (ctx: EffectContext<S, A>) => void;
143
+ }
144
+ type AnyPlugin = PluginDef<any, any, any>;
145
+ type DocStatus = 'loading' | 'locked' | 'ready' | 'error';
146
+ interface DocInfo {
147
+ id: string;
148
+ name?: string;
149
+ /** Lifecycle state — the tab bar renders directly off this. */
150
+ status: DocStatus;
151
+ /** 0 until the document is `ready`. */
152
+ pageCount: number;
153
+ /** `locked` only: a supplied password was rejected (show "incorrect"). */
154
+ passwordProvided?: boolean;
155
+ }
156
+ /** Field-wise DocInfo equality — the ONE definition every adapter's reactive
157
+ * `docs` read keys on, so a new lifecycle field can never silently stop
158
+ * re-rendering one framework's tab bar. */
159
+ declare const docInfoEquals: (a: DocInfo, b: DocInfo) => boolean;
160
+ declare const docInfoListEquals: (a: readonly DocInfo[], b: readonly DocInfo[]) => boolean;
161
+ /** Options for opening a document: kernel concerns (activate/name) + engine OpenOptions. */
162
+ type OpenDocumentOptions = OpenOptions & {
163
+ activate?: boolean;
164
+ name?: string;
165
+ };
166
+ /**
167
+ * What `open()` accepts: an engine `OpenInput`, or a thunk producing one.
168
+ * The thunk form makes the FETCH happen under the loading tab — the slot is
169
+ * reserved synchronously, then the thunk runs (network), then the engine
170
+ * opens. Prefer it for anything that isn't already in memory.
171
+ *
172
+ * The thunk receives an AbortSignal that fires if the tab is closed while
173
+ * the fetch is still running — pass it to `fetch()` so a closed tab stops
174
+ * the network work. Zero-argument thunks keep working unchanged.
175
+ */
176
+ type OpenSource = OpenInput | ((signal: AbortSignal) => OpenInput | Promise<OpenInput>);
177
+ /**
178
+ * One boot document for `documents.openAll()` — THE shared shape every
179
+ * framework adapter's `initialDocuments` input uses (adapters re-export it,
180
+ * never redefine it). `active` picks the selected tab (default: the first);
181
+ * all other open options (name, password, scope, identity, …) pass straight
182
+ * through to `open()`, so the declarative and imperative paths cannot drift.
183
+ */
184
+ type InitialDocument = {
185
+ source: OpenSource;
186
+ active?: boolean;
187
+ } & Omit<OpenDocumentOptions, 'activate'>;
188
+ interface DocumentsCapability {
189
+ open(input: OpenSource, options?: OpenDocumentOptions): Promise<string>;
190
+ /**
191
+ * Boot-open a batch: fires every `open()` WITHOUT awaiting, so each tab
192
+ * slot is reserved synchronously — all tabs exist immediately, in array
193
+ * order — and exactly ONE is selected (the `active` entry, else the
194
+ * first), decided at request time so a slow document can never steal
195
+ * focus. Failures surface as the tab's `error`/`locked` status, never as
196
+ * unhandled rejections. This is kernel-owned POLICY: adapters call this
197
+ * one line instead of each re-implementing activation and error handling.
198
+ */
199
+ openAll(docs: readonly InitialDocument[]): void;
200
+ /**
201
+ * Unlock a `locked` document with a password and promote it to `ready`.
202
+ * Rejects with the engine's DocPasswordIncorrect on a wrong password —
203
+ * the document stays locked and unlock can be called again. Identical
204
+ * behavior on the local (worker loads the parked bytes) and cloud
205
+ * (/access grant) engines.
206
+ */
207
+ unlock(id: string, input: {
208
+ password: string;
209
+ }): Promise<void>;
210
+ close(id: string): Promise<void>;
211
+ closeAll(): Promise<void>;
212
+ setActive(id: string): void;
213
+ activeId(): string | null;
214
+ list(): DocInfo[];
215
+ get(id: string): DocInfo | null;
216
+ has(id: string): boolean;
217
+ count(): number;
218
+ order(): string[];
219
+ /** Move a document (tab) to a new position in the order. */
220
+ move(id: string, toIndex: number): void;
221
+ /** Swap two documents (tabs) in the order. */
222
+ swap(a: string, b: string): void;
223
+ /**
224
+ * Save the COMPLETE document (base + layer) to PDF bytes. `mode` is
225
+ * `'incremental'` (append changes, original bytes preserved) or `'rewrite'`
226
+ * (flatten to a fresh PDF). Defaults to the active document.
227
+ */
228
+ download(id?: string, opts?: {
229
+ mode?: PdfSaveMode;
230
+ }): Promise<Uint8Array>;
231
+ /**
232
+ * Export JUST the document's LAYER artifact (re-openable via `OpenInputLayerBytes`).
233
+ * Rejects when the document was opened without a layer, or the engine can't
234
+ * export one (cloud manages layers server-side — `DocumentHandle.downloadLayer`
235
+ * is absent there). Defaults to the active document.
236
+ */
237
+ downloadLayer(id?: string): Promise<Uint8Array>;
238
+ }
239
+ /** Built-in token for the document registry capability (provided by the kernel). */
240
+ declare const DocumentsToken: CapabilityToken<DocumentsCapability>;
241
+ //#endregion
242
+ //#region src/kernel.d.ts
243
+ /** Kernel lifecycle. Monotonic: created → starting → started, then destroying →
244
+ * destroyed; `failed` is a terminal branch off starting. */
245
+ type KernelStatus = 'created' | 'starting' | 'started' | 'failed' | 'destroying' | 'destroyed';
246
+ interface Kernel {
247
+ readonly engine: Engine;
248
+ readonly documents: DocumentsCapability;
249
+ /** Resolve a capability. For document-scoped tokens, `documentId` defaults to the active doc. */
250
+ capability<T>(token: CapabilityToken<T>, documentId?: string): T;
251
+ /**
252
+ * Total sibling of `capability()`: `null` instead of throwing — no
253
+ * provider, no document, or a document that isn't `ready` yet. This is the
254
+ * method adapters subscribe to (`useKernelValue`-style): resolution is a
255
+ * VALUE derived from kernel state, not a pure function of its arguments —
256
+ * a pending document's promotion changes the result while the id stays the
257
+ * same, so caching a `capability()` call by id goes stale. The returned
258
+ * instance is reference-stable per (plugin, document), so equality-cached
259
+ * reads don't churn.
260
+ */
261
+ tryCapability<T>(token: CapabilityToken<T>, documentId?: string): T | null;
262
+ /** A token's scope — adapters use this to decide whether to bind a document. */
263
+ scopeOf(token: CapabilityToken<unknown>): PluginScope;
264
+ subscribe(listener: () => void): Unsubscribe;
265
+ getState(): GlobalState;
266
+ status(): KernelStatus;
267
+ /** Idempotent: a second call joins the first. Throws after destroy(). */
268
+ start(): Promise<void>;
269
+ /**
270
+ * Idempotent: every call returns the same promise. Joins an in-flight
271
+ * start(), closes every document (their engine handles included), then
272
+ * unwinds workspace resources. Never throws.
273
+ */
274
+ destroy(): Promise<void>;
275
+ }
276
+ /**
277
+ * Assemble a kernel from an engine + plugins.
278
+ *
279
+ * planPlugins — validate dependencies, order them
280
+ * resolveCapability — workspace singletons, or per-document instances built lazily
281
+ * document lifecycle — one DocumentSession per document: transactional open
282
+ * (publish-last), one idempotent close for every phase
283
+ * start / destroy — explicit status machine; destroy closes everything
284
+ *
285
+ * The kernel closes every handle it opened; it never destroys the engine —
286
+ * ownership follows acquisition, and the engine was handed in by the caller.
287
+ */
288
+ declare function createKernel(opts: {
289
+ engine: Engine;
290
+ plugins: AnyPlugin[];
291
+ /** Observability seam: teardown/effect/join failures land here. Default: console.error. */
292
+ report?: (error: unknown) => void;
293
+ }): Kernel;
294
+ //#endregion
295
+ //#region src/scope.d.ts
296
+ /**
297
+ * A lifecycle operation was cancelled — the tab was closed mid-open, or the
298
+ * kernel was destroyed mid-start. NOT a failure: callers that race `open()`
299
+ * against `close()` should treat this rejection as "the close won".
300
+ */
301
+ declare class CancelledError extends Error {
302
+ constructor(what: string);
303
+ }
304
+ declare const isCancelled: (error: unknown) => error is CancelledError;
305
+ //#endregion
306
+ //#region src/index.d.ts
307
+ /** Create a typed capability token. `name` is for debugging only. */
308
+ declare function createCapabilityToken<T>(name: string): CapabilityToken<T>;
309
+ /** Identity helper that pins a plugin's generics. The real win is inference. */
310
+ declare function definePlugin<S = unknown, A extends Action = Action, C = unknown>(def: PluginDef<S, A, C>): PluginDef<S, A, C>;
311
+ //#endregion
312
+ export { AbortablePromise, Action, AnyPlugin, CONTINUOUS_RENDER_POLICY, CORE_ACTIVE_CHANGED, CORE_DOCUMENT_ADDED, CORE_DOCUMENT_LOCKED, CORE_DOCUMENT_OPENING, CORE_DOCUMENT_OPEN_FAILED, CORE_DOCUMENT_PAGES_UPDATED, CORE_DOCUMENT_REMOVED, CORE_ORDER_CHANGED, CancelledError, CapabilityToken, CoreState, type DocCapability, DocInfo, DocStatus, type DocumentEvent, type DocumentHandle, DocumentMeta, type DocumentMetadata, DocumentsCapability, DocumentsToken, EffectContext, type Engine, type EngineFactory, type EngineRenderPolicy, GlobalState, InitialDocument, Kernel, KernelStatus, type MetadataPatch, type MetadataUpdateResult, OpenDocumentOptions, type OpenInput, type OpenOptions, OpenSource, type PageDeleteResult, type PageHandle, type PageImageHandle, type PageImageObjectUrl, type PageImageOptions, type PageLayout, type PageMoveResult, type PageObjectNumber, type PageRaster, type PageRenderOptions, type PageRenderTarget, type PageRenderViewport, type PageRotateResult, type PageRotation, type PdfDestination, type PdfRect, type PdfSaveMode, PendingMeta, PluginContext, PluginDef, PluginScope, Unsubscribe, createCapabilityToken, createKernel, definePlugin, docInfoEquals, docInfoListEquals, isCancelled, snapAppearanceScale, snapFullPageViewport, snapTileScale };
313
+ //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1 +1,313 @@
1
- export * from './lib';
1
+ import { AbortablePromise, CONTINUOUS_RENDER_POLICY, DocCapability, DocumentEvent, DocumentHandle, DocumentMetadata, Engine, EngineFactory, EngineRenderPolicy, EngineRenderPolicy as EngineRenderPolicy$1, MetadataPatch, MetadataUpdateResult, OpenInput, OpenOptions, PageDeleteResult, PageHandle, PageImageHandle, PageImageObjectUrl, PageImageOptions, PageLayout, PageMoveResult, PageObjectNumber, PageRaster, PageRenderOptions, PageRenderTarget, PageRenderViewport, PageRotateResult, PageRotation, PdfDestination, PdfRect, PdfSaveMode, snapAppearanceScale, snapFullPageViewport, snapTileScale } from "@embedpdf/engine-core/runtime";
2
+ //#region src/types.d.ts
3
+ type Unsubscribe = () => void;
4
+ /** Every state transition is a plain, serializable action. */
5
+ interface Action {
6
+ readonly type: string;
7
+ }
8
+ /** Kernel-emitted document-lifecycle actions; plugins may react via `onAction`. */
9
+ declare const CORE_DOCUMENT_ADDED = "@@core/document-added";
10
+ declare const CORE_DOCUMENT_REMOVED = "@@core/document-removed";
11
+ declare const CORE_ACTIVE_CHANGED = "@@core/active-changed";
12
+ declare const CORE_ORDER_CHANGED = "@@core/order-changed";
13
+ /** A document's page registry was replaced by a mutation event (rotate/move/delete). */
14
+ declare const CORE_DOCUMENT_PAGES_UPDATED = "@@core/document-pages-updated";
15
+ /** A tab slot was reserved: `open()` was called; the document is loading. */
16
+ declare const CORE_DOCUMENT_OPENING = "@@core/document-opening";
17
+ /** The engine reports the document needs a password (`documents.unlock`). */
18
+ declare const CORE_DOCUMENT_LOCKED = "@@core/document-locked";
19
+ /** The open failed; the tab stays with `status: 'error'` until closed. */
20
+ declare const CORE_DOCUMENT_OPEN_FAILED = "@@core/document-open-failed";
21
+ /** A typed handle to a capability — typed resolution, no string casts. */
22
+ interface CapabilityToken<T> {
23
+ readonly name: string;
24
+ /** phantom — never present at runtime */
25
+ readonly __type?: T;
26
+ }
27
+ /**
28
+ * What the kernel knows about an open document — the page registry captured at open.
29
+ * `pages` is the engine's own snapshot (`PageLayout`: index, pageObjectNumber, size,
30
+ * rotation, label, boxes). The `pageObjectNumber` (pon) is the durable per-page
31
+ * identity; the array index is only display order.
32
+ */
33
+ interface DocumentMeta {
34
+ readonly id: string;
35
+ readonly name?: string;
36
+ readonly pageCount: number;
37
+ readonly pages: readonly PageLayout[];
38
+ /**
39
+ * Bumps every time the page registry is replaced by a document mutation
40
+ * event (rotate/move/delete). The registry's monotonic version: anything
41
+ * caching a derivation of `pages` (e.g. the Stage's laid-out scene) keys
42
+ * on it so a same-`pageCount` change — like a rotation — still invalidates.
43
+ */
44
+ readonly revision: number;
45
+ /**
46
+ * The deployment render policy the document's engine advertises — a
47
+ * document FACT like `pages`, materialized by the kernel at open (before
48
+ * publish), NOT plugin state. One lifecycle (here), one interpretation
49
+ * (engine-core's pure `snap*` helpers); any plugin reads it. Engines
50
+ * without a render service — and failed policy reads — resolve to
51
+ * `continuous`, so consumers never branch on absence. Naming rule: the
52
+ * domain appears exactly once — bare `policy()` on the render SERVICE,
53
+ * `renderPolicy` on flat envelopes like this one and `/v1/access`.
54
+ */
55
+ readonly renderPolicy: EngineRenderPolicy$1;
56
+ }
57
+ /**
58
+ * A tab slot whose document is not (yet) real: still opening, waiting for a
59
+ * password, or failed. Lives beside `documents`, never inside it — plugins
60
+ * only ever see READY documents; pending slots are pure registry/UI state.
61
+ * Request-time lifecycle: `open()` reserves the slot (id, order position,
62
+ * activation) synchronously; only the content arrives at completion time.
63
+ */
64
+ interface PendingMeta {
65
+ readonly id: string;
66
+ readonly name?: string;
67
+ readonly status: 'loading' | 'locked' | 'error';
68
+ /** `locked` only: a password was supplied at open and rejected — the
69
+ * prompt should show its "incorrect password" copy, not "required". */
70
+ readonly passwordProvided?: boolean;
71
+ /** `error` only: what the open rejected with. Never carries a password. */
72
+ readonly error?: unknown;
73
+ }
74
+ /** The document registry — what document scope is built on. */
75
+ interface CoreState {
76
+ readonly documents: Readonly<Record<string, DocumentMeta>>;
77
+ readonly pending: Readonly<Record<string, PendingMeta>>;
78
+ /** THE tab strip: spans ready docs and pending slots, in request order. */
79
+ readonly order: readonly string[];
80
+ /** May point at a pending slot (a loading or locked tab can be selected). */
81
+ readonly activeId: string | null;
82
+ }
83
+ interface GlobalState {
84
+ readonly core: CoreState;
85
+ readonly plugins: Readonly<Record<string, unknown>>;
86
+ }
87
+ type PluginScope = 'workspace' | 'document';
88
+ /**
89
+ * The context a plugin receives. Document-scoped plugins get a context bound to a
90
+ * single document — `documentId`, `document()` (metadata), `doc` (the engine handle),
91
+ * and `get()` resolving document-scoped capabilities for it.
92
+ */
93
+ interface PluginContext<S, A extends Action = Action> {
94
+ readonly id: string;
95
+ readonly engine: Engine;
96
+ /** The bound document (document-scoped plugins only; undefined for workspace). */
97
+ readonly documentId?: string;
98
+ /** The bound document's engine handle; for workspace plugins, the active doc's handle, or null. */
99
+ readonly doc: DocumentHandle | null;
100
+ /** Resolve a live engine handle by document id; omitted follows this context's normal active/bound rule. */
101
+ documentHandle(documentId?: string): DocumentHandle | null;
102
+ getState(): S;
103
+ dispatch(action: A): void;
104
+ subscribe(listener: () => void): Unsubscribe;
105
+ core(): CoreState;
106
+ /** The bound document's metadata; for workspace plugins, the active doc's, or null. */
107
+ document(): DocumentMeta | null;
108
+ get<T>(token: CapabilityToken<T>): T;
109
+ forDocument<T>(token: CapabilityToken<T>, documentId: string): T;
110
+ tryGet<T>(token: CapabilityToken<T>): T | null;
111
+ /**
112
+ * Register a resource teardown owned by this plugin instance. Document-
113
+ * scoped callbacks run when that document closes; workspace callbacks run
114
+ * when the kernel is destroyed. Asynchronous teardowns are awaited.
115
+ * Registering after the owner is already disposed runs the teardown
116
+ * immediately instead of dropping it — a late registration cannot leak.
117
+ * Safe for capability-held timers, runtimes, subscriptions, object URLs,
118
+ * and binary caches.
119
+ */
120
+ cleanup(fn: () => void | Promise<void>): void;
121
+ }
122
+ /** Side-effect context: the only place async/IO/cross-plugin reactions live. */
123
+ interface EffectContext<S, A extends Action = Action> extends PluginContext<S, A> {
124
+ watch<R>(select: () => R, handler: (value: R, previous: R) => void, isEqual?: (a: R, b: R) => boolean): Unsubscribe;
125
+ onAction(type: string, handler: (action: Action) => void): Unsubscribe;
126
+ }
127
+ /**
128
+ * A plugin definition. `scope` decides multiplexing:
129
+ * 'workspace' (default) — one instance; can see every document.
130
+ * 'document' — one instance PER open document; authored single-document.
131
+ */
132
+ interface PluginDef<S = unknown, A extends Action = Action, C = unknown> {
133
+ readonly id: string;
134
+ readonly token?: CapabilityToken<C>;
135
+ readonly scope?: PluginScope;
136
+ readonly requires?: ReadonlyArray<CapabilityToken<unknown>>;
137
+ readonly optional?: ReadonlyArray<CapabilityToken<unknown>>;
138
+ readonly initialState?: S | (() => S);
139
+ readonly reduce?: (state: S, action: A) => S;
140
+ readonly capability?: (ctx: PluginContext<S, A>) => C;
141
+ readonly init?: (ctx: PluginContext<S, A>) => void | Promise<void>;
142
+ readonly effects?: (ctx: EffectContext<S, A>) => void;
143
+ }
144
+ type AnyPlugin = PluginDef<any, any, any>;
145
+ type DocStatus = 'loading' | 'locked' | 'ready' | 'error';
146
+ interface DocInfo {
147
+ id: string;
148
+ name?: string;
149
+ /** Lifecycle state — the tab bar renders directly off this. */
150
+ status: DocStatus;
151
+ /** 0 until the document is `ready`. */
152
+ pageCount: number;
153
+ /** `locked` only: a supplied password was rejected (show "incorrect"). */
154
+ passwordProvided?: boolean;
155
+ }
156
+ /** Field-wise DocInfo equality — the ONE definition every adapter's reactive
157
+ * `docs` read keys on, so a new lifecycle field can never silently stop
158
+ * re-rendering one framework's tab bar. */
159
+ declare const docInfoEquals: (a: DocInfo, b: DocInfo) => boolean;
160
+ declare const docInfoListEquals: (a: readonly DocInfo[], b: readonly DocInfo[]) => boolean;
161
+ /** Options for opening a document: kernel concerns (activate/name) + engine OpenOptions. */
162
+ type OpenDocumentOptions = OpenOptions & {
163
+ activate?: boolean;
164
+ name?: string;
165
+ };
166
+ /**
167
+ * What `open()` accepts: an engine `OpenInput`, or a thunk producing one.
168
+ * The thunk form makes the FETCH happen under the loading tab — the slot is
169
+ * reserved synchronously, then the thunk runs (network), then the engine
170
+ * opens. Prefer it for anything that isn't already in memory.
171
+ *
172
+ * The thunk receives an AbortSignal that fires if the tab is closed while
173
+ * the fetch is still running — pass it to `fetch()` so a closed tab stops
174
+ * the network work. Zero-argument thunks keep working unchanged.
175
+ */
176
+ type OpenSource = OpenInput | ((signal: AbortSignal) => OpenInput | Promise<OpenInput>);
177
+ /**
178
+ * One boot document for `documents.openAll()` — THE shared shape every
179
+ * framework adapter's `initialDocuments` input uses (adapters re-export it,
180
+ * never redefine it). `active` picks the selected tab (default: the first);
181
+ * all other open options (name, password, scope, identity, …) pass straight
182
+ * through to `open()`, so the declarative and imperative paths cannot drift.
183
+ */
184
+ type InitialDocument = {
185
+ source: OpenSource;
186
+ active?: boolean;
187
+ } & Omit<OpenDocumentOptions, 'activate'>;
188
+ interface DocumentsCapability {
189
+ open(input: OpenSource, options?: OpenDocumentOptions): Promise<string>;
190
+ /**
191
+ * Boot-open a batch: fires every `open()` WITHOUT awaiting, so each tab
192
+ * slot is reserved synchronously — all tabs exist immediately, in array
193
+ * order — and exactly ONE is selected (the `active` entry, else the
194
+ * first), decided at request time so a slow document can never steal
195
+ * focus. Failures surface as the tab's `error`/`locked` status, never as
196
+ * unhandled rejections. This is kernel-owned POLICY: adapters call this
197
+ * one line instead of each re-implementing activation and error handling.
198
+ */
199
+ openAll(docs: readonly InitialDocument[]): void;
200
+ /**
201
+ * Unlock a `locked` document with a password and promote it to `ready`.
202
+ * Rejects with the engine's DocPasswordIncorrect on a wrong password —
203
+ * the document stays locked and unlock can be called again. Identical
204
+ * behavior on the local (worker loads the parked bytes) and cloud
205
+ * (/access grant) engines.
206
+ */
207
+ unlock(id: string, input: {
208
+ password: string;
209
+ }): Promise<void>;
210
+ close(id: string): Promise<void>;
211
+ closeAll(): Promise<void>;
212
+ setActive(id: string): void;
213
+ activeId(): string | null;
214
+ list(): DocInfo[];
215
+ get(id: string): DocInfo | null;
216
+ has(id: string): boolean;
217
+ count(): number;
218
+ order(): string[];
219
+ /** Move a document (tab) to a new position in the order. */
220
+ move(id: string, toIndex: number): void;
221
+ /** Swap two documents (tabs) in the order. */
222
+ swap(a: string, b: string): void;
223
+ /**
224
+ * Save the COMPLETE document (base + layer) to PDF bytes. `mode` is
225
+ * `'incremental'` (append changes, original bytes preserved) or `'rewrite'`
226
+ * (flatten to a fresh PDF). Defaults to the active document.
227
+ */
228
+ download(id?: string, opts?: {
229
+ mode?: PdfSaveMode;
230
+ }): Promise<Uint8Array>;
231
+ /**
232
+ * Export JUST the document's LAYER artifact (re-openable via `OpenInputLayerBytes`).
233
+ * Rejects when the document was opened without a layer, or the engine can't
234
+ * export one (cloud manages layers server-side — `DocumentHandle.downloadLayer`
235
+ * is absent there). Defaults to the active document.
236
+ */
237
+ downloadLayer(id?: string): Promise<Uint8Array>;
238
+ }
239
+ /** Built-in token for the document registry capability (provided by the kernel). */
240
+ declare const DocumentsToken: CapabilityToken<DocumentsCapability>;
241
+ //#endregion
242
+ //#region src/kernel.d.ts
243
+ /** Kernel lifecycle. Monotonic: created → starting → started, then destroying →
244
+ * destroyed; `failed` is a terminal branch off starting. */
245
+ type KernelStatus = 'created' | 'starting' | 'started' | 'failed' | 'destroying' | 'destroyed';
246
+ interface Kernel {
247
+ readonly engine: Engine;
248
+ readonly documents: DocumentsCapability;
249
+ /** Resolve a capability. For document-scoped tokens, `documentId` defaults to the active doc. */
250
+ capability<T>(token: CapabilityToken<T>, documentId?: string): T;
251
+ /**
252
+ * Total sibling of `capability()`: `null` instead of throwing — no
253
+ * provider, no document, or a document that isn't `ready` yet. This is the
254
+ * method adapters subscribe to (`useKernelValue`-style): resolution is a
255
+ * VALUE derived from kernel state, not a pure function of its arguments —
256
+ * a pending document's promotion changes the result while the id stays the
257
+ * same, so caching a `capability()` call by id goes stale. The returned
258
+ * instance is reference-stable per (plugin, document), so equality-cached
259
+ * reads don't churn.
260
+ */
261
+ tryCapability<T>(token: CapabilityToken<T>, documentId?: string): T | null;
262
+ /** A token's scope — adapters use this to decide whether to bind a document. */
263
+ scopeOf(token: CapabilityToken<unknown>): PluginScope;
264
+ subscribe(listener: () => void): Unsubscribe;
265
+ getState(): GlobalState;
266
+ status(): KernelStatus;
267
+ /** Idempotent: a second call joins the first. Throws after destroy(). */
268
+ start(): Promise<void>;
269
+ /**
270
+ * Idempotent: every call returns the same promise. Joins an in-flight
271
+ * start(), closes every document (their engine handles included), then
272
+ * unwinds workspace resources. Never throws.
273
+ */
274
+ destroy(): Promise<void>;
275
+ }
276
+ /**
277
+ * Assemble a kernel from an engine + plugins.
278
+ *
279
+ * planPlugins — validate dependencies, order them
280
+ * resolveCapability — workspace singletons, or per-document instances built lazily
281
+ * document lifecycle — one DocumentSession per document: transactional open
282
+ * (publish-last), one idempotent close for every phase
283
+ * start / destroy — explicit status machine; destroy closes everything
284
+ *
285
+ * The kernel closes every handle it opened; it never destroys the engine —
286
+ * ownership follows acquisition, and the engine was handed in by the caller.
287
+ */
288
+ declare function createKernel(opts: {
289
+ engine: Engine;
290
+ plugins: AnyPlugin[];
291
+ /** Observability seam: teardown/effect/join failures land here. Default: console.error. */
292
+ report?: (error: unknown) => void;
293
+ }): Kernel;
294
+ //#endregion
295
+ //#region src/scope.d.ts
296
+ /**
297
+ * A lifecycle operation was cancelled — the tab was closed mid-open, or the
298
+ * kernel was destroyed mid-start. NOT a failure: callers that race `open()`
299
+ * against `close()` should treat this rejection as "the close won".
300
+ */
301
+ declare class CancelledError extends Error {
302
+ constructor(what: string);
303
+ }
304
+ declare const isCancelled: (error: unknown) => error is CancelledError;
305
+ //#endregion
306
+ //#region src/index.d.ts
307
+ /** Create a typed capability token. `name` is for debugging only. */
308
+ declare function createCapabilityToken<T>(name: string): CapabilityToken<T>;
309
+ /** Identity helper that pins a plugin's generics. The real win is inference. */
310
+ declare function definePlugin<S = unknown, A extends Action = Action, C = unknown>(def: PluginDef<S, A, C>): PluginDef<S, A, C>;
311
+ //#endregion
312
+ export { AbortablePromise, Action, AnyPlugin, CONTINUOUS_RENDER_POLICY, CORE_ACTIVE_CHANGED, CORE_DOCUMENT_ADDED, CORE_DOCUMENT_LOCKED, CORE_DOCUMENT_OPENING, CORE_DOCUMENT_OPEN_FAILED, CORE_DOCUMENT_PAGES_UPDATED, CORE_DOCUMENT_REMOVED, CORE_ORDER_CHANGED, CancelledError, CapabilityToken, CoreState, type DocCapability, DocInfo, DocStatus, type DocumentEvent, type DocumentHandle, DocumentMeta, type DocumentMetadata, DocumentsCapability, DocumentsToken, EffectContext, type Engine, type EngineFactory, type EngineRenderPolicy, GlobalState, InitialDocument, Kernel, KernelStatus, type MetadataPatch, type MetadataUpdateResult, OpenDocumentOptions, type OpenInput, type OpenOptions, OpenSource, type PageDeleteResult, type PageHandle, type PageImageHandle, type PageImageObjectUrl, type PageImageOptions, type PageLayout, type PageMoveResult, type PageObjectNumber, type PageRaster, type PageRenderOptions, type PageRenderTarget, type PageRenderViewport, type PageRotateResult, type PageRotation, type PdfDestination, type PdfRect, type PdfSaveMode, PendingMeta, PluginContext, PluginDef, PluginScope, Unsubscribe, createCapabilityToken, createKernel, definePlugin, docInfoEquals, docInfoListEquals, isCancelled, snapAppearanceScale, snapFullPageViewport, snapTileScale };
313
+ //# sourceMappingURL=index.d.ts.map