@embedpdf/engine-core 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 (55) hide show
  1. package/LICENSE +192 -0
  2. package/README.md +24 -0
  3. package/dist/AbortError-ByBflvEl.cjs +38 -0
  4. package/dist/AbortError-ByBflvEl.cjs.map +1 -0
  5. package/dist/AbortError-CjSasIlL.js +27 -0
  6. package/dist/AbortError-CjSasIlL.js.map +1 -0
  7. package/dist/AnnotationListSnapshot-W0RCsyDE.d.cts +5043 -0
  8. package/dist/AnnotationListSnapshot-W0RCsyDE.d.ts +5043 -0
  9. package/dist/DocumentSecurityService-B-tULKNY.d.ts +332 -0
  10. package/dist/DocumentSecurityService-Df79fgpe.d.cts +332 -0
  11. package/dist/Engine-B7Oe7f5i.d.ts +1013 -0
  12. package/dist/Engine-D9loFZc1.d.cts +1013 -0
  13. package/dist/builders-BvikWRuO.cjs +1684 -0
  14. package/dist/builders-BvikWRuO.cjs.map +1 -0
  15. package/dist/builders-C548U47M.js +1367 -0
  16. package/dist/builders-C548U47M.js.map +1 -0
  17. package/dist/conformance.cjs +5414 -0
  18. package/dist/conformance.cjs.map +1 -0
  19. package/dist/conformance.d.cts +530 -0
  20. package/dist/conformance.d.ts +530 -0
  21. package/dist/conformance.js +5394 -0
  22. package/dist/conformance.js.map +1 -0
  23. package/dist/fold-CB4fAOOy.js +175 -0
  24. package/dist/fold-CB4fAOOy.js.map +1 -0
  25. package/dist/fold-IaMph3CO.cjs +216 -0
  26. package/dist/fold-IaMph3CO.cjs.map +1 -0
  27. package/dist/index.cjs +82 -0
  28. package/dist/index.d.cts +2 -0
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.js +5 -0
  31. package/dist/resolver-DAZWVoJL.cjs +434 -0
  32. package/dist/resolver-DAZWVoJL.cjs.map +1 -0
  33. package/dist/resolver-DiPMTfcy.js +363 -0
  34. package/dist/resolver-DiPMTfcy.js.map +1 -0
  35. package/dist/runtime.cjs +453 -0
  36. package/dist/runtime.cjs.map +1 -0
  37. package/dist/runtime.d.cts +1002 -0
  38. package/dist/runtime.d.ts +1002 -0
  39. package/dist/runtime.js +361 -0
  40. package/dist/runtime.js.map +1 -0
  41. package/dist/schemas-9OpSSeM6.js +2493 -0
  42. package/dist/schemas-9OpSSeM6.js.map +1 -0
  43. package/dist/schemas-B_1VyFsm.cjs +3608 -0
  44. package/dist/schemas-B_1VyFsm.cjs.map +1 -0
  45. package/dist/subtype-BvAzLCGC.js +196 -0
  46. package/dist/subtype-BvAzLCGC.js.map +1 -0
  47. package/dist/subtype-qejjVr6h.cjs +231 -0
  48. package/dist/subtype-qejjVr6h.cjs.map +1 -0
  49. package/dist/wire.cjs +1516 -0
  50. package/dist/wire.cjs.map +1 -0
  51. package/dist/wire.d.cts +1546 -0
  52. package/dist/wire.d.ts +1546 -0
  53. package/dist/wire.js +1280 -0
  54. package/dist/wire.js.map +1 -0
  55. package/package.json +74 -0
