@cloudpdf/engine 3.0.0-next.8 → 3.0.0-next.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -450,6 +450,13 @@ var CloudDocumentFormsService = class {
450
450
  };
451
451
  //#endregion
452
452
  //#region src/document/CloudDocumentPagesService.ts
453
+ /** Detach a Uint8Array view into a standalone ArrayBuffer (the resource-map
454
+ * shape) without disturbing a larger buffer the caller still owns. */
455
+ function copyToExactBuffer(view) {
456
+ const copy = new ArrayBuffer(view.byteLength);
457
+ new Uint8Array(copy).set(view);
458
+ return copy;
459
+ }
453
460
  /**
454
461
  * Cloud-side document pages service. Mirrors `LocalDocumentPagesService`
455
462
  * over HTTP: GET /pages for `list`, POST /pages/move for the reorder.
@@ -542,6 +549,46 @@ var CloudDocumentPagesService = class {
542
549
  return result;
543
550
  });
544
551
  }
552
+ insert(bytes, destIndex) {
553
+ if (this.isClosed()) return _embedpdf_engine_core_runtime.AbortablePromise.rejectReason(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocNotOpen, `document ${this.docId} is closed`));
554
+ return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
555
+ const buffer = bytes instanceof ArrayBuffer ? bytes : copyToExactBuffer(bytes);
556
+ const form = buildMutationForm(destIndex !== void 0 ? { destIndex } : {}, { source: {
557
+ bytes: buffer,
558
+ mimeType: "application/pdf",
559
+ name: "source.pdf"
560
+ } });
561
+ const result = await this.http.postMultipartJson(_embedpdf_engine_core_wire.wirePaths.layerPagesInsert(this.docId, this.layerName), form, (raw) => _embedpdf_engine_core_wire.PageInsertResultSchema.parse(raw), signal);
562
+ if (result.cache) this.manifest.applyPageInsert(result.cache);
563
+ this.publisher.publishLocal({
564
+ type: "pages.inserted",
565
+ destIndex,
566
+ ...result
567
+ });
568
+ return result;
569
+ });
570
+ }
571
+ insertBlank(spec, destIndex) {
572
+ if (this.isClosed()) return _embedpdf_engine_core_runtime.AbortablePromise.rejectReason(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocNotOpen, `document ${this.docId} is closed`));
573
+ return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
574
+ const result = await this.http.postJson(_embedpdf_engine_core_wire.wirePaths.layerPagesInsertBlank(this.docId, this.layerName), {
575
+ size: spec.size,
576
+ ...spec.count !== void 0 ? { count: spec.count } : {},
577
+ ...destIndex !== void 0 ? { destIndex } : {}
578
+ }, (raw) => _embedpdf_engine_core_wire.PageInsertResultSchema.parse(raw), signal);
579
+ if (result.cache) this.manifest.applyPageInsert(result.cache);
580
+ this.publisher.publishLocal({
581
+ type: "pages.inserted",
582
+ destIndex,
583
+ ...result
584
+ });
585
+ return result;
586
+ });
587
+ }
588
+ extract(pageObjectNumbers) {
589
+ if (this.isClosed()) return _embedpdf_engine_core_runtime.AbortablePromise.rejectReason(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocNotOpen, `document ${this.docId} is closed`));
590
+ return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => this.http.postJsonBytes(_embedpdf_engine_core_wire.wirePaths.layerPagesExtract(this.docId, this.layerName), { pageObjectNumbers }, signal));
591
+ }
545
592
  flatten(pageObjectNumbers, usage = "display") {
546
593
  if (this.isClosed()) return _embedpdf_engine_core_runtime.AbortablePromise.rejectReason(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocNotOpen, `document ${this.docId} is closed`));
547
594
  return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
@@ -810,8 +857,7 @@ var CloudDocumentSecurityService = class {
810
857
  * and `applyCdnAccess` short-circuits to origin; safe to call always.
811
858
  */
