@cloudpdf/engine 3.0.0-next.14 → 3.0.0-next.16
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 +2294 -1204
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +501 -225
- package/dist/index.d.ts +501 -225
- package/dist/index.js +2406 -1299
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AbortablePromise, AnnotationAppearanceImageOptions, AnnotationAppearanceImagesResult, AnnotationBundle, AnnotationCreateOptions, AnnotationCreateResult, AnnotationDeleteResult, AnnotationDraft, AnnotationExportSelection, AnnotationFlattenResult, AnnotationImportOptions, AnnotationImportResult, AnnotationList, AnnotationListOptions, AnnotationPatch, AnnotationPosition, AnnotationRef, AnnotationReorderResult, AnnotationResourceRole, AnnotationUpdateOptions, AnnotationUpdateResult, BundleLimits, CallFacts, Change, ChangeAnswer, ChangeResult, CustomMetadataService, DocumentActionsService, DocumentAnnotationsService, DocumentAttachmentsService, DocumentEventStream, DocumentFormsService, DocumentHandle, DocumentMetadata, DocumentOutlineService, DocumentPagesService, DocumentRedactionService, DocumentRenderService, DocumentSearchService, DocumentSecurityService, DocumentSignaturesService, DownloadOptions, EditSessionAccess, EditSessionStatus, Engine, EngineError, FlattenWriteOptions, MetadataPatch, MetadataService, MetadataUpdateResult, MutationMeta, ObjectNumberPool, ObjectNumberRange, ObjectNumbersLost, OpenInput, OpenOptions, PageAnnotationsService, PageCoordinates, PageExtractOptions, PageFlattenResult, PageFormsService, PageHandle, PageImageOptions, PageLayerRights, PageLayout, PageListSnapshot, PageMeasureService, PageMeasurementViewportList, PageNameInput, PageNameResult, PagePrintRights, PageRef, PageRemoveNameInput, PageRenderImage, PageRenderService, PageScaleResult, PageStructureVerb, PageTextService, PageTextSnapshot, PdfMeasure, SearchRequest, SearchSlice, SessionEventPublisher, TextLayout, TextRange, TokenSource, WireAnnotationResources, WorkingSetPage, WriteOptions } from "@embedpdf/engine-core/runtime";
|
|
2
2
|
import { CdnAccessInfoForApply, DocumentHead, DocumentManifest, LayerScopePlane } from "@embedpdf/engine-core/wire";
|
|
3
|
-
|
|
3
|
+
export * from "@embedpdf/engine-core/public";
|
|
4
4
|
//#region src/transport/HttpClient.d.ts
|
|
5
|
+
/** CloudPDF SaaS: where an engine connects when it names no server of its own. */
|
|
6
|
+
declare const CLOUDPDF_SAAS_URL = "https://engine.cloudpdf.com";
|
|
5
7
|
interface HttpClientOptions {
|
|
6
|
-
|
|
8
|
+
/** Where your CloudPDF runs: your own `@cloudpdf/server`, or CloudPDF SaaS
|
|
9
|
+
* ({@link CLOUDPDF_SAAS_URL}) when left out. */
|
|
10
|
+
baseUrl?: string;
|
|
7
11
|
/**
|
|
8
12
|
* Optional bearer token. Either a string or a function that
|
|
9
13
|
* returns a fresh token on every call (so callers can rotate
|
|
@@ -12,26 +16,30 @@ interface HttpClientOptions {
|
|
|
12
16
|
* scenario where the doc-scoped token is provided per-`open` and
|
|
13
17
|
* the engine itself has no engine-level credentials.
|
|
14
18
|
*/
|
|
15
|
-
token?:
|
|
19
|
+
token?: TokenSource;
|
|
16
20
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
21
|
+
* The open document's session id, sent as `X-Engine-Session-Id` where the
|
|
22
|
+
* server reads it: on writes, `/access`, the event stream and the bulk
|
|
23
|
+
* reservation (see {@link RequestOptions}). The server keeps the editing
|
|
24
|
+
* session's object numbers under it, and stores it on a write's audit
|
|
25
|
+
* row, so the document's own stream can drop its echoes. Each open
|
|
26
|
+
* document has its own (see {@link HttpClient.forDocument}); the engine's
|
|
27
|
+
* client has none.
|
|
20
28
|
*/
|
|
21
29
|
sessionId?: string;
|
|
22
30
|
/** Replace the global fetch (e.g. in Node tests with undici). */
|
|
23
31
|
fetch?: typeof globalThis.fetch;
|
|
24
32
|
/**
|
|
25
|
-
* Document affinity key: `X-CloudPDF-Doc` is sent
|
|
33
|
+
* Document affinity key: `X-CloudPDF-Doc` is sent by default on
|
|
26
34
|
* origin-bound doc requests so consistent-hash load balancers can pin
|
|
27
35
|
* a document's traffic to one warm replica. Routing hints are
|
|
28
|
-
* unconditional client behavior — whether they are
|
|
36
|
+
* unconditional client behavior — whether they are used is the
|
|
29
37
|
* operator's choice at the load balancer, never the app's. Derived
|
|
30
38
|
* from the request path (`/v1/docs/:docId/…` — the same extraction
|
|
31
39
|
* the Helm chart's uri-mode fallback uses); never sent on
|
|
32
40
|
* CDN-rewritten requests.
|
|
33
41
|
*
|
|
34
|
-
* `false` is an
|
|
42
|
+
* `false` is an escape hatch, not a feature toggle: use it only
|
|
35
43
|
* against a stale server whose CORS allowlist predates the header
|
|
36
44
|
* (browser preflights would fail) or behind a proxy that rejects
|
|
37
45
|
* unknown request headers.
|
|
@@ -63,15 +71,35 @@ interface CdnBinding {
|
|
|
63
71
|
readonly layerName: string;
|
|
64
72
|
}
|
|
65
73
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
74
|
+
* What a write sends beside its request: its `opId` as `Idempotency-Key`,
|
|
75
|
+
* so a retry is answered with what the first try committed, and how many
|
|
76
|
+
* object numbers to top the editing session up by.
|
|
69
77
|
*/
|
|
78
|
+
interface WriteRequest {
|
|
79
|
+
/** Absent for a request of changes: its body names each change by its own `opId`. */
|
|
80
|
+
readonly opId?: string;
|
|
81
|
+
/** `EmbedPDF-Reserve-Object-Numbers`, when more than 0. */
|
|
82
|
+
readonly reserveObjectNumbers?: number;
|
|
83
|
+
/** Called with the numbers the response hands out (`EmbedPDF-Object-Numbers`). */
|
|
84
|
+
readonly onObjectNumbers?: (ranges: ObjectNumberRange[]) => void;
|
|
85
|
+
}
|
|
86
|
+
/** How one request is sent, beyond its path and body. */
|
|
87
|
+
interface RequestOptions {
|
|
88
|
+
/**
|
|
89
|
+
* A write: sent as the editing session with its `Idempotency-Key`, and
|
|
90
|
+
* sent again with the same key after a network failure.
|
|
91
|
+
*/
|
|
92
|
+
readonly write?: WriteRequest;
|
|
93
|
+
/** Sent as the editing session though not a write: `/access`, the bulk reservation. */
|
|
94
|
+
readonly session?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/** A raw-bytes response plus its headers. */
|
|
70
97
|
interface HttpFileResponse {
|
|
71
98
|
bytes: Uint8Array;
|
|
72
99
|
headers: Headers;
|
|
73
100
|
}
|
|
74
101
|
declare class HttpClient {
|
|
102
|
+
private readonly options;
|
|
75
103
|
private readonly base;
|
|
76
104
|
private readonly tokenFn;
|
|
77
105
|
private readonly fetchFn;
|
|
@@ -80,9 +108,12 @@ declare class HttpClient {
|
|
|
80
108
|
private static readonly MAX_RETRIES;
|
|
81
109
|
private static readonly RETRY_AFTER_CAP_MS;
|
|
82
110
|
private static readonly RETRY_AFTER_DEFAULT_MS;
|
|
83
|
-
|
|
111
|
+
/** A write whose request failed on the network is sent again after these waits. */
|
|
112
|
+
private static readonly NETWORK_RETRY_MS;
|
|
113
|
+
/** The open document's session id; `null` on the engine's own client. */
|
|
114
|
+
readonly sessionId: string | null;
|
|
84
115
|
private cdnBinding;
|
|
85
|
-
constructor(
|
|
116
|
+
constructor(options: HttpClientOptions);
|
|
86
117
|
/** Normalized server base URL (no trailing slash). */
|
|
87
118
|
get baseUrl(): string;
|
|
88
119
|
/**
|
|
@@ -93,13 +124,16 @@ declare class HttpClient {
|
|
|
93
124
|
*/
|
|
94
125
|
get fetchImpl(): typeof globalThis.fetch;
|
|
95
126
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
127
|
+
* A client for one open document: this client's settings, the document's
|
|
128
|
+
* own editing session, its own CDN binding, and `token` as its bearer
|
|
129
|
+
* when the open names one (else this client's). Two open documents never
|
|
130
|
+
* share object numbers, event echoes or a CDN binding, even two opens of
|
|
131
|
+
* the same document on one engine.
|
|
101
132
|
*/
|
|
102
|
-
|
|
133
|
+
forDocument({ sessionId, token }: {
|
|
134
|
+
sessionId: string;
|
|
135
|
+
token?: TokenSource;
|
|
136
|
+
}): HttpClient;
|
|
103
137
|
/**
|
|
104
138
|
* Raw streaming GET (the SSE channel). Same auth/session headers and
|
|
105
139
|
* error mapping as every other request; the caller owns the body stream.
|
|
@@ -110,13 +144,13 @@ declare class HttpClient {
|
|
|
110
144
|
* route everything to origin again — useful on session close or
|
|
111
145
|
* when an adapter swap happens mid-session (rare).
|
|
112
146
|
*
|
|
113
|
-
* The HttpClient stays dumb about
|
|
147
|
+
* The HttpClient stays dumb about when to do this; the cloud
|
|
114
148
|
* document handle pushes the binding in after /access succeeds.
|
|
115
149
|
*
|
|
116
150
|
* Side effect: in the browser, signedCookies are written to
|
|
117
151
|
* `document.cookie` once per setCdnAccess call so the CDN edge
|
|
118
|
-
* receives them on subsequent fetches.
|
|
119
|
-
*
|
|
152
|
+
* receives them on subsequent fetches. Outside the browser signed
|
|
153
|
+
* cookies are ignored: this client keeps no cookie jar.
|
|
120
154
|
*/
|
|
121
155
|
setCdnAccess(binding: CdnBinding | null): void;
|
|
122
156
|
/** Current CDN binding (or null). Exposed for diagnostics/tests. */
|
|
@@ -175,26 +209,28 @@ declare class HttpClient {
|
|
|
175
209
|
* `onStaleVersion` (a manifest refresh) and one re-resolve + retry.
|
|
176
210
|
*/
|
|
177
211
|
getFileWithRefresh(buildPath: (signal: AbortSignal) => Promise<string>, onStaleVersion: (signal: AbortSignal) => Promise<void>, signal: AbortSignal): Promise<HttpFileResponse>;
|
|
178
|
-
postMultipartJson<T>(path: string, body: FormData, parser: (raw: unknown) => T, signal: AbortSignal): Promise<T>;
|
|
212
|
+
postMultipartJson<T>(path: string, body: FormData, parser: (raw: unknown) => T, signal: AbortSignal, options?: RequestOptions): Promise<T>;
|
|
179
213
|
/** PATCH counterpart of {@link postMultipartJson} (binary-carrying mutations). */
|
|
180
|
-
patchMultipartJson<T>(path: string, body: FormData, parser: (raw: unknown) => T, signal: AbortSignal): Promise<T>;
|
|
181
|
-
postJson<T>(path: string, body: unknown, parser: (raw: unknown) => T, signal: AbortSignal): Promise<T>;
|
|
182
|
-
putJson<T>(path: string, body: unknown, parser: (raw: unknown) => T, signal: AbortSignal): Promise<T>;
|
|
214
|
+
patchMultipartJson<T>(path: string, body: FormData, parser: (raw: unknown) => T, signal: AbortSignal, options?: RequestOptions): Promise<T>;
|
|
215
|
+
postJson<T>(path: string, body: unknown, parser: (raw: unknown) => T, signal: AbortSignal, options?: RequestOptions): Promise<T>;
|
|
216
|
+
putJson<T>(path: string, body: unknown, parser: (raw: unknown) => T, signal: AbortSignal, options?: RequestOptions): Promise<T>;
|
|
217
|
+
/** POST a JSON body and parse a `multipart/form-data` response (a large annotation export). */
|
|
218
|
+
postJsonFormData(path: string, body: unknown, signal: AbortSignal): Promise<FormData>;
|
|
183
219
|
/** POST a JSON body and return the raw binary response (pages.extract). */
|
|
184
220
|
postJsonBytes(path: string, body: unknown, signal: AbortSignal): Promise<Uint8Array>;
|
|
185
221
|
/** POST a raw binary body (FDF/XFDF import) and parse the JSON response. */
|
|
186
|
-
postBytesJson<T>(path: string, bytes: Uint8Array, contentType: string, parser: (raw: unknown) => T, signal: AbortSignal): Promise<T>;
|
|
187
|
-
patchJson<T>(path: string, body: unknown, parser: (raw: unknown) => T, signal: AbortSignal): Promise<T>;
|
|
188
|
-
deleteJson<T>(path: string, parser: (raw: unknown) => T, signal: AbortSignal): Promise<T>;
|
|
189
|
-
deleteEmpty(path: string, signal: AbortSignal): Promise<void>;
|
|
190
|
-
postEmpty(path: string, body: unknown, signal: AbortSignal): Promise<void>;
|
|
222
|
+
postBytesJson<T>(path: string, bytes: Uint8Array, contentType: string, parser: (raw: unknown) => T, signal: AbortSignal, options?: RequestOptions): Promise<T>;
|
|
223
|
+
patchJson<T>(path: string, body: unknown, parser: (raw: unknown) => T, signal: AbortSignal, options?: RequestOptions): Promise<T>;
|
|
224
|
+
deleteJson<T>(path: string, parser: (raw: unknown) => T, signal: AbortSignal, options?: RequestOptions): Promise<T>;
|
|
191
225
|
private requestJson;
|
|
192
226
|
private request;
|
|
193
227
|
private execute;
|
|
194
228
|
private parseJsonResponse;
|
|
195
229
|
/**
|
|
196
230
|
* Decide where this request actually goes. With no CDN binding (or
|
|
197
|
-
* binding's `cdn` is null) every request stays on origin
|
|
231
|
+
* binding's `cdn` is null) every request stays on origin, and so does
|
|
232
|
+
* every request that isn't a read (`GET`, `HEAD`): a write must reach the
|
|
233
|
+
* server itself, whatever read its path looks like. Otherwise
|
|
198
234
|
* `applyCdnAccess` decides per-request based on the resource the
|
|
199
235
|
* path resolves to (and whether the caller's scope granted CDN
|
|
200
236
|
* access to it).
|
|
@@ -204,21 +240,31 @@ declare class HttpClient {
|
|
|
204
240
|
}
|
|
205
241
|
//#endregion
|
|
206
242
|
//#region src/CloudEngine.d.ts
|
|
207
|
-
|
|
243
|
+
/**
|
|
244
|
+
* `cloudEngine()`'s options: the HTTP client's, minus the session id, which
|
|
245
|
+
* the engine mints for each document it opens.
|
|
246
|
+
*/
|
|
247
|
+
interface CloudEngineOptions extends Omit<HttpClientOptions, 'sessionId'> {}
|
|
208
248
|
/**
|
|
209
249
|
* Cloud engine: speaks the same Engine interface as @embedpdf/engine
|
|
210
250
|
* but routes everything through HTTPS to a remote @cloudpdf/server (or
|
|
211
251
|
* CloudPDF SaaS). Identical observable contract; only the transport differs.
|
|
212
252
|
*/
|
|
213
|
-
declare class CloudEngine implements Engine
|
|
253
|
+
declare class CloudEngine implements Engine {
|
|
214
254
|
private readonly http;
|
|
215
|
-
/** This engine instance's identity on every event's `origin.sessionId`. */
|
|
216
|
-
private readonly sessionId;
|
|
217
255
|
static fromOptions(opts: CloudEngineOptions): CloudEngine;
|
|
256
|
+
/** It opens the documents your server holds, never a file's bytes. */
|
|
257
|
+
readonly canOpenFiles = false;
|
|
218
258
|
private destroyed;
|
|
259
|
+
/** The documents this engine opened and nobody closed yet. */
|
|
260
|
+
private readonly handles;
|
|
219
261
|
private constructor();
|
|
220
|
-
open(input: OpenInput
|
|
221
|
-
|
|
262
|
+
open(input: OpenInput, options?: OpenOptions): AbortablePromise<DocumentHandle>;
|
|
263
|
+
/**
|
|
264
|
+
* Close every document this engine opened (their event streams stop), then
|
|
265
|
+
* refuse new opens. As on the local engine, a handle is unusable after.
|
|
266
|
+
*/
|
|
267
|
+
destroy(): AbortablePromise<void>;
|
|
222
268
|
}
|
|
223
269
|
//#endregion
|
|
224
270
|
//#region src/document/CloudDocumentSearchService.d.ts
|
|
@@ -227,14 +273,14 @@ declare class CloudEngine implements Engine$1 {
|
|
|
227
273
|
*
|
|
228
274
|
* Every slice URL is a canonical cache key — the search token pins the
|
|
229
275
|
* layer's content epoch (computed from the cached manifest), the
|
|
230
|
-
*
|
|
276
|
+
* canonical query (default-fold literals collapse case/diacritic
|
|
231
277
|
* variants into one entry), and the resume position. Identical searches
|
|
232
278
|
* from any reader of the document hit the same CDN entry; matches are
|
|
233
279
|
* all that ever crosses the trust boundary, and the rects/full endpoint
|
|
234
280
|
* split keeps permission tiers in disjoint cache namespaces.
|
|
235
281
|
*
|
|
236
282
|
* Staleness rides the standard versioned-read signal: a first slice
|
|
237
|
-
* answered `NotFound` means
|
|
283
|
+
* answered `NotFound` means our manifest is stale → refresh and retry
|
|
238
284
|
* once; a continuation answered `NotFound` means the document changed
|
|
239
285
|
* mid-search → `InvalidArg`, same contract as the local engine's cursor.
|
|
240
286
|
*/
|
|
@@ -245,29 +291,192 @@ declare class CloudDocumentSearchService implements DocumentSearchService {
|
|
|
245
291
|
private readonly isClosed;
|
|
246
292
|
private readonly manifest;
|
|
247
293
|
constructor(http: HttpClient, docId: string, layerName: string, isClosed: () => boolean, manifest: ManifestAccessor);
|
|
248
|
-
query(request: SearchRequest): AbortablePromise
|
|
294
|
+
query(request: SearchRequest): AbortablePromise<SearchSlice>;
|
|
295
|
+
}
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region src/document/CloudObjectNumberPool.d.ts
|
|
298
|
+
interface CloudObjectNumberPoolOptions {
|
|
299
|
+
/** `POST …/object-numbers`: `count` more numbers for this editing session. */
|
|
300
|
+
reserve(count: number, signal: AbortSignal): Promise<{
|
|
301
|
+
objectNumbers: ObjectNumberRange[];
|
|
302
|
+
expiresIn: number;
|
|
303
|
+
}>;
|
|
304
|
+
now?: () => number;
|
|
305
|
+
}
|
|
306
|
+
/** What became of the numbers a write named. */
|
|
307
|
+
type WriteOutcome =
|
|
308
|
+
/** It committed: they are spent. */
|
|
309
|
+
'committed' |
|
|
310
|
+
/** The server refused them (`ObjectNumberUnavailable`): the caller knows. */
|
|
311
|
+
'refused' |
|
|
312
|
+
/** It failed otherwise: the caller still holds them, for a retry. */
|
|
313
|
+
'failed';
|
|
314
|
+
/**
|
|
315
|
+
* The cloud engine's object numbers: what the server handed this editing
|
|
316
|
+
* session (the engine's `X-Engine-Session-Id` with the token's subject).
|
|
317
|
+
*
|
|
318
|
+
* Numbers arrive with `/access`, with a write's response (the top-up a
|
|
319
|
+
* write asks for when fewer than 8 are held), with the event stream's
|
|
320
|
+
* `session` events, and from `reserve`'s bulk reservation. A number
|
|
321
|
+
* `take` hands out is the caller's until a write naming it commits.
|
|
322
|
+
*
|
|
323
|
+
* The session lives while the event stream is connected or something
|
|
324
|
+
* keeps it alive; without that it expires, and its numbers may go to
|
|
325
|
+
* another session. So once its expiry has passed while the stream is down,
|
|
326
|
+
* the pool hands out nothing until the server says again what it holds.
|
|
327
|
+
* The stream's `session` event lists everything the session holds: any
|
|
328
|
+
* number this pool held or handed out that isn't on it, and that no write
|
|
329
|
+
* in flight names, is lost (`onLost`, `'reclaimed'`). A new version of the
|
|
330
|
+
* document numbers objects anew: everything is lost (`'versioned'`).
|
|
331
|
+
*/
|
|
332
|
+
declare class CloudObjectNumberPool implements ObjectNumberPool {
|
|
333
|
+
private readonly opts;
|
|
334
|
+
private readonly now;
|
|
335
|
+
/** Held and not handed out, lowest first. */
|
|
336
|
+
private available;
|
|
337
|
+
/** Handed out by `take`, not yet spent by a write. */
|
|
338
|
+
private readonly taken;
|
|
339
|
+
/** Named by a write in flight, and how many writes name each. */
|
|
340
|
+
private readonly writing;
|
|
341
|
+
/** When the session expires unless kept alive (ms since the epoch). */
|
|
342
|
+
private expiresAt;
|
|
343
|
+
/** Half the longest lifetime the server has told: what a write's touch guarantees. */
|
|
344
|
+
private halfLifetimeMs;
|
|
345
|
+
private streamConnected;
|
|
346
|
+
private readonly listeners;
|
|
347
|
+
/** The bulk reservation in flight, which later `reserve` calls wait behind. */
|
|
348
|
+
private reserving;
|
|
349
|
+
/** The newest version a `versioned` call named. */
|
|
350
|
+
private version;
|
|
351
|
+
constructor(opts: CloudObjectNumberPoolOptions);
|
|
352
|
+
get held(): number;
|
|
353
|
+
take(): number | null;
|
|
354
|
+
reserve(count: number): AbortablePromise<void>;
|
|
355
|
+
onLost(listener: (lost: ObjectNumbersLost) => void): () => void;
|
|
356
|
+
/** How many numbers a write should ask the server for: 0 while enough are held. */
|
|
357
|
+
topUp(): number;
|
|
358
|
+
/** How many numbers `/access` should ask for: enough to make up the first block. */
|
|
359
|
+
wantedAtAccess(): number;
|
|
360
|
+
/**
|
|
361
|
+
* `/access` answered for the editing session. A session the server made
|
|
362
|
+
* anew holds nothing of what this pool had.
|
|
363
|
+
*/
|
|
364
|
+
opened(edit: EditSessionAccess): void;
|
|
365
|
+
/**
|
|
366
|
+
* Numbers handed to the session: by `/access`, a write's top-up or the
|
|
367
|
+
* bulk reservation; `expiresIn` (seconds) when the answer told it. Numbers
|
|
368
|
+
* held from before an expiry the server can't vouch for any more are
|
|
369
|
+
* dropped: only a `session` event says which survived.
|
|
370
|
+
*/
|
|
371
|
+
receive(ranges: readonly ObjectNumberRange[], expiresIn?: number): void;
|
|
372
|
+
/**
|
|
373
|
+
* The event stream's `session` event: everything the session holds now.
|
|
374
|
+
* What this pool held or handed out and the list doesn't name, unless a
|
|
375
|
+
* write in flight names it, is lost.
|
|
376
|
+
*/
|
|
377
|
+
sync(status: EditSessionStatus): void;
|
|
378
|
+
/**
|
|
379
|
+
* Version `sha256` was published: it numbers objects anew, so every number
|
|
380
|
+
* held or handed out is gone. Told once per version (the stream and this
|
|
381
|
+
* engine's own completion both tell it, in either order).
|
|
382
|
+
*/
|
|
383
|
+
versioned(sha256: string): void;
|
|
384
|
+
/** The event stream connected or dropped: while it's up, the server keeps the session alive. */
|
|
385
|
+
connected(connected: boolean): void;
|
|
386
|
+
/** A write that names `numbers` was called. */
|
|
387
|
+
beginWrite(numbers: readonly number[]): void;
|
|
388
|
+
/**
|
|
389
|
+
* The write that named `numbers` settled. A committed write also kept the
|
|
390
|
+
* session alive: at least half its lifetime is left.
|
|
391
|
+
*/
|
|
392
|
+
endWrite(numbers: readonly number[], outcome: WriteOutcome): void;
|
|
393
|
+
private usable;
|
|
394
|
+
private expiresIn;
|
|
395
|
+
private add;
|
|
396
|
+
/** Held or handed out, and named by no write in flight. */
|
|
397
|
+
private unspent;
|
|
398
|
+
private lose;
|
|
399
|
+
private emit;
|
|
400
|
+
}
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region src/document/CloudWrites.d.ts
|
|
403
|
+
/**
|
|
404
|
+
* One write's place in its document's line (see {@link CloudWrites}): its
|
|
405
|
+
* request goes out once every write called before it has settled.
|
|
406
|
+
*/
|
|
407
|
+
interface CloudWrite {
|
|
408
|
+
/**
|
|
409
|
+
* Wait for this write's turn, then send its request with `options`: the
|
|
410
|
+
* write's `opId` as `Idempotency-Key`, a top-up when the pool runs low,
|
|
411
|
+
* and the numbers the response hands out back into the pool.
|
|
412
|
+
*/
|
|
413
|
+
send<T>(request: (options: RequestOptions) => Promise<T>): Promise<T>;
|
|
414
|
+
}
|
|
415
|
+
/** A change as its request sends it: its `opId`, and its ops with the bytes they carry. */
|
|
416
|
+
interface SentChange {
|
|
417
|
+
readonly opId: string;
|
|
418
|
+
readonly change: Change<PageCoordinates, WireAnnotationResources>;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Sends one request of changes (`POST …/changes`) with `options`, the
|
|
422
|
+
* changes in line order, and answers each, in the same order.
|
|
423
|
+
*/
|
|
424
|
+
type ChangeSender = (changes: readonly SentChange[], options: RequestOptions) => Promise<readonly ChangeAnswer[]>;
|
|
425
|
+
/** How a change takes its place in the line (see {@link CloudWrites.change}). */
|
|
426
|
+
interface LinedChangeOptions {
|
|
427
|
+
/** The object numbers the change creates objects at. */
|
|
428
|
+
readonly named?: readonly number[];
|
|
429
|
+
/**
|
|
430
|
+
* The change carries bytes: it goes in a request of its own, so bytes the
|
|
431
|
+
* server refuses refuse only this change.
|
|
432
|
+
*/
|
|
433
|
+
readonly alone?: boolean;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* A document's writes, sent one at a time in the order they were called,
|
|
437
|
+
* so the server applies them in that order: a create, then an update of
|
|
438
|
+
* what it made, never the other way round. Reads don't wait.
|
|
439
|
+
*
|
|
440
|
+
* A write takes its place when it is called: `run` must be the first thing
|
|
441
|
+
* a write does, before anything it awaits. What it does before `send`
|
|
442
|
+
* (reading a file to upload, say) happens meanwhile; its turn ends when it
|
|
443
|
+
* settles, after the event it publishes.
|
|
444
|
+
*
|
|
445
|
+
* Changes (`doc.apply`) called one after another share a place: while the
|
|
446
|
+
* write before them is in flight they wait together, and go out as one
|
|
447
|
+
* request when their turn comes, each answered on its own.
|
|
448
|
+
*/
|
|
449
|
+
declare class CloudWrites {
|
|
450
|
+
private readonly pool;
|
|
451
|
+
private readonly sendChanges;
|
|
452
|
+
/** Settles when every write so far has settled. */
|
|
453
|
+
private last;
|
|
454
|
+
/** The changes still waiting for their turn, which the next change joins. */
|
|
455
|
+
private open;
|
|
456
|
+
constructor(pool: CloudObjectNumberPool, sendChanges?: ChangeSender);
|
|
457
|
+
run<T>(opId: string, signal: AbortSignal, body: (write: CloudWrite) => Promise<T>,
|
|
458
|
+
/** The object numbers the write creates objects at. */
|
|
459
|
+
named?: readonly (number | undefined)[]): Promise<T>;
|
|
460
|
+
/**
|
|
461
|
+
* Take a change's place in the line: it joins the changes waiting for
|
|
462
|
+
* their turn, and goes out with them. `ready` is what the request sends
|
|
463
|
+
* for it, which it may still be preparing (reading bytes). A change aborted
|
|
464
|
+
* before its request goes out is left out of it; once out, it is answered.
|
|
465
|
+
*/
|
|
466
|
+
change(signal: AbortSignal, ready: Promise<SentChange>, { named, alone }?: LinedChangeOptions): Promise<ChangeAnswer>;
|
|
467
|
+
/** A new batch at the end of the line, open for the changes that follow. */
|
|
468
|
+
private queue;
|
|
469
|
+
/** A batch's turn: nothing joins it any more, and what's ready goes out. */
|
|
470
|
+
private send;
|
|
249
471
|
}
|
|
250
472
|
//#endregion
|
|
251
473
|
//#region src/document/CloudMetadataService.d.ts
|
|
252
|
-
declare class CloudMetadataService implements MetadataService
|
|
253
|
-
|
|
254
|
-
private readonly
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
private readonly publisher;
|
|
259
|
-
constructor(http: HttpClient, docId: string, layerName: string, isClosed: () => boolean, manifest: ManifestAccessor, publisher: SessionEventPublisher);
|
|
260
|
-
/**
|
|
261
|
-
* Document metadata read. The Info-dict JSON lives at the
|
|
262
|
-
* content-addressed `/metadata@metadataVersion=N` leaf (not in the
|
|
263
|
-
* manifest); the manifest only publishes the `metadataVersion` pointer.
|
|
264
|
-
* So `read()` pulls `metadataVersion` from the cached manifest, fetches
|
|
265
|
-
* the leaf, and on a 404 (stale pointer) transparently refreshes the
|
|
266
|
-
* manifest and retries once. `metadataVersion` bumps only on metadata
|
|
267
|
-
* writes, so this leaf stays cached across page and annotation edits.
|
|
268
|
-
*/
|
|
269
|
-
read(): AbortablePromise$1<DocumentMetadata>;
|
|
270
|
-
update(patch: MetadataPatch): AbortablePromise$1<MetadataUpdateResult>;
|
|
474
|
+
declare class CloudMetadataService implements MetadataService {
|
|
475
|
+
readonly custom: CustomMetadataService;
|
|
476
|
+
private readonly deps;
|
|
477
|
+
constructor(http: HttpClient, docId: string, layerName: string, isClosed: () => boolean, manifest: ManifestAccessor, publisher: SessionEventPublisher, writes: CloudWrites);
|
|
478
|
+
get(): AbortablePromise<DocumentMetadata>;
|
|
479
|
+
update(patch: MetadataPatch, options?: WriteOptions): AbortablePromise<MetadataUpdateResult>;
|
|
271
480
|
}
|
|
272
481
|
//#endregion
|
|
273
482
|
//#region src/document/CloudDocumentHandle.d.ts
|
|
@@ -291,42 +500,39 @@ interface ManifestAccessor {
|
|
|
291
500
|
* base → layer, so any observed mutation proves the plane diverged.
|
|
292
501
|
*/
|
|
293
502
|
apply(meta: MutationMeta, owns: readonly LayerScopePlane[]): void;
|
|
294
|
-
/**
|
|
295
|
-
*
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* pages' manifest rows so per-page leaf URLs stop resolving locally. */
|
|
299
|
-
applyPageDelete(cache: PageStructureCache, deletedPages: PageObjectNumber[]): void;
|
|
300
|
-
/** Page insert: the cached manifest has no rows for the fresh PONs (the
|
|
503
|
+
/** A page delete: the advance, plus dropping the deleted pages' manifest
|
|
504
|
+
* rows so per-page leaf URLs stop resolving locally. */
|
|
505
|
+
applyPageDelete(meta: MutationMeta, deletedPages: readonly PageRef[]): void;
|
|
506
|
+
/** Page insert: the cached manifest has no rows for the fresh page object numbers (the
|
|
301
507
|
* result carries only their object numbers), so the absorb drops the
|
|
302
508
|
* cache for a lazy refetch instead of patching. */
|
|
303
|
-
applyPageInsert(
|
|
304
|
-
/** Advance the cached manifest's docVersion + metadataVersion after a metadata write. */
|
|
305
|
-
applyMetadata(cache: MetadataCache): void;
|
|
306
|
-
/** Advance the cached manifest's docVersion + attachmentsVersion after an
|
|
307
|
-
* attachment create/delete. */
|
|
308
|
-
applyAttachments(cache: AttachmentsCache): void;
|
|
509
|
+
applyPageInsert(meta: MutationMeta): void;
|
|
309
510
|
}
|
|
310
|
-
declare class CloudDocumentHandle implements DocumentHandle
|
|
511
|
+
declare class CloudDocumentHandle implements DocumentHandle {
|
|
311
512
|
private readonly http;
|
|
312
513
|
private readonly layerName;
|
|
514
|
+
/** Called once, when the handle closes (the engine forgets it). */
|
|
515
|
+
private readonly onClose;
|
|
313
516
|
readonly id: string;
|
|
314
|
-
readonly capabilities: {
|
|
315
|
-
readonly weakAnnotationEditSessions: "required";
|
|
316
|
-
readonly pageEditSessions: "unsupported";
|
|
317
|
-
};
|
|
318
517
|
readonly metadata: CloudMetadataService;
|
|
319
|
-
readonly annotations: DocumentAnnotationsService
|
|
518
|
+
readonly annotations: DocumentAnnotationsService;
|
|
320
519
|
readonly actions: DocumentActionsService;
|
|
520
|
+
readonly outline: DocumentOutlineService;
|
|
321
521
|
readonly attachments: DocumentAttachmentsService;
|
|
322
522
|
readonly signatures: DocumentSignaturesService;
|
|
323
523
|
readonly forms: DocumentFormsService;
|
|
324
524
|
readonly search: CloudDocumentSearchService;
|
|
325
|
-
readonly pages: DocumentPagesService
|
|
525
|
+
readonly pages: DocumentPagesService;
|
|
526
|
+
/** The page reads behind `pages`, the layout per page among them. */
|
|
527
|
+
private readonly pageReads;
|
|
326
528
|
readonly redaction: DocumentRedactionService;
|
|
327
|
-
readonly security: DocumentSecurityService
|
|
529
|
+
readonly security: DocumentSecurityService;
|
|
328
530
|
readonly render: DocumentRenderService;
|
|
329
531
|
readonly events: DocumentEventStream;
|
|
532
|
+
readonly objectNumbers: ObjectNumberPool;
|
|
533
|
+
private readonly pool;
|
|
534
|
+
private readonly writes;
|
|
535
|
+
private readonly changes;
|
|
330
536
|
private readonly publisher;
|
|
331
537
|
private readonly hub;
|
|
332
538
|
private readonly sessionId;
|
|
@@ -349,6 +555,7 @@ declare class CloudDocumentHandle implements DocumentHandle$1 {
|
|
|
349
555
|
private manifestFloorVersion;
|
|
350
556
|
private pendingInitialHead;
|
|
351
557
|
private readonly manifestAccessor;
|
|
558
|
+
private readonly cloudSecurity;
|
|
352
559
|
constructor(http: HttpClient, id: string, layerName?: string, initialHead?: DocumentHead,
|
|
353
560
|
/**
|
|
354
561
|
* The doc-scoped JWT the engine was opened with, decoded
|
|
@@ -357,11 +564,28 @@ declare class CloudDocumentHandle implements DocumentHandle$1 {
|
|
|
357
564
|
* compatibility; without it the local-fallback path returns an
|
|
358
565
|
* empty scope and null identity until /access is called.
|
|
359
566
|
*/
|
|
360
|
-
initialToken?: string | null,
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
567
|
+
initialToken?: string | null,
|
|
568
|
+
/** Called once, when the handle closes (the engine forgets it). */
|
|
569
|
+
onClose?: () => void);
|
|
570
|
+
page(ref: PageRef): PageHandle;
|
|
571
|
+
/**
|
|
572
|
+
* This handle: the cloud engine sends every call as it's made, in
|
|
573
|
+
* parallel, and the server runs them in arrival order, so a call's facts
|
|
574
|
+
* change nothing here.
|
|
575
|
+
*/
|
|
576
|
+
with(_facts: CallFacts): DocumentHandle;
|
|
577
|
+
/** One change as one transaction, or the undo of one (see `DocumentHandle.apply`). */
|
|
578
|
+
apply(change: Change, options?: WriteOptions): AbortablePromise<ChangeResult>;
|
|
579
|
+
/** Ignored: the server learns what's needed from what is asked of it. */
|
|
580
|
+
setWorkingSet(_view: string, _pages: readonly WorkingSetPage[]): void;
|
|
581
|
+
download(options?: DownloadOptions): AbortablePromise<Uint8Array>;
|
|
582
|
+
/**
|
|
583
|
+
* Learn what the document's signatures forbid before the caller's first
|
|
584
|
+
* question: the manifest carries it, so `open()` fetches it up front and
|
|
585
|
+
* `security.allows()` answers as the server would from the start. A locked
|
|
586
|
+
* document, which the server won't describe yet, learns it from `unlock()`.
|
|
587
|
+
*/
|
|
588
|
+
learnProtection(signal: AbortSignal): Promise<void>;
|
|
365
589
|
/**
|
|
366
590
|
* Return the cached manifest, fetching cold-cache once if needed.
|
|
367
591
|
* Concurrent callers share a single inflight request (singleflight)
|
|
@@ -376,9 +600,9 @@ declare class CloudDocumentHandle implements DocumentHandle$1 {
|
|
|
376
600
|
*/
|
|
377
601
|
refreshManifest(signal: AbortSignal): Promise<DocumentManifest>;
|
|
378
602
|
/**
|
|
379
|
-
* Monotone plane-scope flip: mark the planes a mutation
|
|
603
|
+
* Monotone plane-scope flip: mark the planes a mutation owns as layer-scoped in
|
|
380
604
|
* the cached manifest. Scopes only ever move base → layer (no revert op
|
|
381
|
-
* exists), so flipping is safe under
|
|
605
|
+
* exists), so flipping is safe under any event ordering — a duplicate or
|
|
382
606
|
* out-of-order event still proves the plane diverged at some point — and
|
|
383
607
|
* the manifest fetch stays the authoritative source (the 404 → refresh
|
|
384
608
|
* rail heals any miss, e.g. a future mutation kind this client doesn't
|
|
@@ -387,122 +611,132 @@ declare class CloudDocumentHandle implements DocumentHandle$1 {
|
|
|
387
611
|
private flipScopes;
|
|
388
612
|
absorbMutation(meta: MutationMeta, owns: readonly LayerScopePlane[]): void;
|
|
389
613
|
/**
|
|
390
|
-
* Patch the cached manifest after a
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
* advance it in place; otherwise we drop it and refetch lazily.
|
|
397
|
-
*/
|
|
398
|
-
private absorbPageStructure;
|
|
399
|
-
/**
|
|
400
|
-
* Patch the cached manifest after a page delete: the shared structural
|
|
401
|
-
* advance plus dropping the deleted pages' manifest rows, so no leaf URL
|
|
402
|
-
* for a retired PON can be built from the cache (a stale request would
|
|
403
|
-
* 404 anyway — this keeps the failure local and instant).
|
|
614
|
+
* Patch the cached manifest after a page delete: the shared advance plus
|
|
615
|
+
* dropping the deleted pages' manifest rows, so no leaf URL for a retired
|
|
616
|
+
* page object number can be built from the cache (a stale request would
|
|
617
|
+
* 404 anyway — this keeps the failure local and instant). Delete changes
|
|
618
|
+
* the page set: a view that removed content must never resolve base
|
|
619
|
+
* artifacts again, so content, annotations and forms flip with layout.
|
|
404
620
|
*/
|
|
405
621
|
private absorbPageDelete;
|
|
406
622
|
/**
|
|
407
623
|
* Patch bookkeeping after a page insert — the mirror of
|
|
408
624
|
* {@link absorbPageDelete}, with one asymmetry: delete can patch the
|
|
409
|
-
* cached manifest losslessly (it only
|
|
410
|
-
* manifest rows for the fresh
|
|
411
|
-
* this absorb flips the planes (insert changes the page
|
|
412
|
-
* delete it owns content
|
|
413
|
-
* version floor, and
|
|
625
|
+
* cached manifest losslessly (it only removes rows), but an insert needs
|
|
626
|
+
* manifest rows for the fresh page object numbers and the result doesn't carry them. So
|
|
627
|
+
* this absorb flips the planes (insert changes the page set, so like
|
|
628
|
+
* delete it owns content, annotations and forms alongside layout), raises the
|
|
629
|
+
* version floor, and drops the cache — the next read refetches a manifest
|
|
414
630
|
* that includes the new pages' rows. The UI never waits on that refetch:
|
|
415
631
|
* the mutation result / event already carries the full new layout.
|
|
416
632
|
*/
|
|
417
633
|
private absorbPageInsert;
|
|
418
|
-
/**
|
|
419
|
-
* Patch the cached manifest after a metadata write. Symmetric with
|
|
420
|
-
* {@link absorbPageMove}: a metadata edit advances `docVersion` (so leaf
|
|
421
|
-
* URLs re-resolve) and `metadataVersion` (so the /metadata leaf re-fetches),
|
|
422
|
-
* but leaves `layoutVersion` and every per-page pin untouched. Raise the
|
|
423
|
-
* floor unconditionally and, when our cache is exactly one version behind,
|
|
424
|
-
* advance it in place; otherwise drop it and refetch lazily.
|
|
425
|
-
*/
|
|
426
|
-
private absorbMetadata;
|
|
427
|
-
/**
|
|
428
|
-
* Patch the cached manifest after an attachment create/delete. Symmetric
|
|
429
|
-
* with {@link absorbMetadata}: an attachment write advances `docVersion`
|
|
430
|
-
* (so leaf URLs re-resolve) and `attachmentsVersion` (so the /attachments
|
|
431
|
-
* listing and /attachment-files leaves re-fetch), but leaves
|
|
432
|
-
* `layoutVersion` and every per-page pin untouched. Raise the floor
|
|
433
|
-
* unconditionally and, when our cache is exactly one version behind,
|
|
434
|
-
* advance it in place; otherwise drop it and refetch lazily.
|
|
435
|
-
*/
|
|
436
|
-
private absorbAttachments;
|
|
437
634
|
private startManifestFetch;
|
|
438
635
|
private fetchManifest;
|
|
439
636
|
private consumeInitialHead;
|
|
440
637
|
private fetchManifestForHead;
|
|
441
|
-
close(): AbortablePromise
|
|
638
|
+
close(): AbortablePromise<void>;
|
|
442
639
|
private retainRemoteStream;
|
|
443
640
|
private releaseRemoteStream;
|
|
444
|
-
/** Patch the cached manifest from a
|
|
641
|
+
/** Patch the cached manifest from a remote event's coherence pins — the
|
|
445
642
|
* same absorb rails local mutations use, so reads stay warm no matter
|
|
446
|
-
* whose hand caused the change.
|
|
643
|
+
* whose hand caused the change. Every event kind is named below, so a new
|
|
644
|
+
* one can't be forgotten: a missed one leaves this client reading the
|
|
645
|
+
* old version from an immutable, cached URL. */
|
|
447
646
|
private absorbRemoteEvent;
|
|
448
647
|
}
|
|
449
648
|
//#endregion
|
|
450
649
|
//#region src/document/CloudDocumentAnnotationsService.d.ts
|
|
451
|
-
declare class CloudDocumentAnnotationsService implements DocumentAnnotationsService
|
|
650
|
+
declare class CloudDocumentAnnotationsService implements DocumentAnnotationsService {
|
|
452
651
|
private readonly http;
|
|
453
652
|
private readonly docId;
|
|
454
653
|
private readonly layerName;
|
|
455
654
|
private readonly isClosed;
|
|
456
655
|
private readonly manifest;
|
|
457
|
-
|
|
656
|
+
private readonly publisher;
|
|
657
|
+
private readonly writes;
|
|
658
|
+
/** The server's import limits, as its `/v1/access` advertises them. */
|
|
659
|
+
private readonly importLimits;
|
|
660
|
+
constructor(http: HttpClient, docId: string, layerName: string, isClosed: () => boolean, manifest: ManifestAccessor, publisher: SessionEventPublisher, writes: CloudWrites,
|
|
661
|
+
/** The server's import limits, as its `/v1/access` advertises them. */
|
|
662
|
+
importLimits: () => Promise<BundleLimits>);
|
|
458
663
|
/**
|
|
459
|
-
*
|
|
460
|
-
* `annotations/items@annotationsVersion=N` leaf at the
|
|
461
|
-
* materialized server-side by one raw (no page-load)
|
|
462
|
-
* because the pin bumps only when annotation list
|
|
463
|
-
* A stale pin mid-read (a concurrent mutation →
|
|
464
|
-
* manifest and retries, so the result always belongs
|
|
465
|
-
* moment (the torn read this method exists to prevent).
|
|
664
|
+
* Every page: one coherent whole-document snapshot, a single read of the
|
|
665
|
+
* immutable `annotations/items@annotationsVersion=N` leaf at the
|
|
666
|
+
* manifest's pin — materialized server-side by one raw (no page-load)
|
|
667
|
+
* sweep, CDN-cacheable because the pin bumps only when annotation list
|
|
668
|
+
* bodies actually change. A stale pin mid-read (a concurrent mutation →
|
|
669
|
+
* 404) refreshes the manifest and retries, so the result always belongs
|
|
670
|
+
* to one document moment (the torn read this method exists to prevent).
|
|
671
|
+
*
|
|
672
|
+
* Some pages: each page's versioned leaf, the same read as
|
|
673
|
+
* `page.annotations.list()`, in the order asked.
|
|
466
674
|
*/
|
|
467
|
-
|
|
675
|
+
list(options?: AnnotationListOptions): AbortablePromise<AnnotationList>;
|
|
468
676
|
/** One bulk leaf read at the manifest's pin. The server stamps the body's
|
|
469
677
|
* `auditHead` at materialization time; a CDN-cached body may carry a
|
|
470
678
|
* cursor older than the current manifest's, which is still safe — the
|
|
471
679
|
* pin proves no items-affecting mutation landed in between, so replaying
|
|
472
680
|
* that window over the body is all no-ops. */
|
|
473
681
|
private readBulkAt;
|
|
474
|
-
|
|
682
|
+
/** One page's versioned leaf, with the standard stale-pin retry
|
|
683
|
+
* (404 → refresh the manifest → once). */
|
|
684
|
+
private readPage;
|
|
685
|
+
/**
|
|
686
|
+
* One versioned, CDN-cacheable read at the manifest's annotation and
|
|
687
|
+
* layout pins, with the stale-pin retry (404 → refresh the manifest →
|
|
688
|
+
* once). The response is the bundle without its bytes and one part per
|
|
689
|
+
* resource; every part is checked against its id before it is returned.
|
|
690
|
+
*/
|
|
691
|
+
export(selection?: AnnotationExportSelection): AbortablePromise<AnnotationBundle>;
|
|
692
|
+
/**
|
|
693
|
+
* One request: the bundle's manifest and each resource once, as parts of
|
|
694
|
+
* one multipart POST under the import's `opId` as `Idempotency-Key`, so a
|
|
695
|
+
* retry applies once. The server holds the limits; the same numbers are checked
|
|
696
|
+
* here first, so a bundle past one fails before its bytes move.
|
|
697
|
+
*/
|
|
698
|
+
import(bundle: AnnotationBundle, options?: AnnotationImportOptions): AbortablePromise<AnnotationImportResult>;
|
|
699
|
+
/**
|
|
700
|
+
* The cacheable export URL for `selection` at the manifest's pins — the
|
|
701
|
+
* base leaf while the layer inherits both planes the bundle depends on —
|
|
702
|
+
* or `null` when a URL can't carry it: a URL has room for a few hundred
|
|
703
|
+
* refs.
|
|
704
|
+
*/
|
|
705
|
+
private exportPathAt;
|
|
475
706
|
/** Versioned leaf URL for one manifest page entry, with the same
|
|
476
707
|
* plane routing as `CloudPageAnnotationsService.list()`: an inherited
|
|
477
708
|
* `annotations` plane reads the doc-level base leaf. */
|
|
478
709
|
private pagePathAt;
|
|
479
710
|
private versionedPagePath;
|
|
480
|
-
beginWeakEdit(pageObjectNumbers: readonly PageObjectNumber[]): AbortablePromise$1<WeakAnnotationEditSession>;
|
|
481
711
|
}
|
|
482
712
|
//#endregion
|
|
483
713
|
//#region src/document/CloudDocumentPagesService.d.ts
|
|
484
714
|
/**
|
|
485
|
-
* Cloud-side document pages service
|
|
486
|
-
* over HTTP
|
|
715
|
+
* Cloud-side document pages service: the reads, extract, flatten and the page
|
|
716
|
+
* names, over HTTP, as `LocalDocumentPagesService` has them. The structure
|
|
717
|
+
* verbs are changes (`pageVerbs`), so they can be undone.
|
|
487
718
|
*
|
|
488
719
|
* Page identity rule (locked with the user, do not change):
|
|
489
|
-
* - Pages are addressed exclusively by their indirect
|
|
490
|
-
* `pageObjectNumber
|
|
491
|
-
*
|
|
492
|
-
* account for index drift
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
720
|
+
* - Pages are addressed exclusively by `PageRef` (their indirect
|
|
721
|
+
* `pageObjectNumber`); mutation bodies ship `{ pages: PageRef[] }`.
|
|
722
|
+
* The wire never sends a page index for a mutation. This keeps
|
|
723
|
+
* multi-call client logic from having to account for index drift
|
|
724
|
+
* between requests.
|
|
725
|
+
* - A page reorder (a change) returns the new `layout` (order + geometry)
|
|
726
|
+
* plus cloud coherence pins. It bumps only `docVersion` +
|
|
727
|
+
* `layoutVersion`; every per-page pin stays warm.
|
|
497
728
|
*/
|
|
498
|
-
declare class CloudDocumentPagesService implements DocumentPagesService
|
|
729
|
+
declare class CloudDocumentPagesService implements Omit<DocumentPagesService, PageStructureVerb> {
|
|
499
730
|
private readonly http;
|
|
500
731
|
private readonly docId;
|
|
501
732
|
private readonly layerName;
|
|
502
733
|
private readonly isClosed;
|
|
503
734
|
private readonly manifest;
|
|
504
735
|
private readonly publisher;
|
|
505
|
-
|
|
736
|
+
private readonly writes;
|
|
737
|
+
/** The last layout leaf read by {@link pageLayout}, keyed by its URL path. */
|
|
738
|
+
private layoutMemo;
|
|
739
|
+
constructor(http: HttpClient, docId: string, layerName: string, isClosed: () => boolean, manifest: ManifestAccessor, publisher: SessionEventPublisher, writes: CloudWrites);
|
|
506
740
|
/**
|
|
507
741
|
* Page-geometry list. The geometry bytes live at the content-addressed
|
|
508
742
|
* `/layout@layoutVersion=N` leaf (not in the manifest); the manifest only
|
|
@@ -513,22 +747,31 @@ declare class CloudDocumentPagesService implements DocumentPagesService$1 {
|
|
|
513
747
|
* only on structural page ops, so this leaf stays cached across content
|
|
514
748
|
* and annotation edits.
|
|
515
749
|
*/
|
|
516
|
-
list(): AbortablePromise
|
|
517
|
-
move(pageObjectNumbers: PageObjectNumber[], destIndex: number): AbortablePromise$1<PageMoveResult>;
|
|
518
|
-
setName(input: PageNameInput): AbortablePromise$1<PageNameResult>;
|
|
519
|
-
removeName(input: PageRemoveNameInput): AbortablePromise$1<PageNameResult>;
|
|
750
|
+
list(): AbortablePromise<PageListSnapshot>;
|
|
520
751
|
/**
|
|
521
|
-
*
|
|
752
|
+
* One page's layout, for renders to size their image without a round
|
|
753
|
+
* trip per tile. The layout leaf never changes at a given URL, so the
|
|
754
|
+
* last one read is kept and shared until the manifest points elsewhere.
|
|
755
|
+
*/
|
|
756
|
+
pageLayout(ref: PageRef, signal: AbortSignal): Promise<PageLayout>;
|
|
757
|
+
/**
|
|
758
|
+
* Plane-scope rule: the layout leaf depends on the `layout` plane —
|
|
759
|
+
* while inherited (no reorder/rotate/insert/delete ever ran), every
|
|
760
|
+
* visitor's page list is one doc-level URL served from the base
|
|
761
|
+
* session; the SDK open sequence creates no layer session.
|
|
762
|
+
*/
|
|
763
|
+
private layoutPath;
|
|
764
|
+
private fetchLayout;
|
|
765
|
+
setName(input: PageNameInput, options?: WriteOptions): AbortablePromise<PageNameResult>;
|
|
766
|
+
removeName(input: PageRemoveNameInput, options?: WriteOptions): AbortablePromise<PageNameResult>;
|
|
767
|
+
/**
|
|
768
|
+
* Named pages are layout: both verbs share the page-reorder patch exactly —
|
|
522
769
|
* docVersion + layoutVersion advance, no per-page pin changes, so the
|
|
523
770
|
* cached manifest is patched in place and the fresh layout is published.
|
|
524
771
|
*/
|
|
525
772
|
private runNameMutation;
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
insert(bytes: Uint8Array | ArrayBuffer, destIndex?: number): AbortablePromise$1<PageInsertResult>;
|
|
529
|
-
insertBlank(spec: PageInsertBlankSpec, destIndex?: number): AbortablePromise$1<PageInsertResult>;
|
|
530
|
-
extract(pageObjectNumbers: PageObjectNumber[]): AbortablePromise$1<Uint8Array>;
|
|
531
|
-
flatten(pageObjectNumbers: PageObjectNumber[], usage?: PageFlattenUsage): AbortablePromise$1<PageFlattenResult>;
|
|
773
|
+
extract(pages: PageRef[], options?: PageExtractOptions): AbortablePromise<Uint8Array>;
|
|
774
|
+
flatten(pages: PageRef[], options?: FlattenWriteOptions): AbortablePromise<PageFlattenResult>;
|
|
532
775
|
}
|
|
533
776
|
//#endregion
|
|
534
777
|
//#region src/document/CloudPageAnnotationsService.d.ts
|
|
@@ -541,36 +784,35 @@ declare class CloudDocumentPagesService implements DocumentPagesService$1 {
|
|
|
541
784
|
* Reads use immutable versioned layer URLs discovered from the
|
|
542
785
|
* manifest. Mutations use unversioned layer URLs and are never cached.
|
|
543
786
|
*/
|
|
544
|
-
declare class CloudPageAnnotationsService implements PageAnnotationsService
|
|
787
|
+
declare class CloudPageAnnotationsService implements PageAnnotationsService {
|
|
545
788
|
private readonly http;
|
|
546
789
|
private readonly docId;
|
|
547
790
|
private readonly layerName;
|
|
548
|
-
private readonly
|
|
791
|
+
private readonly pageRef;
|
|
549
792
|
private readonly isClosed;
|
|
550
793
|
private readonly manifest;
|
|
551
794
|
private readonly publisher;
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
/**
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
/** PATCH as plain JSON, or as multipart when the patch carried binaries. */
|
|
795
|
+
private readonly writes;
|
|
796
|
+
constructor(http: HttpClient, docId: string, layerName: string, pageRef: PageRef, isClosed: () => boolean, manifest: ManifestAccessor, publisher: SessionEventPublisher, writes: CloudWrites);
|
|
797
|
+
list(): AbortablePromise<AnnotationList>;
|
|
798
|
+
renderAppearances(options?: AnnotationAppearanceImageOptions): AbortablePromise<AnnotationAppearanceImagesResult>;
|
|
799
|
+
/**
|
|
800
|
+
* One of the annotation's resources. `file` is a read over the immutable
|
|
801
|
+
* `attachment-files` leaf, pinned by the manifest's `attachmentsVersion`
|
|
802
|
+
* (annotation-level files re-key on the same pin as document-level ones),
|
|
803
|
+
* with the same stale-404 refresh retry as {@link list}. `appearance` is a
|
|
804
|
+
* derived read (no-store), like {@link exportAppearance}. Both address the
|
|
805
|
+
* annotation by the same `:annotKey` update()/delete() use.
|
|
806
|
+
*/
|
|
807
|
+
downloadResource(ref: AnnotationRef, role: AnnotationResourceRole): AbortablePromise<Uint8Array>;
|
|
808
|
+
create(draft: AnnotationDraft, options?: AnnotationCreateOptions): AbortablePromise<AnnotationCreateResult>;
|
|
809
|
+
update(ref: AnnotationRef, patch: AnnotationPatch, options?: AnnotationUpdateOptions): AbortablePromise<AnnotationUpdateResult>;
|
|
810
|
+
/** PATCH as plain JSON, or as multipart when resources came with the patch. */
|
|
569
811
|
private patchMutation;
|
|
570
|
-
delete(ref: AnnotationRef): AbortablePromise
|
|
571
|
-
|
|
572
|
-
flatten(refs: AnnotationRef[],
|
|
573
|
-
exportAppearance(refs: AnnotationRef[]): AbortablePromise
|
|
812
|
+
delete(ref: AnnotationRef, options?: WriteOptions): AbortablePromise<AnnotationDeleteResult>;
|
|
813
|
+
reorder(refs: AnnotationRef[], position: AnnotationPosition, options?: WriteOptions): AbortablePromise<AnnotationReorderResult>;
|
|
814
|
+
flatten(refs: AnnotationRef[], options?: FlattenWriteOptions): AbortablePromise<AnnotationFlattenResult>;
|
|
815
|
+
exportAppearance(refs: AnnotationRef[]): AbortablePromise<Uint8Array>;
|
|
574
816
|
/**
|
|
575
817
|
* Patch the cached manifest, then publish the mutation to the document's
|
|
576
818
|
* event stream (in that order — listeners reading the manifest in their
|
|
@@ -578,52 +820,78 @@ declare class CloudPageAnnotationsService implements PageAnnotationsService$1 {
|
|
|
578
820
|
* `type` with the matching result by construction; the cast localizes that
|
|
579
821
|
* pairing here instead of widening every site.
|
|
580
822
|
*/
|
|
823
|
+
/** A delete's event names what went, for listeners that didn't delete it. */
|
|
824
|
+
private absorbDelete;
|
|
581
825
|
private absorbMutation;
|
|
582
826
|
}
|
|
583
827
|
//#endregion
|
|
584
|
-
//#region src/document/
|
|
585
|
-
|
|
828
|
+
//#region src/document/CloudPageFormsService.d.ts
|
|
829
|
+
/**
|
|
830
|
+
* Cloud page form service: the page's widget images, one read of the
|
|
831
|
+
* immutable `form/pages/{p}/appearances@` leaf at the page's `widgetVersion`,
|
|
832
|
+
* at the base's URL while the layer inherits the `forms` plane.
|
|
833
|
+
*/
|
|
834
|
+
declare class CloudPageFormsService implements PageFormsService {
|
|
586
835
|
private readonly http;
|
|
587
836
|
private readonly docId;
|
|
588
837
|
private readonly layerName;
|
|
589
|
-
private readonly
|
|
838
|
+
private readonly pageRef;
|
|
590
839
|
private readonly isClosed;
|
|
591
840
|
private readonly manifest;
|
|
592
|
-
constructor(http: HttpClient, docId: string, layerName: string,
|
|
593
|
-
|
|
841
|
+
constructor(http: HttpClient, docId: string, layerName: string, pageRef: PageRef, isClosed: () => boolean, manifest: ManifestAccessor);
|
|
842
|
+
renderAppearances(options?: AnnotationAppearanceImageOptions): AbortablePromise<AnnotationAppearanceImagesResult>;
|
|
594
843
|
}
|
|
595
844
|
//#endregion
|
|
596
845
|
//#region src/document/CloudPageRenderService.d.ts
|
|
597
|
-
declare class CloudPageRenderService implements PageRenderService
|
|
846
|
+
declare class CloudPageRenderService implements PageRenderService {
|
|
598
847
|
private readonly http;
|
|
599
848
|
private readonly docId;
|
|
600
849
|
private readonly layerName;
|
|
601
|
-
private readonly
|
|
850
|
+
private readonly pageRef;
|
|
602
851
|
private readonly isClosed;
|
|
603
852
|
private readonly manifest;
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
853
|
+
private readonly layout;
|
|
854
|
+
/** What the caller may read, when the client can know it; null leaves it to the server. */
|
|
855
|
+
private readonly layerRights;
|
|
856
|
+
/** What the caller may print, when the client can know it; null leaves it to the server. */
|
|
857
|
+
private readonly printRights;
|
|
858
|
+
constructor(http: HttpClient, docId: string, layerName: string, pageRef: PageRef, isClosed: () => boolean, manifest: ManifestAccessor, layout: (signal: AbortSignal) => Promise<PageLayout>,
|
|
859
|
+
/** What the caller may read, when the client can know it; null leaves it to the server. */
|
|
860
|
+
layerRights: () => PageLayerRights | null,
|
|
861
|
+
/** What the caller may print, when the client can know it; null leaves it to the server. */
|
|
862
|
+
printRights: () => PagePrintRights | null);
|
|
863
|
+
image(options?: PageImageOptions): AbortablePromise<PageRenderImage>;
|
|
864
|
+
/**
|
|
865
|
+
* The image's transform, computed like the server's render (the same
|
|
866
|
+
* `renderSize` and matrix), so the handle knows its size and its pixels
|
|
867
|
+
* before any are fetched. Only a full page needs the page's layout.
|
|
868
|
+
*/
|
|
869
|
+
private transformOf;
|
|
607
870
|
}
|
|
608
871
|
//#endregion
|
|
609
872
|
//#region src/document/CloudPageTextService.d.ts
|
|
610
873
|
/**
|
|
611
|
-
* Cloud-side per-page text service. `
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
* manifest. On a 404 (stale version) the SDK transparently
|
|
615
|
-
* `/head` + `/manifest@docVersion=N`, rebuilds the URL with the
|
|
616
|
-
* and retries exactly once.
|
|
874
|
+
* Cloud-side per-page text service. `get()` fetches the content-addressed
|
|
875
|
+
* URL `/v1/docs/:id/text/pages/:pon/data@contentVersion=N` and `layout()`
|
|
876
|
+
* its geometry twin, where `N` is the page's current `contentVersion` from
|
|
877
|
+
* the cached manifest. On a 404 (stale version) the SDK transparently
|
|
878
|
+
* refreshes `/head` + `/manifest@docVersion=N`, rebuilds the URL with the
|
|
879
|
+
* fresh version, and retries exactly once.
|
|
617
880
|
*/
|
|
618
|
-
declare class CloudPageTextService implements PageTextService
|
|
881
|
+
declare class CloudPageTextService implements PageTextService {
|
|
619
882
|
private readonly http;
|
|
620
883
|
private readonly docId;
|
|
621
884
|
private readonly layerName;
|
|
622
|
-
private readonly
|
|
885
|
+
private readonly pageRef;
|
|
623
886
|
private readonly isClosed;
|
|
624
887
|
private readonly manifest;
|
|
625
|
-
constructor(http: HttpClient, docId: string, layerName: string,
|
|
626
|
-
|
|
888
|
+
constructor(http: HttpClient, docId: string, layerName: string, pageRef: PageRef, isClosed: () => boolean, manifest: ManifestAccessor);
|
|
889
|
+
get(): AbortablePromise<PageTextSnapshot>;
|
|
890
|
+
slice(range: TextRange): AbortablePromise<string>;
|
|
891
|
+
layout(): AbortablePromise<TextLayout>;
|
|
892
|
+
/** One of the page's content leaves at the manifest's pin, with the stale-pin retry. */
|
|
893
|
+
private readLeaf;
|
|
894
|
+
private leafPath;
|
|
627
895
|
}
|
|
628
896
|
//#endregion
|
|
629
897
|
//#region src/document/CloudPageMeasureService.d.ts
|
|
@@ -631,26 +899,32 @@ declare class CloudPageMeasureService implements PageMeasureService {
|
|
|
631
899
|
private readonly http;
|
|
632
900
|
private readonly docId;
|
|
633
901
|
private readonly layerName;
|
|
634
|
-
private readonly
|
|
902
|
+
private readonly pageRef;
|
|
635
903
|
private readonly isClosed;
|
|
636
904
|
private readonly manifest;
|
|
637
905
|
private readonly publisher;
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
906
|
+
private readonly writes;
|
|
907
|
+
constructor(http: HttpClient, docId: string, layerName: string, pageRef: PageRef, isClosed: () => boolean, manifest: ManifestAccessor, publisher: SessionEventPublisher, writes: CloudWrites);
|
|
908
|
+
listViewports(): AbortablePromise<PageMeasurementViewportList>;
|
|
909
|
+
setScale(measure: PdfMeasure | null, options?: WriteOptions): AbortablePromise<PageScaleResult>;
|
|
641
910
|
private check;
|
|
642
911
|
}
|
|
643
912
|
//#endregion
|
|
644
913
|
//#region src/document/CloudPageHandle.d.ts
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
914
|
+
/**
|
|
915
|
+
* Cloud page handle, keyed on `ref` — the page's durable address (its
|
|
916
|
+
* object number). Every service below addresses the wire by it
|
|
917
|
+
* (`/pages/obj:N/…`), keys the manifest by its number, and publishes
|
|
918
|
+
* that number in events.
|
|
919
|
+
*/
|
|
920
|
+
declare class CloudPageHandle implements PageHandle {
|
|
921
|
+
readonly ref: PageRef;
|
|
648
922
|
readonly annotations: CloudPageAnnotationsService;
|
|
923
|
+
readonly forms: CloudPageFormsService;
|
|
649
924
|
readonly text: CloudPageTextService;
|
|
650
|
-
readonly geometry: CloudPageGeometryService;
|
|
651
925
|
readonly render: CloudPageRenderService;
|
|
652
926
|
readonly measure: CloudPageMeasureService;
|
|
653
|
-
constructor(
|
|
927
|
+
constructor(ref: PageRef, http: HttpClient, docId: string, layerName: string, isClosed: () => boolean, manifest: ManifestAccessor, publisher: SessionEventPublisher, writes: CloudWrites, layout: (signal: AbortSignal) => Promise<PageLayout>, layerRights: () => PageLayerRights | null, printRights: () => PagePrintRights | null);
|
|
654
928
|
}
|
|
655
929
|
//#endregion
|
|
656
930
|
//#region src/transport/decodeUnverifiedClaims.d.ts
|
|
@@ -683,7 +957,7 @@ declare function decodeUnverifiedClaims(token: string): UnverifiedClaims;
|
|
|
683
957
|
/**
|
|
684
958
|
* Share-session exchange: the client half of the no-backend embed flow.
|
|
685
959
|
*
|
|
686
|
-
* A share token (`shr_…`) is a
|
|
960
|
+
* A share token (`shr_…`) is a reference to a stored grant on the
|
|
687
961
|
* server, not a credential — `exchangeShareToken` trades it for an
|
|
688
962
|
* ordinary short-lived doc JWT, and `shareSessionSource` wraps that in
|
|
689
963
|
* a self-renewing token source. Because the engine's transport
|
|
@@ -732,7 +1006,7 @@ declare function exchangeShareToken(baseUrl: string, shareToken: string, opts?:
|
|
|
732
1006
|
* retry). Everything else maps by meaning, with the HTTP status as the
|
|
733
1007
|
* fallback discriminator.
|
|
734
1008
|
*/
|
|
735
|
-
declare function engineErrorFromShareExchange(error: ShareExchangeError): EngineError
|
|
1009
|
+
declare function engineErrorFromShareExchange(error: ShareExchangeError): EngineError;
|
|
736
1010
|
/**
|
|
737
1011
|
* A caching, self-renewing token source over the exchange — the callable
|
|
738
1012
|
* member of the engine's `TokenSource` union, assignable wherever one is
|
|
@@ -743,7 +1017,6 @@ declare function engineErrorFromShareExchange(error: ShareExchangeError): Engine
|
|
|
743
1017
|
declare function shareSessionSource(baseUrl: string, shareToken: string, opts?: ShareExchangeOptions): () => Promise<string>;
|
|
744
1018
|
//#endregion
|
|
745
1019
|
//#region src/index.d.ts
|
|
746
|
-
declare function createCloudEngine(opts: CloudEngineOptions): CloudEngine;
|
|
747
1020
|
/**
|
|
748
1021
|
* Create a cloud {@link CloudEngine} — the drop-in counterpart of
|
|
749
1022
|
* `localEngine()`, so swapping local for cloud is a one-import change.
|
|
@@ -755,16 +1028,19 @@ declare function createCloudEngine(opts: CloudEngineOptions): CloudEngine;
|
|
|
755
1028
|
* to let a `<Viewer>` own the lifetime instead.
|
|
756
1029
|
*
|
|
757
1030
|
* Note the deliberate asymmetry with `localEngine()`: there is no `fonts`
|
|
758
|
-
* option. Fallback fonts are a
|
|
1031
|
+
* option. Fallback fonts are a server policy on the cloud (`Engine.fonts` is
|
|
759
1032
|
* `undefined` cloud-side), so they cannot be configured from the client. This
|
|
760
1033
|
* is the local-vs-cloud split, surfaced in the API.
|
|
761
1034
|
*
|
|
1035
|
+
* Without a `baseUrl` it connects to CloudPDF SaaS; your own server names itself:
|
|
1036
|
+
*
|
|
762
1037
|
* ```ts
|
|
763
|
-
* const engine = cloudEngine(
|
|
1038
|
+
* const engine = cloudEngine(); // CloudPDF SaaS
|
|
1039
|
+
* const own = cloudEngine({ baseUrl: 'https://pdf.example.com' }); // your @cloudpdf/server
|
|
764
1040
|
* <Viewer engine={engine} plugins={[stagePlugin(), renderPlugin()]} />
|
|
765
1041
|
* ```
|
|
766
1042
|
*/
|
|
767
|
-
declare function cloudEngine(opts
|
|
1043
|
+
declare function cloudEngine(opts?: CloudEngineOptions): CloudEngine;
|
|
768
1044
|
//#endregion
|
|
769
|
-
export {
|
|
1045
|
+
export { CLOUDPDF_SAAS_URL, CloudDocumentAnnotationsService, CloudDocumentHandle, CloudDocumentPagesService, CloudEngine, type CloudEngineOptions, CloudMetadataService, CloudPageAnnotationsService, CloudPageHandle, CloudPageRenderService, HttpClient, type HttpClientOptions, ShareExchangeError, type ShareExchangeOptions, type ShareSession, type UnverifiedClaims, cloudEngine, decodeUnverifiedClaims, engineErrorFromShareExchange, exchangeShareToken, shareSessionSource };
|
|
770
1046
|
//# sourceMappingURL=index.d.cts.map
|