@cloudpdf/engine 3.0.0-next.7 → 3.0.0-next.8
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 +67 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +67 -8
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -810,8 +810,7 @@ var CloudDocumentSecurityService = class {
|
|
|
810
810
|
* and `applyCdnAccess` short-circuits to origin; safe to call always.
|
|
811
811
|
*/
|
|
812
812
|
async postAccess(signal, body) {
|
|
813
|
-
const response = await this.http.postJson(_embedpdf_engine_core_wire.wirePaths.access, {
|
|
814
|
-
docId: this.docId,
|
|
813
|
+
const response = await this.http.postJson(_embedpdf_engine_core_wire.wirePaths.access(this.docId), {
|
|
815
814
|
layerName: this.layerName,
|
|
816
815
|
...body.password ? { password: body.password } : {},
|
|
817
816
|
mode: body.mode
|
|
@@ -1935,7 +1934,7 @@ function fallbackUnknownHead(id) {
|
|
|
1935
1934
|
access: {
|
|
1936
1935
|
required: true,
|
|
1937
1936
|
reasons: ["permissions-unknown"],
|
|
1938
|
-
endpoint: _embedpdf_engine_core_wire.wirePaths.access
|
|
1937
|
+
endpoint: _embedpdf_engine_core_wire.wirePaths.access(id)
|
|
1939
1938
|
}
|
|
1940
1939
|
};
|
|
1941
1940
|
}
|
|
@@ -2043,6 +2042,8 @@ var HttpClient = class HttpClient {
|
|
|
2043
2042
|
_defineProperty(this, "base", void 0);
|
|
2044
2043
|
_defineProperty(this, "tokenFn", void 0);
|
|
2045
2044
|
_defineProperty(this, "fetchFn", void 0);
|
|
2045
|
+
_defineProperty(this, "docAffinityHeader", void 0);
|
|
2046
|
+
_defineProperty(this, "onRetry", void 0);
|
|
2046
2047
|
_defineProperty(this, "sessionId", void 0);
|
|
2047
2048
|
_defineProperty(this, "cdnBinding", null);
|
|
2048
2049
|
this.base = opts.baseUrl.replace(/\/$/, "");
|
|
@@ -2050,6 +2051,8 @@ var HttpClient = class HttpClient {
|
|
|
2050
2051
|
this.tokenFn = token === void 0 ? null : typeof token === "function" ? token : () => token;
|
|
2051
2052
|
this.sessionId = opts.sessionId ?? null;
|
|
2052
2053
|
this.fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
2054
|
+
this.docAffinityHeader = opts.docAffinityHeader ?? false;
|
|
2055
|
+
this.onRetry = opts.onRetry;
|
|
2053
2056
|
}
|
|
2054
2057
|
/** Normalized server base URL (no trailing slash). */
|
|
2055
2058
|
get baseUrl() {
|
|
@@ -2326,7 +2329,7 @@ var HttpClient = class HttpClient {
|
|
|
2326
2329
|
});
|
|
2327
2330
|
}
|
|
2328
2331
|
async request(path, init) {
|
|
2329
|
-
const { url, extraHeader } = this.resolveOutgoing(path);
|
|
2332
|
+
const { url, extraHeader, routedToCdn } = this.resolveOutgoing(path);
|
|
2330
2333
|
const headers = new Headers(init.headers ?? {});
|
|
2331
2334
|
if (this.tokenFn) {
|
|
2332
2335
|
const token = await this.tokenFn();
|
|
@@ -2335,11 +2338,32 @@ var HttpClient = class HttpClient {
|
|
|
2335
2338
|
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
2336
2339
|
if (this.sessionId) headers.set("X-Engine-Session-Id", this.sessionId);
|
|
2337
2340
|
if (extraHeader) headers.set(extraHeader.name, extraHeader.value);
|
|
2338
|
-
|
|
2339
|
-
|
|
2341
|
+
if (this.docAffinityHeader && !routedToCdn) {
|
|
2342
|
+
const doc = /^\/v1\/docs\/([^/]+)\//.exec(path);
|
|
2343
|
+
if (doc) headers.set("X-CloudPDF-Doc", decodeURIComponent(doc[1]));
|
|
2344
|
+
}
|
|
2345
|
+
for (let attempt = 0;; attempt++) {
|
|
2346
|
+
const res = await this.execute(url, {
|
|
2340
2347
|
...init,
|
|
2341
2348
|
headers
|
|
2342
2349
|
});
|
|
2350
|
+
if (res.status !== 503 || attempt >= HttpClient.MAX_RETRIES || isStreamBody(init.body ?? null)) return res;
|
|
2351
|
+
const code = await peekErrorCode(res);
|
|
2352
|
+
if (code === null || !RETRYABLE_503.has(code)) return res;
|
|
2353
|
+
const hinted = Number(res.headers.get("retry-after"));
|
|
2354
|
+
const waitMs = (Number.isFinite(hinted) ? Math.min(Math.max(hinted, 0) * 1e3, HttpClient.RETRY_AFTER_CAP_MS) : HttpClient.RETRY_AFTER_DEFAULT_MS) * (.9 + .2 * Math.random());
|
|
2355
|
+
this.onRetry?.({
|
|
2356
|
+
path,
|
|
2357
|
+
code,
|
|
2358
|
+
attempt,
|
|
2359
|
+
waitMs
|
|
2360
|
+
});
|
|
2361
|
+
await sleepRacingAbort(waitMs, init.signal ?? null);
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
async execute(url, init) {
|
|
2365
|
+
try {
|
|
2366
|
+
return await this.fetchFn(url, init);
|
|
2343
2367
|
} catch (err) {
|
|
2344
2368
|
if (init.signal?.aborted) throw new _embedpdf_engine_core_runtime.AbortError(init.signal.reason ?? err);
|
|
2345
2369
|
if (err?.name === "AbortError") throw new _embedpdf_engine_core_runtime.AbortError(err.message);
|
|
@@ -2365,7 +2389,8 @@ var HttpClient = class HttpClient {
|
|
|
2365
2389
|
resolveOutgoing(path) {
|
|
2366
2390
|
if (!this.cdnBinding || !this.cdnBinding.cdn) return {
|
|
2367
2391
|
url: `${this.baseUrl}${path}`,
|
|
2368
|
-
extraHeader: null
|
|
2392
|
+
extraHeader: null,
|
|
2393
|
+
routedToCdn: false
|
|
2369
2394
|
};
|
|
2370
2395
|
const applied = (0, _embedpdf_engine_core_wire.applyCdnAccess)({
|
|
2371
2396
|
path,
|
|
@@ -2376,7 +2401,8 @@ var HttpClient = class HttpClient {
|
|
|
2376
2401
|
});
|
|
2377
2402
|
return {
|
|
2378
2403
|
url: applied.url,
|
|
2379
|
-
extraHeader: applied.routedToCdn && applied.authHeader ? applied.authHeader : null
|
|
2404
|
+
extraHeader: applied.routedToCdn && applied.authHeader ? applied.authHeader : null,
|
|
2405
|
+
routedToCdn: applied.routedToCdn
|
|
2380
2406
|
};
|
|
2381
2407
|
}
|
|
2382
2408
|
async throwFromBody(res) {
|
|
@@ -2396,6 +2422,9 @@ var HttpClient = class HttpClient {
|
|
|
2396
2422
|
throw new _embedpdf_engine_core_runtime.EngineError(code, `HTTP ${res.status}`, { details: { status: res.status } });
|
|
2397
2423
|
}
|
|
2398
2424
|
};
|
|
2425
|
+
_defineProperty(HttpClient, "MAX_RETRIES", 2);
|
|
2426
|
+
_defineProperty(HttpClient, "RETRY_AFTER_CAP_MS", 5e3);
|
|
2427
|
+
_defineProperty(HttpClient, "RETRY_AFTER_DEFAULT_MS", 1e3);
|
|
2399
2428
|
function mapStatusToCode(status) {
|
|
2400
2429
|
if (status === 401) return _embedpdf_engine_core_runtime.EngineErrorCode.Unauthenticated;
|
|
2401
2430
|
if (status === 403) return _embedpdf_engine_core_runtime.EngineErrorCode.Forbidden;
|
|
@@ -2410,6 +2439,36 @@ function trySerialized(value) {
|
|
|
2410
2439
|
const result = _embedpdf_engine_core_wire.EngineErrorPayloadSchema.safeParse(value);
|
|
2411
2440
|
return result.success ? result.data : null;
|
|
2412
2441
|
}
|
|
2442
|
+
const RETRYABLE_503 = /* @__PURE__ */ new Set(["EngineBusy", "EngineRestarting"]);
|
|
2443
|
+
function isStreamBody(body) {
|
|
2444
|
+
return typeof ReadableStream !== "undefined" && body instanceof ReadableStream;
|
|
2445
|
+
}
|
|
2446
|
+
/** Read the error code from a 503 body without consuming the response. */
|
|
2447
|
+
async function peekErrorCode(res) {
|
|
2448
|
+
try {
|
|
2449
|
+
const code = (await res.clone().json())?.error?.code;
|
|
2450
|
+
return typeof code === "string" ? code : null;
|
|
2451
|
+
} catch {
|
|
2452
|
+
return null;
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
function sleepRacingAbort(ms, signal) {
|
|
2456
|
+
return new Promise((resolve, reject) => {
|
|
2457
|
+
if (signal?.aborted) {
|
|
2458
|
+
reject(new _embedpdf_engine_core_runtime.AbortError(signal.reason ?? "aborted"));
|
|
2459
|
+
return;
|
|
2460
|
+
}
|
|
2461
|
+
const timer = setTimeout(() => {
|
|
2462
|
+
signal?.removeEventListener("abort", onAbort);
|
|
2463
|
+
resolve();
|
|
2464
|
+
}, ms);
|
|
2465
|
+
const onAbort = () => {
|
|
2466
|
+
clearTimeout(timer);
|
|
2467
|
+
reject(new _embedpdf_engine_core_runtime.AbortError(signal?.reason ?? "aborted"));
|
|
2468
|
+
};
|
|
2469
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2413
2472
|
//#endregion
|
|
2414
2473
|
//#region src/CloudEngine.ts
|
|
2415
2474
|
/**
|