812
859
  async postAccess(signal, body) {
813
- const response = await this.http.postJson(_embedpdf_engine_core_wire.wirePaths.access(this.docId), {
814
- layerName: this.layerName,
860
+ const response = await this.http.postJson(_embedpdf_engine_core_wire.wirePaths.access(this.docId, this.layerName), {
815
861
  ...body.password ? { password: body.password } : {},
816
862
  mode: body.mode
817
863
  }, (raw) => _embedpdf_engine_core_wire.AccessResponseSchema.parse(raw), signal);
@@ -1341,6 +1387,12 @@ function auditRowToEvent(row, mySessionId) {
1341
1387
  origin,
1342
1388
  ...row.payload
1343
1389
  };
1390
+ case "pages.insert":
1391
+ case "pages.insertBlank": return {
1392
+ type: "pages.inserted",
1393
+ origin,
1394
+ ...row.payload
1395
+ };
1344
1396
  case "pages.flatten": return {
1345
1397
  type: "pages.flattened",
1346
1398
  origin,
@@ -1583,6 +1635,7 @@ var CloudDocumentHandle = class {
1583
1635
  apply: (meta, owns) => this.absorbMutation(meta, owns),
1584
1636
  applyPageStructure: (cache) => this.absorbPageStructure(cache),
1585
1637
  applyPageDelete: (cache, deletedPages) => this.absorbPageDelete(cache, deletedPages),
1638
+ applyPageInsert: (cache) => this.absorbPageInsert(cache),
1586
1639
  applyMetadata: (cache) => this.absorbMetadata(cache),
1587
1640
  applyAttachments: (cache) => this.absorbAttachments(cache)
1588
1641
  };
@@ -1748,6 +1801,27 @@ var CloudDocumentHandle = class {
1748
1801
  };
1749
1802
  }
1750
1803
  /**
1804
+ * Patch bookkeeping after a page insert — the mirror of
1805
+ * {@link absorbPageDelete}, with one asymmetry: delete can patch the
1806
+ * cached manifest losslessly (it only REMOVES rows), but an insert needs
1807
+ * manifest rows for the fresh PONs and the result doesn't carry them. So
1808
+ * this absorb flips the planes (insert changes the page SET, so like
1809
+ * delete it owns content + annotations alongside layout), raises the
1810
+ * version floor, and DROPS the cache — the next read refetches a manifest
1811
+ * that includes the new pages' rows. The UI never waits on that refetch:
1812
+ * the mutation result / event already carries the full new layout.
1813
+ */
1814
+ absorbPageInsert(cache) {
1815
+ this.flipScopes([
1816
+ "layout",
1817
+ "content",
1818
+ "annotations"
1819
+ ]);
1820
+ this.manifestFloorVersion = Math.max(this.manifestFloorVersion, cache.docVersion);
1821
+ this.inflightManifest = null;
1822
+ this.manifestCache = null;
1823
+ }
1824
+ /**
1751
1825
  * Patch the cached manifest after a metadata write. Symmetric with
1752
1826
  * {@link absorbPageMove}: a metadata edit advances `docVersion` (so leaf
1753
1827
  * URLs re-resolve) and `metadataVersion` (so the /metadata leaf re-fetches),
@@ -1883,6 +1957,9 @@ var CloudDocumentHandle = class {
1883
1957
  case "pages.deleted":
1884
1958
  if (event.cache) this.absorbPageDelete(event.cache, event.pageObjectNumbers);
1885
1959
  return;
1960
+ case "pages.inserted":
1961
+ if (event.cache) this.absorbPageInsert(event.cache);
1962
+ return;
1886
1963
  case "metadata.updated":
1887
1964
  if (event.cache) this.absorbMetadata(event.cache);
1888
1965
  return;
@@ -1934,7 +2011,7 @@ function fallbackUnknownHead(id) {
1934
2011
  access: {
1935
2012
  required: true,
1936
2013
  reasons: ["permissions-unknown"],
1937
- endpoint: _embedpdf_engine_core_wire.wirePaths.access(id)
2014
+ endpoint: _embedpdf_engine_core_wire.wirePaths.access(id, _embedpdf_engine_core_wire.DEFAULT_LAYER_NAME)
1938
2015
  }
1939
2016
  };
1940
2017
  }
@@ -2051,7 +2128,7 @@ var HttpClient = class HttpClient {
2051
2128
  this.tokenFn = token === void 0 ? null : typeof token === "function" ? token : () => token;
2052
2129
  this.sessionId = opts.sessionId ?? null;
2053
2130
  this.fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
2054
- this.docAffinityHeader = opts.docAffinityHeader ?? false;
2131
+ this.docAffinityHeader = opts.docAffinityHeader ?? true;
2055
2132
  this.onRetry = opts.onRetry;
2056
2133
  }
2057
2134
  /** Normalized server base URL (no trailing slash). */
@@ -2283,6 +2360,12 @@ var HttpClient = class HttpClient {
2283
2360
  const res = await this.requestJson(path, "POST", body, signal);
2284
2361
  return await this.parseJsonResponse(res, parser);
2285
2362
  }
2363
+ /** POST a JSON body and return the raw binary response (pages.extract). */
2364
+ async postJsonBytes(path, body, signal) {
2365
+ const res = await this.requestJson(path, "POST", body, signal);
2366
+ if (!res.ok) await this.throwFromBody(res);
2367
+ return new Uint8Array(await res.arrayBuffer());
2368
+ }
2286
2369
  /** POST a raw binary body (FDF/XFDF import) and parse the JSON response. */
2287
2370
  async postBytesJson(path, bytes, contentType, parser, signal) {
2288
2371
  const headers = new Headers({ "Content-Type": contentType });