@cloudpdf/engine 3.0.0-next.2 → 3.0.0-next.4
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 +116 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -6
- package/dist/index.d.ts +29 -6
- package/dist/index.js +116 -63
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1956,20 +1956,114 @@ function awaitSignal(promise, signal) {
|
|
|
1956
1956
|
});
|
|
1957
1957
|
}
|
|
1958
1958
|
//#endregion
|
|
1959
|
+
//#region src/share.ts
|
|
1960
|
+
/**
|
|
1961
|
+
* Thrown on a non-OK exchange. `code` is the server's wire code:
|
|
1962
|
+
* `SharePasswordRequired` (prompt and retry with a password),
|
|
1963
|
+
* `OriginNotAllowed` / `OriginRequired`, `ShareExpired`, `NotFound`
|
|
1964
|
+
* (unknown or revoked — indistinguishable by design), or
|
|
1965
|
+
* `TooManyRequests`.
|
|
1966
|
+
*/
|
|
1967
|
+
var ShareExchangeError = class extends Error {
|
|
1968
|
+
constructor(code, message, status) {
|
|
1969
|
+
super(message);
|
|
1970
|
+
this.code = code;
|
|
1971
|
+
this.status = status;
|
|
1972
|
+
this.name = "ShareExchangeError";
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
async function exchangeShareToken(baseUrl, shareToken, opts = {}) {
|
|
1976
|
+
const res = await (opts.fetch ?? globalThis.fetch)(`${baseUrl.replace(/\/$/, "")}/v1/share-sessions`, {
|
|
1977
|
+
method: "POST",
|
|
1978
|
+
headers: { "content-type": "application/json" },
|
|
1979
|
+
body: JSON.stringify({
|
|
1980
|
+
shareToken,
|
|
1981
|
+
...opts.password !== void 0 ? { password: opts.password } : {}
|
|
1982
|
+
})
|
|
1983
|
+
});
|
|
1984
|
+
if (!res.ok) {
|
|
1985
|
+
let code = "Unknown";
|
|
1986
|
+
let message = `share exchange failed with status ${res.status}`;
|
|
1987
|
+
try {
|
|
1988
|
+
const payload = await res.json();
|
|
1989
|
+
if (payload.error?.code) code = payload.error.code;
|
|
1990
|
+
if (payload.error?.message) message = payload.error.message;
|
|
1991
|
+
} catch {}
|
|
1992
|
+
throw new ShareExchangeError(code, message, res.status);
|
|
1993
|
+
}
|
|
1994
|
+
return await res.json();
|
|
1995
|
+
}
|
|
1996
|
+
/**
|
|
1997
|
+
* Lift a {@link ShareExchangeError} into the engine's error taxonomy, so
|
|
1998
|
+
* `open({ kind: 'share' })` and every later renewal fail with the same
|
|
1999
|
+
* `EngineError` family as all other engine calls. The wire code and HTTP
|
|
2000
|
+
* status survive in `details`; the original error rides as `cause`.
|
|
2001
|
+
*
|
|
2002
|
+
* `SharePasswordRequired` gets its own engine code — it is the one outcome
|
|
2003
|
+
* callers branch on programmatically (prompt for the grant passphrase and
|
|
2004
|
+
* retry). Everything else maps by meaning, with the HTTP status as the
|
|
2005
|
+
* fallback discriminator.
|
|
2006
|
+
*/
|
|
2007
|
+
function engineErrorFromShareExchange(error) {
|
|
2008
|
+
return new _embedpdf_engine_core_runtime.EngineError(error.code === "SharePasswordRequired" ? _embedpdf_engine_core_runtime.EngineErrorCode.SharePasswordRequired : error.code === "NotFound" ? _embedpdf_engine_core_runtime.EngineErrorCode.NotFound : error.code === "ShareExpired" || error.code === "OriginNotAllowed" || error.code === "OriginRequired" ? _embedpdf_engine_core_runtime.EngineErrorCode.Forbidden : error.status === 401 ? _embedpdf_engine_core_runtime.EngineErrorCode.Unauthenticated : error.status === 400 ? _embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg : _embedpdf_engine_core_runtime.EngineErrorCode.Unknown, `share exchange failed: ${error.message}`, {
|
|
2009
|
+
details: {
|
|
2010
|
+
shareCode: error.code,
|
|
2011
|
+
status: error.status
|
|
2012
|
+
},
|
|
2013
|
+
cause: error
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
/** Renew this many seconds before `expiresAt` so in-flight requests never race expiry. */
|
|
2017
|
+
const RENEW_MARGIN_SECONDS = 60;
|
|
2018
|
+
/**
|
|
2019
|
+
* A caching, self-renewing token source over the exchange — the callable
|
|
2020
|
+
* member of the engine's `TokenSource` union, assignable wherever one is
|
|
2021
|
+
* taken.
|
|
2022
|
+
* Concurrent callers share one in-flight exchange; a failed exchange
|
|
2023
|
+
* clears it so the next request retries rather than caching the error.
|
|
2024
|
+
*/
|
|
2025
|
+
function shareSessionSource(baseUrl, shareToken, opts = {}) {
|
|
2026
|
+
let session = null;
|
|
2027
|
+
let inflight = null;
|
|
2028
|
+
return async () => {
|
|
2029
|
+
if (session && session.expiresAt - Date.now() / 1e3 > RENEW_MARGIN_SECONDS) return session.token;
|
|
2030
|
+
inflight ?? (inflight = exchangeShareToken(baseUrl, shareToken, opts).then((next) => {
|
|
2031
|
+
session = next;
|
|
2032
|
+
return next.token;
|
|
2033
|
+
}).finally(() => {
|
|
2034
|
+
inflight = null;
|
|
2035
|
+
}));
|
|
2036
|
+
return inflight;
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2039
|
+
//#endregion
|
|
1959
2040
|
//#region src/transport/HttpClient.ts
|
|
1960
2041
|
var HttpClient = class HttpClient {
|
|
1961
2042
|
constructor(opts) {
|
|
1962
|
-
_defineProperty(this, "
|
|
2043
|
+
_defineProperty(this, "base", void 0);
|
|
1963
2044
|
_defineProperty(this, "tokenFn", void 0);
|
|
1964
2045
|
_defineProperty(this, "fetchFn", void 0);
|
|
1965
2046
|
_defineProperty(this, "sessionId", void 0);
|
|
1966
2047
|
_defineProperty(this, "cdnBinding", null);
|
|
1967
|
-
this.
|
|
2048
|
+
this.base = opts.baseUrl.replace(/\/$/, "");
|
|
1968
2049
|
const token = opts.token;
|
|
1969
2050
|
this.tokenFn = token === void 0 ? null : typeof token === "function" ? token : () => token;
|
|
1970
2051
|
this.sessionId = opts.sessionId ?? null;
|
|
1971
2052
|
this.fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
1972
2053
|
}
|
|
2054
|
+
/** Normalized server base URL (no trailing slash). */
|
|
2055
|
+
get baseUrl() {
|
|
2056
|
+
return this.base;
|
|
2057
|
+
}
|
|
2058
|
+
/**
|
|
2059
|
+
* The fetch implementation this client sends requests through (injected
|
|
2060
|
+
* or global). Exposed so sibling transports spawned per-open — the
|
|
2061
|
+
* share-session exchange, most of all — ride the same fetch the engine
|
|
2062
|
+
* was configured with (test doubles, SSR `Origin`-attaching wrappers).
|
|
2063
|
+
*/
|
|
2064
|
+
get fetchImpl() {
|
|
2065
|
+
return this.fetchFn;
|
|
2066
|
+
}
|
|
1973
2067
|
/**
|
|
1974
2068
|
* Return a clone of this client bound to a different bearer. Used
|
|
1975
2069
|
* by `CloudEngine.open` to mint a per-handle client carrying the
|
|
@@ -2341,6 +2435,24 @@ var CloudEngine = class CloudEngine {
|
|
|
2341
2435
|
options?.scope;
|
|
2342
2436
|
options?.identity;
|
|
2343
2437
|
const effectivePassword = options && "password" in options ? options.password ?? null : input.password ?? null;
|
|
2438
|
+
if (input.kind === "share") {
|
|
2439
|
+
const raw = shareSessionSource(this.http.baseUrl, input.shareToken, {
|
|
2440
|
+
...input.sharePassword !== void 0 ? { password: input.sharePassword } : {},
|
|
2441
|
+
fetch: this.http.fetchImpl
|
|
2442
|
+
});
|
|
2443
|
+
const token = async () => {
|
|
2444
|
+
try {
|
|
2445
|
+
return await raw();
|
|
2446
|
+
} catch (error) {
|
|
2447
|
+
throw error instanceof ShareExchangeError ? engineErrorFromShareExchange(error) : error;
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
return this.open({
|
|
2451
|
+
kind: "token",
|
|
2452
|
+
token,
|
|
2453
|
+
password: input.password ?? null
|
|
2454
|
+
}, options);
|
|
2455
|
+
}
|
|
2344
2456
|
if (input.kind === "token") {
|
|
2345
2457
|
const tokenSource = input.token;
|
|
2346
2458
|
return _embedpdf_engine_core_runtime.AbortablePromise.run(async (signal) => {
|
|
@@ -2377,7 +2489,7 @@ var CloudEngine = class CloudEngine {
|
|
|
2377
2489
|
return handle;
|
|
2378
2490
|
});
|
|
2379
2491
|
}
|
|
2380
|
-
return _embedpdf_engine_core_runtime.AbortablePromise.rejectReason(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `cloud engine supports OpenInput.kind === 'token' or '
|
|
2492
|
+
return _embedpdf_engine_core_runtime.AbortablePromise.rejectReason(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.InvalidArg, `cloud engine supports OpenInput.kind === 'token', 'id', or 'share' (got '${input.kind}')`));
|
|
2381
2493
|
}
|
|
2382
2494
|
destroy() {
|
|
2383
2495
|
if (this.destroyed) return _embedpdf_engine_core_runtime.AbortablePromise.resolveValue(void 0);
|
|
@@ -2444,65 +2556,6 @@ async function settleLinked(pending, signal) {
|
|
|
2444
2556
|
}
|
|
2445
2557
|
}
|
|
2446
2558
|
//#endregion
|
|
2447
|
-
//#region src/share.ts
|
|
2448
|
-
/**
|
|
2449
|
-
* Thrown on a non-OK exchange. `code` is the server's wire code:
|
|
2450
|
-
* `SharePasswordRequired` (prompt and retry with a password),
|
|
2451
|
-
* `OriginNotAllowed` / `OriginRequired`, `ShareExpired`, `NotFound`
|
|
2452
|
-
* (unknown or revoked — indistinguishable by design), or
|
|
2453
|
-
* `TooManyRequests`.
|
|
2454
|
-
*/
|
|
2455
|
-
var ShareExchangeError = class extends Error {
|
|
2456
|
-
constructor(code, message, status) {
|
|
2457
|
-
super(message);
|
|
2458
|
-
this.code = code;
|
|
2459
|
-
this.status = status;
|
|
2460
|
-
this.name = "ShareExchangeError";
|
|
2461
|
-
}
|
|
2462
|
-
};
|
|
2463
|
-
async function exchangeShareToken(baseUrl, shareToken, opts = {}) {
|
|
2464
|
-
const res = await (opts.fetch ?? globalThis.fetch)(`${baseUrl.replace(/\/$/, "")}/v1/share-sessions`, {
|
|
2465
|
-
method: "POST",
|
|
2466
|
-
headers: { "content-type": "application/json" },
|
|
2467
|
-
body: JSON.stringify({
|
|
2468
|
-
shareToken,
|
|
2469
|
-
...opts.password !== void 0 ? { password: opts.password } : {}
|
|
2470
|
-
})
|
|
2471
|
-
});
|
|
2472
|
-
if (!res.ok) {
|
|
2473
|
-
let code = "Unknown";
|
|
2474
|
-
let message = `share exchange failed with status ${res.status}`;
|
|
2475
|
-
try {
|
|
2476
|
-
const payload = await res.json();
|
|
2477
|
-
if (payload.error?.code) code = payload.error.code;
|
|
2478
|
-
if (payload.error?.message) message = payload.error.message;
|
|
2479
|
-
} catch {}
|
|
2480
|
-
throw new ShareExchangeError(code, message, res.status);
|
|
2481
|
-
}
|
|
2482
|
-
return await res.json();
|
|
2483
|
-
}
|
|
2484
|
-
/** Renew this many seconds before `expiresAt` so in-flight requests never race expiry. */
|
|
2485
|
-
const RENEW_MARGIN_SECONDS = 60;
|
|
2486
|
-
/**
|
|
2487
|
-
* A caching, self-renewing {@link TokenSource} over the exchange.
|
|
2488
|
-
* Concurrent callers share one in-flight exchange; a failed exchange
|
|
2489
|
-
* clears it so the next request retries rather than caching the error.
|
|
2490
|
-
*/
|
|
2491
|
-
function shareSessionSource(baseUrl, shareToken, opts = {}) {
|
|
2492
|
-
let session = null;
|
|
2493
|
-
let inflight = null;
|
|
2494
|
-
return async () => {
|
|
2495
|
-
if (session && session.expiresAt - Date.now() / 1e3 > RENEW_MARGIN_SECONDS) return session.token;
|
|
2496
|
-
inflight ?? (inflight = exchangeShareToken(baseUrl, shareToken, opts).then((next) => {
|
|
2497
|
-
session = next;
|
|
2498
|
-
return next.token;
|
|
2499
|
-
}).finally(() => {
|
|
2500
|
-
inflight = null;
|
|
2501
|
-
}));
|
|
2502
|
-
return inflight;
|
|
2503
|
-
};
|
|
2504
|
-
}
|
|
2505
|
-
//#endregion
|
|
2506
2559
|
//#region src/index.ts
|
|
2507
2560
|
function createCloudEngine(opts) {
|
|
2508
2561
|
return CloudEngine.fromOptions(opts);
|
|
@@ -2569,6 +2622,7 @@ exports.ShareExchangeError = ShareExchangeError;
|
|
|
2569
2622
|
exports.cloudEngine = cloudEngine;
|
|
2570
2623
|
exports.createCloudEngine = createCloudEngine;
|
|
2571
2624
|
exports.decodeUnverifiedClaims = decodeUnverifiedClaims;
|
|
2625
|
+
exports.engineErrorFromShareExchange = engineErrorFromShareExchange;
|
|
2572
2626
|
exports.exchangeShareToken = exchangeShareToken;
|
|
2573
2627
|
exports.shareSessionSource = shareSessionSource;
|
|
2574
2628
|
|