@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.
- package/LICENSE +192 -0
- package/README.md +24 -0
- package/dist/AbortError-ByBflvEl.cjs +38 -0
- package/dist/AbortError-ByBflvEl.cjs.map +1 -0
- package/dist/AbortError-CjSasIlL.js +27 -0
- package/dist/AbortError-CjSasIlL.js.map +1 -0
- package/dist/AnnotationListSnapshot-W0RCsyDE.d.cts +5043 -0
- package/dist/AnnotationListSnapshot-W0RCsyDE.d.ts +5043 -0
- package/dist/DocumentSecurityService-B-tULKNY.d.ts +332 -0
- package/dist/DocumentSecurityService-Df79fgpe.d.cts +332 -0
- package/dist/Engine-B7Oe7f5i.d.ts +1013 -0
- package/dist/Engine-D9loFZc1.d.cts +1013 -0
- package/dist/builders-BvikWRuO.cjs +1684 -0
- package/dist/builders-BvikWRuO.cjs.map +1 -0
- package/dist/builders-C548U47M.js +1367 -0
- package/dist/builders-C548U47M.js.map +1 -0
- package/dist/conformance.cjs +5414 -0
- package/dist/conformance.cjs.map +1 -0
- package/dist/conformance.d.cts +530 -0
- package/dist/conformance.d.ts +530 -0
- package/dist/conformance.js +5394 -0
- package/dist/conformance.js.map +1 -0
- package/dist/fold-CB4fAOOy.js +175 -0
- package/dist/fold-CB4fAOOy.js.map +1 -0
- package/dist/fold-IaMph3CO.cjs +216 -0
- package/dist/fold-IaMph3CO.cjs.map +1 -0
- package/dist/index.cjs +82 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/resolver-DAZWVoJL.cjs +434 -0
- package/dist/resolver-DAZWVoJL.cjs.map +1 -0
- package/dist/resolver-DiPMTfcy.js +363 -0
- package/dist/resolver-DiPMTfcy.js.map +1 -0
- package/dist/runtime.cjs +453 -0
- package/dist/runtime.cjs.map +1 -0
- package/dist/runtime.d.cts +1002 -0
- package/dist/runtime.d.ts +1002 -0
- package/dist/runtime.js +361 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schemas-9OpSSeM6.js +2493 -0
- package/dist/schemas-9OpSSeM6.js.map +1 -0
- package/dist/schemas-B_1VyFsm.cjs +3608 -0
- package/dist/schemas-B_1VyFsm.cjs.map +1 -0
- package/dist/subtype-BvAzLCGC.js +196 -0
- package/dist/subtype-BvAzLCGC.js.map +1 -0
- package/dist/subtype-qejjVr6h.cjs +231 -0
- package/dist/subtype-qejjVr6h.cjs.map +1 -0
- package/dist/wire.cjs +1516 -0
- package/dist/wire.cjs.map +1 -0
- package/dist/wire.d.cts +1546 -0
- package/dist/wire.d.ts +1546 -0
- package/dist/wire.js +1280 -0
- package/dist/wire.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { Hs as DocCapability, Us as IdentityClaims, Ys as PdfBits } from "./AnnotationListSnapshot-W0RCsyDE.js";
|
|
2
|
+
//#region src/promise/AbortablePromise.d.ts
|
|
3
|
+
type AbortableExecutor<T, P> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason: unknown) => void, progress: (p: P) => void, signal: AbortSignal) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Awaitable Promise subclass with abort and progress.
|
|
6
|
+
*
|
|
7
|
+
* Symbol.species returns plain Promise so chained .then/.catch/.finally
|
|
8
|
+
* return regular promises and never try to synthesize a new
|
|
9
|
+
* AbortablePromise (which would have no executor).
|
|
10
|
+
*
|
|
11
|
+
* Settlement contract:
|
|
12
|
+
* - The first settlement wins. resolve/reject handed to the executor
|
|
13
|
+
* are wrapped so that any subsequent call (whether by the executor,
|
|
14
|
+
* by abort(), or by both racing) becomes a silent no-op.
|
|
15
|
+
* - abort() rejects the public promise with AbortError immediately,
|
|
16
|
+
* even if the executor never observes the AbortSignal. The executor
|
|
17
|
+
* still receives the AbortSignal so it can stop real work
|
|
18
|
+
* cooperatively (release a queue slot, abort fetch, post a worker
|
|
19
|
+
* abort, etc.). Anything the executor does after that — including
|
|
20
|
+
* a late resolve(value), a late reject(error), or a rejected inner
|
|
21
|
+
* Promise inside AbortablePromise.run — is dropped silently.
|
|
22
|
+
* - abort() after settlement is a no-op.
|
|
23
|
+
*/
|
|
24
|
+
declare class AbortablePromise<T, P = never> extends Promise<T> {
|
|
25
|
+
static get [Symbol.species](): PromiseConstructor;
|
|
26
|
+
readonly signal: AbortSignal;
|
|
27
|
+
private readonly _ctrl;
|
|
28
|
+
private readonly _progressCbs;
|
|
29
|
+
private readonly _state;
|
|
30
|
+
private readonly _internalReject;
|
|
31
|
+
constructor(executor: AbortableExecutor<T, P>);
|
|
32
|
+
/**
|
|
33
|
+
* Abort the underlying operation.
|
|
34
|
+
*
|
|
35
|
+
* - If the promise has already settled, this is a no-op.
|
|
36
|
+
* - Otherwise the public promise rejects synchronously with an
|
|
37
|
+
* AbortError (wrapping the supplied reason if it is not already an
|
|
38
|
+
* AbortError) and the AbortSignal fires for any cooperative
|
|
39
|
+
* cancellation the executor wired up.
|
|
40
|
+
*/
|
|
41
|
+
abort(reason?: unknown): void;
|
|
42
|
+
/**
|
|
43
|
+
* Subscribe to progress events. Returns an unsubscribe function.
|
|
44
|
+
*/
|
|
45
|
+
onProgress(cb: (p: P) => void): () => void;
|
|
46
|
+
/**
|
|
47
|
+
* Wrap a value in an already-resolved AbortablePromise. Mirrors Promise.resolve.
|
|
48
|
+
*/
|
|
49
|
+
static resolveValue<T>(value: T | PromiseLike<T>): AbortablePromise<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Wrap a thrown reason in an already-rejected AbortablePromise.
|
|
52
|
+
*/
|
|
53
|
+
static rejectReason<T = never>(reason: unknown): AbortablePromise<T>;
|
|
54
|
+
/**
|
|
55
|
+
* Run an async function as an AbortablePromise so callers get .abort() and .signal.
|
|
56
|
+
* The async function receives the AbortSignal (and a progress emitter) so it can
|
|
57
|
+
* cooperate with the abort.
|
|
58
|
+
*
|
|
59
|
+
* If abort() fires while the inner async function is still running, the
|
|
60
|
+
* public promise rejects with AbortError immediately. The inner async
|
|
61
|
+
* function's eventual settlement (resolve or reject) is funneled through
|
|
62
|
+
* the wrapped settlers and silently dropped — including a late rejection
|
|
63
|
+
* from the underlying work, which prevents an UnhandledRejection because
|
|
64
|
+
* the .then(resolve, reject) below "handles" it via the no-op.
|
|
65
|
+
*/
|
|
66
|
+
static run<T, P = never>(fn: (signal: AbortSignal, progress: (p: P) => void) => Promise<T>): AbortablePromise<T, P>;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/engine/passwordPrompt.d.ts
|
|
70
|
+
type PasswordPrompt = {
|
|
71
|
+
readonly state: 'none';
|
|
72
|
+
} | {
|
|
73
|
+
readonly state: 'required';
|
|
74
|
+
readonly hint: 'user' | 'owner' | null;
|
|
75
|
+
} | {
|
|
76
|
+
readonly state: 'optional';
|
|
77
|
+
readonly hint: 'owner';
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Derive the high-level password prompt from the raw security state.
|
|
81
|
+
*
|
|
82
|
+
* The function is pure and total — every `DocumentSecurityState`
|
|
83
|
+
* maps to exactly one `PasswordPrompt`. Use this as the SINGLE source
|
|
84
|
+
* of truth wherever the SDK exposes a "do you need a password?" flag:
|
|
85
|
+
* both `LocalDocumentSecurityService` and `CloudDocumentSecurityService`
|
|
86
|
+
* call it, so the contract can never drift.
|
|
87
|
+
*
|
|
88
|
+
* Mapping rules (top to bottom; first match wins):
|
|
89
|
+
*
|
|
90
|
+
* 1. encryption.state === 'none'
|
|
91
|
+
* → { state: 'none' } the document isn't encrypted
|
|
92
|
+
*
|
|
93
|
+
* 2. !permissions.known
|
|
94
|
+
* → { state: 'required', hint: null } we haven't probed yet; can't
|
|
95
|
+
* tell user-vs-owner; show
|
|
96
|
+
* generic prompt
|
|
97
|
+
*
|
|
98
|
+
* 3. requiresPassword && openedAs === 'none'
|
|
99
|
+
* → { state: 'required', hint: 'user' } encrypted, anonymous open
|
|
100
|
+
* failed → user pwd needed
|
|
101
|
+
*
|
|
102
|
+
* 4. openedAs === 'owner'
|
|
103
|
+
* → { state: 'none' } already at the top — nothing more
|
|
104
|
+
* to unlock
|
|
105
|
+
*
|
|
106
|
+
* 5. permissions.canUpgradeToOwner === true
|
|
107
|
+
* → { state: 'optional', hint: 'owner' } open as user (or as none
|
|
108
|
+
* for owner-pwd-only docs)
|
|
109
|
+
* but more is available
|
|
110
|
+
*
|
|
111
|
+
* 6. fallthrough → { state: 'none' } open and nothing more available
|
|
112
|
+
*/
|
|
113
|
+
declare function passwordPromptFromState(state: DocumentSecurityState): PasswordPrompt;
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/engine/DocumentSecurityService.d.ts
|
|
116
|
+
type DocumentOpenMode = 'none' | 'user' | 'owner';
|
|
117
|
+
type DocumentEncryptionState = 'unknown' | 'none' | 'encrypted' | 'unsupported';
|
|
118
|
+
type DocumentAccessReason = 'password' | 'cdn' | 'permissions-unknown';
|
|
119
|
+
/**
|
|
120
|
+
* Boolean view of "what the PDF's permission bits allow," surfaced for
|
|
121
|
+
* client UI badges ("this PDF disallows printing", "copy is blocked",
|
|
122
|
+
* etc.). Names mirror the user-facing capability they correspond to,
|
|
123
|
+
* not the raw bit names — so docs can render "Print: disabled" without
|
|
124
|
+
* the reader needing to know PDF bit positions.
|
|
125
|
+
*
|
|
126
|
+
* Computed from {@link PdfBits} via the strict ISO 32000 rules:
|
|
127
|
+
* bit 12 only meaningful when bit 3 is also set
|
|
128
|
+
* form modification requires both bit 6 AND bit 4
|
|
129
|
+
* form fill is satisfied by bit 6 OR bit 9
|
|
130
|
+
*/
|
|
131
|
+
interface PdfPermissionAdvisory {
|
|
132
|
+
readonly canPrint: boolean;
|
|
133
|
+
readonly canPrintHigh: boolean;
|
|
134
|
+
readonly canCopy: boolean;
|
|
135
|
+
readonly canAnnotate: boolean;
|
|
136
|
+
readonly canFillForms: boolean;
|
|
137
|
+
readonly canModifyForms: boolean;
|
|
138
|
+
readonly canModifyPages: boolean;
|
|
139
|
+
readonly canAssemble: boolean;
|
|
140
|
+
}
|
|
141
|
+
interface PdfPermissionInfo {
|
|
142
|
+
readonly known: boolean;
|
|
143
|
+
readonly allAllowed: boolean | null;
|
|
144
|
+
readonly bits: number | null;
|
|
145
|
+
readonly openedAs: DocumentOpenMode | null;
|
|
146
|
+
readonly securityHandlerRevision: number | null;
|
|
147
|
+
/**
|
|
148
|
+
* Typed boolean view of `bits`. Present whenever the caller had
|
|
149
|
+
* access to the document's PDF bits at construction time (always
|
|
150
|
+
* true in the /access response; not always populated by the cheaper
|
|
151
|
+
* /head shape).
|
|
152
|
+
*/
|
|
153
|
+
readonly flags?: PdfBits;
|
|
154
|
+
/**
|
|
155
|
+
* Capability-shaped "what does this PDF natively allow" view for UI
|
|
156
|
+
* badges. Same population rule as `flags`.
|
|
157
|
+
*/
|
|
158
|
+
readonly advisory?: PdfPermissionAdvisory;
|
|
159
|
+
}
|
|
160
|
+
interface DocumentSecurityState {
|
|
161
|
+
readonly encryption: {
|
|
162
|
+
readonly state: DocumentEncryptionState;
|
|
163
|
+
readonly requiresPassword: boolean | null;
|
|
164
|
+
};
|
|
165
|
+
readonly permissions: {
|
|
166
|
+
readonly known: boolean;
|
|
167
|
+
readonly bits: number | null;
|
|
168
|
+
readonly allAllowed: boolean | null;
|
|
169
|
+
readonly openedAs: DocumentOpenMode | null;
|
|
170
|
+
readonly securityHandlerRevision: number | null;
|
|
171
|
+
readonly canUpgradeToOwner: boolean;
|
|
172
|
+
};
|
|
173
|
+
readonly access: {
|
|
174
|
+
readonly required: boolean;
|
|
175
|
+
readonly reasons: DocumentAccessReason[];
|
|
176
|
+
readonly endpoint?: string;
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The CDN adapter identifier surfaced on the wire. Cloudflare users
|
|
181
|
+
* deploy a custom Worker that verifies HMAC-SHA256 signatures and
|
|
182
|
+
* configure the `custom-hmac` adapter — no first-class `'cloudflare'`
|
|
183
|
+
* value is needed.
|
|
184
|
+
*/
|
|
185
|
+
type CdnAdapter = 'none' | 'cloudfront' | 'cloud-cdn' | 'bunny' | 'azure-fd' | 'custom-hmac';
|
|
186
|
+
/**
|
|
187
|
+
* Per-caller CDN access bits returned in the /access response. The
|
|
188
|
+
* SDK fetch wrapper applies whatever channels are populated:
|
|
189
|
+
* - baseUrlOverrides : swap the origin host/path-prefix for the CDN URL
|
|
190
|
+
* - authHeader : attach a single header to every CDN request
|
|
191
|
+
* - signedQueryParams : append params to every CDN URL (single-token signers)
|
|
192
|
+
* - signedCookies : set cookies on the CDN origin before requests
|
|
193
|
+
* - signedPathPolicies : per-prefix params (one signature covers a path subtree)
|
|
194
|
+
*
|
|
195
|
+
* Each adapter populates only the channels it uses; the others stay
|
|
196
|
+
* null. Frontend stays provider-agnostic — it doesn't branch on
|
|
197
|
+
* `adapter`, it just applies whatever's present.
|
|
198
|
+
*/
|
|
199
|
+
interface CdnAccessInfo {
|
|
200
|
+
readonly adapter: CdnAdapter;
|
|
201
|
+
readonly expiresAt: number;
|
|
202
|
+
readonly cache: {
|
|
203
|
+
readonly scope: 'browser-private' | 'edge-shared';
|
|
204
|
+
readonly immutableVersionedReads: boolean;
|
|
205
|
+
};
|
|
206
|
+
readonly baseUrlOverrides: Partial<Record<string, string>> | null;
|
|
207
|
+
readonly authHeader: {
|
|
208
|
+
name: string;
|
|
209
|
+
value: string;
|
|
210
|
+
} | null;
|
|
211
|
+
readonly signedQueryParams: Record<string, string> | null;
|
|
212
|
+
readonly signedCookies: ReadonlyArray<{
|
|
213
|
+
readonly name: string;
|
|
214
|
+
readonly value: string;
|
|
215
|
+
readonly domain?: string;
|
|
216
|
+
readonly path?: string;
|
|
217
|
+
readonly expires?: number;
|
|
218
|
+
}> | null;
|
|
219
|
+
readonly signedPathPolicies: ReadonlyArray<{
|
|
220
|
+
readonly pathPrefix: string;
|
|
221
|
+
readonly queryParams: Record<string, string>;
|
|
222
|
+
}> | null;
|
|
223
|
+
}
|
|
224
|
+
interface DocumentAccessInfo {
|
|
225
|
+
readonly cdn: CdnAccessInfo;
|
|
226
|
+
readonly passwordGrant: string | null;
|
|
227
|
+
readonly pdfPermissions: PdfPermissionInfo | null;
|
|
228
|
+
/**
|
|
229
|
+
* Raw scope array exactly as the JWT carried it. Useful for debugging
|
|
230
|
+
* and for clients that want to display the literal grants.
|
|
231
|
+
*/
|
|
232
|
+
readonly scope: string[];
|
|
233
|
+
/**
|
|
234
|
+
* Concrete capability set granted to this caller, after expanding
|
|
235
|
+
* `pdf.permissions` against the document's PDF bits and applying
|
|
236
|
+
* the implication rules in the resolver (e.g. annotation collab
|
|
237
|
+
* scopes imply `doc.annotate.read`). Client UI should drive feature
|
|
238
|
+
* visibility off this, not off the raw `scope`.
|
|
239
|
+
*
|
|
240
|
+
* Sorted alphabetically for stable display.
|
|
241
|
+
*/
|
|
242
|
+
readonly effectiveScope: string[];
|
|
243
|
+
readonly identity: {
|
|
244
|
+
readonly user_id?: string;
|
|
245
|
+
readonly group_id?: string;
|
|
246
|
+
readonly groups?: string[];
|
|
247
|
+
readonly display_name?: string;
|
|
248
|
+
};
|
|
249
|
+
readonly originPasswordPolicy: {
|
|
250
|
+
readonly mode: 'not-needed' | 'client-retry' | 'server-session';
|
|
251
|
+
};
|
|
252
|
+
readonly expiresAt: number;
|
|
253
|
+
/**
|
|
254
|
+
* The deployment's render lattice: canonical full-page
|
|
255
|
+
* `viewport.width` points whose renders are durable, CDN-shared
|
|
256
|
+
* artifacts, plus the reserved tile-pyramid block. Local engines report
|
|
257
|
+
* nothing here (continuous rendering); cloud engines surface it so
|
|
258
|
+
* `snapFullPageViewport` can conform requests EXPLICITLY — the SDK
|
|
259
|
+
* never snaps implicitly (engine parity).
|
|
260
|
+
*/
|
|
261
|
+
readonly renderPolicy?: {
|
|
262
|
+
readonly fullPage: {
|
|
263
|
+
readonly widths: readonly number[];
|
|
264
|
+
};
|
|
265
|
+
readonly tiles?: {
|
|
266
|
+
readonly tileSizes: readonly number[];
|
|
267
|
+
readonly scales: readonly number[];
|
|
268
|
+
};
|
|
269
|
+
readonly appearances?: {
|
|
270
|
+
readonly scales: readonly number[];
|
|
271
|
+
};
|
|
272
|
+
readonly maxRenderPixels?: number;
|
|
273
|
+
readonly formats: readonly ('webp' | 'png')[];
|
|
274
|
+
readonly background: 'white';
|
|
275
|
+
readonly enforced: boolean;
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
interface DocumentUnlockInput {
|
|
279
|
+
readonly password: string;
|
|
280
|
+
readonly mode?: 'any' | 'owner';
|
|
281
|
+
}
|
|
282
|
+
interface DocumentUnlockResult {
|
|
283
|
+
readonly security: DocumentSecurityState;
|
|
284
|
+
readonly access?: DocumentAccessInfo;
|
|
285
|
+
}
|
|
286
|
+
interface DocumentSecurityService {
|
|
287
|
+
/**
|
|
288
|
+
* Raw structured security probe. Stable across engines, refreshed
|
|
289
|
+
* after unlock/refresh. Power users and diagnostic tools read this;
|
|
290
|
+
* most dev code uses the higher-level accessors below.
|
|
291
|
+
*/
|
|
292
|
+
readonly current: DocumentSecurityState;
|
|
293
|
+
/**
|
|
294
|
+
* The caller's expanded capability set — raw scope + pdf bits +
|
|
295
|
+
* implication rules, enumerated for DISPLAY ("here's what you can
|
|
296
|
+
* do"). Identical shape on local and cloud; cloud uses the
|
|
297
|
+
* server-canonical value when available, else computes locally from
|
|
298
|
+
* JWT scope + /head bits.
|
|
299
|
+
*
|
|
300
|
+
* NOTE: this is an *enumeration*, not an authorization check. The `*`
|
|
301
|
+
* admin wildcard and unbounded parametric collab grants are NOT
|
|
302
|
+
* listed here (they can't be). To gate UI, use {@link allows} — the
|
|
303
|
+
* same wildcard-aware predicate the engine enforces with.
|
|
304
|
+
*/
|
|
305
|
+
readonly effectiveScope: ReadonlyArray<string>;
|
|
306
|
+
/**
|
|
307
|
+
* Wildcard-aware authorization check — the SAME predicate the engine
|
|
308
|
+
* enforces with (`checkCapability`). A shown control gated on this
|
|
309
|
+
* mirrors exactly what the engine will allow: the `*` admin grant and
|
|
310
|
+
* `pdf.permissions`-derived bits are both honored. Use this for edit
|
|
311
|
+
* gating (e.g. `allows('doc.pages.assemble')`); use `effectiveScope`
|
|
312
|
+
* only to *display* the concrete grants.
|
|
313
|
+
*/
|
|
314
|
+
allows(capability: DocCapability): boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Identity of the current caller, or null when anonymous.
|
|
317
|
+
*/
|
|
318
|
+
readonly identity: IdentityClaims | null;
|
|
319
|
+
/**
|
|
320
|
+
* "Should I prompt the user for a password?" — the single source
|
|
321
|
+
* of truth. Three states, each carrying exactly the data needed:
|
|
322
|
+
* - `none` — do nothing
|
|
323
|
+
* - `required` — hard block; show modal; `hint` labels the prompt
|
|
324
|
+
* - `optional` — soft offer; show banner; only ever asks for owner
|
|
325
|
+
* See {@link PasswordPrompt} for the full contract.
|
|
326
|
+
*/
|
|
327
|
+
readonly passwordPrompt: PasswordPrompt;
|
|
328
|
+
unlock(input: DocumentUnlockInput): AbortablePromise<DocumentUnlockResult>;
|
|
329
|
+
}
|
|
330
|
+
//#endregion
|
|
331
|
+
export { DocumentEncryptionState as a, DocumentSecurityState as c, PdfPermissionAdvisory as d, PdfPermissionInfo as f, AbortablePromise as g, AbortableExecutor as h, DocumentAccessReason as i, DocumentUnlockInput as l, passwordPromptFromState as m, CdnAdapter as n, DocumentOpenMode as o, PasswordPrompt as p, DocumentAccessInfo as r, DocumentSecurityService as s, CdnAccessInfo as t, DocumentUnlockResult as u };
|
|
332
|
+
//# sourceMappingURL=DocumentSecurityService-B-tULKNY.d.ts.map
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { Hs as DocCapability, Us as IdentityClaims, Ys as PdfBits } from "./AnnotationListSnapshot-W0RCsyDE.cjs";
|
|
2
|
+
//#region src/promise/AbortablePromise.d.ts
|
|
3
|
+
type AbortableExecutor<T, P> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason: unknown) => void, progress: (p: P) => void, signal: AbortSignal) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Awaitable Promise subclass with abort and progress.
|
|
6
|
+
*
|
|
7
|
+
* Symbol.species returns plain Promise so chained .then/.catch/.finally
|
|
8
|
+
* return regular promises and never try to synthesize a new
|
|
9
|
+
* AbortablePromise (which would have no executor).
|
|
10
|
+
*
|
|
11
|
+
* Settlement contract:
|
|
12
|
+
* - The first settlement wins. resolve/reject handed to the executor
|
|
13
|
+
* are wrapped so that any subsequent call (whether by the executor,
|
|
14
|
+
* by abort(), or by both racing) becomes a silent no-op.
|
|
15
|
+
* - abort() rejects the public promise with AbortError immediately,
|
|
16
|
+
* even if the executor never observes the AbortSignal. The executor
|
|
17
|
+
* still receives the AbortSignal so it can stop real work
|
|
18
|
+
* cooperatively (release a queue slot, abort fetch, post a worker
|
|
19
|
+
* abort, etc.). Anything the executor does after that — including
|
|
20
|
+
* a late resolve(value), a late reject(error), or a rejected inner
|
|
21
|
+
* Promise inside AbortablePromise.run — is dropped silently.
|
|
22
|
+
* - abort() after settlement is a no-op.
|
|
23
|
+
*/
|
|
24
|
+
declare class AbortablePromise<T, P = never> extends Promise<T> {
|
|
25
|
+
static get [Symbol.species](): PromiseConstructor;
|
|
26
|
+
readonly signal: AbortSignal;
|
|
27
|
+
private readonly _ctrl;
|
|
28
|
+
private readonly _progressCbs;
|
|
29
|
+
private readonly _state;
|
|
30
|
+
private readonly _internalReject;
|
|
31
|
+
constructor(executor: AbortableExecutor<T, P>);
|
|
32
|
+
/**
|
|
33
|
+
* Abort the underlying operation.
|
|
34
|
+
*
|
|
35
|
+
* - If the promise has already settled, this is a no-op.
|
|
36
|
+
* - Otherwise the public promise rejects synchronously with an
|
|
37
|
+
* AbortError (wrapping the supplied reason if it is not already an
|
|
38
|
+
* AbortError) and the AbortSignal fires for any cooperative
|
|
39
|
+
* cancellation the executor wired up.
|
|
40
|
+
*/
|
|
41
|
+
abort(reason?: unknown): void;
|
|
42
|
+
/**
|
|
43
|
+
* Subscribe to progress events. Returns an unsubscribe function.
|
|
44
|
+
*/
|
|
45
|
+
onProgress(cb: (p: P) => void): () => void;
|
|
46
|
+
/**
|
|
47
|
+
* Wrap a value in an already-resolved AbortablePromise. Mirrors Promise.resolve.
|
|
48
|
+
*/
|
|
49
|
+
static resolveValue<T>(value: T | PromiseLike<T>): AbortablePromise<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Wrap a thrown reason in an already-rejected AbortablePromise.
|
|
52
|
+
*/
|
|
53
|
+
static rejectReason<T = never>(reason: unknown): AbortablePromise<T>;
|
|
54
|
+
/**
|
|
55
|
+
* Run an async function as an AbortablePromise so callers get .abort() and .signal.
|
|
56
|
+
* The async function receives the AbortSignal (and a progress emitter) so it can
|
|
57
|
+
* cooperate with the abort.
|
|
58
|
+
*
|
|
59
|
+
* If abort() fires while the inner async function is still running, the
|
|
60
|
+
* public promise rejects with AbortError immediately. The inner async
|
|
61
|
+
* function's eventual settlement (resolve or reject) is funneled through
|
|
62
|
+
* the wrapped settlers and silently dropped — including a late rejection
|
|
63
|
+
* from the underlying work, which prevents an UnhandledRejection because
|
|
64
|
+
* the .then(resolve, reject) below "handles" it via the no-op.
|
|
65
|
+
*/
|
|
66
|
+
static run<T, P = never>(fn: (signal: AbortSignal, progress: (p: P) => void) => Promise<T>): AbortablePromise<T, P>;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/engine/passwordPrompt.d.ts
|
|
70
|
+
type PasswordPrompt = {
|
|
71
|
+
readonly state: 'none';
|
|
72
|
+
} | {
|
|
73
|
+
readonly state: 'required';
|
|
74
|
+
readonly hint: 'user' | 'owner' | null;
|
|
75
|
+
} | {
|
|
76
|
+
readonly state: 'optional';
|
|
77
|
+
readonly hint: 'owner';
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Derive the high-level password prompt from the raw security state.
|
|
81
|
+
*
|
|
82
|
+
* The function is pure and total — every `DocumentSecurityState`
|
|
83
|
+
* maps to exactly one `PasswordPrompt`. Use this as the SINGLE source
|
|
84
|
+
* of truth wherever the SDK exposes a "do you need a password?" flag:
|
|
85
|
+
* both `LocalDocumentSecurityService` and `CloudDocumentSecurityService`
|
|
86
|
+
* call it, so the contract can never drift.
|
|
87
|
+
*
|
|
88
|
+
* Mapping rules (top to bottom; first match wins):
|
|
89
|
+
*
|
|
90
|
+
* 1. encryption.state === 'none'
|
|
91
|
+
* → { state: 'none' } the document isn't encrypted
|
|
92
|
+
*
|
|
93
|
+
* 2. !permissions.known
|
|
94
|
+
* → { state: 'required', hint: null } we haven't probed yet; can't
|
|
95
|
+
* tell user-vs-owner; show
|
|
96
|
+
* generic prompt
|
|
97
|
+
*
|
|
98
|
+
* 3. requiresPassword && openedAs === 'none'
|
|
99
|
+
* → { state: 'required', hint: 'user' } encrypted, anonymous open
|
|
100
|
+
* failed → user pwd needed
|
|
101
|
+
*
|
|
102
|
+
* 4. openedAs === 'owner'
|
|
103
|
+
* → { state: 'none' } already at the top — nothing more
|
|
104
|
+
* to unlock
|
|
105
|
+
*
|
|
106
|
+
* 5. permissions.canUpgradeToOwner === true
|
|
107
|
+
* → { state: 'optional', hint: 'owner' } open as user (or as none
|
|
108
|
+
* for owner-pwd-only docs)
|
|
109
|
+
* but more is available
|
|
110
|
+
*
|
|
111
|
+
* 6. fallthrough → { state: 'none' } open and nothing more available
|
|
112
|
+
*/
|
|
113
|
+
declare function passwordPromptFromState(state: DocumentSecurityState): PasswordPrompt;
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/engine/DocumentSecurityService.d.ts
|
|
116
|
+
type DocumentOpenMode = 'none' | 'user' | 'owner';
|
|
117
|
+
type DocumentEncryptionState = 'unknown' | 'none' | 'encrypted' | 'unsupported';
|
|
118
|
+
type DocumentAccessReason = 'password' | 'cdn' | 'permissions-unknown';
|
|
119
|
+
/**
|
|
120
|
+
* Boolean view of "what the PDF's permission bits allow," surfaced for
|
|
121
|
+
* client UI badges ("this PDF disallows printing", "copy is blocked",
|
|
122
|
+
* etc.). Names mirror the user-facing capability they correspond to,
|
|
123
|
+
* not the raw bit names — so docs can render "Print: disabled" without
|
|
124
|
+
* the reader needing to know PDF bit positions.
|
|
125
|
+
*
|
|
126
|
+
* Computed from {@link PdfBits} via the strict ISO 32000 rules:
|
|
127
|
+
* bit 12 only meaningful when bit 3 is also set
|
|
128
|
+
* form modification requires both bit 6 AND bit 4
|
|
129
|
+
* form fill is satisfied by bit 6 OR bit 9
|
|
130
|
+
*/
|
|
131
|
+
interface PdfPermissionAdvisory {
|
|
132
|
+
readonly canPrint: boolean;
|
|
133
|
+
readonly canPrintHigh: boolean;
|
|
134
|
+
readonly canCopy: boolean;
|
|
135
|
+
readonly canAnnotate: boolean;
|
|
136
|
+
readonly canFillForms: boolean;
|
|
137
|
+
readonly canModifyForms: boolean;
|
|
138
|
+
readonly canModifyPages: boolean;
|
|
139
|
+
readonly canAssemble: boolean;
|
|
140
|
+
}
|
|
141
|
+
interface PdfPermissionInfo {
|
|
142
|
+
readonly known: boolean;
|
|
143
|
+
readonly allAllowed: boolean | null;
|
|
144
|
+
readonly bits: number | null;
|
|
145
|
+
readonly openedAs: DocumentOpenMode | null;
|
|
146
|
+
readonly securityHandlerRevision: number | null;
|
|
147
|
+
/**
|
|
148
|
+
* Typed boolean view of `bits`. Present whenever the caller had
|
|
149
|
+
* access to the document's PDF bits at construction time (always
|
|
150
|
+
* true in the /access response; not always populated by the cheaper
|
|
151
|
+
* /head shape).
|
|
152
|
+
*/
|
|
153
|
+
readonly flags?: PdfBits;
|
|
154
|
+
/**
|
|
155
|
+
* Capability-shaped "what does this PDF natively allow" view for UI
|
|
156
|
+
* badges. Same population rule as `flags`.
|
|
157
|
+
*/
|
|
158
|
+
readonly advisory?: PdfPermissionAdvisory;
|
|
159
|
+
}
|
|
160
|
+
interface DocumentSecurityState {
|
|
161
|
+
readonly encryption: {
|
|
162
|
+
readonly state: DocumentEncryptionState;
|
|
163
|
+
readonly requiresPassword: boolean | null;
|
|
164
|
+
};
|
|
165
|
+
readonly permissions: {
|
|
166
|
+
readonly known: boolean;
|
|
167
|
+
readonly bits: number | null;
|
|
168
|
+
readonly allAllowed: boolean | null;
|
|
169
|
+
readonly openedAs: DocumentOpenMode | null;
|
|
170
|
+
readonly securityHandlerRevision: number | null;
|
|
171
|
+
readonly canUpgradeToOwner: boolean;
|
|
172
|
+
};
|
|
173
|
+
readonly access: {
|
|
174
|
+
readonly required: boolean;
|
|
175
|
+
readonly reasons: DocumentAccessReason[];
|
|
176
|
+
readonly endpoint?: string;
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The CDN adapter identifier surfaced on the wire. Cloudflare users
|
|
181
|
+
* deploy a custom Worker that verifies HMAC-SHA256 signatures and
|
|
182
|
+
* configure the `custom-hmac` adapter — no first-class `'cloudflare'`
|
|
183
|
+
* value is needed.
|
|
184
|
+
*/
|
|
185
|
+
type CdnAdapter = 'none' | 'cloudfront' | 'cloud-cdn' | 'bunny' | 'azure-fd' | 'custom-hmac';
|
|
186
|
+
/**
|
|
187
|
+
* Per-caller CDN access bits returned in the /access response. The
|
|
188
|
+
* SDK fetch wrapper applies whatever channels are populated:
|
|
189
|
+
* - baseUrlOverrides : swap the origin host/path-prefix for the CDN URL
|
|
190
|
+
* - authHeader : attach a single header to every CDN request
|
|
191
|
+
* - signedQueryParams : append params to every CDN URL (single-token signers)
|
|
192
|
+
* - signedCookies : set cookies on the CDN origin before requests
|
|
193
|
+
* - signedPathPolicies : per-prefix params (one signature covers a path subtree)
|
|
194
|
+
*
|
|
195
|
+
* Each adapter populates only the channels it uses; the others stay
|
|
196
|
+
* null. Frontend stays provider-agnostic — it doesn't branch on
|
|
197
|
+
* `adapter`, it just applies whatever's present.
|
|
198
|
+
*/
|
|
199
|
+
interface CdnAccessInfo {
|
|
200
|
+
readonly adapter: CdnAdapter;
|
|
201
|
+
readonly expiresAt: number;
|
|
202
|
+
readonly cache: {
|
|
203
|
+
readonly scope: 'browser-private' | 'edge-shared';
|
|
204
|
+
readonly immutableVersionedReads: boolean;
|
|
205
|
+
};
|
|
206
|
+
readonly baseUrlOverrides: Partial<Record<string, string>> | null;
|
|
207
|
+
readonly authHeader: {
|
|
208
|
+
name: string;
|
|
209
|
+
value: string;
|
|
210
|
+
} | null;
|
|
211
|
+
readonly signedQueryParams: Record<string, string> | null;
|
|
212
|
+
readonly signedCookies: ReadonlyArray<{
|
|
213
|
+
readonly name: string;
|
|
214
|
+
readonly value: string;
|
|
215
|
+
readonly domain?: string;
|
|
216
|
+
readonly path?: string;
|
|
217
|
+
readonly expires?: number;
|
|
218
|
+
}> | null;
|
|
219
|
+
readonly signedPathPolicies: ReadonlyArray<{
|
|
220
|
+
readonly pathPrefix: string;
|
|
221
|
+
readonly queryParams: Record<string, string>;
|
|
222
|
+
}> | null;
|
|
223
|
+
}
|
|
224
|
+
interface DocumentAccessInfo {
|
|
225
|
+
readonly cdn: CdnAccessInfo;
|
|
226
|
+
readonly passwordGrant: string | null;
|
|
227
|
+
readonly pdfPermissions: PdfPermissionInfo | null;
|
|
228
|
+
/**
|
|
229
|
+
* Raw scope array exactly as the JWT carried it. Useful for debugging
|
|
230
|
+
* and for clients that want to display the literal grants.
|
|
231
|
+
*/
|
|
232
|
+
readonly scope: string[];
|
|
233
|
+
/**
|
|
234
|
+
* Concrete capability set granted to this caller, after expanding
|
|
235
|
+
* `pdf.permissions` against the document's PDF bits and applying
|
|
236
|
+
* the implication rules in the resolver (e.g. annotation collab
|
|
237
|
+
* scopes imply `doc.annotate.read`). Client UI should drive feature
|
|
238
|
+
* visibility off this, not off the raw `scope`.
|
|
239
|
+
*
|
|
240
|
+
* Sorted alphabetically for stable display.
|
|
241
|
+
*/
|
|
242
|
+
readonly effectiveScope: string[];
|
|
243
|
+
readonly identity: {
|
|
244
|
+
readonly user_id?: string;
|
|
245
|
+
readonly group_id?: string;
|
|
246
|
+
readonly groups?: string[];
|
|
247
|
+
readonly display_name?: string;
|
|
248
|
+
};
|
|
249
|
+
readonly originPasswordPolicy: {
|
|
250
|
+
readonly mode: 'not-needed' | 'client-retry' | 'server-session';
|
|
251
|
+
};
|
|
252
|
+
readonly expiresAt: number;
|
|
253
|
+
/**
|
|
254
|
+
* The deployment's render lattice: canonical full-page
|
|
255
|
+
* `viewport.width` points whose renders are durable, CDN-shared
|
|
256
|
+
* artifacts, plus the reserved tile-pyramid block. Local engines report
|
|
257
|
+
* nothing here (continuous rendering); cloud engines surface it so
|
|
258
|
+
* `snapFullPageViewport` can conform requests EXPLICITLY — the SDK
|
|
259
|
+
* never snaps implicitly (engine parity).
|
|
260
|
+
*/
|
|
261
|
+
readonly renderPolicy?: {
|
|
262
|
+
readonly fullPage: {
|
|
263
|
+
readonly widths: readonly number[];
|
|
264
|
+
};
|
|
265
|
+
readonly tiles?: {
|
|
266
|
+
readonly tileSizes: readonly number[];
|
|
267
|
+
readonly scales: readonly number[];
|
|
268
|
+
};
|
|
269
|
+
readonly appearances?: {
|
|
270
|
+
readonly scales: readonly number[];
|
|
271
|
+
};
|
|
272
|
+
readonly maxRenderPixels?: number;
|
|
273
|
+
readonly formats: readonly ('webp' | 'png')[];
|
|
274
|
+
readonly background: 'white';
|
|
275
|
+
readonly enforced: boolean;
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
interface DocumentUnlockInput {
|
|
279
|
+
readonly password: string;
|
|
280
|
+
readonly mode?: 'any' | 'owner';
|
|
281
|
+
}
|
|
282
|
+
interface DocumentUnlockResult {
|
|
283
|
+
readonly security: DocumentSecurityState;
|
|
284
|
+
readonly access?: DocumentAccessInfo;
|
|
285
|
+
}
|
|
286
|
+
interface DocumentSecurityService {
|
|
287
|
+
/**
|
|
288
|
+
* Raw structured security probe. Stable across engines, refreshed
|
|
289
|
+
* after unlock/refresh. Power users and diagnostic tools read this;
|
|
290
|
+
* most dev code uses the higher-level accessors below.
|
|
291
|
+
*/
|
|
292
|
+
readonly current: DocumentSecurityState;
|
|
293
|
+
/**
|
|
294
|
+
* The caller's expanded capability set — raw scope + pdf bits +
|
|
295
|
+
* implication rules, enumerated for DISPLAY ("here's what you can
|
|
296
|
+
* do"). Identical shape on local and cloud; cloud uses the
|
|
297
|
+
* server-canonical value when available, else computes locally from
|
|
298
|
+
* JWT scope + /head bits.
|
|
299
|
+
*
|
|
300
|
+
* NOTE: this is an *enumeration*, not an authorization check. The `*`
|
|
301
|
+
* admin wildcard and unbounded parametric collab grants are NOT
|
|
302
|
+
* listed here (they can't be). To gate UI, use {@link allows} — the
|
|
303
|
+
* same wildcard-aware predicate the engine enforces with.
|
|
304
|
+
*/
|
|
305
|
+
readonly effectiveScope: ReadonlyArray<string>;
|
|
306
|
+
/**
|
|
307
|
+
* Wildcard-aware authorization check — the SAME predicate the engine
|
|
308
|
+
* enforces with (`checkCapability`). A shown control gated on this
|
|
309
|
+
* mirrors exactly what the engine will allow: the `*` admin grant and
|
|
310
|
+
* `pdf.permissions`-derived bits are both honored. Use this for edit
|
|
311
|
+
* gating (e.g. `allows('doc.pages.assemble')`); use `effectiveScope`
|
|
312
|
+
* only to *display* the concrete grants.
|
|
313
|
+
*/
|
|
314
|
+
allows(capability: DocCapability): boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Identity of the current caller, or null when anonymous.
|
|
317
|
+
*/
|
|
318
|
+
readonly identity: IdentityClaims | null;
|
|
319
|
+
/**
|
|
320
|
+
* "Should I prompt the user for a password?" — the single source
|
|
321
|
+
* of truth. Three states, each carrying exactly the data needed:
|
|
322
|
+
* - `none` — do nothing
|
|
323
|
+
* - `required` — hard block; show modal; `hint` labels the prompt
|
|
324
|
+
* - `optional` — soft offer; show banner; only ever asks for owner
|
|
325
|
+
* See {@link PasswordPrompt} for the full contract.
|
|
326
|
+
*/
|
|
327
|
+
readonly passwordPrompt: PasswordPrompt;
|
|
328
|
+
unlock(input: DocumentUnlockInput): AbortablePromise<DocumentUnlockResult>;
|
|
329
|
+
}
|
|
330
|
+
//#endregion
|
|
331
|
+
export { DocumentEncryptionState as a, DocumentSecurityState as c, PdfPermissionAdvisory as d, PdfPermissionInfo as f, AbortablePromise as g, AbortableExecutor as h, DocumentAccessReason as i, DocumentUnlockInput as l, passwordPromptFromState as m, CdnAdapter as n, DocumentOpenMode as o, PasswordPrompt as p, DocumentAccessInfo as r, DocumentSecurityService as s, CdnAccessInfo as t, DocumentUnlockResult as u };
|
|
332
|
+
//# sourceMappingURL=DocumentSecurityService-Df79fgpe.d.cts.map
|