@arbidocs/client 0.5.25 → 0.5.26
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 +101 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +101 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1116,6 +1116,67 @@ function createBearerAuthMiddleware(config) {
|
|
|
1116
1116
|
};
|
|
1117
1117
|
}
|
|
1118
1118
|
|
|
1119
|
+
// src/session-gate.ts
|
|
1120
|
+
function abortError() {
|
|
1121
|
+
return new DOMException("The session ended.", "AbortError");
|
|
1122
|
+
}
|
|
1123
|
+
function isAbortError(error) {
|
|
1124
|
+
for (let e = error, depth = 0; e && typeof e === "object" && depth < 5; depth++) {
|
|
1125
|
+
if (e.name === "AbortError") return true;
|
|
1126
|
+
e = e.cause;
|
|
1127
|
+
}
|
|
1128
|
+
return false;
|
|
1129
|
+
}
|
|
1130
|
+
function eitherSignal(a, b) {
|
|
1131
|
+
if (!b) return a;
|
|
1132
|
+
if (typeof AbortSignal.any === "function") return AbortSignal.any([a, b]);
|
|
1133
|
+
const controller = new AbortController();
|
|
1134
|
+
const abort = (signal) => () => controller.abort(signal.reason);
|
|
1135
|
+
if (a.aborted || b.aborted) controller.abort((a.aborted ? a : b).reason);
|
|
1136
|
+
else {
|
|
1137
|
+
a.addEventListener("abort", abort(a), { once: true });
|
|
1138
|
+
b.addEventListener("abort", abort(b), { once: true });
|
|
1139
|
+
}
|
|
1140
|
+
return controller.signal;
|
|
1141
|
+
}
|
|
1142
|
+
function createSessionGate() {
|
|
1143
|
+
let controller = new AbortController();
|
|
1144
|
+
let closed = false;
|
|
1145
|
+
return {
|
|
1146
|
+
get signal() {
|
|
1147
|
+
return controller.signal;
|
|
1148
|
+
},
|
|
1149
|
+
get closed() {
|
|
1150
|
+
return closed;
|
|
1151
|
+
},
|
|
1152
|
+
close() {
|
|
1153
|
+
closed = true;
|
|
1154
|
+
},
|
|
1155
|
+
abort() {
|
|
1156
|
+
controller.abort(abortError());
|
|
1157
|
+
},
|
|
1158
|
+
reopen() {
|
|
1159
|
+
if (controller.signal.aborted) controller = new AbortController();
|
|
1160
|
+
closed = false;
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
function gatedFetch(gate, fetch2) {
|
|
1165
|
+
return (input, init) => {
|
|
1166
|
+
if (gate.closed) return Promise.reject(abortError());
|
|
1167
|
+
const own = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
1168
|
+
return fetch2(input, { ...init, signal: eitherSignal(gate.signal, own) });
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
function createSessionGateMiddleware(gate) {
|
|
1172
|
+
return {
|
|
1173
|
+
onRequest({ request }) {
|
|
1174
|
+
const signal = gate.closed ? AbortSignal.abort(abortError()) : gate.signal;
|
|
1175
|
+
return new Request(request, { signal: eitherSignal(signal, request.signal) });
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1119
1180
|
// src/workspace-keys.ts
|
|
1120
1181
|
function createWorkspaceKeys(deps) {
|
|
1121
1182
|
const wrapped = /* @__PURE__ */ new Map();
|
|
@@ -1912,6 +1973,8 @@ function createTransport(options) {
|
|
|
1912
1973
|
const baseUrlOption = options.baseUrl;
|
|
1913
1974
|
const base = typeof baseUrlOption === "function" ? baseUrlOption : () => baseUrlOption;
|
|
1914
1975
|
const retryFetch = createRetryFetch();
|
|
1976
|
+
const gate = createSessionGate();
|
|
1977
|
+
const sessionFetch = gatedFetch(gate, retryFetch);
|
|
1915
1978
|
const session = options.session ?? createSessionManager();
|
|
1916
1979
|
if (userEmail) session.setUser(userEmail);
|
|
1917
1980
|
const tokenProvider = createTokenProvider(session);
|
|
@@ -1929,7 +1992,7 @@ function createTransport(options) {
|
|
|
1929
1992
|
const rawFetch = createFetchClient__default.default({
|
|
1930
1993
|
baseUrl: base(),
|
|
1931
1994
|
credentials,
|
|
1932
|
-
fetch:
|
|
1995
|
+
fetch: sessionFetch
|
|
1933
1996
|
});
|
|
1934
1997
|
let response;
|
|
1935
1998
|
try {
|
|
@@ -1942,7 +2005,7 @@ function createTransport(options) {
|
|
|
1942
2005
|
}
|
|
1943
2006
|
});
|
|
1944
2007
|
} catch (error) {
|
|
1945
|
-
console.warn("[API] Login call unreachable:", error);
|
|
2008
|
+
if (!isAbortError(error)) console.warn("[API] Login call unreachable:", error);
|
|
1946
2009
|
return "unreachable";
|
|
1947
2010
|
}
|
|
1948
2011
|
if (response.error || !response.data) {
|
|
@@ -1959,7 +2022,7 @@ function createTransport(options) {
|
|
|
1959
2022
|
}
|
|
1960
2023
|
};
|
|
1961
2024
|
async function listWorkspaces(accessToken) {
|
|
1962
|
-
const response = await
|
|
2025
|
+
const response = await sessionFetch(`${base()}${API_PREFIX}/user/workspaces`, {
|
|
1963
2026
|
method: "GET",
|
|
1964
2027
|
headers: {
|
|
1965
2028
|
Authorization: `Bearer ${accessToken}`,
|
|
@@ -1977,7 +2040,7 @@ function createTransport(options) {
|
|
|
1977
2040
|
getServerSessionKey: () => session.getState().serverSessionKey,
|
|
1978
2041
|
listWorkspaces,
|
|
1979
2042
|
async primeKey(accessToken, workspaceId, sealedKey) {
|
|
1980
|
-
const response = await
|
|
2043
|
+
const response = await sessionFetch(
|
|
1981
2044
|
`${base()}${API_PREFIX}/workspace/${workspaceId}/prime-key`,
|
|
1982
2045
|
{
|
|
1983
2046
|
method: "POST",
|
|
@@ -2008,7 +2071,7 @@ function createTransport(options) {
|
|
|
2008
2071
|
async openWorkspace(accessToken, workspaceId, encryptedWorkspaceKey) {
|
|
2009
2072
|
const query = "?include_documents=false&include_conversations=false&include_tags=false";
|
|
2010
2073
|
try {
|
|
2011
|
-
const response = await
|
|
2074
|
+
const response = await sessionFetch(
|
|
2012
2075
|
`${base()}${API_PREFIX}/workspace/${workspaceId}/open${query}`,
|
|
2013
2076
|
{
|
|
2014
2077
|
method: "POST",
|
|
@@ -2038,6 +2101,7 @@ function createTransport(options) {
|
|
|
2038
2101
|
};
|
|
2039
2102
|
let lastFailure = null;
|
|
2040
2103
|
const expiredListeners = /* @__PURE__ */ new Set();
|
|
2104
|
+
const signingOutListeners = /* @__PURE__ */ new Set();
|
|
2041
2105
|
const rawRelogin = createReloginHandler({
|
|
2042
2106
|
crypto: cryptoProvider,
|
|
2043
2107
|
persistence,
|
|
@@ -2057,6 +2121,7 @@ function createTransport(options) {
|
|
|
2057
2121
|
}
|
|
2058
2122
|
});
|
|
2059
2123
|
async function relogin() {
|
|
2124
|
+
if (gate.closed) return null;
|
|
2060
2125
|
const tokenBefore = session.getState().accessToken;
|
|
2061
2126
|
const token = await rawRelogin();
|
|
2062
2127
|
if (token) return token;
|
|
@@ -2078,7 +2143,7 @@ function createTransport(options) {
|
|
|
2078
2143
|
workspaceOpenProvider: rawWorkspaceOpenProvider
|
|
2079
2144
|
});
|
|
2080
2145
|
let reopening = null;
|
|
2081
|
-
const reopenWorkspace = () => reopening ??= workspaceOpens.run(() => authState.getSelectedWorkspaceId(), reopenSelected).finally(() => {
|
|
2146
|
+
const reopenWorkspace = () => gate.closed ? Promise.resolve(false) : reopening ??= workspaceOpens.run(() => authState.getSelectedWorkspaceId(), reopenSelected).finally(() => {
|
|
2082
2147
|
reopening = null;
|
|
2083
2148
|
});
|
|
2084
2149
|
const openEveryWorkspace = createAllWorkspacesOpener({
|
|
@@ -2101,6 +2166,7 @@ function createTransport(options) {
|
|
|
2101
2166
|
fetch: retryFetch
|
|
2102
2167
|
});
|
|
2103
2168
|
if (typeof baseUrlOption === "function") readBaseUrlPerRequest(fetchClient, base);
|
|
2169
|
+
fetchClient.use(createSessionGateMiddleware(gate));
|
|
2104
2170
|
fetchClient.use(createBearerAuthMiddleware({ tokenProvider }));
|
|
2105
2171
|
for (const m of middleware) fetchClient.use(m);
|
|
2106
2172
|
fetchClient.use(
|
|
@@ -2128,18 +2194,39 @@ function createTransport(options) {
|
|
|
2128
2194
|
relogin,
|
|
2129
2195
|
reopenWorkspace,
|
|
2130
2196
|
openAllWorkspaces,
|
|
2197
|
+
onSigningOut(listener) {
|
|
2198
|
+
signingOutListeners.add(listener);
|
|
2199
|
+
return () => {
|
|
2200
|
+
signingOutListeners.delete(listener);
|
|
2201
|
+
};
|
|
2202
|
+
},
|
|
2203
|
+
isSigningOut: () => gate.closed,
|
|
2204
|
+
sessionSignal: () => gate.signal,
|
|
2131
2205
|
async logout({ everywhere = false } = {}) {
|
|
2132
|
-
|
|
2206
|
+
gate.close();
|
|
2207
|
+
for (const listener of [...signingOutListeners]) {
|
|
2133
2208
|
try {
|
|
2134
|
-
|
|
2135
|
-
params: { query: { all_sessions: everywhere } }
|
|
2136
|
-
});
|
|
2209
|
+
listener();
|
|
2137
2210
|
} catch (error) {
|
|
2138
|
-
console.warn("[API]
|
|
2211
|
+
console.warn("[API] A sign-out listener failed:", error);
|
|
2139
2212
|
}
|
|
2140
2213
|
}
|
|
2141
|
-
|
|
2142
|
-
|
|
2214
|
+
gate.abort();
|
|
2215
|
+
try {
|
|
2216
|
+
const accessToken = session.getState().accessToken;
|
|
2217
|
+
if (accessToken) {
|
|
2218
|
+
const query = `?all_sessions=${everywhere}`;
|
|
2219
|
+
await retryFetch(`${base()}${API_PREFIX}/user/logout${query}`, {
|
|
2220
|
+
method: "POST",
|
|
2221
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
2222
|
+
credentials
|
|
2223
|
+
}).catch((error) => console.warn("[API] Server logout failed:", error));
|
|
2224
|
+
}
|
|
2225
|
+
session.clear();
|
|
2226
|
+
if (everywhere) await clearAllData();
|
|
2227
|
+
} finally {
|
|
2228
|
+
gate.reopen();
|
|
2229
|
+
}
|
|
2143
2230
|
},
|
|
2144
2231
|
async unlock({ email, password }) {
|
|
2145
2232
|
const saved = await persistence.getSession();
|
|
@@ -2294,6 +2381,7 @@ exports.hasSession = hasSession;
|
|
|
2294
2381
|
exports.identityFromLoginResponse = identityFromLoginResponse;
|
|
2295
2382
|
exports.initSodium = initSodium;
|
|
2296
2383
|
exports.initializeDatabase = initializeDatabase;
|
|
2384
|
+
exports.isAbortError = isAbortError;
|
|
2297
2385
|
exports.isEncryptedRecoveryKey = isEncryptedRecoveryKey;
|
|
2298
2386
|
exports.isMessageType = isMessageType;
|
|
2299
2387
|
exports.openCallKeyOf = openCallKeyOf;
|