@cloudpdf/engine 3.0.0-next.3 → 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 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, "baseUrl", void 0);
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.baseUrl = opts.baseUrl.replace(/\/$/, "");
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 'id' (got '${input.kind}')`));
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