@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
package/dist/wire.cjs ADDED
@@ -0,0 +1,1516 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_resolver = require("./resolver-DAZWVoJL.cjs");
3
+ const require_schemas = require("./schemas-B_1VyFsm.cjs");
4
+ //#region src/wire/token.ts
5
+ const DEFAULT_MAX_TOKEN_LENGTH = 256;
6
+ const FIELD_NAME_RE = /^[A-Za-z][A-Za-z0-9]*(?:\.[A-Za-z][A-Za-z0-9]*)*$/;
7
+ const VALUE_RE = /^[A-Za-z0-9.-]+$/;
8
+ function encodeToken(schema, input) {
9
+ assertSchema(schema);
10
+ const allowed = new Set(schema.fields);
11
+ const pairs = [];
12
+ for (const [key, value] of Object.entries(input)) {
13
+ if (value === void 0) continue;
14
+ assertKnownField(allowed, key);
15
+ const encoded = encodeScalar(key, value);
16
+ assertSafeValue(key, encoded);
17
+ pairs.push([key, encoded]);
18
+ }
19
+ pairs.sort(([a], [b]) => a.localeCompare(b));
20
+ const token = pairs.map(([key, value]) => `${key}=${value}`).join(",");
21
+ if (token.length === 0) throw new Error("token must not be empty");
22
+ assertTokenLength(schema, token);
23
+ return token;
24
+ }
25
+ function decodeToken(schema, raw) {
26
+ assertSchema(schema);
27
+ const token = raw.startsWith("@") ? raw.slice(1) : raw;
28
+ assertTokenLength(schema, token);
29
+ if (token.length === 0) throw new Error("token must not be empty");
30
+ const allowed = new Set(schema.fields);
31
+ const output = {};
32
+ let previousKey;
33
+ for (const pair of token.split(",")) {
34
+ if (pair.length === 0) throw new Error("token contains an empty field");
35
+ const separator = pair.indexOf("=");
36
+ if (separator <= 0 || separator === pair.length - 1) throw new Error(`token field "${pair}" must be key=value`);
37
+ const key = pair.slice(0, separator);
38
+ const value = pair.slice(separator + 1);
39
+ assertKnownField(allowed, key);
40
+ assertSafeValue(key, value);
41
+ if (output[key] !== void 0) throw new Error(`token field "${key}" appears more than once`);
42
+ if (previousKey !== void 0 && key.localeCompare(previousKey) <= 0) throw new Error("token fields must be in alphabetical order");
43
+ previousKey = key;
44
+ output[key] = value;
45
+ }
46
+ return output;
47
+ }
48
+ function assertSchema(schema) {
49
+ for (const field of schema.fields) if (!FIELD_NAME_RE.test(field)) throw new Error(`token field name "${field}" must be camelCase segments joined by "."`);
50
+ }
51
+ function assertKnownField(allowed, key) {
52
+ if (!allowed.has(key)) throw new Error(`unknown token field "${key}"`);
53
+ }
54
+ function encodeScalar(key, value) {
55
+ if (typeof value === "boolean") return value ? "true" : "false";
56
+ if (typeof value === "number") {
57
+ if (!Number.isFinite(value)) throw new Error(`token field "${key}" must be finite`);
58
+ return Number.isInteger(value) ? String(value) : trimDecimal(value);
59
+ }
60
+ return value;
61
+ }
62
+ function trimDecimal(value) {
63
+ return value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "");
64
+ }
65
+ function assertSafeValue(key, value) {
66
+ if (!VALUE_RE.test(value)) throw new Error(`token field "${key}" value contains a reserved character`);
67
+ }
68
+ function assertTokenLength(schema, token) {
69
+ const maxLength = schema.maxLength ?? DEFAULT_MAX_TOKEN_LENGTH;
70
+ if (token.length > maxLength) throw new Error(`token exceeds ${maxLength} characters`);
71
+ }
72
+ //#endregion
73
+ //#region src/wire/tokenSchemas.ts
74
+ const DocTokenSchema = { fields: ["docVersion"] };
75
+ const ContentTokenSchema = { fields: ["contentVersion"] };
76
+ const LayoutTokenSchema = { fields: ["layoutVersion"] };
77
+ const MetadataTokenSchema = { fields: ["metadataVersion"] };
78
+ const AnnotationTokenSchema = { fields: ["annotationVersion"] };
79
+ const ActionsTokenSchema = { fields: ["actionsVersion"] };
80
+ const AttachmentsTokenSchema = { fields: ["attachmentsVersion"] };
81
+ const DownloadTokenSchema = {
82
+ fields: ["docVersion", "mode"],
83
+ maxLength: 128
84
+ };
85
+ /**
86
+ * Allowed flat keys for the render token, expressed as dotted paths that
87
+ * mirror the SDK `PageImageOptions` shape 1:1. The token codec is fully
88
+ * generic over this list — adding a new render option means adding its
89
+ * dotted path here and a matching branch in `PageImageOptionsWireSchema`.
90
+ * No encoder/decoder code changes.
91
+ *
92
+ * `includeAnnotations` is deliberately NOT a token field: annotatedness
93
+ * changes the artifact's plane-dependency
94
+ * set, so it is expressed by the path FAMILY (`…/render/pages/` vs
95
+ * `…/render/annotated/pages/`), never inside the token. `annotationVersion`
96
+ * belongs to the annotated family's tokens only — each family's query
97
+ * schema enforces its own pin grammar.
98
+ */
99
+ const RenderTokenSchema = {
100
+ fields: [
101
+ "annotationVersion",
102
+ "background",
103
+ "contentVersion",
104
+ "format",
105
+ "quality",
106
+ "rotation",
107
+ "target.kind",
108
+ "target.rect.bottom",
109
+ "target.rect.left",
110
+ "target.rect.right",
111
+ "target.rect.top",
112
+ "viewport.kind",
113
+ "viewport.scale",
114
+ "viewport.width"
115
+ ],
116
+ maxLength: 512
117
+ };
118
+ /**
119
+ * Token for the versioned search endpoints (`/search/{rects,full}/data@…`).
120
+ * One token carries the whole cache key: the content epoch, the query
121
+ * (text/pattern rides base64-variant-encoded in `q` — the token value
122
+ * charset excludes free text), and the resume position. Canonical by
123
+ * construction: the codec sorts fields and the encoder omits every
124
+ * default, so equal searches produce byte-equal tokens — the property CDN
125
+ * cache hits live on. Mode is NOT a field; it is the endpoint (separate
126
+ * permission tiers must never share cache entries).
127
+ */
128
+ const SearchTokenSchema = {
129
+ fields: [
130
+ "epoch",
131
+ "matchCase",
132
+ "matchDiacritics",
133
+ "maxMatches",
134
+ "maxPages",
135
+ "q",
136
+ "regex",
137
+ "skip",
138
+ "startPage",
139
+ "wholeWord"
140
+ ],
141
+ maxLength: 2048
142
+ };
143
+ /**
144
+ * Token for the batch annotation-appearance render endpoint. Narrower than
145
+ * the page render token: appearance bitmaps are sized per annotation `/Rect`
146
+ * so there is no target/viewport — only a uniform `scale` and page
147
+ * `rotation`. Keyed by `annotationVersion` only (appearances do not depend on
148
+ * page base content). The cloud endpoint renders the Normal appearance only,
149
+ * so `modes` is intentionally absent here (it is a worker/local-only option).
150
+ */
151
+ const AnnotationAppearancesRenderTokenSchema = {
152
+ fields: [
153
+ "annotationVersion",
154
+ "format",
155
+ "quality",
156
+ "rotation",
157
+ "scale"
158
+ ],
159
+ maxLength: 256
160
+ };
161
+ //#endregion
162
+ //#region src/wire/tokens.ts
163
+ const encodeDocToken = (docVersion) => encodeToken(DocTokenSchema, { docVersion });
164
+ const decodeDocToken = (raw) => decodePositiveInteger(decodeToken(DocTokenSchema, raw).docVersion, "docVersion");
165
+ const encodeContentToken = (contentVersion) => encodeToken(ContentTokenSchema, { contentVersion });
166
+ const decodeContentToken = (raw) => decodePositiveInteger(decodeToken(ContentTokenSchema, raw).contentVersion, "contentVersion");
167
+ const encodeLayoutToken = (layoutVersion) => encodeToken(LayoutTokenSchema, { layoutVersion });
168
+ const decodeLayoutToken = (raw) => decodePositiveInteger(decodeToken(LayoutTokenSchema, raw).layoutVersion, "layoutVersion");
169
+ const encodeMetadataToken = (metadataVersion) => encodeToken(MetadataTokenSchema, { metadataVersion });
170
+ const decodeMetadataToken = (raw) => decodePositiveInteger(decodeToken(MetadataTokenSchema, raw).metadataVersion, "metadataVersion");
171
+ const encodeAnnotationToken = (annotationVersion) => encodeToken(AnnotationTokenSchema, { annotationVersion });
172
+ const decodeAnnotationToken = (raw) => decodePositiveInteger(decodeToken(AnnotationTokenSchema, raw).annotationVersion, "annotationVersion");
173
+ const encodeActionsToken = (actionsVersion) => encodeToken(ActionsTokenSchema, { actionsVersion });
174
+ const decodeActionsToken = (raw) => decodePositiveInteger(decodeToken(ActionsTokenSchema, raw).actionsVersion, "actionsVersion");
175
+ const encodeAttachmentsToken = (attachmentsVersion) => encodeToken(AttachmentsTokenSchema, { attachmentsVersion });
176
+ const decodeAttachmentsToken = (raw) => decodePositiveInteger(decodeToken(AttachmentsTokenSchema, raw).attachmentsVersion, "attachmentsVersion");
177
+ const encodeDownloadToken = (input) => encodeToken(DownloadTokenSchema, {
178
+ docVersion: input.docVersion,
179
+ mode: input.mode
180
+ });
181
+ const decodeDownloadToken = (raw) => {
182
+ const decoded = decodeToken(DownloadTokenSchema, raw);
183
+ return {
184
+ docVersion: decodePositiveInteger(decoded.docVersion, "docVersion"),
185
+ mode: decodePdfSaveMode(decoded.mode)
186
+ };
187
+ };
188
+ /**
189
+ * Encode a render token from a flat wire-shape input. The input is the
190
+ * output of `flatten(...)` over an SDK `PageImageOptions`-shaped object plus
191
+ * cache versions. Semantic invariants (viewport-kind XOR fields, per-family
192
+ * pin grammar — annotatedness itself is PATH-expressed, never a token key —
193
+ * target rect coherence) live in the per-family render query schemas —
194
+ * running them here would duplicate the spec.
195
+ */
196
+ const encodeRenderToken = (input) => encodeToken(RenderTokenSchema, input);
197
+ /**
198
+ * Decode a render token to a flat `Record<string, string>` of allowed
199
+ * fields. Use `unflatten(...)` + `PageImageOptionsWireSchema.parse(...)` to
200
+ * recover the nested SDK shape with full coercion + validation.
201
+ */
202
+ const decodeRenderToken = (raw) => decodeToken(RenderTokenSchema, raw);
203
+ /**
204
+ * Encode an annotation-appearance render token from a flat wire-shape input
205
+ * (the `flatten(...)` of an `AnnotationAppearanceImageOptions`-shaped object
206
+ * plus cache versions). Semantic validation lives in
207
+ * `AnnotationAppearancesQuerySchema`.
208
+ */
209
+ const encodeAnnotationAppearancesRenderToken = (input) => encodeToken(AnnotationAppearancesRenderTokenSchema, input);
210
+ /** Decode an annotation-appearance render token to a flat field map. */
211
+ const decodeAnnotationAppearancesRenderToken = (raw) => decodeToken(AnnotationAppearancesRenderTokenSchema, raw);
212
+ const encodeSearchToken = (input) => {
213
+ const q = input.query;
214
+ return encodeToken(SearchTokenSchema, {
215
+ epoch: input.epoch,
216
+ q: encodeTokenText(q.text),
217
+ regex: q.regex ? true : void 0,
218
+ matchCase: q.matchCase ? true : void 0,
219
+ matchDiacritics: q.matchDiacritics ? true : void 0,
220
+ wholeWord: q.wholeWord ? true : void 0,
221
+ startPage: input.startPage,
222
+ skip: input.skip > 0 ? input.skip : void 0,
223
+ maxPages: input.budget?.maxPages,
224
+ maxMatches: input.budget?.maxMatches
225
+ });
226
+ };
227
+ const decodeSearchToken = (raw) => {
228
+ const t = decodeToken(SearchTokenSchema, raw);
229
+ if (t.epoch === void 0) throw new Error("search token is missing \"epoch\"");
230
+ if (t.q === void 0) throw new Error("search token is missing \"q\"");
231
+ const query = {
232
+ text: decodeTokenText(t.q),
233
+ ...t.regex === "true" ? { regex: true } : {},
234
+ ...t.matchCase === "true" ? { matchCase: true } : {},
235
+ ...t.matchDiacritics === "true" ? { matchDiacritics: true } : {},
236
+ ...t.wholeWord === "true" ? { wholeWord: true } : {}
237
+ };
238
+ const maxPages = t.maxPages === void 0 ? void 0 : decodePositiveInteger(t.maxPages, "maxPages");
239
+ const maxMatches = t.maxMatches === void 0 ? void 0 : decodePositiveInteger(t.maxMatches, "maxMatches");
240
+ return {
241
+ epoch: t.epoch,
242
+ query,
243
+ ...t.startPage === void 0 ? {} : { startPage: decodePositiveInteger(t.startPage, "startPage") },
244
+ skip: t.skip === void 0 ? 0 : decodePositiveInteger(t.skip, "skip"),
245
+ ...maxPages !== void 0 || maxMatches !== void 0 ? { budget: {
246
+ ...maxPages !== void 0 ? { maxPages } : {},
247
+ ...maxMatches !== void 0 ? { maxMatches } : {}
248
+ } } : {}
249
+ };
250
+ };
251
+ const TOKEN_TEXT_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.";
252
+ function encodeTokenText(text) {
253
+ const bytes = new TextEncoder().encode(text);
254
+ let out = "";
255
+ for (let i = 0; i < bytes.length; i += 3) {
256
+ const b0 = bytes[i];
257
+ const b1 = bytes[i + 1];
258
+ const b2 = bytes[i + 2];
259
+ out += TOKEN_TEXT_ALPHABET[b0 >> 2];
260
+ out += TOKEN_TEXT_ALPHABET[(b0 & 3) << 4 | (b1 ?? 0) >> 4];
261
+ if (b1 === void 0) break;
262
+ out += TOKEN_TEXT_ALPHABET[(b1 & 15) << 2 | (b2 ?? 0) >> 6];
263
+ if (b2 === void 0) break;
264
+ out += TOKEN_TEXT_ALPHABET[b2 & 63];
265
+ }
266
+ return out;
267
+ }
268
+ function decodeTokenText(encoded) {
269
+ if (encoded.length % 4 === 1) throw new Error("malformed token text");
270
+ const bytes = [];
271
+ let buffer = 0;
272
+ let bits = 0;
273
+ for (const ch of encoded) {
274
+ const value = TOKEN_TEXT_ALPHABET.indexOf(ch);
275
+ if (value < 0) throw new Error("malformed token text");
276
+ buffer = buffer << 6 | value;
277
+ bits += 6;
278
+ if (bits >= 8) {
279
+ bits -= 8;
280
+ bytes.push(buffer >> bits & 255);
281
+ }
282
+ }
283
+ return new TextDecoder("utf-8", { fatal: true }).decode(Uint8Array.from(bytes));
284
+ }
285
+ function decodePositiveInteger(raw, field) {
286
+ if (raw === void 0 || !/^\d+$/.test(raw)) throw new Error(`token field "${field}" must be a positive integer`);
287
+ const value = Number(raw);
288
+ if (!Number.isInteger(value) || value <= 0) throw new Error(`token field "${field}" must be a positive integer`);
289
+ return value;
290
+ }
291
+ function decodePdfSaveMode(raw) {
292
+ if (raw === "incremental" || raw === "rewrite") return raw;
293
+ throw new Error(`token field "mode" must be "incremental" or "rewrite"`);
294
+ }
295
+ //#endregion
296
+ //#region src/wire/paths.ts
297
+ /**
298
+ * Single source of truth for cloud HTTP paths. Both @cloudpdf/engine and
299
+ * @cloudpdf/server import these so they cannot drift.
300
+ *
301
+ * **URL layout convention (paths v2)**
302
+ *
303
+ * Each resource type lives at its own distinct path prefix. This
304
+ * lets prefix-matching CDNs (Bunny, Cloud CDN, Azure FD) enforce
305
+ * per-resource scope at the edge — a Bunny token signed at
306
+ * `/v1/docs/{id}/render/pages/` can only authorize render bytes,
307
+ * never text or annotations.
308
+ *
309
+ * Shape:
310
+ * /v1/docs/{id} — doc root
311
+ * /v1/docs/{id}/manifest@{ver} — doc-level read
312
+ * /v1/docs/{id}/render/pages/{N}/data@{ver} — render is its own prefix
313
+ * /v1/docs/{id}/text/pages/{N}/data@{ver} — text is its own prefix
314
+ * /v1/docs/{id}/geometry/pages/{N}/data@{ver} — geometry is its own prefix
315
+ * /v1/docs/{id}/layers/{L}/manifest@{ver}
316
+ * /v1/docs/{id}/layers/{L}/metadata@{ver}
317
+ * /v1/docs/{id}/layers/{L}/render/pages/{N}/data@{ver}
318
+ * /v1/docs/{id}/layers/{L}/text/pages/{N}/data@{ver}
319
+ * /v1/docs/{id}/layers/{L}/geometry/pages/{N}/data@{ver}
320
+ * /v1/docs/{id}/layers/{L}/annotations/pages/{N}/items@{ver} — collection (read)
321
+ * /v1/docs/{id}/layers/{L}/annotations/pages/{N}/items — collection (create)
322
+ * /v1/docs/{id}/layers/{L}/annotations/pages/{N}/items/{key} — member
323
+ * /v1/docs/{id}/layers/{L}/annotations/pages/{N}/items/move — batch reorder
324
+ * /v1/docs/{id}/layers/{L}/pages/move — batch page reorder
325
+ * /v1/docs/{id}/layers/{L}/pages/rotate — batch absolute rotation
326
+ * /v1/docs/{id}/layers/{L}/pages/delete — batch page delete
327
+ * /v1/docs/{id}/layers/{L}/form — reconciled snapshot (read)
328
+ * /v1/docs/{id}/layers/{L}/form/fields — field collection (create)
329
+ * /v1/docs/{id}/layers/{L}/form/fields/{key} — field member (read/patch/delete)
330
+ * /v1/docs/{id}/layers/{L}/form/fields/{key}/value — value write (fill)
331
+ * /v1/docs/{id}/layers/{L}/form/fields/{key}/reset — reset to /DV (fill)
332
+ * /v1/docs/{id}/layers/{L}/form/fields/{key}/widgets — adopt a widget (attach)
333
+ * /v1/docs/{id}/layers/{L}/form/fields/{key}/widgets/detach — release a widget
334
+ * /v1/docs/{id}/layers/{L}/form/data — FDF/XFDF export (GET) / import (POST)
335
+ * /v1/docs/{id}/layers/{L}/form/repair — durable reconciliation
336
+ * /v1/docs/{id}/layers/{L}/download@{ver}
337
+ *
338
+ * `items` appears on both the read collection (`items@{ver}`) and
339
+ * the mutation surface (`items` POST, `items/{key}` PATCH/DELETE)
340
+ * for symmetry — `items@version` is the page's versioned annotation
341
+ * collection; `items/{key}` is one annotation inside it.
342
+ */
343
+ const DEFAULT_LAYER_NAME = "default";
344
+ const wirePaths = {
345
+ /** POST: grant document access/caching credentials for the current bearer. */
346
+ access: "/v1/access",
347
+ /**
348
+ * GET: open the document referenced by the doc-scoped JWT and
349
+ * return its `DocumentHead`. The server materialises the base
350
+ * PDF into its file cache and binds it to a worker the first
351
+ * time this is hit.
352
+ */
353
+ docHead: (docId) => `/v1/docs/${encodeURIComponent(docId)}/head`,
354
+ /**
355
+ * GET: layer-scoped head. The cloud SDK always uses a layer namespace;
356
+ * tokens without `layer_name` bind to `DEFAULT_LAYER_NAME`.
357
+ */
358
+ layerHead: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/head`,
359
+ /**
360
+ * GET: full document manifest at a specific `docVersion`. Content-
361
+ * addressed: the URL bytes are immutable for the lifetime of the
362
+ * version, so CDNs may cache `public, max-age=31536000, immutable`.
363
+ * A request whose `docVersion` mismatches the current version
364
+ * returns 404 — the SDK refetches `/head` to learn the new
365
+ * version, then re-requests the manifest at the new URL.
366
+ */
367
+ docManifest: (docId, docVersion) => `/v1/docs/${encodeURIComponent(docId)}/manifest@${encodeDocToken(docVersion)}`,
368
+ /**
369
+ * GET: full layer manifest at a specific layer document version.
370
+ * Never-mutated layers may fall through to the immutable base view;
371
+ * once a layer row exists, `layers.doc_version` and `layer_pages`
372
+ * drive the response.
373
+ */
374
+ layerManifest: (docId, layerName, docVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/manifest@${encodeDocToken(docVersion)}`,
375
+ /**
376
+ * GET: page-geometry list for the whole layer at a specific
377
+ * `layoutVersion`. Content-addressed; CDN may cache forever. The
378
+ * `layoutVersion` lives in the manifest (doc-level pointer) and bumps
379
+ * only on structural page ops. Stale-version requests 404 and the SDK's
380
+ * transparent retry walks `/head` -> `/manifest@docVersion=N` to learn
381
+ * the new `layoutVersion`.
382
+ */
383
+ layerLayout: (docId, layerName, layoutVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/layout@${encodeLayoutToken(layoutVersion)}`,
384
+ /**
385
+ * Immutable BASE page-geometry list (plane-scope model): the shared-URL
386
+ * variant a layout-inheriting layer resolves at — every visitor's page
387
+ * list is ONE CDN object served from the base worker session.
388
+ */
389
+ docLayout: (docId, layoutVersion) => `/v1/docs/${encodeURIComponent(docId)}/layout@${encodeLayoutToken(layoutVersion)}`,
390
+ layerLayoutCurrent: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/layout`,
391
+ /**
392
+ * GET: full document metadata for the layer at a specific
393
+ * `metadataVersion`. Content-addressed; CDN may cache forever. The
394
+ * `metadataVersion` lives in the manifest (doc-level pointer) and bumps
395
+ * only on metadata writes. Stale-version requests 404 and the SDK's
396
+ * transparent retry walks `/head` -> `/manifest@docVersion=N` to learn
397
+ * the new `metadataVersion`.
398
+ */
399
+ layerMetadata: (docId, layerName, metadataVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/metadata@${encodeMetadataToken(metadataVersion)}`,
400
+ layerMetadataCurrent: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/metadata`,
401
+ /** Immutable BASE metadata (plane-scope model): the shared-URL variant a
402
+ * metadata-inheriting layer resolves at. */
403
+ docMetadata: (docId, metadataVersion) => `/v1/docs/${encodeURIComponent(docId)}/metadata@${encodeMetadataToken(metadataVersion)}`,
404
+ /** Immutable catalog-owned actions, independently pinned in the manifest. */
405
+ layerActions: (docId, layerName, actionsVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/actions@${encodeActionsToken(actionsVersion)}`,
406
+ /** Immutable BASE catalog actions (plane-scope model): the shared-URL
407
+ * variant an actions-inheriting layer resolves at. */
408
+ docActions: (docId, actionsVersion) => `/v1/docs/${encodeURIComponent(docId)}/actions@${encodeActionsToken(actionsVersion)}`,
409
+ /** POST: rewrite the document Info dict for the layer (metadata edit). */
410
+ layerMetadataUpdate: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/metadata`,
411
+ /**
412
+ * Immutable BASE /EmbeddedFiles listing: the shared-URL variant an
413
+ * attachments-undiverged layer resolves at — every visitor's sidebar list
414
+ * is ONE CDN object served from the base worker session.
415
+ */
416
+ docAttachments: (docId, attachmentsVersion) => `/v1/docs/${encodeURIComponent(docId)}/attachments@${encodeAttachmentsToken(attachmentsVersion)}`,
417
+ /** Immutable BASE decoded bytes of one embedded file (twin of
418
+ * `layerAttachmentFile` — same capability tier split). */
419
+ docAttachmentFile: (docId, key, attachmentsVersion) => `/v1/docs/${encodeURIComponent(docId)}/attachment-files/${encodeTokenText(key)}/data@${encodeAttachmentsToken(attachmentsVersion)}`,
420
+ /** Immutable /EmbeddedFiles listing, pinned by `attachmentsVersion`. */
421
+ layerAttachments: (docId, layerName, attachmentsVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/attachments@${encodeAttachmentsToken(attachmentsVersion)}`,
422
+ /** POST: create a document-level embedded file (multipart mutation envelope). */
423
+ layerAttachmentsCollection: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/attachments`,
424
+ /** DELETE: remove a document-level embedded file by name-tree key. */
425
+ layerAttachmentItem: (docId, layerName, key) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/attachments/${encodeTokenText(key)}`,
426
+ /**
427
+ * Immutable decoded bytes of one document-level embedded file. Lives
428
+ * under its own `attachment-files` prefix — a stronger capability tier
429
+ * than the metadata listing, so a CDN credential for one can never
430
+ * authorize the other (the search-rects/search-full rule).
431
+ */
432
+ layerAttachmentFile: (docId, layerName, key, attachmentsVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/attachment-files/${encodeTokenText(key)}/data@${encodeAttachmentsToken(attachmentsVersion)}`,
433
+ /** Immutable decoded bytes of a FileAttachment annotation's embedded file. */
434
+ layerAnnotationFile: (docId, layerName, pageObjectNumber, annotKey, attachmentsVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/attachment-files/pages/${pageObjectNumber}/items/${encodeURIComponent(annotKey)}/data@${encodeAttachmentsToken(attachmentsVersion)}`,
435
+ /**
436
+ * Immutable BASE bytes of a FileAttachment annotation's embedded file
437
+ * (plane-scope model). Depends on the `annotations` plane (the annotation
438
+ * exists in this view) AND the `attachments` plane (the pin); the origin
439
+ * guard requires both inherited.
440
+ */
441
+ docAnnotationFile: (docId, pageObjectNumber, annotKey, attachmentsVersion) => `/v1/docs/${encodeURIComponent(docId)}/attachment-files/pages/${pageObjectNumber}/items/${encodeURIComponent(annotKey)}/data@${encodeAttachmentsToken(attachmentsVersion)}`,
442
+ /**
443
+ * GET: full plain-text extraction for a single page at a specific
444
+ * `contentVersion`. Content-addressed; CDN may cache forever.
445
+ * Stale-version requests return 404 and the SDK's transparent
446
+ * retry walks `/head` → `/manifest@docVersion=N` to learn the new
447
+ * `contentVersion`.
448
+ */
449
+ docPageText: (docId, pageObjectNumber, contentVersion) => `/v1/docs/${encodeURIComponent(docId)}/text/pages/${pageObjectNumber}/data@${encodeContentToken(contentVersion)}`,
450
+ layerPageText: (docId, layerName, pageObjectNumber, contentVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/text/pages/${pageObjectNumber}/data@${encodeContentToken(contentVersion)}`,
451
+ layerPageTextCurrent: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/text/pages/${pageObjectNumber}/data`,
452
+ docPageGeometry: (docId, pageObjectNumber, contentVersion) => `/v1/docs/${encodeURIComponent(docId)}/geometry/pages/${pageObjectNumber}/data@${encodeContentToken(contentVersion)}`,
453
+ docPageGeometryCurrent: (docId, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/geometry/pages/${pageObjectNumber}/data`,
454
+ docPageRender: (docId, pageObjectNumber, token) => `/v1/docs/${encodeURIComponent(docId)}/render/pages/${pageObjectNumber}/data@${encodeRenderToken(token)}`,
455
+ docPageRenderCurrent: (docId, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/render/pages/${pageObjectNumber}/data`,
456
+ /**
457
+ * Immutable BASE annotated render (plane-scope model). Its OWN path family,
458
+ * not a token flag under `/render/pages/`: an annotated render depends on
459
+ * `content + annotations`, an annotation-free one on `content` alone, and
460
+ * edge grants are prefix-scoped — the prefix law says a path's prefix must
461
+ * identify its full plane-dependency set. Annotatedness is therefore
462
+ * PATH-ONLY (the token/path law): the wire token has no
463
+ * `includeAnnotations` key at all; the annotated family's token carries
464
+ * `annotationVersion`, the free family's cannot.
465
+ */
466
+ docPageRenderAnnotated: (docId, pageObjectNumber, token) => `/v1/docs/${encodeURIComponent(docId)}/render/annotated/pages/${pageObjectNumber}/data@${encodeRenderToken(token)}`,
467
+ layerPageGeometry: (docId, layerName, pageObjectNumber, contentVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/geometry/pages/${pageObjectNumber}/data@${encodeContentToken(contentVersion)}`,
468
+ layerPageGeometryCurrent: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/geometry/pages/${pageObjectNumber}/data`,
469
+ layerPageRender: (docId, layerName, pageObjectNumber, token) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/render/pages/${pageObjectNumber}/data@${encodeRenderToken(token)}`,
470
+ layerPageRenderCurrent: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/render/pages/${pageObjectNumber}/data`,
471
+ /** Layer twin of `docPageRenderAnnotated` — the grammar is uniform:
472
+ * annotatedness is path-only at BOTH tiers. */
473
+ layerPageRenderAnnotated: (docId, layerName, pageObjectNumber, token) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/render/annotated/pages/${pageObjectNumber}/data@${encodeRenderToken(token)}`,
474
+ layerPageRenderAnnotatedCurrent: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/render/annotated/pages/${pageObjectNumber}/data`,
475
+ /**
476
+ * Immutable BASE annotation list for a single page (plane-scope model):
477
+ * the shared-URL variant an annotations-inheriting layer resolves at — a
478
+ * base's own annotations (weak-identity ones included) are simply visible
479
+ * through every pristine layer, so 1,000 visitors' sidebars are ONE CDN
480
+ * object served from the base worker session.
481
+ */
482
+ docPageAnnotations: (docId, pageObjectNumber, annotationVersion) => `/v1/docs/${encodeURIComponent(docId)}/annotations/pages/${pageObjectNumber}/items@${encodeAnnotationToken(annotationVersion)}`,
483
+ /** Immutable BASE appearance batch (twin of
484
+ * `layerPageAnnotationAppearances` — same `annotations` plane gate). */
485
+ docPageAnnotationAppearances: (docId, pageObjectNumber, token) => `/v1/docs/${encodeURIComponent(docId)}/annotations/pages/${pageObjectNumber}/appearances@${encodeAnnotationAppearancesRenderToken(token)}`,
486
+ /**
487
+ * GET: full annotation list for a single page at a specific
488
+ * `annotationVersion`. Same cache-control rules and 404-retry
489
+ * semantics as `docPageText`. The `items` suffix is the
490
+ * collection name — see file-level docstring.
491
+ */
492
+ layerPageAnnotations: (docId, layerName, pageObjectNumber, annotationVersion) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/annotations/pages/${pageObjectNumber}/items@${encodeAnnotationToken(annotationVersion)}`,
493
+ layerPageAnnotationsCurrent: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/annotations/pages/${pageObjectNumber}/items`,
494
+ /**
495
+ * GET: batch-rendered annotation appearance bitmaps for a single page as a
496
+ * `multipart/form-data` body. Sibling collection of `items` under the same
497
+ * `annotations/pages/{N}/` resource, so it shares the `annotations-read`
498
+ * gate (`doc.annotate.read`) and CDN coverage — reading an annotation lets
499
+ * you see its rendered appearance, the same boundary Adobe uses.
500
+ *
501
+ * Content-addressed via the appearance render token (`annotationVersion`
502
+ * plus render options like scale/format); CDN may cache forever. Appearance
503
+ * pixels depend only on the annotation `/AP` stream, so `contentVersion` is
504
+ * deliberately NOT part of the key.
505
+ */
506
+ layerPageAnnotationAppearances: (docId, layerName, pageObjectNumber, token) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/annotations/pages/${pageObjectNumber}/appearances@${encodeAnnotationAppearancesRenderToken(token)}`,
507
+ layerPageAnnotationAppearancesCurrent: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/annotations/pages/${pageObjectNumber}/appearances`,
508
+ layerPageAnnotationsCreate: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/annotations/pages/${pageObjectNumber}/items`,
509
+ layerAnnotationByKey: (docId, layerName, pageObjectNumber, key) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/annotations/pages/${pageObjectNumber}/items/${encodeURIComponent(key)}`,
510
+ layerPageAnnotationsMove: (docId, layerName, pageObjectNumber) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/annotations/pages/${pageObjectNumber}/items/move`,
511
+ /**
512
+ * GET: the reconciled form snapshot (field tree + widget joins) for the
513
+ * layer's CURRENT state. Forms are document-scoped (one AcroForm per
514
+ * document), so there is no per-page collection and — unlike annotations —
515
+ * no content-addressed `@version` variant: the snapshot is always served
516
+ * `no-store`. Mutation results carry the per-page `cacheDelta` that keeps
517
+ * annotation/render caches coherent when widget appearances change.
518
+ */
519
+ layerForm: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form`,
520
+ /** POST: create a field (optionally with styled widget placements). */
521
+ layerFormFields: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/fields`,
522
+ /**
523
+ * Field member: GET (single field) / PATCH (updateField) / DELETE
524
+ * (deleteField + widget cascade). `fieldKey` is an encoded `FormFieldRef`
525
+ * (`encodeFieldRefKey`): `obj:12` or `fqn:billing.name`.
526
+ */
527
+ layerFormFieldByKey: (docId, layerName, fieldKey) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/fields/${encodeURIComponent(fieldKey)}`,
528
+ /** POST: replace the field's value (`{ value: FormFieldValue }`). */
529
+ layerFormFieldValue: (docId, layerName, fieldKey) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/fields/${encodeURIComponent(fieldKey)}/value`,
530
+ /** POST: reset the field to /DV (or clear). Empty body. */
531
+ layerFormFieldReset: (docId, layerName, fieldKey) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/fields/${encodeURIComponent(fieldKey)}/reset`,
532
+ /** POST: adopt an inert widget annotation (`{ widget, onState? }`). */
533
+ layerFormFieldWidgets: (docId, layerName, fieldKey) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/fields/${encodeURIComponent(fieldKey)}/widgets`,
534
+ /**
535
+ * POST: release a widget back to the inert annotation plane
536
+ * (`{ widget }`). An action POST rather than a member DELETE because a
537
+ * widget ref is a (page, annotation) pair — carrying it in the body keeps
538
+ * one codec instead of inventing a second composite key syntax.
539
+ */
540
+ layerFormFieldWidgetsDetach: (docId, layerName, fieldKey) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/fields/${encodeURIComponent(fieldKey)}/widgets/detach`,
541
+ /**
542
+ * GET: serialized form data (`?format=fdf|xfdf`, default `xfdf`).
543
+ * POST: import an FDF/XFDF payload (raw bytes body; format sniffed
544
+ * server-side unless `?format=` pins it).
545
+ */
546
+ layerFormData: (docId, layerName, format) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/data${format ? `?format=${format}` : ""}`,
547
+ /** POST: durable reconciliation (`{ bakeAppearances? }`). */
548
+ layerFormRepair: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/repair`,
549
+ layerFormEffects: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/form/effects`,
550
+ /**
551
+ * GET: one budgeted search slice, versioned form. The token
552
+ * (`encodeSearchToken`) IS the cache key: content epoch + query +
553
+ * position. Immutable; CDN may cache forever. Mode is the path — rects
554
+ * and full are separate resources so permission tiers never share
555
+ * cache entries (`'rects'` needs `doc.text.search`; `'full'` also
556
+ * needs `doc.text.copy`).
557
+ */
558
+ layerSearchRects: (docId, layerName, token) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/search/rects/data@${token}`,
559
+ layerSearchFull: (docId, layerName, token) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/search/full/data@${token}`,
560
+ /**
561
+ * GET: unversioned form — same fields as flat query params (`q` as
562
+ * plain text), served from the CURRENT content, always `no-store`.
563
+ * The debug/simple-client variant; the SDK uses the versioned form.
564
+ */
565
+ layerSearchRectsCurrent: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/search/rects/data`,
566
+ layerSearchFullCurrent: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/search/full/data`,
567
+ layerPagesMove: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/pages/move`,
568
+ layerPagesRotate: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/pages/rotate`,
569
+ layerPagesDelete: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/pages/delete`,
570
+ layerPagesFlatten: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/pages/flatten`,
571
+ layerRedactionsApply: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/redactions/apply`,
572
+ layerEvents: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/events`,
573
+ layerDownload: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/download`,
574
+ layerDownloadVersioned: (docId, layerName, token) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/download@${encodeDownloadToken(token)}`,
575
+ /**
576
+ * Weak-annotation-sessions: pluralized in v2 so the collection
577
+ * lives at `/weak-annotation-sessions` and members at
578
+ * `/weak-annotation-sessions/{sessionId}` — REST-conventional.
579
+ */
580
+ layerWeakAnnotationSession: (docId, layerName) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/weak-annotation-sessions`,
581
+ layerWeakAnnotationSessionHeartbeat: (docId, layerName, sessionId) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/weak-annotation-sessions/${encodeURIComponent(sessionId)}/heartbeat`,
582
+ layerWeakAnnotationSessionPages: (docId, layerName, sessionId) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/weak-annotation-sessions/${encodeURIComponent(sessionId)}/pages`,
583
+ layerWeakAnnotationSessionRelease: (docId, layerName, sessionId) => `/v1/docs/${encodeURIComponent(docId)}/layers/${encodeURIComponent(layerName)}/weak-annotation-sessions/${encodeURIComponent(sessionId)}`,
584
+ /**
585
+ * POST: pre-warm the doc cache + worker open before any user
586
+ * request lands. Body is `{ docId }`. Doc-scoped token required.
587
+ */
588
+ docWarm: "/v1/warm"
589
+ };
590
+ //#endregion
591
+ //#region src/wire/resources.ts
592
+ /**
593
+ * URL layout (paths v2): each resource type lives at a distinct path
594
+ * prefix so prefix-matching CDNs (Bunny, Cloud CDN, Azure FD) can
595
+ * enforce per-resource scope at the edge. See wire/paths.ts for the
596
+ * full shape and rationale.
597
+ */
598
+ const DOC_RESOURCES = {
599
+ head: {
600
+ id: "head",
601
+ pathPattern: "/v1/docs/{docId}/head",
602
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/head`,
603
+ pathPrefix: "/v1/docs/{docId}/head",
604
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/head`,
605
+ requirement: {
606
+ kind: "single",
607
+ capability: "doc.open"
608
+ },
609
+ routeKind: "origin",
610
+ cdnCacheable: false
611
+ },
612
+ manifest: {
613
+ id: "manifest",
614
+ pathPattern: "/v1/docs/{docId}/manifest@*",
615
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/manifest@*`,
616
+ pathPrefix: "/v1/docs/{docId}/manifest@",
617
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/manifest@`,
618
+ requirement: {
619
+ kind: "single",
620
+ capability: "doc.open"
621
+ },
622
+ routeKind: "versioned-read",
623
+ cdnCacheable: true
624
+ },
625
+ "layer-manifest": {
626
+ id: "layer-manifest",
627
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/manifest@*",
628
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/manifest@*`,
629
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/manifest@",
630
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/manifest@`,
631
+ requirement: {
632
+ kind: "single",
633
+ capability: "doc.open"
634
+ },
635
+ routeKind: "versioned-read",
636
+ cdnCacheable: true
637
+ },
638
+ "page-render": {
639
+ id: "page-render",
640
+ pathPattern: "/v1/docs/{docId}/render/pages/*/data@*",
641
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/render/pages/*/data@*`,
642
+ pathPrefix: "/v1/docs/{docId}/render/pages/",
643
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/render/pages/`,
644
+ requirement: {
645
+ kind: "single",
646
+ capability: "doc.render"
647
+ },
648
+ routeKind: "versioned-read",
649
+ cdnCacheable: true
650
+ },
651
+ "page-render-annotated": {
652
+ id: "page-render-annotated",
653
+ pathPattern: "/v1/docs/{docId}/render/annotated/pages/*/data@*",
654
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/render/annotated/pages/*/data@*`,
655
+ pathPrefix: "/v1/docs/{docId}/render/annotated/pages/",
656
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/render/annotated/pages/`,
657
+ requirement: {
658
+ kind: "single",
659
+ capability: "doc.render"
660
+ },
661
+ routeKind: "versioned-read",
662
+ cdnCacheable: true
663
+ },
664
+ "page-annotations": {
665
+ id: "page-annotations",
666
+ pathPattern: "/v1/docs/{docId}/annotations/pages/*/items@*",
667
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/annotations/pages/*/items@*`,
668
+ pathPrefix: "/v1/docs/{docId}/annotations/pages/",
669
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/annotations/pages/`,
670
+ requirement: {
671
+ kind: "single",
672
+ capability: "doc.annotate.read"
673
+ },
674
+ routeKind: "versioned-read",
675
+ cdnCacheable: true
676
+ },
677
+ layout: {
678
+ id: "layout",
679
+ pathPattern: "/v1/docs/{docId}/layout@*",
680
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/layout@*`,
681
+ pathPrefix: "/v1/docs/{docId}/layout@",
682
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/layout@`,
683
+ requirement: {
684
+ kind: "single",
685
+ capability: "doc.open"
686
+ },
687
+ routeKind: "versioned-read",
688
+ cdnCacheable: true
689
+ },
690
+ metadata: {
691
+ id: "metadata",
692
+ pathPattern: "/v1/docs/{docId}/metadata@*",
693
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/metadata@*`,
694
+ pathPrefix: "/v1/docs/{docId}/metadata@",
695
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/metadata@`,
696
+ requirement: {
697
+ kind: "single",
698
+ capability: "doc.open"
699
+ },
700
+ routeKind: "versioned-read",
701
+ cdnCacheable: true
702
+ },
703
+ actions: {
704
+ id: "actions",
705
+ pathPattern: "/v1/docs/{docId}/actions@*",
706
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/actions@*`,
707
+ pathPrefix: "/v1/docs/{docId}/actions@",
708
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/actions@`,
709
+ requirement: {
710
+ kind: "single",
711
+ capability: "doc.open"
712
+ },
713
+ routeKind: "versioned-read",
714
+ cdnCacheable: true
715
+ },
716
+ "layer-layout": {
717
+ id: "layer-layout",
718
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/layout@*",
719
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/layout@*`,
720
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/layout@",
721
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/layout@`,
722
+ requirement: {
723
+ kind: "single",
724
+ capability: "doc.open"
725
+ },
726
+ routeKind: "versioned-read",
727
+ cdnCacheable: true
728
+ },
729
+ "layer-metadata": {
730
+ id: "layer-metadata",
731
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/metadata@*",
732
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/metadata@*`,
733
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/metadata@",
734
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/metadata@`,
735
+ requirement: {
736
+ kind: "single",
737
+ capability: "doc.open"
738
+ },
739
+ routeKind: "versioned-read",
740
+ cdnCacheable: true
741
+ },
742
+ "layer-actions": {
743
+ id: "layer-actions",
744
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/actions@*",
745
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/actions@*`,
746
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/actions@",
747
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/actions@`,
748
+ requirement: {
749
+ kind: "single",
750
+ capability: "doc.open"
751
+ },
752
+ routeKind: "versioned-read",
753
+ cdnCacheable: true
754
+ },
755
+ attachments: {
756
+ id: "attachments",
757
+ pathPattern: "/v1/docs/{docId}/attachments@*",
758
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/attachments@*`,
759
+ pathPrefix: "/v1/docs/{docId}/attachments@",
760
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/attachments@`,
761
+ requirement: {
762
+ kind: "single",
763
+ capability: "doc.open"
764
+ },
765
+ routeKind: "versioned-read",
766
+ cdnCacheable: true
767
+ },
768
+ "attachment-files": {
769
+ id: "attachment-files",
770
+ pathPattern: "/v1/docs/{docId}/attachment-files/*",
771
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/attachment-files/*`,
772
+ pathPrefix: "/v1/docs/{docId}/attachment-files/",
773
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/attachment-files/`,
774
+ requirement: {
775
+ kind: "single",
776
+ capability: "doc.download"
777
+ },
778
+ routeKind: "versioned-read",
779
+ cdnCacheable: true
780
+ },
781
+ "layer-attachments": {
782
+ id: "layer-attachments",
783
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/attachments@*",
784
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/attachments@*`,
785
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/attachments@",
786
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/attachments@`,
787
+ requirement: {
788
+ kind: "single",
789
+ capability: "doc.open"
790
+ },
791
+ routeKind: "versioned-read",
792
+ cdnCacheable: true
793
+ },
794
+ "layer-attachment-files": {
795
+ id: "layer-attachment-files",
796
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/attachment-files/*",
797
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/attachment-files/*`,
798
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/attachment-files/",
799
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/attachment-files/`,
800
+ requirement: {
801
+ kind: "single",
802
+ capability: "doc.download"
803
+ },
804
+ routeKind: "versioned-read",
805
+ cdnCacheable: true
806
+ },
807
+ "layer-page-render": {
808
+ id: "layer-page-render",
809
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/render/pages/*/data@*",
810
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/render/pages/*/data@*`,
811
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/render/pages/",
812
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/render/pages/`,
813
+ requirement: {
814
+ kind: "single",
815
+ capability: "doc.render"
816
+ },
817
+ routeKind: "versioned-read",
818
+ cdnCacheable: true
819
+ },
820
+ "layer-page-render-annotated": {
821
+ id: "layer-page-render-annotated",
822
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/render/annotated/pages/*/data@*",
823
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/render/annotated/pages/*/data@*`,
824
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/render/annotated/pages/",
825
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/render/annotated/pages/`,
826
+ requirement: {
827
+ kind: "single",
828
+ capability: "doc.render"
829
+ },
830
+ routeKind: "versioned-read",
831
+ cdnCacheable: true
832
+ },
833
+ "page-text": {
834
+ id: "page-text",
835
+ pathPattern: "/v1/docs/{docId}/text/pages/*/data@*",
836
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/text/pages/*/data@*`,
837
+ pathPrefix: "/v1/docs/{docId}/text/pages/",
838
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/text/pages/`,
839
+ requirement: {
840
+ kind: "single",
841
+ capability: "doc.text.copy"
842
+ },
843
+ routeKind: "versioned-read",
844
+ cdnCacheable: true
845
+ },
846
+ "layer-page-text": {
847
+ id: "layer-page-text",
848
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/text/pages/*/data@*",
849
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/text/pages/*/data@*`,
850
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/text/pages/",
851
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/text/pages/`,
852
+ requirement: {
853
+ kind: "single",
854
+ capability: "doc.text.copy"
855
+ },
856
+ routeKind: "versioned-read",
857
+ cdnCacheable: true
858
+ },
859
+ "page-geometry": {
860
+ id: "page-geometry",
861
+ pathPattern: "/v1/docs/{docId}/geometry/pages/*/data@*",
862
+ resolvePathPattern: (docId) => `/v1/docs/${docId}/geometry/pages/*/data@*`,
863
+ pathPrefix: "/v1/docs/{docId}/geometry/pages/",
864
+ resolvePathPrefix: (docId) => `/v1/docs/${docId}/geometry/pages/`,
865
+ requirement: {
866
+ kind: "single",
867
+ capability: "doc.text.select"
868
+ },
869
+ routeKind: "versioned-read",
870
+ cdnCacheable: true
871
+ },
872
+ "layer-page-geometry": {
873
+ id: "layer-page-geometry",
874
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/geometry/pages/*/data@*",
875
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/geometry/pages/*/data@*`,
876
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/geometry/pages/",
877
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/geometry/pages/`,
878
+ requirement: {
879
+ kind: "single",
880
+ capability: "doc.text.select"
881
+ },
882
+ routeKind: "versioned-read",
883
+ cdnCacheable: true
884
+ },
885
+ "layer-search-rects": {
886
+ id: "layer-search-rects",
887
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/search/rects/data@*",
888
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/search/rects/data@*`,
889
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/search/rects/data@",
890
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/search/rects/data@`,
891
+ requirement: {
892
+ kind: "single",
893
+ capability: "doc.text.search"
894
+ },
895
+ routeKind: "versioned-read",
896
+ cdnCacheable: true
897
+ },
898
+ "layer-search-full": {
899
+ id: "layer-search-full",
900
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/search/full/data@*",
901
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/search/full/data@*`,
902
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/search/full/data@",
903
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/search/full/data@`,
904
+ requirement: {
905
+ kind: "all",
906
+ capabilities: ["doc.text.search", "doc.text.copy"]
907
+ },
908
+ routeKind: "versioned-read",
909
+ cdnCacheable: true
910
+ },
911
+ "annotations-read": {
912
+ id: "annotations-read",
913
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/annotations/pages/*/items@*",
914
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/annotations/pages/*/items@*`,
915
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/annotations/pages/",
916
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/annotations/pages/`,
917
+ requirement: {
918
+ kind: "single",
919
+ capability: "doc.annotate.read"
920
+ },
921
+ routeKind: "versioned-read",
922
+ cdnCacheable: true
923
+ },
924
+ "download-current": {
925
+ id: "download-current",
926
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/download",
927
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/download`,
928
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/download",
929
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/download`,
930
+ requirement: {
931
+ kind: "single",
932
+ capability: "doc.download"
933
+ },
934
+ routeKind: "origin",
935
+ cdnCacheable: false
936
+ },
937
+ "download-versioned": {
938
+ id: "download-versioned",
939
+ pathPattern: "/v1/docs/{docId}/layers/{layerName}/download@*",
940
+ resolvePathPattern: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/download@*`,
941
+ pathPrefix: "/v1/docs/{docId}/layers/{layerName}/download@",
942
+ resolvePathPrefix: (docId, layerName = "default") => `/v1/docs/${docId}/layers/${layerName}/download@`,
943
+ requirement: {
944
+ kind: "single",
945
+ capability: "doc.download"
946
+ },
947
+ routeKind: "versioned-read",
948
+ cdnCacheable: true
949
+ }
950
+ };
951
+ /**
952
+ * True iff the scope grants access to the named resource.
953
+ *
954
+ * Looks up the resource descriptor, then dispatches to
955
+ * `checkCapability` or `checkAnyCapability` based on the requirement
956
+ * shape. Used by both server route guards and the CDN signer.
957
+ */
958
+ function checkResourceAccess(resourceId, rawScope, pdfBits) {
959
+ const r = DOC_RESOURCES[resourceId];
960
+ switch (r.requirement.kind) {
961
+ case "single": return require_resolver.checkCapability(r.requirement.capability, rawScope, pdfBits);
962
+ case "any": return require_resolver.checkAnyCapability(r.requirement.capabilities, rawScope, pdfBits);
963
+ case "all": return r.requirement.capabilities.every((cap) => require_resolver.checkCapability(cap, rawScope, pdfBits));
964
+ }
965
+ }
966
+ //#endregion
967
+ //#region src/wire/cdn/coverage.ts
968
+ /**
969
+ * Enumerate the CDN-cacheable resources the scope can access. Returns
970
+ * one {@link CdnCoverageEntry} per granted cacheable resource, carrying
971
+ * both the pattern and the prefix so each adapter can pick the
972
+ * projection it needs.
973
+ *
974
+ * Resources that are not cacheable (head, download-current) are
975
+ * filtered out automatically — they're still gated by their
976
+ * `requirement` at the origin route, but the CDN never gets a
977
+ * credential for them.
978
+ *
979
+ * The URL restructure (paths v2) guarantees each cacheable resource
980
+ * type has a distinct prefix, so prefix-matching adapters get
981
+ * per-resource scope enforcement at the edge — a Bunny token signed
982
+ * at `/v1/docs/{id}/render/pages/` can only authorize render bytes,
983
+ * never text or annotations.
984
+ */
985
+ /**
986
+ * Plane map: the planes each DOC-LEVEL shared resource depends on. A
987
+ * layer token's edge credential covers a resource's prefix iff EVERY listed
988
+ * plane is inherited (`'base'`) in the caller's scopes — the same condition
989
+ * the origin guard enforces (origin is the truth; this grant is the
990
+ * TTL-bounded optimization). Resources absent from this map (head, manifest,
991
+ * every layer-scoped resource) are not plane-gated.
992
+ *
993
+ * `attachment-files` deliberately lists only `attachments` even though its
994
+ * prefix also serves FileAttachment-annotation bytes (an `annotations`-plane
995
+ * read): the origin guard on that route additionally requires `annotations`
996
+ * inherited, and withholding the whole prefix on annotation divergence would
997
+ * break plain attachment-file sharing for the most common divergence. The
998
+ * residual is a warm-edge window bounded by the grant TTL — the same class
999
+ * as every edge grant.
1000
+ */
1001
+ const RESOURCE_PLANES = {
1002
+ "page-render": ["content"],
1003
+ "page-text": ["content"],
1004
+ "page-geometry": ["content"],
1005
+ "page-render-annotated": ["content", "annotations"],
1006
+ "page-annotations": ["annotations"],
1007
+ layout: ["layout"],
1008
+ metadata: ["metadata"],
1009
+ actions: ["actions"],
1010
+ attachments: ["attachments"],
1011
+ "attachment-files": ["attachments"]
1012
+ };
1013
+ function cdnCoverageForScope(rawScope, pdfBits, context) {
1014
+ const out = [];
1015
+ const scopes = context.scopes;
1016
+ for (const id of Object.keys(DOC_RESOURCES)) {
1017
+ const r = DOC_RESOURCES[id];
1018
+ if (!r.cdnCacheable) continue;
1019
+ const planes = RESOURCE_PLANES[id];
1020
+ if (planes && scopes && planes.some((plane) => scopes[plane] === "layer")) continue;
1021
+ if (!checkResourceAccess(id, rawScope, pdfBits)) continue;
1022
+ out.push({
1023
+ resourceId: id,
1024
+ pathPattern: r.resolvePathPattern(context.docId, context.layerName),
1025
+ pathPrefix: r.resolvePathPrefix(context.docId, context.layerName)
1026
+ });
1027
+ }
1028
+ return out;
1029
+ }
1030
+ //#endregion
1031
+ //#region src/wire/cdn/applyCdnAccess.ts
1032
+ /**
1033
+ * Pure function that turns a request path + a `CdnAccessInfo` block
1034
+ * into the final URL the SDK should hit, plus any header/cookie side
1035
+ * effects to attach. Used by both:
1036
+ * - the @cloudpdf/engine HttpClient (to actually route requests through
1037
+ * the CDN edge when an /access response says it can)
1038
+ * - the smoke/diagnostic inspector (to PREVIEW what the SDK would do
1039
+ * for a given path, with no network)
1040
+ *
1041
+ * Keeping this in engine-core means cloud-side request routing and
1042
+ * server-side test fixtures use the SAME algorithm. If a regression
1043
+ * sneaks in, both ends break together.
1044
+ *
1045
+ * Selection rules
1046
+ * ───────────────
1047
+ * 1. Resolve the request path to a `DocResourceId` via DOC_RESOURCES
1048
+ * (longest-prefix-match on the resolved `pathPrefix`). Routes
1049
+ * that don't map to a known resource (admin, /access itself) get
1050
+ * `routedToCdn: false` and stay on origin.
1051
+ * 2. If `baseUrlOverrides[resourceId]` exists, swap the request's
1052
+ * origin to that CDN origin. If absent, the request stays on
1053
+ * origin — that's how scope narrowing works at the edge: the
1054
+ * server only emits overrides for resources the caller's scope
1055
+ * grants.
1056
+ * 3. Find the LONGEST-matching `signedPathPolicies` entry (its
1057
+ * `pathPrefix` is a prefix of the request path). Append its
1058
+ * `queryParams`. No match falls back to `signedQueryParams` if
1059
+ * the adapter emitted a global token.
1060
+ * 4. `signedCookies` and `authHeader` are surfaced verbatim — the
1061
+ * HttpClient sets cookies once per session and applies the
1062
+ * header to every CDN request.
1063
+ */
1064
+ function applyCdnAccess(input) {
1065
+ const { path, originUrl, docId, layerName, cdn } = input;
1066
+ const resourceId = resolveResourceIdForPath(path, docId, layerName ?? "default");
1067
+ if (!cdn || cdn.adapter === "none") return {
1068
+ url: `${trimRight(originUrl)}${path}`,
1069
+ resourceId,
1070
+ routedToCdn: false,
1071
+ matchedPolicy: null,
1072
+ authHeader: null,
1073
+ cookies: null,
1074
+ fallbackReason: cdn ? "CDN signer is `none` — every request stays on origin." : "No CdnAccessInfo on this session — request stays on origin."
1075
+ };
1076
+ if (!resourceId) return {
1077
+ url: `${trimRight(originUrl)}${path}`,
1078
+ resourceId: null,
1079
+ routedToCdn: false,
1080
+ matchedPolicy: null,
1081
+ authHeader: null,
1082
+ cookies: null,
1083
+ fallbackReason: "Request path does not match any known DOC_RESOURCES route."
1084
+ };
1085
+ const cdnOrigin = cdn.baseUrlOverrides?.[resourceId];
1086
+ if (!cdnOrigin) return {
1087
+ url: `${trimRight(originUrl)}${path}`,
1088
+ resourceId,
1089
+ routedToCdn: false,
1090
+ matchedPolicy: null,
1091
+ authHeader: null,
1092
+ cookies: null,
1093
+ fallbackReason: `No baseUrlOverrides[${resourceId}] — scope does not grant this resource through the CDN.`
1094
+ };
1095
+ const matchedPolicy = (cdn.signedPathPolicies ?? []).filter((p) => path.startsWith(p.pathPrefix)).sort((a, b) => b.pathPrefix.length - a.pathPrefix.length)[0];
1096
+ const url = new URL(`${trimRight(cdnOrigin)}${path}`);
1097
+ if (matchedPolicy) for (const [k, v] of Object.entries(matchedPolicy.queryParams)) url.searchParams.set(k, v);
1098
+ else if (cdn.signedQueryParams) for (const [k, v] of Object.entries(cdn.signedQueryParams)) url.searchParams.set(k, v);
1099
+ return {
1100
+ url: url.toString(),
1101
+ resourceId,
1102
+ routedToCdn: true,
1103
+ matchedPolicy: matchedPolicy ? {
1104
+ pathPrefix: matchedPolicy.pathPrefix,
1105
+ queryParams: matchedPolicy.queryParams
1106
+ } : null,
1107
+ authHeader: cdn.authHeader,
1108
+ cookies: cdn.signedCookies,
1109
+ fallbackReason: ""
1110
+ };
1111
+ }
1112
+ /**
1113
+ * Walk DOC_RESOURCES and pick the entry whose resolved `pathPrefix`
1114
+ * is a (longest) prefix of `path`. Returns null when no resource
1115
+ * matches — admin routes, /access, /warm fall into this bucket.
1116
+ *
1117
+ * Each cacheable resource has a DISTINCT prefix (paths v2 invariant),
1118
+ * so longest-match is deterministic.
1119
+ */
1120
+ function resolveResourceIdForPath(path, docId, layerName) {
1121
+ let best = null;
1122
+ for (const id of Object.keys(DOC_RESOURCES)) {
1123
+ const prefix = DOC_RESOURCES[id].resolvePathPrefix(docId, layerName);
1124
+ if (!path.startsWith(prefix)) continue;
1125
+ if (!best || prefix.length > best.prefixLength) best = {
1126
+ id,
1127
+ prefixLength: prefix.length
1128
+ };
1129
+ }
1130
+ return best?.id ?? null;
1131
+ }
1132
+ function trimRight(url) {
1133
+ return url.endsWith("/") ? url.slice(0, -1) : url;
1134
+ }
1135
+ //#endregion
1136
+ //#region src/wire/flatten.ts
1137
+ const PATH_SEPARATOR = ".";
1138
+ function flatten(value, prefix = "") {
1139
+ const out = {};
1140
+ flattenInto(value, prefix, out);
1141
+ return out;
1142
+ }
1143
+ function flattenInto(value, prefix, out) {
1144
+ if (value === void 0 || value === null) return;
1145
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1146
+ if (!prefix) throw new Error("flatten: root value must be an object, not a scalar");
1147
+ if (typeof value === "number" && !Number.isFinite(value)) throw new Error(`flatten: non-finite number at "${prefix}"`);
1148
+ out[prefix] = value;
1149
+ return;
1150
+ }
1151
+ if (Array.isArray(value)) throw new Error(`flatten: arrays are not supported (at "${prefix || "<root>"}")`);
1152
+ if (typeof value !== "object") throw new Error(`flatten: unsupported value type at "${prefix || "<root>"}"`);
1153
+ for (const [k, v] of Object.entries(value)) {
1154
+ if (k.includes(PATH_SEPARATOR)) throw new Error(`flatten: object key "${k}" must not contain "${PATH_SEPARATOR}"`);
1155
+ flattenInto(v, prefix ? `${prefix}${PATH_SEPARATOR}${k}` : k, out);
1156
+ }
1157
+ }
1158
+ /**
1159
+ * Inverse of `flatten`. Takes a flat string-or-scalar map and reconstructs a
1160
+ * nested object using `.` as the path separator. Values are passed through
1161
+ * unchanged — downstream schema validation (e.g. Zod with `.coerce`) is
1162
+ * responsible for type coercion from `string` to numbers/booleans when the
1163
+ * input came from a token or query string.
1164
+ *
1165
+ * Throws on conflicting paths (e.g. having both `viewport` and
1166
+ * `viewport.kind` in the same input).
1167
+ */
1168
+ function unflatten(flat) {
1169
+ const root = {};
1170
+ for (const [key, value] of Object.entries(flat)) {
1171
+ if (value === void 0) continue;
1172
+ if (key.length === 0) throw new Error("unflatten: empty key");
1173
+ if (key.startsWith(PATH_SEPARATOR) || key.endsWith(PATH_SEPARATOR)) throw new Error(`unflatten: key "${key}" must not start or end with "${PATH_SEPARATOR}"`);
1174
+ if (key.includes(`${PATH_SEPARATOR}${PATH_SEPARATOR}`)) throw new Error(`unflatten: key "${key}" must not contain empty segments`);
1175
+ const path = key.split(PATH_SEPARATOR);
1176
+ let cur = root;
1177
+ for (let i = 0; i < path.length - 1; i++) {
1178
+ const seg = path[i];
1179
+ const existing = cur[seg];
1180
+ if (existing === void 0) {
1181
+ const next = {};
1182
+ cur[seg] = next;
1183
+ cur = next;
1184
+ continue;
1185
+ }
1186
+ if (existing === null || typeof existing !== "object" || Array.isArray(existing)) throw new Error(`unflatten: conflicting paths at "${path.slice(0, i + 1).join(PATH_SEPARATOR)}"`);
1187
+ cur = existing;
1188
+ }
1189
+ const leaf = path[path.length - 1];
1190
+ if (cur[leaf] !== void 0) throw new Error(`unflatten: duplicate key "${key}"`);
1191
+ cur[leaf] = value;
1192
+ }
1193
+ return root;
1194
+ }
1195
+ //#endregion
1196
+ //#region src/wire/renderOptionsCodec.ts
1197
+ /**
1198
+ * Project image render options plus cache versions into the flat wire shape
1199
+ * the render token encoder consumes. The output is a generic dotted-key map
1200
+ * (`viewport.kind`, `target.rect.left`, …) — the schema and codec never need
1201
+ * to know about specific option fields. Adding a new render option means
1202
+ * extending `PageImageOptions`, the render query schemas, and
1203
+ * `RenderTokenSchema.fields`; this function does not change.
1204
+ *
1205
+ * Token/path rule: tokens carry VERSION PINS and RENDER
1206
+ * PARAMETERS; anything that changes the artifact's plane-dependency set is
1207
+ * PATH-expressed. Annotatedness changes the planes (`content` vs
1208
+ * `content + annotations`), so the wire map never carries
1209
+ * `includeAnnotations` — the caller picks the path FAMILY
1210
+ * (`…/render/pages/` vs `…/render/annotated/pages/`) and passes
1211
+ * `annotationVersion` iff it chose the annotated one. Contradictory states
1212
+ * are unrepresentable; each family's query schema enforces its own pin
1213
+ * grammar structurally.
1214
+ *
1215
+ * Semantic validation (viewport-kind invariants, per-family pin presence,
1216
+ * rect coherence) lives in `PageRenderQuerySchema` /
1217
+ * `PageRenderAnnotatedQuerySchema` and runs when the resulting URL is
1218
+ * decoded server-side. Round-tripping (flatten → encode → decode →
1219
+ * unflatten → schema parse) recovers the original SDK options.
1220
+ */
1221
+ function renderImageOptionsToWire(options, versions) {
1222
+ const { includeAnnotations: _pathExpressed, ...wireOptions } = options;
1223
+ return flatten({
1224
+ ...wireOptions,
1225
+ contentVersion: versions.contentVersion,
1226
+ ...versions.annotationVersion !== void 0 ? { annotationVersion: versions.annotationVersion } : {}
1227
+ });
1228
+ }
1229
+ /**
1230
+ * Convenience: build the full encoded render token in one call. Equivalent
1231
+ * to `encodeRenderToken(renderImageOptionsToWire(options, versions))`.
1232
+ */
1233
+ function renderImageOptionsToToken(options, versions) {
1234
+ return encodeRenderToken(renderImageOptionsToWire(options, versions));
1235
+ }
1236
+ /**
1237
+ * Re-attach `includeAnnotations` onto the worker-side `PageRenderOptions`
1238
+ * shape. Pure shape transform; consumed by the server route after
1239
+ * `PageRenderQuerySchema` has produced the SDK-shaped options.
1240
+ */
1241
+ function pageRenderOptionsFromImageOptions(options, includeAnnotations) {
1242
+ return {
1243
+ ...options.target ? { target: options.target } : {},
1244
+ ...options.viewport ? { viewport: options.viewport } : {},
1245
+ ...options.rotation !== void 0 ? { rotation: options.rotation } : {},
1246
+ ...options.background !== void 0 ? { background: options.background } : {},
1247
+ includeAnnotations
1248
+ };
1249
+ }
1250
+ /**
1251
+ * Project annotation-appearance image options plus the annotation version
1252
+ * into the flat wire shape the appearance render token encoder consumes.
1253
+ * Mirrors {@link renderImageOptionsToWire}.
1254
+ */
1255
+ function annotationAppearancesImageOptionsToWire(options, versions) {
1256
+ return flatten({
1257
+ ...options,
1258
+ annotationVersion: versions.annotationVersion
1259
+ });
1260
+ }
1261
+ /** Convenience: build the full encoded appearance render token in one call. */
1262
+ function annotationAppearancesImageOptionsToToken(options, versions) {
1263
+ return encodeAnnotationAppearancesRenderToken(annotationAppearancesImageOptionsToWire(options, versions));
1264
+ }
1265
+ /**
1266
+ * Strip image-encoding fields, leaving the worker-side
1267
+ * `AnnotationAppearanceRenderOptions`. Pure shape transform consumed by the
1268
+ * server route after `AnnotationAppearancesQuerySchema` produces the
1269
+ * SDK-shaped options.
1270
+ */
1271
+ function annotationRenderOptionsFromImageOptions(options) {
1272
+ return {
1273
+ ...options.scale !== void 0 ? { scale: options.scale } : {},
1274
+ ...options.rotation !== void 0 ? { rotation: options.rotation } : {},
1275
+ ...options.modes ? { modes: options.modes } : {}
1276
+ };
1277
+ }
1278
+ //#endregion
1279
+ exports.ANNOTATION_KINDS = require_schemas.ANNOTATION_KINDS;
1280
+ exports.AccessRequestSchema = require_schemas.AccessRequestSchema;
1281
+ exports.AccessResponseSchema = require_schemas.AccessResponseSchema;
1282
+ exports.ActionsTokenSchema = ActionsTokenSchema;
1283
+ exports.AnnotationAppearanceManifestSchema = require_schemas.AnnotationAppearanceManifestSchema;
1284
+ exports.AnnotationAppearancesQuerySchema = require_schemas.AnnotationAppearancesQuerySchema;
1285
+ exports.AnnotationAppearancesRenderTokenSchema = AnnotationAppearancesRenderTokenSchema;
1286
+ exports.AnnotationBaseShape = require_schemas.AnnotationBaseShape;
1287
+ exports.AnnotationBorderStyleSchema = require_schemas.AnnotationBorderStyleSchema;
1288
+ exports.AnnotationCreateResultSchema = require_schemas.AnnotationCreateResultSchema;
1289
+ exports.AnnotationDTOSchema = require_schemas.AnnotationDTOSchema;
1290
+ exports.AnnotationDeleteResultSchema = require_schemas.AnnotationDeleteResultSchema;
1291
+ exports.AnnotationDraftBaseShape = require_schemas.AnnotationDraftBaseShape;
1292
+ exports.AnnotationDraftSchema = require_schemas.AnnotationDraftSchema;
1293
+ exports.AnnotationFlagsPartialSchema = require_schemas.AnnotationFlagsPartialSchema;
1294
+ exports.AnnotationFlagsSchema = require_schemas.AnnotationFlagsSchema;
1295
+ exports.AnnotationListMutationMetaSchema = require_schemas.AnnotationListMutationMetaSchema;
1296
+ exports.AnnotationListPageSnapshotSchema = require_schemas.AnnotationListPageSnapshotSchema;
1297
+ exports.AnnotationListSnapshotAllPagesSchema = require_schemas.AnnotationListSnapshotAllPagesSchema;
1298
+ exports.AnnotationMoveResultSchema = require_schemas.AnnotationMoveResultSchema;
1299
+ exports.AnnotationPatchBaseShape = require_schemas.AnnotationPatchBaseShape;
1300
+ exports.AnnotationPatchSchema = require_schemas.AnnotationPatchSchema;
1301
+ exports.AnnotationRefSchema = require_schemas.AnnotationRefSchema;
1302
+ exports.AnnotationStableIdSchema = require_schemas.AnnotationStableIdSchema;
1303
+ exports.AnnotationTokenSchema = AnnotationTokenSchema;
1304
+ exports.AnnotationUpdateResultSchema = require_schemas.AnnotationUpdateResultSchema;
1305
+ exports.AppearanceOutcomeSchema = require_schemas.AppearanceOutcomeSchema;
1306
+ exports.AttachmentCreateResultSchema = require_schemas.AttachmentCreateResultSchema;
1307
+ exports.AttachmentDeleteResultSchema = require_schemas.AttachmentDeleteResultSchema;
1308
+ exports.AttachmentFileInfoSchema = require_schemas.AttachmentFileInfoSchema;
1309
+ exports.AttachmentsCacheSchema = require_schemas.AttachmentsCacheSchema;
1310
+ exports.BlendModeSchema = require_schemas.BlendModeSchema;
1311
+ exports.CacheDeltaSchema = require_schemas.CacheDeltaSchema;
1312
+ exports.CachePinsSchema = require_schemas.CachePinsSchema;
1313
+ exports.CalloutLineSchema = require_schemas.CalloutLineSchema;
1314
+ exports.CaretDTOSchema = require_schemas.CaretDTOSchema;
1315
+ exports.CaretDraftSchema = require_schemas.CaretDraftSchema;
1316
+ exports.CaretIntentSchema = require_schemas.CaretIntentSchema;
1317
+ exports.CaretPatchSchema = require_schemas.CaretPatchSchema;
1318
+ exports.CircleDTOSchema = require_schemas.CircleDTOSchema;
1319
+ exports.CircleDraftSchema = require_schemas.CircleDraftSchema;
1320
+ exports.CirclePatchSchema = require_schemas.CirclePatchSchema;
1321
+ exports.ColorSchema = require_schemas.ColorSchema;
1322
+ exports.ContentTokenSchema = ContentTokenSchema;
1323
+ exports.DEFAULT_LAYER_NAME = DEFAULT_LAYER_NAME;
1324
+ exports.DOC_RESOURCES = DOC_RESOURCES;
1325
+ exports.DocTokenSchema = DocTokenSchema;
1326
+ exports.DocumentActionsSnapshotSchema = require_schemas.DocumentActionsSnapshotSchema;
1327
+ exports.DocumentHeadSchema = require_schemas.DocumentHeadSchema;
1328
+ exports.DocumentManifestSchema = require_schemas.DocumentManifestSchema;
1329
+ exports.DocumentMetadataSchema = require_schemas.DocumentMetadataSchema;
1330
+ exports.DocumentSecurityStateSchema = require_schemas.DocumentSecurityStateSchema;
1331
+ exports.EmbeddedFileItemSchema = require_schemas.EmbeddedFileItemSchema;
1332
+ exports.EmbeddedFileRefSchema = require_schemas.EmbeddedFileRefSchema;
1333
+ exports.EngineErrorPayloadSchema = require_schemas.EngineErrorPayloadSchema;
1334
+ exports.FileAttachmentDTOSchema = require_schemas.FileAttachmentDTOSchema;
1335
+ exports.FileAttachmentIconSchema = require_schemas.FileAttachmentIconSchema;
1336
+ exports.FileAttachmentPatchSchema = require_schemas.FileAttachmentPatchSchema;
1337
+ exports.FileAttachmentWireDraftSchema = require_schemas.FileAttachmentWireDraftSchema;
1338
+ exports.FormDataFormatSchema = require_schemas.FormDataFormatSchema;
1339
+ exports.FormEffectSchema = require_schemas.FormEffectSchema;
1340
+ exports.FormEffectsResultSchema = require_schemas.FormEffectsResultSchema;
1341
+ exports.FormFieldCreateResultSchema = require_schemas.FormFieldCreateResultSchema;
1342
+ exports.FormFieldDTOSchema = require_schemas.FormFieldDTOSchema;
1343
+ exports.FormFieldDeleteResultSchema = require_schemas.FormFieldDeleteResultSchema;
1344
+ exports.FormFieldDraftSchema = require_schemas.FormFieldDraftSchema;
1345
+ exports.FormFieldFlagsSchema = require_schemas.FormFieldFlagsSchema;
1346
+ exports.FormFieldOptionInputSchema = require_schemas.FormFieldOptionInputSchema;
1347
+ exports.FormFieldOptionSchema = require_schemas.FormFieldOptionSchema;
1348
+ exports.FormFieldPatchSchema = require_schemas.FormFieldPatchSchema;
1349
+ exports.FormFieldRefSchema = require_schemas.FormFieldRefSchema;
1350
+ exports.FormFieldUpdateResultSchema = require_schemas.FormFieldUpdateResultSchema;
1351
+ exports.FormFieldValueSchema = require_schemas.FormFieldValueSchema;
1352
+ exports.FormImportResultSchema = require_schemas.FormImportResultSchema;
1353
+ exports.FormKindSchema = require_schemas.FormKindSchema;
1354
+ exports.FormRepairResultSchema = require_schemas.FormRepairResultSchema;
1355
+ exports.FormSetValueResultSchema = require_schemas.FormSetValueResultSchema;
1356
+ exports.FormSnapshotSchema = require_schemas.FormSnapshotSchema;
1357
+ exports.FormValueEntrySchema = require_schemas.FormValueEntrySchema;
1358
+ exports.FormWidgetLinkResultSchema = require_schemas.FormWidgetLinkResultSchema;
1359
+ exports.FormWidgetRefSchema = require_schemas.FormWidgetRefSchema;
1360
+ exports.FreeTextDTOSchema = require_schemas.FreeTextDTOSchema;
1361
+ exports.FreeTextDraftSchema = require_schemas.FreeTextDraftSchema;
1362
+ exports.FreeTextIntentSchema = require_schemas.FreeTextIntentSchema;
1363
+ exports.FreeTextPatchSchema = require_schemas.FreeTextPatchSchema;
1364
+ exports.HighlightDTOSchema = require_schemas.HighlightDTOSchema;
1365
+ exports.HighlightDraftSchema = require_schemas.HighlightDraftSchema;
1366
+ exports.HighlightPatchSchema = require_schemas.HighlightPatchSchema;
1367
+ exports.InkDTOSchema = require_schemas.InkDTOSchema;
1368
+ exports.InkDraftSchema = require_schemas.InkDraftSchema;
1369
+ exports.InkIntentSchema = require_schemas.InkIntentSchema;
1370
+ exports.InkListSchema = require_schemas.InkListSchema;
1371
+ exports.InkPatchSchema = require_schemas.InkPatchSchema;
1372
+ exports.KIND_BY_SUBTYPE = require_schemas.KIND_BY_SUBTYPE;
1373
+ exports.LayerScopesSchema = require_schemas.LayerScopesSchema;
1374
+ exports.LayoutTokenSchema = LayoutTokenSchema;
1375
+ exports.LineDTOSchema = require_schemas.LineDTOSchema;
1376
+ exports.LineDraftSchema = require_schemas.LineDraftSchema;
1377
+ exports.LineEndingSchema = require_schemas.LineEndingSchema;
1378
+ exports.LineEndingsSchema = require_schemas.LineEndingsSchema;
1379
+ exports.LinePatchSchema = require_schemas.LinePatchSchema;
1380
+ exports.LinePointsSchema = require_schemas.LinePointsSchema;
1381
+ exports.LinkDTOSchema = require_schemas.LinkDTOSchema;
1382
+ exports.LinkDraftSchema = require_schemas.LinkDraftSchema;
1383
+ exports.LinkPatchSchema = require_schemas.LinkPatchSchema;
1384
+ exports.ManifestPageSchema = require_schemas.ManifestPageSchema;
1385
+ exports.MetadataPatchSchema = require_schemas.MetadataPatchSchema;
1386
+ exports.MetadataTokenSchema = MetadataTokenSchema;
1387
+ exports.MetadataUpdateResultSchema = require_schemas.MetadataUpdateResultSchema;
1388
+ exports.MutationMetaSchema = require_schemas.MutationMetaSchema;
1389
+ exports.NoteIconSchema = require_schemas.NoteIconSchema;
1390
+ exports.OpenDocumentResponseSchema = require_schemas.OpenDocumentResponseSchema;
1391
+ exports.PageBoxesSchema = require_schemas.PageBoxesSchema;
1392
+ exports.PageDeleteInputSchema = require_schemas.PageDeleteInputSchema;
1393
+ exports.PageDeleteResultSchema = require_schemas.PageDeleteResultSchema;
1394
+ exports.PageFlattenInputSchema = require_schemas.PageFlattenInputSchema;
1395
+ exports.PageFlattenResultSchema = require_schemas.PageFlattenResultSchema;
1396
+ exports.PageGeometrySnapshotSchema = require_schemas.PageGeometrySnapshotSchema;
1397
+ exports.PageLayoutSchema = require_schemas.PageLayoutSchema;
1398
+ exports.PageListSnapshotSchema = require_schemas.PageListSnapshotSchema;
1399
+ exports.PageMoveInputSchema = require_schemas.PageMoveInputSchema;
1400
+ exports.PageMoveResultSchema = require_schemas.PageMoveResultSchema;
1401
+ exports.PageNetworkRenderFormatSchema = require_schemas.PageNetworkRenderFormatSchema;
1402
+ exports.PageRenderAnnotatedQuerySchema = require_schemas.PageRenderAnnotatedQuerySchema;
1403
+ exports.PageRenderQuerySchema = require_schemas.PageRenderQuerySchema;
1404
+ exports.PageRotateInputSchema = require_schemas.PageRotateInputSchema;
1405
+ exports.PageRotateResultSchema = require_schemas.PageRotateResultSchema;
1406
+ exports.PageStateSchema = require_schemas.PageStateSchema;
1407
+ exports.PageStructureCacheSchema = require_schemas.PageStructureCacheSchema;
1408
+ exports.PageTextSnapshotSchema = require_schemas.PageTextSnapshotSchema;
1409
+ exports.PdfActionNodeSchema = require_schemas.PdfActionNodeSchema;
1410
+ exports.PdfActionTreeSchema = require_schemas.PdfActionTreeSchema;
1411
+ exports.PdfActionTypeSchema = require_schemas.PdfActionTypeSchema;
1412
+ exports.PdfAnnotationActionsSchema = require_schemas.PdfAnnotationActionsSchema;
1413
+ exports.PdfDestinationSchema = require_schemas.PdfDestinationSchema;
1414
+ exports.PdfFieldActionsSchema = require_schemas.PdfFieldActionsSchema;
1415
+ exports.PdfLinkTargetSchema = require_schemas.PdfLinkTargetSchema;
1416
+ exports.PdfLinkTargetWritableSchema = require_schemas.PdfLinkTargetWritableSchema;
1417
+ exports.PdfPageActionsSchema = require_schemas.PdfPageActionsSchema;
1418
+ exports.PdfPointSchema = require_schemas.PdfPointSchema;
1419
+ exports.PdfQuadSchema = require_schemas.PdfQuadSchema;
1420
+ exports.PdfRectDifferencesSchema = require_schemas.PdfRectDifferencesSchema;
1421
+ exports.PdfRectSchema = require_schemas.PdfRectSchema;
1422
+ exports.PdfRotationSchema = require_schemas.PdfRotationSchema;
1423
+ exports.PdfSaveModeSchema = require_schemas.PdfSaveModeSchema;
1424
+ exports.PdfSizeSchema = require_schemas.PdfSizeSchema;
1425
+ exports.PointSchema = require_schemas.PointSchema;
1426
+ exports.PolygonDTOSchema = require_schemas.PolygonDTOSchema;
1427
+ exports.PolygonDraftSchema = require_schemas.PolygonDraftSchema;
1428
+ exports.PolygonPatchSchema = require_schemas.PolygonPatchSchema;
1429
+ exports.PolylineDTOSchema = require_schemas.PolylineDTOSchema;
1430
+ exports.PolylineDraftSchema = require_schemas.PolylineDraftSchema;
1431
+ exports.PolylinePatchSchema = require_schemas.PolylinePatchSchema;
1432
+ exports.RectSchema = require_schemas.RectSchema;
1433
+ exports.RedactionApplyResultSchema = require_schemas.RedactionApplyResultSchema;
1434
+ exports.RedactionApplyScopeSchema = require_schemas.RedactionApplyScopeSchema;
1435
+ exports.RefetchReasonSchema = require_schemas.RefetchReasonSchema;
1436
+ exports.RenderTokenSchema = RenderTokenSchema;
1437
+ exports.ResourceRefSchema = require_schemas.ResourceRefSchema;
1438
+ exports.RevisionTokenSchema = require_schemas.RevisionTokenSchema;
1439
+ exports.SearchMatchSchema = require_schemas.SearchMatchSchema;
1440
+ exports.SearchModeSchema = require_schemas.SearchModeSchema;
1441
+ exports.SearchQuerySchema = require_schemas.SearchQuerySchema;
1442
+ exports.SearchRequestSchema = require_schemas.SearchRequestSchema;
1443
+ exports.SearchSliceSchema = require_schemas.SearchSliceSchema;
1444
+ exports.SearchSnippetSchema = require_schemas.SearchSnippetSchema;
1445
+ exports.SearchTokenSchema = SearchTokenSchema;
1446
+ exports.SquareDTOSchema = require_schemas.SquareDTOSchema;
1447
+ exports.SquareDraftSchema = require_schemas.SquareDraftSchema;
1448
+ exports.SquarePatchSchema = require_schemas.SquarePatchSchema;
1449
+ exports.SquigglyDTOSchema = require_schemas.SquigglyDTOSchema;
1450
+ exports.SquigglyDraftSchema = require_schemas.SquigglyDraftSchema;
1451
+ exports.SquigglyPatchSchema = require_schemas.SquigglyPatchSchema;
1452
+ exports.StampDTOSchema = require_schemas.StampDTOSchema;
1453
+ exports.StampWireDraftSchema = require_schemas.StampWireDraftSchema;
1454
+ exports.StampWirePatchSchema = require_schemas.StampWirePatchSchema;
1455
+ exports.StandardFontSchema = require_schemas.StandardFontSchema;
1456
+ exports.StrikeoutDTOSchema = require_schemas.StrikeoutDTOSchema;
1457
+ exports.StrikeoutDraftSchema = require_schemas.StrikeoutDraftSchema;
1458
+ exports.StrikeoutIntentSchema = require_schemas.StrikeoutIntentSchema;
1459
+ exports.StrikeoutPatchSchema = require_schemas.StrikeoutPatchSchema;
1460
+ exports.TextAlignmentSchema = require_schemas.TextAlignmentSchema;
1461
+ exports.TextDTOSchema = require_schemas.TextDTOSchema;
1462
+ exports.TextDraftSchema = require_schemas.TextDraftSchema;
1463
+ exports.TextPatchSchema = require_schemas.TextPatchSchema;
1464
+ exports.ToggleFieldWidgetSchema = require_schemas.ToggleFieldWidgetSchema;
1465
+ exports.UnderlineDTOSchema = require_schemas.UnderlineDTOSchema;
1466
+ exports.UnderlineDraftSchema = require_schemas.UnderlineDraftSchema;
1467
+ exports.UnderlinePatchSchema = require_schemas.UnderlinePatchSchema;
1468
+ exports.UnsupportedDTOSchema = require_schemas.UnsupportedDTOSchema;
1469
+ exports.UnsupportedDraftSchema = require_schemas.UnsupportedDraftSchema;
1470
+ exports.UnsupportedPatchSchema = require_schemas.UnsupportedPatchSchema;
1471
+ exports.WeakAnnotationSessionPagesRequestSchema = require_schemas.WeakAnnotationSessionPagesRequestSchema;
1472
+ exports.WeakAnnotationSessionResponseSchema = require_schemas.WeakAnnotationSessionResponseSchema;
1473
+ exports.WidgetAppearanceSchema = require_schemas.WidgetAppearanceSchema;
1474
+ exports.WidgetPlacementSchema = require_schemas.WidgetPlacementSchema;
1475
+ exports.WireAttachmentFileSchema = require_schemas.WireAttachmentFileSchema;
1476
+ exports.annotationAppearancesImageOptionsToToken = annotationAppearancesImageOptionsToToken;
1477
+ exports.annotationAppearancesImageOptionsToWire = annotationAppearancesImageOptionsToWire;
1478
+ exports.annotationRenderOptionsFromImageOptions = annotationRenderOptionsFromImageOptions;
1479
+ exports.applyCdnAccess = applyCdnAccess;
1480
+ exports.cdnCoverageForScope = cdnCoverageForScope;
1481
+ exports.checkResourceAccess = checkResourceAccess;
1482
+ exports.decodeActionsToken = decodeActionsToken;
1483
+ exports.decodeAnnotationAppearancesRenderToken = decodeAnnotationAppearancesRenderToken;
1484
+ exports.decodeAnnotationToken = decodeAnnotationToken;
1485
+ exports.decodeAttachmentsToken = decodeAttachmentsToken;
1486
+ exports.decodeContentToken = decodeContentToken;
1487
+ exports.decodeDocToken = decodeDocToken;
1488
+ exports.decodeDownloadToken = decodeDownloadToken;
1489
+ exports.decodeLayoutToken = decodeLayoutToken;
1490
+ exports.decodeMetadataToken = decodeMetadataToken;
1491
+ exports.decodeRenderToken = decodeRenderToken;
1492
+ exports.decodeSearchToken = decodeSearchToken;
1493
+ exports.decodeToken = decodeToken;
1494
+ exports.decodeTokenText = decodeTokenText;
1495
+ exports.encodeActionsToken = encodeActionsToken;
1496
+ exports.encodeAnnotationAppearancesRenderToken = encodeAnnotationAppearancesRenderToken;
1497
+ exports.encodeAnnotationToken = encodeAnnotationToken;
1498
+ exports.encodeAttachmentsToken = encodeAttachmentsToken;
1499
+ exports.encodeContentToken = encodeContentToken;
1500
+ exports.encodeDocToken = encodeDocToken;
1501
+ exports.encodeDownloadToken = encodeDownloadToken;
1502
+ exports.encodeLayoutToken = encodeLayoutToken;
1503
+ exports.encodeMetadataToken = encodeMetadataToken;
1504
+ exports.encodeRenderToken = encodeRenderToken;
1505
+ exports.encodeSearchToken = encodeSearchToken;
1506
+ exports.encodeToken = encodeToken;
1507
+ exports.encodeTokenText = encodeTokenText;
1508
+ exports.flatten = flatten;
1509
+ exports.pageRenderOptionsFromImageOptions = pageRenderOptionsFromImageOptions;
1510
+ exports.renderImageOptionsToToken = renderImageOptionsToToken;
1511
+ exports.renderImageOptionsToWire = renderImageOptionsToWire;
1512
+ exports.resolveResourceIdForPath = resolveResourceIdForPath;
1513
+ exports.unflatten = unflatten;
1514
+ exports.wirePaths = wirePaths;
1515
+
1516
+ //# sourceMappingURL=wire.cjs.map