@@ -0,0 +1,1013 @@
1
+ import { Aa as EmbeddedFileItem, Ai as AnnotationCreateResult, Ao as PageImageHandle, Ar as FormFieldDeleteResult, Bo as PageRenderOptions, Di as FormWidgetRef, Ea as AttachmentContent, Ei as FormFieldRef, Fn as RedactionApplyScope, Fr as FormWidgetLinkResult, Gn as PageRotateResult, Gr as FormFieldPatch, Hn as PageInsertResult, Hr as FormFieldValue, Io as PageRaster, Ir as FormEffect, Jn as PageMoveResult, Jo as PageTextSnapshot, Mc as DocumentActionsSnapshot, Mi as AnnotationMoveResult, Mn as MetadataUpdateResult, Mo as PageImageOptions, Mr as FormImportResult, Ni as AnnotationUpdateResult, Nr as FormRepairResult, Or as FormDataExport, Pn as RedactionApplyResult, Pr as FormSetValueResult, So as AnnotationAppearanceRenderOptions, Tr as SearchSlice, Un as PageDeleteResult, Uo as PageRenderViewport, Vc as DocumentMetadata, Vn as PageFlattenUsage, Vr as FormDataFormat, Zr as FormFieldDraft, Zs as AnnotationRef, _o as AnnotationAppearanceImagesResult, _s as OpenOptions, do as FontSpec, ds as OpenInput, ec as PageObjectNumber, go as AnnotationAppearanceImageOptions, ii as FormSnapshot, ja as EmbeddedFileRef, ji as AnnotationDeleteResult, jr as FormFieldUpdateResult, ka as AttachmentFileSource, kc as PdfRotation, kr as FormFieldCreateResult, l as AnnotationPatch, la as AttachmentCreateResult, lo as FontHandle, n as AnnotationListSnapshotAllPages, o as AnnotationDraft, os as PageListSnapshot, pi as FormFieldDTO, po as PdfSaveMode, qo as PageGeometrySnapshot, t as AnnotationListPageSnapshot, ua as AttachmentDeleteResult, uo as FontKey, us as MetadataPatch, wo as AnnotationAppearancesResult, wr as SearchRequest, zn as PageFlattenResult, zr as FormEffectsResult } from "./AnnotationListSnapshot-W0RCsyDE.cjs";
2
+ import { g as AbortablePromise, s as DocumentSecurityService } from "./DocumentSecurityService-Df79fgpe.cjs";
3
+ //#region src/engine/DocumentActionsService.d.ts
4
+ /** Lazy, catalog-owned PDF action read. This API extracts; it never executes. */
5
+ interface DocumentActionsService {
6
+ read(): AbortablePromise<DocumentActionsSnapshot>;
7
+ }
8
+ //#endregion
9
+ //#region src/engine/DocumentAnnotationsService.d.ts
10
+ interface WeakAnnotationEditSession {
11
+ readonly id: string;
12
+ readonly expiresAt: number;
13
+ readonly heartbeatIntervalMs: number;
14
+ readonly pageObjectNumbers: readonly PageObjectNumber[];
15
+ covers(pageObjectNumber: PageObjectNumber): boolean;
16
+ updatePages(pageObjectNumbers: readonly PageObjectNumber[]): AbortablePromise<void>;
17
+ heartbeat(): AbortablePromise<void>;
18
+ release(): AbortablePromise<void>;
19
+ }
20
+ /**
21
+ * Document-scoped annotation service exposed via
22
+ * `DocumentHandle.annotations`. The two read paths matter:
23
+ *
24
+ * `listRawAll()` - whole-doc raw read. No `pagePtr` is acquired; uses
25
+ * `EPDFPage_GetAnnotCountRaw` + `EPDFPage_GetAnnotRaw`.
26
+ * Cheapest possible path; ideal for "do anything with
27
+ * a document" UX where the caller wants to know what's
28
+ * where but does not need full per-subtype fields yet.
29
+ *
30
+ * `listRaw(p)` - single-page raw read. Same fast path scoped to one
31
+ * page, by PDF object number.
32
+ *
33
+ * The slow per-subtype `pagePtr`-driven read lives on
34
+ * `PageAnnotationsService.list()`.
35
+ */
36
+ interface DocumentAnnotationsService {
37
+ listRawAll(): AbortablePromise<AnnotationListSnapshotAllPages>;
38
+ listRaw(pageObjectNumber: PageObjectNumber): AbortablePromise<AnnotationListPageSnapshot>;
39
+ beginWeakEdit(pageObjectNumbers: readonly PageObjectNumber[]): AbortablePromise<WeakAnnotationEditSession>;
40
+ }
41
+ //#endregion
42
+ //#region src/engine/DocumentAttachmentsService.d.ts
43
+ /**
44
+ * Document-level attachments: the catalog's `/EmbeddedFiles` name tree
45
+ * (ISO 32000 §7.11.4). Exposed via `DocumentHandle.attachments`.
46
+ *
47
+ * Addressing is by name-tree KEY (`EmbeddedFileRef`) — unique by
48
+ * construction, so there is no weak/index tier and no revision to
49
+ * validate (see the ref's doc comment). `list()` returns metadata only;
50
+ * bytes leave the engine exclusively through {@link download}. The
51
+ * annotation-level counterpart is
52
+ * `PageAnnotationsService.downloadFile(ref)`.
53
+ *
54
+ * `create`/`delete` are optional (the `downloadLayer?` pattern) while
55
+ * transports ship — feature-detect with `attachments.create !== undefined`.
56
+ */
57
+ interface DocumentAttachmentsService {
58
+ /** Snapshot of the `/EmbeddedFiles` name tree, in tree (key-sorted) order. */
59
+ list(): AbortablePromise<EmbeddedFileItem[]>;
60
+ /**
61
+ * Decode and return one embedded file's bytes plus the metadata needed
62
+ * to hand it to a user (name, mime type). Throws
63
+ * `EngineError(NotFound)` when no entry has the ref's key and
64
+ * `EngineError(InvalidArg)` when the entry has no embedded file stream.
65
+ */
66
+ download(ref: EmbeddedFileRef): AbortablePromise<AttachmentContent>;
67
+ /**
68
+ * Create an embedded file in the name tree. The file's `name` becomes
69
+ * the tree key (`/UF` = `/F` = key); a duplicate key rejects with
70
+ * `EngineError(InvalidArg)` — rename and retry. A MUTATION: layer
71
+ * sessions persist an artifact and an `attachment.created` event is
72
+ * published. Note the tree is key-sorted, so other entries' indices
73
+ * may shift; keys never move.
74
+ */
75
+ create?(file: AttachmentFileSource): AbortablePromise<AttachmentCreateResult>;
76
+ /**
77
+ * Delete an embedded file from the name tree. Unlinks the entry only —
78
+ * the stream bytes remain in the document until a full rewrite (the
79
+ * immutable-base/layer model). Throws `EngineError(NotFound)` for an
80
+ * unknown key. A MUTATION: layer sessions persist an artifact and an
81
+ * `attachment.deleted` event is published.
82
+ */
83
+ delete?(ref: EmbeddedFileRef): AbortablePromise<AttachmentDeleteResult>;
84
+ }
85
+ //#endregion
86
+ //#region src/engine/DocumentFormsService.d.ts
87
+ /** Options for {@link DocumentFormsService.repair}. */
88
+ interface FormRepairOptions {
89
+ /**
90
+ * Also regenerate widget appearance streams: widgets with no /AP get
91
+ * one, and when the /AcroForm sets /NeedAppearances every widget is
92
+ * re-baked and the flag cleared, making rendering deterministic across
93
+ * viewers.
94
+ */
95
+ bakeAppearances?: boolean;
96
+ }
97
+ /**
98
+ * The document's interactive form: a document-scoped record system where
99
+ * fields hold the values and widget annotations are their page-scoped
100
+ * views. Filling mutates the field plane; rendering only ever reads the
101
+ * widget plane (through the annotation subsystem — join widgets to
102
+ * annotations via `FormFieldWidget.annotObjectNumber`).
103
+ *
104
+ * Reads are gated by `doc.forms.read`, value writes and imports by
105
+ * `doc.forms.fill`, and repair by `doc.forms.modify`. On layer documents
106
+ * every write lands as a minimal delta over the shared immutable base — a
107
+ * filled form layer is semantically an FDF diff.
108
+ */
109
+ interface DocumentFormsService {
110
+ /**
111
+ * The complete reconciled form state: every terminal field with its
112
+ * effective value, options, and widgets. Fields broken producers left
113
+ * out of /AcroForm /Fields are included with `origin: 'recovered'`.
114
+ */
115
+ list(): AbortablePromise<FormSnapshot>;
116
+ /**
117
+ * One field by ref. Prefer `objectNumber` refs (durable); `fqn` refs
118
+ * resolve against the current field tree. Fails with `NotFound` when
119
+ * the ref matches nothing.
120
+ */
121
+ get(ref: FormFieldRef): AbortablePromise<FormFieldDTO>;
122
+ /**
123
+ * Write one field's value. The value's `type` must match the field
124
+ * family (see {@link FormFieldValue}). Validation happens before any
125
+ * write — a failed call leaves the document untouched. Appearance
126
+ * streams regenerate for text/choice widgets; toggles flip their
127
+ * appearance state. Emits `form.valueChanged`.
128
+ */
129
+ setValue(ref: FormFieldRef, value: FormFieldValue): AbortablePromise<FormSetValueResult>;
130
+ /**
131
+ * Restore a field to its default value (/DV), or clear it when no
132
+ * default exists. Emits `form.valueChanged`.
133
+ */
134
+ reset(ref: FormFieldRef): AbortablePromise<FormSetValueResult>;
135
+ /**
136
+ * Apply one script run's ordered effects as one worker/cloud job. The batch
137
+ * is not rollback-atomic. All references are preflighted before writes;
138
+ * after a post-preflight internal failure the remaining effects are marked
139
+ * skipped and any landed state is finalized as one artifact/event/version.
140
+ */
141
+ applyEffects?(effects: FormEffect[]): AbortablePromise<FormEffectsResult>;
142
+ /**
143
+ * Serialize the form data for interchange. Defaults to `'xfdf'` (the
144
+ * XML sibling; UTF-8, friendliest to web pipelines) — pass `'fdf'` for
145
+ * the PDF-native container. Exports read the same reconciled view as
146
+ * `list()`, so recovered fields are included and, on layer documents,
147
+ * filled values win over the base.
148
+ */
149
+ exportData(format?: FormDataFormat): AbortablePromise<FormDataExport>;
150
+ /**
151
+ * Apply an FDF or XFDF payload. The format is sniffed from the bytes
152
+ * when `format` is omitted. Each entry replays through the same typed,
153
+ * validated write path as `setValue` — one bad entry is skipped and
154
+ * counted, never fatal. Emits `form.imported`.
155
+ */
156
+ importData(data: Uint8Array | ArrayBuffer, format?: FormDataFormat): AbortablePromise<FormImportResult>;
157
+ /**
158
+ * Create a logical form field, optionally with styled widgets, in one
159
+ * atomic job. Widgets are born through the annotation plane and adopted
160
+ * (see {@link attachWidget}); the inline `widget(s)` config is sugar for
161
+ * exactly that composition. Gated by `doc.forms.modify`. Emits
162
+ * `form.fieldCreated`.
163
+ */
164
+ createField(draft: FormFieldDraft): AbortablePromise<FormFieldCreateResult>;
165
+ /**
166
+ * Update field-plane properties (name, universal and family flags,
167
+ * options, default value, names). The patch's `family` must match the
168
+ * target field. Validate-then-apply per property. Emits
169
+ * `form.fieldUpdated`.
170
+ */
171
+ updateField(ref: FormFieldRef, patch: FormFieldPatch): AbortablePromise<FormFieldUpdateResult>;
172
+ /**
173
+ * Delete a terminal field and cascade: every widget is removed from its
174
+ * page, the field leaves the tree, and empty ancestors are pruned.
175
+ * Emits `form.fieldDeleted`.
176
+ */
177
+ deleteField(ref: FormFieldRef): AbortablePromise<FormFieldDeleteResult>;
178
+ /**
179
+ * Adopt an existing, unattached widget annotation as a view of the
180
+ * field. `onState` names the checked appearance state and is required
181
+ * for radio groups (checkboxes default to "Yes"). Attaching into a
182
+ * legacy merged field splits it — the FIELD object number never
183
+ * changes; widget identity may. Emits `form.widgetAttached`.
184
+ */
185
+ attachWidget(ref: FormFieldRef, widget: FormWidgetRef, options?: {
186
+ onState?: string;
187
+ }): AbortablePromise<FormWidgetLinkResult>;
188
+ /**
189
+ * The inverse of {@link attachWidget}: the widget keeps its page
190
+ * placement and last appearance but becomes an ordinary, inert
191
+ * annotation (deletable through the annotation APIs). The field
192
+ * survives, "unplaced" when this was its last widget. Emits
193
+ * `form.widgetDetached`.
194
+ */
195
+ detachWidget(ref: FormFieldRef, widget: FormWidgetRef): AbortablePromise<FormWidgetLinkResult>;
196
+ /**
197
+ * Make the engine's read-time reconciliation durable in the document
198
+ * ("form doctor"): bootstrap a missing /AcroForm, link recovered field
199
+ * roots into /Fields, re-attach stray widgets to their parent's /Kids,
200
+ * and optionally bake appearances. Validate-then-apply and idempotent —
201
+ * a second call reports zero fixes. Emits `form.repaired`.
202
+ */
203
+ repair(options?: FormRepairOptions): AbortablePromise<FormRepairResult>;
204
+ }
205
+ //#endregion
206
+ //#region src/engine/DocumentPagesService.d.ts
207
+ /**
208
+ * Document-scoped page service exposed via `DocumentHandle.pages`.
209
+ *
210
+ * Mirrors the shape of `DocumentAnnotationsService` so that anything
211
+ * touching "many things at the document level" lives in one place. The
212
+ * structure verbs are `move`, `rotate`, and `delete`; the surface is
213
+ * designed for `insert` to slot in without API churn.
214
+ *
215
+ * Identity rule: pages are addressed by indirect `pageObjectNumber`
216
+ * everywhere except `list()`, which exposes display order through
217
+ * `PageState.pageIndex`. There is no "weak page ref" model — structure
218
+ * verbs therefore do not bump per-page revisions and do not invalidate
219
+ * any in-flight annotation refs on surviving pages.
220
+ */
221
+ interface DocumentPagesService {
222
+ /**
223
+ * Snapshot of every page in display order. Cheap; never acquires a
224
+ * `pagePtr`.
225
+ */
226
+ list(): AbortablePromise<PageListSnapshot>;
227
+ /**
228
+ * Reorder pages. The supplied pages are detached and re-inserted as
229
+ * a contiguous block starting at `destIndex` in the post-removal
230
+ * index space, preserving caller order. Per-page `RevisionToken`s
231
+ * survive — index-based annotation refs the caller is holding remain
232
+ * valid across a page reorder.
233
+ *
234
+ * @param pageObjectNumbers Pages to move, in the order they should
235
+ * appear after the move.
236
+ * @param destIndex Insertion point in `[0, pageCount - len]`.
237
+ */
238
+ move(pageObjectNumbers: PageObjectNumber[], destIndex: number): AbortablePromise<PageMoveResult>;
239
+ /**
240
+ * Set the ABSOLUTE display rotation of the supplied pages (one value
241
+ * for all — the multi-select thumbnail gesture). Pure presentation
242
+ * metadata: content coordinates are normalized, so cached renders,
243
+ * annotation refs, and `RevisionToken`s all survive untouched. See
244
+ * `PageRotateInput` for why the wire is absolute, never relative.
245
+ */
246
+ rotate(pageObjectNumbers: PageObjectNumber[], rotation: PdfRotation): AbortablePromise<PageRotateResult>;
247
+ /**
248
+ * Delete pages. Deleting every page is rejected (`InvalidArg`) — a
249
+ * document must keep at least one. Deleted PONs are retired, never
250
+ * recycled; surviving pages keep their identity and revisions.
251
+ */
252
+ delete(pageObjectNumbers: PageObjectNumber[]): AbortablePromise<PageDeleteResult>;
253
+ /**
254
+ * Paint eligible annotation appearances into page content and remove only
255
+ * those annotations that were painted. This changes content and annotation
256
+ * liveness, not layout. The default usage is normal display.
257
+ */
258
+ flatten?(pageObjectNumbers: PageObjectNumber[], usage?: PageFlattenUsage): AbortablePromise<PageFlattenResult>;
259
+ /**
260
+ * Export the given pages, in the supplied order, as a standalone PDF
261
+ * (bytes of a new document containing copies of those pages). A READ:
262
+ * the source document is untouched — no revisions bump, no event is
263
+ * published. This is how a page becomes a portable asset (a vector
264
+ * stamp, a signature) that re-enters a document as a stamp draft's
265
+ * `source` bytes.
266
+ *
267
+ * Optional while the cloud endpoint ships (the `downloadLayer?`
268
+ * pattern): the local engine implements it; the cloud engine omits it
269
+ * until the server exposes extraction. Feature-detect with
270
+ * `pages.extract !== undefined`.
271
+ */
272
+ extract?(pageObjectNumbers: PageObjectNumber[]): AbortablePromise<Uint8Array>;
273
+ /**
274
+ * Insert every page of a standalone PDF (`bytes`) at `destIndex`
275
+ * (omitted → append). The pages are COPIED in; the inserted copies get
276
+ * fresh object numbers, returned in insertion order. Bytes are a call
277
+ * ARGUMENT (the same law as annotation binaries): the local engine
278
+ * transfers them to its worker, the cloud engine will ship them as a
279
+ * multipart mutation.
280
+ *
281
+ * Slated REQUIRED-parity (a cloud viewer must be able to add pages);
282
+ * optional only until the server endpoint ships — feature-detect with
283
+ * `pages.insert !== undefined`.
284
+ */
285
+ insert?(bytes: Uint8Array | ArrayBuffer, destIndex?: number): AbortablePromise<PageInsertResult>;
286
+ }
287
+ //#endregion
288
+ //#region src/engine/DocumentRedactionService.d.ts
289
+ /**
290
+ * The destructive half of the two-stage redaction model (ISO 32000-2
291
+ * 12.5.6.23). MARKING is annotation-plane work: a `redact` annotation rides
292
+ * the normal create/update/delete verbs and destroys nothing. APPLYING —
293
+ * this service — permanently removes the content under each marked region,
294
+ * paints the configured overlay in its place, and removes the consumed
295
+ * REDACT annotations along with any annotation intersecting the region.
296
+ *
297
+ * Trust boundary (deliberate, documented): on a layered document, apply
298
+ * rewrites THIS LAYER's bytes only. The immutable base document still
299
+ * contains the original content — byte-perfect original recovery is a
300
+ * feature of the storage model, not a leak. Redacted content becomes truly
301
+ * unrecoverable only in what leaves the system: a layer download/export, or
302
+ * a local document saved after apply. Surfaces that promise "permanent
303
+ * removal" must scope that promise to the exported artifact.
304
+ *
305
+ * Applying is irreversible within the layer (no undo). Emits a
306
+ * `redaction.applied` document event; content-scope raster invalidation and
307
+ * search-corpus refresh ride the normal content-version machinery.
308
+ */
309
+ interface DocumentRedactionService {
310
+ /**
311
+ * Apply redactions in `scope`. Ordered batch verb: pages are processed
312
+ * independently and a failed page is recorded in its item result rather
313
+ * than throwing after the first native write; `unchanged` means the page
314
+ * had no matching REDACT annotation. Returns no `meta` only when nothing
315
+ * changed.
316
+ */
317
+ apply(scope: RedactionApplyScope): AbortablePromise<RedactionApplyResult>;
318
+ }
319
+ //#endregion
320
+ //#region src/engine/DocumentRenderService.d.ts
321
+ /**
322
+ * The engine's render-parameter policy.
323
+ *
324
+ * - `continuous` — any viewport renders exactly as requested. The LOCAL
325
+ * engine always answers this: rendering is in-process, there is no
326
+ * shared cache to protect, and exactness is the local product promise.
327
+ * - `lattice` — the deployment treats a finite set of render points as
328
+ * durable, CDN-shared artifacts. The bounded quantity
329
+ * is OUTPUT PIXELS, never zoom:
330
+ *
331
+ * - `fullPage.widths` — full-page renders quantize on `viewport.width`
332
+ * (a scale lattice bounds artifact COUNT but not SIZE: PDF page space
333
+ * is effectively unbounded, so scale 1 of a poster page is a memory
334
+ * bomb while width caps the dominant dimension by construction).
335
+ * - `tiles` — RESERVED for the deep-zoom vertical: a scale-based
336
+ * pyramid × fixed tile size, where per-job cost is constant. Absent
337
+ * until the tiling plugin ships; reserving the shape keeps the SDK
338
+ * contract from churning twice.
339
+ * - `maxRenderPixels` — the worker-side output budget for degenerate
340
+ * geometry (width bounds width, not height).
341
+ *
342
+ * The SDK never conforms a request implicitly — the same `render.image`
343
+ * call must not return different pixels on local vs cloud. Conformance is
344
+ * the caller's visible choice via {@link snapFullPageViewport}.
345
+ */
346
+ type EngineRenderPolicy = {
347
+ readonly kind: 'continuous';
348
+ } | {
349
+ readonly kind: 'lattice';
350
+ readonly fullPage: {
351
+ readonly widths: readonly number[];
352
+ };
353
+ readonly tiles?: {
354
+ readonly tileSizes: readonly number[];
355
+ readonly scales: readonly number[];
356
+ };
357
+ /**
358
+ * Annotation-appearance lattice — SCALE-based, unlike full pages:
359
+ * an appearance is sized by `annotation.rect × scale`, rects span
360
+ * orders of magnitude (a 4pt caret vs a page-sized stamp), and the
361
+ * composite must track the PAGE's effective render scale or
362
+ * annotations sit blurry on a crisp raster. Small images → the
363
+ * ladder affords finer, taller steps than pages ever could.
364
+ */
365
+ readonly appearances?: {
366
+ readonly scales: readonly number[];
367
+ };
368
+ readonly maxRenderPixels?: number;
369
+ readonly formats: readonly ('webp' | 'png')[];
370
+ readonly background: 'white';
371
+ readonly enforced: boolean;
372
+ };
373
+ declare const CONTINUOUS_RENDER_POLICY: EngineRenderPolicy;
374
+ /**
375
+ * Document-scoped render policy surface (`doc.render`). Async because the
376
+ * cloud engine learns its policy from `/v1/access`; the local engine
377
+ * resolves immediately with `continuous`.
378
+ *
379
+ * Per-page rendering itself stays on `page(pon).render` — this service
380
+ * carries POLICY, not pixels.
381
+ */
382
+ interface DocumentRenderService {
383
+ policy(): Promise<EngineRenderPolicy>;
384
+ }
385
+ /**
386
+ * Conform a FULL-PAGE viewport to a render policy — the ONE snap
387
+ * implementation, shared by every engine and plugin. Pure and explicit
388
+ * by design:
389
+ *
390
+ * - `continuous` → identity (local/cloud plugin code stays byte-identical).
391
+ * - `lattice` → returns a `width`-kind viewport at the smallest ladder
392
+ * width ≥ the requested detail (snap UP: always crisp, CSS downscales
393
+ * for free), capped at the largest width — detail beyond the cap is the
394
+ * tile pyramid's job, by design.
395
+ * - `scale`-kind requests convert through the page's width in PDF user
396
+ * units — pass `opts.pageWidth` (the caller has it from the layout);
397
+ * omitting it for a scale viewport under a lattice policy is a
398
+ * programmer error and throws `InvalidArg`.
399
+ */
400
+ declare function snapFullPageViewport(policy: EngineRenderPolicy, viewport: PageRenderViewport, opts?: {
401
+ pageWidth?: number;
402
+ }): PageRenderViewport;
403
+ /**
404
+ * Conform an annotation-appearance scale to the policy's appearance
405
+ * lattice. Same discipline as {@link snapFullPageViewport}: identity on
406
+ * continuous (and when the policy carries no appearance block), snap UP,
407
+ * cap at the largest point. Callers derive `scale` from the page's
408
+ * effective render scale (`snappedWidth / pageWidth`, × devicePixelRatio
409
+ * as needed) so composites stay crisp against the page raster.
410
+ */
411
+ declare function snapAppearanceScale(policy: EngineRenderPolicy, scale: number): number;
412
+ /**
413
+ * Conform a tile-pyramid scale to the policy's tile lattice — the third
414
+ * member of the `snap<PolicyBlock><Quantity>` family. Identity on
415
+ * continuous and while the deployment doesn't advertise a `tiles` block
416
+ * (the block is reserved until the deep-zoom vertical ships server-side;
417
+ * the tiling client uses its own default pyramid then — see
418
+ * plugin-render). Snap UP, cap at the largest scale: per-tile cost is
419
+ * constant by construction (`tileSize²` pixels regardless of level), so
420
+ * the cap bounds artifact COUNT, not memory.
421
+ */
422
+ declare function snapTileScale(policy: EngineRenderPolicy, scale: number): number;
423
+ //#endregion
424
+ //#region src/engine/DocumentSearchService.d.ts
425
+ /**
426
+ * Document-scoped text search, exposed via `DocumentHandle.search`.
427
+ *
428
+ * The contract is a client-driven cursor loop over bounded slices: each
429
+ * `query()` call scans at most a budgeted amount of work (pages/matches)
430
+ * and returns what it found plus a resume cursor. There is no job to
431
+ * start or cancel — a 40K-page document is searched by asking for slices
432
+ * until `nextCursor` is null or the user stops caring. Engines clamp the
433
+ * requested budget to their own ceilings, so no single call can hold a
434
+ * worker (or the server) for minutes.
435
+ *
436
+ * Reads are gated by `doc.text.search`; `mode: 'full'` (snippets) also
437
+ * requires `doc.text.copy` — see {@link SearchMode}. Results always
438
+ * reflect the CURRENT layer view: text removed by redaction in this
439
+ * layer is unfindable, and a cursor issued before a content mutation is
440
+ * rejected rather than resumed over stale pages.
441
+ *
442
+ * Matches carry merged line rects from the same line-merge as text
443
+ * selection (never per-glyph boxes) and text-page character offsets that
444
+ * join the selection/geometry subsystem directly.
445
+ */
446
+ interface DocumentSearchService {
447
+ query(request: SearchRequest): AbortablePromise<SearchSlice>;
448
+ }
449
+ //#endregion
450
+ //#region src/engine/MetadataService.d.ts
451
+ interface MetadataService {
452
+ read(): AbortablePromise<DocumentMetadata>;
453
+ /**
454
+ * Rewrite the document Info dict via a three-state {@link MetadataPatch}
455
+ * (undefined=leave, null=clear, value=set). Returns the re-read metadata
456
+ * plus cloud coherence pins (`null` for local engines). Gated by
457
+ * `doc.metadata.modify` on the cloud.
458
+ */
459
+ update(patch: MetadataPatch): AbortablePromise<MetadataUpdateResult>;
460
+ }
461
+ //#endregion
462
+ //#region src/engine/PageAnnotationsService.d.ts
463
+ /**
464
+ * Per-page annotation service exposed via `PageHandle.annotations`.
465
+ *
466
+ * `list()` is the slow path: the engine acquires a `pagePtr` from the
467
+ * `PagePtrPool`, dispatches per-subtype readers, and returns
468
+ * fully-typed annotations. Mutations all funnel through this service
469
+ * because they need a `pagePtr` anyway.
470
+ *
471
+ * Mutation methods are typed in this slice but throw
472
+ * `EngineError(NotImplemented)` until the next slice. The signatures are
473
+ * stable so client code can be written against them today.
474
+ */
475
+ interface PageAnnotationsService {
476
+ list(): AbortablePromise<AnnotationListPageSnapshot>;
477
+ /**
478
+ * Batch-render every annotation appearance (`/AP`) stream on the page into
479
+ * its own raw RGBA raster, sized to the annotation's `/Rect`. Read-only and
480
+ * gated by `doc.annotate.read` — reading an annotation implies you may see
481
+ * its rendered appearance (the Adobe boundary).
482
+ *
483
+ * Cloud engines do not expose the raw rasters (the HTTP surface ships
484
+ * encoded images); use {@link renderAppearanceImages} there instead.
485
+ */
486
+ renderAppearances(options?: AnnotationAppearanceRenderOptions): AbortablePromise<AnnotationAppearancesResult>;
487
+ /**
488
+ * Encoded counterpart of {@link renderAppearances}: each raster is run
489
+ * through the engine's image encoder (local) or fetched as a
490
+ * `multipart/form-data` body (cloud) and returned as a lazily-resolved
491
+ * `PageImageHandle`. This is the cross-engine portable surface.
492
+ */
493
+ renderAppearanceImages(options?: AnnotationAppearanceImageOptions): AbortablePromise<AnnotationAppearanceImagesResult>;
494
+ /**
495
+ * Decode and return the file embedded in a FileAttachment annotation
496
+ * (its `/FS` filespec). A read — listings carry the file's metadata
497
+ * (`FileAttachmentAnnotationDTO.file`); this is the explicit bytes-out
498
+ * call. Optional while the cloud endpoint ships (the `extract?`
499
+ * pattern); feature-detect with `annotations.downloadFile !== undefined`.
500
+ * Throws `EngineError(InvalidArg)` when the annotation is not a
501
+ * file-attachment or has no embedded file stream.
502
+ */
503
+ downloadFile?(ref: AnnotationRef): AbortablePromise<AttachmentContent>;
504
+ create(draft: AnnotationDraft): AbortablePromise<AnnotationCreateResult>;
505
+ update(ref: AnnotationRef, patch: AnnotationPatch): AbortablePromise<AnnotationUpdateResult>;
506
+ delete(ref: AnnotationRef): AbortablePromise<AnnotationDeleteResult>;
507
+ /**
508
+ * Batch move (contiguous-block; `refs.length === 1` is the
509
+ * single-annotation case). Refs may mix stable ids and weak `index`
510
+ * refs; weak refs are opportunistically upgraded to durable `/NM`
511
+ * before the move (same rule as `update()`). Atomic — one revision
512
+ * bump and one impact computation per batch.
513
+ *
514
+ * @param refs Annotations to move, in the order they should appear
515
+ * after the move.
516
+ * @param toIndex Insertion point in the post-removal /Annots index
517
+ * space, in `[0, count - refs.length]`.
518
+ */
519
+ move(refs: AnnotationRef[], toIndex: number): AbortablePromise<AnnotationMoveResult>;
520
+ }
521
+ //#endregion
522
+ //#region src/engine/PageGeometryService.d.ts
523
+ interface PageGeometryService {
524
+ read(): AbortablePromise<PageGeometrySnapshot>;
525
+ }
526
+ //#endregion
527
+ //#region src/engine/PageRenderService.d.ts
528
+ interface PageRenderService {
529
+ image(options?: PageImageOptions): AbortablePromise<PageImageHandle>;
530
+ raw(options?: PageRenderOptions): AbortablePromise<PageRaster>;
531
+ }
532
+ //#endregion
533
+ //#region src/engine/PageTextService.d.ts
534
+ /**
535
+ * Per-page text service exposed via `PageHandle.text`.
536
+ *
537
+ * `read()` acquires a `pagePtr` on the worker, runs PDFium's
538
+ * `FPDFText_LoadPage` → `FPDFText_GetText` chain, and returns the
539
+ * full plain-text extraction together with the current `PageState`.
540
+ *
541
+ * The single-method shape is intentional: future per-character
542
+ * features (bounding boxes, font runs, search) land on this service
543
+ * as additional methods without changing the existing URL or DTO.
544
+ */
545
+ interface PageTextService {
546
+ read(): AbortablePromise<PageTextSnapshot>;
547
+ }
548
+ //#endregion
549
+ //#region src/dto/PieceInfo.d.ts
550
+ /**
551
+ * Page-piece metadata (ISO 32000 §14.5): private, application-scoped data
552
+ * under `/PieceInfo` on a page or on the document catalog. The engine
553
+ * round-trips a constrained, wire-safe value vocabulary; anything else in
554
+ * the file is PRESERVED untouched and surfaced as `{ type: 'unknown' }`.
555
+ *
556
+ * Reads are lossless-tagged (a PDF name and a PDF string both arrive as
557
+ * JS strings, so the tag is what keeps them distinguishable); writes take
558
+ * plain JS values, with `{ name: '...' }` as the one wrapper needed to
559
+ * request a PDF name. `/LastModified` bookkeeping (application dict, page
560
+ * dict, doc /Info /ModDate) is engine-managed on every write.
561
+ */
562
+ /** One `/Private` value as read from the file. */
563
+ type PieceInfoEntry = {
564
+ type: 'string';
565
+ value: string;
566
+ } | {
567
+ type: 'name';
568
+ value: string;
569
+ } | {
570
+ type: 'number';
571
+ value: number;
572
+ } | {
573
+ type: 'boolean';
574
+ value: boolean;
575
+ } | {
576
+ type: 'string-array';
577
+ value: string[];
578
+ } |
579
+ /** Present in the file but outside the supported vocabulary — preserved
580
+ * by writes to sibling keys, not readable through this API. */
581
+ {
582
+ type: 'unknown';
583
+ };
584
+ /** A write value: plain JS, `{ name }` requests a PDF name, `null` deletes. */
585
+ type PieceInfoPatchValue = string | number | boolean | readonly string[] | {
586
+ name: string;
587
+ };
588
+ type PieceInfoPatch = Record<string, PieceInfoPatchValue | null>;
589
+ interface PieceInfoSnapshot {
590
+ /** The application's `/Private` entries, keyed by PDF key name. */
591
+ entries: Record<string, PieceInfoEntry>;
592
+ /** The application data dict's `/LastModified`, as ISO 8601 (null if absent). */
593
+ lastModified: string | null;
594
+ }
595
+ //#endregion
596
+ //#region src/engine/PieceInfoService.d.ts
597
+ /**
598
+ * Access to `/PieceInfo` private application data (ISO 32000 §14.5). The
599
+ * SAME interface serves both levels — `DocumentHandle.pieceInfo?` reads and
600
+ * writes the catalog's `/PieceInfo`, `PageHandle.pieceInfo?` the page's —
601
+ * mirroring the native API's doc/page symmetry.
602
+ *
603
+ * Optional on the contract while the cloud endpoints ship (the
604
+ * `downloadLayer?` pattern): the local engine implements it; the cloud
605
+ * engine omits it until a cloud consumer exists (writes there also need an
606
+ * authorization-scope decision — currently they ride `doc.metadata.modify`
607
+ * locally). Feature-detect with `handle.pieceInfo !== undefined`.
608
+ *
609
+ * Writes are engine-managed for spec bookkeeping: every update refreshes
610
+ * the application dict's `/LastModified`, the page's `/LastModified`
611
+ * (required once `/PieceInfo` is present), and — for catalog writes — the
612
+ * document `/Info` `/ModDate`. No document event is published: piece data
613
+ * is private app state, not rendered document state.
614
+ */
615
+ interface PieceInfoService {
616
+ /**
617
+ * The application's data, or null when the holder has no well-formed
618
+ * entry for it. Unknown value types arrive as `{ type: 'unknown' }` and
619
+ * survive sibling writes untouched.
620
+ */
621
+ read(application: string): AbortablePromise<PieceInfoSnapshot | null>;
622
+ /**
623
+ * Merge-write entries into the application's `/Private` dictionary:
624
+ * strings/numbers/booleans/string-arrays write as the corresponding PDF
625
+ * types, `{ name }` writes a PDF name, `null` deletes the key. One call
626
+ * is one worker job — atomic with respect to every other engine
627
+ * operation on this document.
628
+ */
629
+ update(application: string, patch: PieceInfoPatch): AbortablePromise<void>;
630
+ /** Application names present under this holder's `/PieceInfo`. */
631
+ applications(): AbortablePromise<string[]>;
632
+ /** Remove the application's entire entry (sibling applications survive). */
633
+ clear(application: string): AbortablePromise<void>;
634
+ }
635
+ //#endregion
636
+ //#region src/engine/PageHandle.d.ts
637
+ /**
638
+ * Page-scoped handle returned by `DocumentHandle.page(pageObjectNumber)`.
639
+ * The handle is keyed on the PDF indirect object number, never the page
640
+ * index, so it survives page-list mutations.
641
+ */
642
+ interface PageHandle {
643
+ readonly pageObjectNumber: PageObjectNumber;
644
+ /**
645
+ * Display index at the time this handle was minted. The engine refreshes
646
+ * this on every annotation/list call against the live `PageRecord`, but
647
+ * callers should treat it as advisory metadata only.
648
+ */
649
+ readonly pageIndex: number;
650
+ readonly annotations: PageAnnotationsService;
651
+ readonly text: PageTextService;
652
+ readonly geometry: PageGeometryService;
653
+ readonly render: PageRenderService;
654
+ /**
655
+ * PAGE-level `/PieceInfo` private application data (ISO 32000 §14.5) —
656
+ * e.g. a stamp page's name/subject. Optional: local implements it; cloud
657
+ * omits it until a cloud consumer ships (the `downloadLayer?` pattern).
658
+ */
659
+ readonly pieceInfo?: PieceInfoService;
660
+ }
661
+ //#endregion
662
+ //#region src/events/DocumentEvent.d.ts
663
+ /**
664
+ * Provenance of a `DocumentEvent` — WHOSE HAND caused the mutation, never
665
+ * which transport delivered it (transport is invisible by design).
666
+ *
667
+ * `kind: 'local'` means caused by THIS ENGINE INSTANCE — not "this user".
668
+ * The same user in two tabs is two sessions: tab A's mutation arrives in
669
+ * tab B as `'remote'` (with the same `sub`). Rule of thumb for consumers:
670
+ * "is this MY ACTION" → check `kind` / `sessionId` (undo stacks, optimism
671
+ * reconciliation); "is this MY USER" → check `sub` (attribution).
672
+ */
673
+ interface EventOrigin {
674
+ /** 'local' = caused by this engine instance; 'remote' = another session. */
675
+ kind: 'local' | 'remote';
676
+ /** Identifies the engine instance that caused the mutation. */
677
+ sessionId: string;
678
+ /** Authenticated subject of the originator (cloud); `null` locally. */
679
+ sub: string | null;
680
+ /** Mutation timestamp (server ts for remote, client ts for local). */
681
+ ts: number;
682
+ /** Server audit-log row id — monotonic per document, the resume cursor.
683
+ * `null` until the mutation has a server identity (local engines; cloud
684
+ * own-mutation events before the server echoes the id). */
685
+ serverId: number | null;
686
+ }
687
+ /**
688
+ * The one event stream both engines speak — the model is the contract, the
689
+ * transport differs (local: in-process after the worker confirms; cloud:
690
+ * in-process for your own mutations, SSE for everyone else's).
691
+ *
692
+ * Invariants (locked — the collaboration design rests on these):
693
+ *
694
+ * - EXACTLY ONCE: every mutation that touches your document appears in
695
+ * your stream exactly once. The engine that performs a mutation emits
696
+ * the event itself at confirmation time; the remote channel exists to
697
+ * tell everyone ELSE (own echoes are dropped by `sessionId`).
698
+ * - GROUND TRUTH ONLY: events fire after the mutation is confirmed —
699
+ * never optimistically. Optimism is a plugin concern.
700
+ * - RESULTS RIDE VERBATIM: each event embeds the mutation result the
701
+ * caller received, unmodified — which (cloud) is byte-identical to the
702
+ * audit-log payload. A handler sees the same fact whether it performed
703
+ * the mutation, watched it locally, or received it over the wire.
704
+ *
705
+ * Handlers updating UI/document state should be ORIGIN-AGNOSTIC ("a page
706
+ * was removed → update the registry"); `origin` is metadata for the few
707
+ * provenance-aware features (undo, attribution toasts, camera etiquette).
708
+ */
709
+ type DocumentEvent = ({
710
+ type: 'annotation.created';
711
+ pageObjectNumber: PageObjectNumber;
712
+ origin: EventOrigin;
713
+ } & AnnotationCreateResult) | ({
714
+ type: 'annotation.updated';
715
+ pageObjectNumber: PageObjectNumber;
716
+ origin: EventOrigin;
717
+ } & AnnotationUpdateResult) | ({
718
+ type: 'annotation.deleted';
719
+ pageObjectNumber: PageObjectNumber;
720
+ origin: EventOrigin;
721
+ } & AnnotationDeleteResult) | ({
722
+ type: 'annotation.moved';
723
+ pageObjectNumber: PageObjectNumber;
724
+ origin: EventOrigin;
725
+ } & AnnotationMoveResult) | ({
726
+ type: 'pages.moved';
727
+ /** Locally: the moved block. Remotely the audit row only records the
728
+ * outcome, so this is the full new order — consumers should read
729
+ * `layout` for positions, never reconstruct the gesture. */
730
+ pageObjectNumbers: PageObjectNumber[];
731
+ /** The originator's insertion point; absent on remote events. */
732
+ destIndex?: number;
733
+ origin: EventOrigin;
734
+ } & PageMoveResult) | ({
735
+ type: 'pages.rotated';
736
+ pageObjectNumbers: PageObjectNumber[];
737
+ rotation: PdfRotation;
738
+ origin: EventOrigin;
739
+ } & PageRotateResult) | ({
740
+ type: 'pages.deleted';
741
+ /** The RETIRED pons — not derivable from the surviving `layout`. */
742
+ pageObjectNumbers: PageObjectNumber[];
743
+ origin: EventOrigin;
744
+ } & PageDeleteResult) | ({
745
+ type: 'pages.inserted';
746
+ /** The originator's insertion point; absent on remote events. */
747
+ destIndex?: number;
748
+ origin: EventOrigin;
749
+ } & PageInsertResult) | ({
750
+ type: 'attachment.created';
751
+ origin: EventOrigin;
752
+ } & AttachmentCreateResult) | ({
753
+ type: 'attachment.deleted';
754
+ origin: EventOrigin;
755
+ } & AttachmentDeleteResult) | ({
756
+ type: 'metadata.updated';
757
+ origin: EventOrigin;
758
+ } & MetadataUpdateResult) | ({
759
+ type: 'form.valueChanged';
760
+ origin: EventOrigin;
761
+ } & FormSetValueResult) | ({
762
+ type: 'form.imported';
763
+ origin: EventOrigin;
764
+ } & FormImportResult) | ({
765
+ type: 'form.repaired';
766
+ origin: EventOrigin;
767
+ } & FormRepairResult) | ({
768
+ type: 'form.fieldCreated';
769
+ origin: EventOrigin;
770
+ } & FormFieldCreateResult) | ({
771
+ type: 'form.fieldUpdated';
772
+ origin: EventOrigin;
773
+ } & FormFieldUpdateResult) | ({
774
+ type: 'form.fieldDeleted';
775
+ origin: EventOrigin;
776
+ } & FormFieldDeleteResult) | ({
777
+ type: 'form.widgetAttached';
778
+ origin: EventOrigin;
779
+ } & FormWidgetLinkResult) | ({
780
+ type: 'form.widgetDetached';
781
+ origin: EventOrigin;
782
+ } & FormWidgetLinkResult) | ({
783
+ type: 'form.effectsApplied';
784
+ origin: EventOrigin;
785
+ } & FormEffectsResult) | ({
786
+ type: 'pages.flattened';
787
+ pageObjectNumbers: PageObjectNumber[];
788
+ usage: PageFlattenUsage;
789
+ origin: EventOrigin;
790
+ } & PageFlattenResult) | ({
791
+ type: 'redaction.applied';
792
+ origin: EventOrigin;
793
+ } & RedactionApplyResult);
794
+ type DocumentEventType = DocumentEvent['type'];
795
+ type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
796
+ /** A `DocumentEvent` before provenance is stamped — what mutation paths
797
+ * hand to their engine's publisher, which adds `origin`. */
798
+ type DocumentEventInit = DistributiveOmit<DocumentEvent, 'origin'>;
799
+ //#endregion
800
+ //#region src/events/DocumentEventStream.d.ts
801
+ /**
802
+ * The subscription surface on `DocumentHandle.events`. Intentionally
803
+ * minimal — no filtering, no replay-from-id: plugins build their own
804
+ * filter wrappers (per-page, per-type, …). One subscription, one stream.
805
+ *
806
+ * Delivery is synchronous fan-out with error isolation: a throwing
807
+ * listener never blocks other listeners, and never fails the mutation
808
+ * whose confirmation produced the event.
809
+ */
810
+ interface DocumentEventStream {
811
+ /** Subscribe to every event for this document. Returns the unsubscriber. */
812
+ subscribe(listener: (event: DocumentEvent) => void): () => void;
813
+ /**
814
+ * Highest `origin.serverId` observed so far — the reconnect/backfill
815
+ * cursor for the remote channel. `null` until a remote-identified event
816
+ * has been seen (always `null` on purely-local engines).
817
+ */
818
+ lastServerId(): number | null;
819
+ }
820
+ //#endregion
821
+ //#region src/engine/DocumentHandle.d.ts
822
+ interface DocumentCapabilities {
823
+ readonly weakAnnotationEditSessions: 'not-needed' | 'required';
824
+ readonly pageEditSessions: 'unsupported' | 'supported';
825
+ }
826
+ interface DocumentHandle {
827
+ readonly id: string;
828
+ readonly capabilities: DocumentCapabilities;
829
+ readonly security: DocumentSecurityService;
830
+ readonly metadata: MetadataService;
831
+ readonly annotations: DocumentAnnotationsService;
832
+ /** Lazy catalog-owned action extraction. The engine never executes scripts. */
833
+ readonly actions?: DocumentActionsService;
834
+ /**
835
+ * Document-level attachments (the catalog's `/EmbeddedFiles` name tree).
836
+ * Optional while transports ship (the `downloadLayer?` pattern) —
837
+ * feature-detect with `doc.attachments !== undefined`. Files attached to
838
+ * annotations are downloaded via `page(pon).annotations.downloadFile`.
839
+ */
840
+ readonly attachments?: DocumentAttachmentsService;
841
+ /** The document's interactive form (AcroForm): fields, values, interchange. */
842
+ readonly forms: DocumentFormsService;
843
+ /**
844
+ * CATALOG-level `/PieceInfo` private application data (ISO 32000 §14.5)
845
+ * — e.g. a stamp library's display name. Optional: the local engine
846
+ * implements it; the cloud engine omits it until a cloud consumer ships
847
+ * (the `downloadLayer?` pattern). Per-page piece data lives on
848
+ * `page(pon).pieceInfo`.
849
+ */
850
+ readonly pieceInfo?: PieceInfoService;
851
+ /** Document text search: budgeted, cursor-resumable slices. */
852
+ readonly search: DocumentSearchService;
853
+ /**
854
+ * Render POLICY surface (`doc.render.policy()`): the engine's render
855
+ * lattice, or `continuous` on engines that render any viewport exactly
856
+ * (the local engine). Pixels stay on `page(pon).render` — this carries
857
+ * policy only. Conformance is explicit via `snapFullPageViewport`; no
858
+ * engine ever snaps a render call implicitly. Optional while engines
859
+ * ship it — feature-detect with `doc.render !== undefined`.
860
+ */
861
+ readonly render?: DocumentRenderService;
862
+ /**
863
+ * Document-scoped page service. Use for cross-page operations:
864
+ * - `pages.list()` for the current display order.
865
+ * - `pages.move(pons, destIndex)` for reorder.
866
+ *
867
+ * Per-page reads/writes still live on `page(pon).annotations`.
868
+ */
869
+ readonly pages: DocumentPagesService;
870
+ /**
871
+ * Destructive redaction apply (the second stage of the two-stage model;
872
+ * marking rides the normal annotation verbs). Optional while engines
873
+ * ship it — feature-detect with `doc.redaction !== undefined`.
874
+ */
875
+ readonly redaction?: DocumentRedactionService;
876
+ /**
877
+ * The document's event stream — every confirmed mutation, exactly once,
878
+ * identical shape on local and cloud engines (see `DocumentEvent`). The
879
+ * engine-instance identity lives on each event's `origin.sessionId`.
880
+ */
881
+ readonly events: DocumentEventStream;
882
+ /**
883
+ * Returns a handle scoped to a page by PDF indirect object number.
884
+ * Throws `EngineError(NotFound)` if the document has no such page.
885
+ * Synchronous because page records are cached on `DocumentSession`.
886
+ */
887
+ page(pageObjectNumber: PageObjectNumber): PageHandle;
888
+ download(opts?: {
889
+ mode?: PdfSaveMode;
890
+ }): AbortablePromise<Uint8Array>;
891
+ /**
892
+ * Export JUST this document's LAYER as a self-contained artifact (the small
893
+ * overlay diff over the immutable base) — re-openable later via
894
+ * `OpenInputLayerBytes` with `{ kind: 'artifact', bytes }`. Optional: only the
895
+ * local engine, opened WITH a layer (`layerBytes`), supports it; the cloud
896
+ * engine manages layers server-side and omits it. Rejects if the document was
897
+ * opened without a layer.
898
+ */
899
+ downloadLayer?(): AbortablePromise<Uint8Array>;
900
+ close(): AbortablePromise<void>;
901
+ }
902
+ //#endregion
903
+ //#region src/engine/FontService.d.ts
904
+ /**
905
+ * Engine-level service for registering runtime fonts and configuring the
906
+ * ordered glyph-fallback chain. Runtime-global, not document-scoped: a
907
+ * registered font is shared by every page render and annotation-authoring
908
+ * call on the engine's PDFium thread, and survives document open/close.
909
+ *
910
+ * Availability is the deliberate local-vs-cloud split:
911
+ * - `@embedpdf/engine` (local/WASM) implements it: the developer embedding
912
+ * the viewer decides what fonts ship to the client runtime.
913
+ * - `@cloudpdf/engine` (cloud) does NOT expose it (`Engine.fonts` is
914
+ * undefined). Fallback fonts are a server policy decision, loaded once on
915
+ * the server runtime; clients cannot influence them.
916
+ *
917
+ * `register` and `addFallback` are intentionally separate calls: registering a
918
+ * font makes it available for explicit annotation authoring
919
+ * (`FreeTextDraft.registeredFontKey`); adding it to the fallback chain *also*
920
+ * makes it eligible for automatic missing-glyph substitution during page
921
+ * rendering and appearance generation. Many fonts want one without the other.
922
+ */
923
+ interface FontService {
924
+ /**
925
+ * Register a single font. Idempotent: registering a font whose `key` (or, if
926
+ * `key` is omitted, whose content hash) is already known resolves to the
927
+ * existing handle without re-uploading bytes to the runtime.
928
+ *
929
+ * Rejects with `EngineErrorCode.InvalidArg` when the runtime cannot load the
930
+ * font (corrupt file, unsupported format, no glyphs).
931
+ */
932
+ register(spec: FontSpec): AbortablePromise<FontHandle>;
933
+ /** Register several fonts, preserving order. */
934
+ registerAll(specs: FontSpec[]): AbortablePromise<FontHandle[]>;
935
+ /**
936
+ * Append a registered font to the ordered fallback chain. Order is
937
+ * precedence: the first registered font that covers a missing glyph wins,
938
+ * with style (weight/italic) used as a tie-breaker by the runtime.
939
+ */
940
+ addFallback(font: FontHandle | FontKey): AbortablePromise<void>;
941
+ /** Clear the fallback chain without unregistering the fonts themselves. */
942
+ clearFallbacks(): AbortablePromise<void>;
943
+ /** Unregister every font and reset the fallback chain. */
944
+ clear(): AbortablePromise<void>;
945
+ /** Currently registered fonts, in registration order. */
946
+ list(): readonly FontHandle[];
947
+ }
948
+ //#endregion
949
+ //#region src/engine/Engine.d.ts
950
+ /**
951
+ * Engine contract shared by `@embedpdf/engine` and
952
+ * `@cloudpdf/engine`. Both implementations expose the same
953
+ * `open()` surface and return the same {@link DocumentHandle} shape;
954
+ * the only observable difference is transport — local goes through a
955
+ * Worker + WASM PDFium, cloud goes through HTTPS to a remote server.
956
+ *
957
+ * Authorization parity:
958
+ * - Cloud reads scope + identity from the doc-scoped JWT it gets at
959
+ * transport setup time. `OpenOptions.scope` / `OpenOptions.identity`
960
+ * are silently ignored by cloud (the JWT is the authority).
961
+ * - Local reads scope + identity from `OpenOptions.scope` /
962
+ * `OpenOptions.identity` (no JWT involved). Defaults to `['*']`
963
+ * wildcard with a one-time console warning.
964
+ *
965
+ * Both engines run the same resolver against the same `pdf.permissions`
966
+ * expansion → identical allow/deny decisions for the same
967
+ * scope+identity+PDF-bits inputs. The parity test at
968
+ * `engine-core/test/scope-parity.test.ts` (commit 17) locks this in.
969
+ */
970
+ interface Engine {
971
+ open(input: OpenInput, options?: OpenOptions): AbortablePromise<DocumentHandle>;
972
+ destroy(): AbortablePromise<void>;
973
+ /**
974
+ * Start booting the engine's backing resources (Worker spawn, WASM compile,
975
+ * transport connect) without performing any work. Optional because some
976
+ * engines have nothing to warm (cloud). Idempotent and non-blocking:
977
+ * engines that boot lazily do so on first use anyway — calling `warmup()`
978
+ * just overlaps that boot with app/plugin initialization instead of paying
979
+ * for it on the first `open()`.
980
+ */
981
+ warmup?(): void;
982
+ /**
983
+ * Runtime font registration + fallback configuration. Present on the local
984
+ * (WASM) engine only; `undefined` on the cloud engine, where fallback fonts
985
+ * are a server-side policy decision and cannot be configured from the
986
+ * client. See {@link FontService}.
987
+ */
988
+ readonly fonts?: FontService;
989
+ }
990
+ /**
991
+ * A thunk that constructs a fresh {@link Engine}. Construction is synchronous
992
+ * and cheap — engines allocate no live resources (no Worker, no WASM, no
993
+ * socket) until first use — so the thunk exists purely to express OWNERSHIP:
994
+ *
995
+ * - Pass an `Engine` INSTANCE to an adapter (`<Viewer>`, `provideEmbedPdf`)
996
+ * and it is BORROWED: the adapter never destroys it. You own the
997
+ * lifetime — the module-scope singleton case.
998
+ * - Pass a THUNK (`() => localEngine()`) and the adapter OWNS the result:
999
+ * it calls the thunk on mount and destroys the engine on unmount. Use
1000
+ * this for per-mount isolation (StrictMode/HMR-clean teardown,
1001
+ * multi-viewer independence).
1002
+ *
1003
+ * DELIBERATELY synchronous — an async thunk would reintroduce a "maybe
1004
+ * engine" that every consumer must await (the deferredEngine problem this
1005
+ * design removed). Async acquisition (dynamic `import()`, remote config)
1006
+ * belongs OUTSIDE the thunk: await it, then hand over the instance. Code
1007
+ * that genuinely needs a lazily-resolved engine models that itself with
1008
+ * `Engine | Promise<Engine>` (see the stamp plugin's `assetEngine`).
1009
+ */
1010
+ type EngineFactory = () => Engine;
1011
+ //#endregion
1012
+ export { DocumentPagesService as A, CONTINUOUS_RENDER_POLICY as C, snapFullPageViewport as D, snapAppearanceScale as E, WeakAnnotationEditSession as F, DocumentActionsService as I, FormRepairOptions as M, DocumentAttachmentsService as N, snapTileScale as O, DocumentAnnotationsService as P, DocumentSearchService as S, EngineRenderPolicy as T, PageTextService as _, DocumentHandle as a, PageAnnotationsService as b, DocumentEventInit as c, PageHandle as d, PieceInfoService as f, PieceInfoSnapshot as g, PieceInfoPatchValue as h, DocumentCapabilities as i, DocumentFormsService as j, DocumentRedactionService as k, DocumentEventType as l, PieceInfoPatch as m, EngineFactory as n, DocumentEventStream as o, PieceInfoEntry as p, FontService as r, DocumentEvent as s, Engine as t, EventOrigin as u, PageRenderService as v, DocumentRenderService as w, MetadataService as x, PageGeometryService as y };
1013
+ //# sourceMappingURL=Engine-D9loFZc1.d.cts.map