@arbidocs/client 0.5.57 → 0.5.59

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
@@ -10,6 +10,90 @@ var sodium__default = /*#__PURE__*/_interopDefault(sodium);
10
10
 
11
11
  // src/client.ts
12
12
 
13
+ // src/memory-persistence.ts
14
+ function copy(keys) {
15
+ return {
16
+ ...keys,
17
+ signingPrivateKey: keys.signingPrivateKey.slice(),
18
+ ...keys.serverSessionKey ? { serverSessionKey: keys.serverSessionKey.slice() } : {}
19
+ };
20
+ }
21
+ function createMemorySessionPersistence() {
22
+ let saved = null;
23
+ const clear = () => {
24
+ saved?.signingPrivateKey.fill(0);
25
+ saved?.serverSessionKey?.fill(0);
26
+ saved = null;
27
+ };
28
+ return {
29
+ async getSession() {
30
+ return saved ? copy(saved) : null;
31
+ },
32
+ async saveSession(keys) {
33
+ const next = copy(keys);
34
+ clear();
35
+ saved = next;
36
+ },
37
+ async clearSession() {
38
+ clear();
39
+ }
40
+ };
41
+ }
42
+
43
+ // src/http-transport.ts
44
+ function createHttpTransport(options = {}) {
45
+ const { timeoutMs } = options;
46
+ if (timeoutMs !== void 0 && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
47
+ throw new RangeError("transport.timeoutMs must be a positive finite number.");
48
+ }
49
+ const wrap = (adapter2) => async (input, init) => {
50
+ const url = new URL(input instanceof Request ? input.url : String(input), "http://localhost");
51
+ url.username = "";
52
+ url.password = "";
53
+ url.search = "";
54
+ url.hash = "";
55
+ const info = {
56
+ method: (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase(),
57
+ url: url.toString()
58
+ };
59
+ options.onRequest?.(info);
60
+ const started = performance.now();
61
+ let timer;
62
+ let requestInit = init;
63
+ if (timeoutMs !== void 0) {
64
+ const controller = new AbortController();
65
+ const own = init?.signal ?? (input instanceof Request ? input.signal : void 0);
66
+ timer = setTimeout(
67
+ () => controller.abort(
68
+ new DOMException("Waiting for HTTP response timed out.", "TimeoutError")
69
+ ),
70
+ timeoutMs
71
+ );
72
+ requestInit = {
73
+ ...init,
74
+ signal: own ? AbortSignal.any([own, controller.signal]) : controller.signal
75
+ };
76
+ }
77
+ let response;
78
+ try {
79
+ response = await adapter2(input, requestInit);
80
+ } catch (error) {
81
+ options.onError?.({ ...info, error, durationMs: performance.now() - started });
82
+ throw error;
83
+ } finally {
84
+ if (timer !== void 0) clearTimeout(timer);
85
+ }
86
+ options.onResponse?.({
87
+ ...info,
88
+ status: response.status,
89
+ durationMs: performance.now() - started
90
+ });
91
+ return response;
92
+ };
93
+ const adapter = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
94
+ return { fetch: wrap(adapter), customFetch: options.fetch !== void 0, withFetch: wrap };
95
+ }
96
+
13
97
  // src/session.ts
14
98
  function createInitialState(isSsoMode = false) {
15
99
  return {
@@ -1161,11 +1245,11 @@ function createSessionGate() {
1161
1245
  }
1162
1246
  };
1163
1247
  }
1164
- function gatedFetch(gate, fetch2) {
1248
+ function gatedFetch(gate, fetch) {
1165
1249
  return (input, init) => {
1166
1250
  if (gate.closed) return Promise.reject(abortError());
1167
1251
  const own = init?.signal ?? (input instanceof Request ? input.signal : void 0);
1168
- return fetch2(input, { ...init, signal: eitherSignal(gate.signal, own) });
1252
+ return fetch(input, { ...init, signal: eitherSignal(gate.signal, own) });
1169
1253
  };
1170
1254
  }
1171
1255
  function createSessionGateMiddleware(gate) {
@@ -1379,7 +1463,7 @@ function createAutoReloginMiddleware(config) {
1379
1463
  if (workspaceId) {
1380
1464
  if (!await config.primeWorkspaceHandler(workspaceId)) return response;
1381
1465
  const retry = cloneCache.get(request) ?? safeClone(request);
1382
- if (retry) return fetch(retry);
1466
+ if (retry) return (config.fetch ?? globalThis.fetch)(retry);
1383
1467
  config.onRetryCloneFailed?.();
1384
1468
  return response;
1385
1469
  }
@@ -1395,7 +1479,7 @@ function createAutoReloginMiddleware(config) {
1395
1479
  const retry = cloneCache.get(request) ?? safeClone(request);
1396
1480
  if (retry) {
1397
1481
  if (token) retry.headers.set("Authorization", `Bearer ${token}`);
1398
- return fetch(retry);
1482
+ return (config.fetch ?? globalThis.fetch)(retry);
1399
1483
  }
1400
1484
  config.onRetryCloneFailed?.();
1401
1485
  return response;
@@ -1407,7 +1491,7 @@ function createAutoReloginMiddleware(config) {
1407
1491
  if (newToken) {
1408
1492
  const retryRequest = cloneCache.get(request) ?? request.clone();
1409
1493
  retryRequest.headers.set("Authorization", `Bearer ${newToken}`);
1410
- return fetch(retryRequest);
1494
+ return (config.fetch ?? globalThis.fetch)(retryRequest);
1411
1495
  }
1412
1496
  }
1413
1497
  }
@@ -1420,12 +1504,12 @@ function createAutoReloginMiddleware(config) {
1420
1504
  const cached = cloneCache.get(request);
1421
1505
  if (cached) {
1422
1506
  cached.headers.set("Authorization", `Bearer ${newToken}`);
1423
- return fetch(cached);
1507
+ return (config.fetch ?? globalThis.fetch)(cached);
1424
1508
  }
1425
1509
  try {
1426
1510
  const retryRequest = request.clone();
1427
1511
  retryRequest.headers.set("Authorization", `Bearer ${newToken}`);
1428
- return fetch(retryRequest);
1512
+ return (config.fetch ?? globalThis.fetch)(retryRequest);
1429
1513
  } catch {
1430
1514
  console.warn("[API] Could not retry request after re-login (body already consumed)");
1431
1515
  config.onRetryCloneFailed?.();
@@ -1874,22 +1958,26 @@ var RETRYABLE_CODES = /* @__PURE__ */ new Set([
1874
1958
  var MAX_RETRIES = 3;
1875
1959
  var BASE_DELAY_MS = 200;
1876
1960
  function isRetryableError(err) {
1877
- if (!(err instanceof Error)) return false;
1961
+ if (!(err instanceof Error) || isAbortError(err)) return false;
1878
1962
  const cause = err.cause;
1879
1963
  if (cause?.code && RETRYABLE_CODES.has(cause.code)) return true;
1880
1964
  const msg = err.message || "";
1881
1965
  return RETRYABLE_CODES.has(msg) || msg.includes("ECONNREFUSED") || msg.includes("ECONNRESET");
1882
1966
  }
1883
- function createRetryFetch() {
1967
+ function createRetryFetch(fetch) {
1884
1968
  return async (input, init) => {
1969
+ const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
1970
+ const maxRetries = method === "GET" || method === "HEAD" ? MAX_RETRIES : 0;
1971
+ const signal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
1885
1972
  let lastError;
1886
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
1973
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1974
+ if (signal?.aborted) throw signal.reason ?? new DOMException("Request aborted.", "AbortError");
1887
1975
  try {
1888
1976
  const fetchInput = input instanceof Request ? input.clone() : input;
1889
- return await globalThis.fetch(fetchInput, init);
1977
+ return await fetch(fetchInput, init);
1890
1978
  } catch (err) {
1891
1979
  lastError = err;
1892
- if (attempt < MAX_RETRIES && isRetryableError(err)) {
1980
+ if (attempt < maxRetries && isRetryableError(err)) {
1893
1981
  await new Promise((r) => setTimeout(r, BASE_DELAY_MS * 2 ** attempt));
1894
1982
  continue;
1895
1983
  }
@@ -1911,9 +1999,9 @@ function readBaseUrlPerRequest(fetchClient, base) {
1911
1999
  }
1912
2000
  var deploymentDomainOf = ({ deploymentDomain }) => typeof deploymentDomain === "function" ? deploymentDomain() : deploymentDomain;
1913
2001
  function createArbiClient(options) {
1914
- const { fetch: fetch2, session, persistence, workspaceKeys, workspaceOpens, auth } = createTransport(options);
2002
+ const { fetch, http, session, persistence, workspaceKeys, workspaceOpens, auth } = createTransport(options);
1915
2003
  const authDeps = {
1916
- fetchClient: fetch2,
2004
+ fetchClient: fetch,
1917
2005
  session,
1918
2006
  get deploymentDomain() {
1919
2007
  return deploymentDomainOf(options);
@@ -1922,7 +2010,8 @@ function createArbiClient(options) {
1922
2010
  signIn: options.signIn
1923
2011
  };
1924
2012
  return {
1925
- fetch: fetch2,
2013
+ fetch,
2014
+ http,
1926
2015
  workspaceKeys,
1927
2016
  workspaceOpens,
1928
2017
  session,
@@ -1954,8 +2043,8 @@ function createArbiClient(options) {
1954
2043
  decryptMessageWithSharedSecret
1955
2044
  },
1956
2045
  storage: {
1957
- getSession,
1958
- saveSession
2046
+ getSession: () => persistence.getSession(),
2047
+ saveSession: (data) => persistence.saveSession(data)
1959
2048
  }
1960
2049
  };
1961
2050
  }
@@ -1969,12 +2058,18 @@ function createTransport(options) {
1969
2058
  onRetryCloneFailed,
1970
2059
  userEmail
1971
2060
  } = options;
1972
- const persistence = options.persistence ?? { getSession, saveSession };
2061
+ const persistence = options.persistence ?? (typeof indexedDB === "undefined" ? createMemorySessionPersistence() : { getSession, saveSession, clearSession: clearAllData });
1973
2062
  const baseUrlOption = options.baseUrl;
1974
2063
  const base = typeof baseUrlOption === "function" ? baseUrlOption : () => baseUrlOption;
1975
- const retryFetch = createRetryFetch();
2064
+ const transport = createHttpTransport(options.transport);
2065
+ const retryFetch = createRetryFetch(transport.fetch);
1976
2066
  const gate = createSessionGate();
1977
2067
  const sessionFetch = gatedFetch(gate, retryFetch);
2068
+ const http = {
2069
+ fetch: gatedFetch(gate, transport.fetch),
2070
+ customFetch: transport.customFetch,
2071
+ withFetch: (adapter) => gatedFetch(gate, transport.withFetch(adapter))
2072
+ };
1978
2073
  const session = options.session ?? createSessionManager();
1979
2074
  if (userEmail) session.setUser(userEmail);
1980
2075
  const tokenProvider = createTokenProvider(session);
@@ -2171,6 +2266,7 @@ function createTransport(options) {
2171
2266
  for (const m of middleware) fetchClient.use(m);
2172
2267
  fetchClient.use(
2173
2268
  createAutoReloginMiddleware({
2269
+ fetch: sessionFetch,
2174
2270
  reloginHandler: relogin,
2175
2271
  reloginExcludePatterns,
2176
2272
  reopenWorkspaceHandler: reopenWorkspace,
@@ -2186,6 +2282,7 @@ function createTransport(options) {
2186
2282
  );
2187
2283
  return {
2188
2284
  fetch: fetchClient,
2285
+ http,
2189
2286
  session,
2190
2287
  persistence,
2191
2288
  workspaceKeys,
@@ -2223,7 +2320,10 @@ function createTransport(options) {
2223
2320
  }).catch((error) => console.warn("[API] Server logout failed:", error));
2224
2321
  }
2225
2322
  session.clear();
2226
- if (everywhere) await clearAllData();
2323
+ if (everywhere) {
2324
+ if (persistence.clearSession) await persistence.clearSession();
2325
+ else if (typeof indexedDB !== "undefined") await clearAllData();
2326
+ }
2227
2327
  } finally {
2228
2328
  gate.reopen();
2229
2329
  }
@@ -2336,6 +2436,8 @@ exports.createAuthMessage = createAuthMessage;
2336
2436
  exports.createAutoReloginMiddleware = createAutoReloginMiddleware;
2337
2437
  exports.createBearerAuthMiddleware = createBearerAuthMiddleware;
2338
2438
  exports.createContentHash = createContentHash;
2439
+ exports.createHttpTransport = createHttpTransport;
2440
+ exports.createMemorySessionPersistence = createMemorySessionPersistence;
2339
2441
  exports.createOfflineSealer = createOfflineSealer;
2340
2442
  exports.createRecoveryFile = createRecoveryFile;
2341
2443
  exports.createRecoveryUrl = createRecoveryUrl;