@finueva/auth 0.1.0 → 0.3.0
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/README.md +32 -5
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/errors-B0S9-QGH.d.ts +100 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +999 -46
- package/dist/server.d.ts +7 -2
- package/dist/server.js +139 -30
- package/package.json +5 -2
- package/dist/errors-C-cHFWC7.d.ts +0 -55
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
1
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/broadcast-channel.mjs
|
|
2
2
|
const kBroadcastChannel = Symbol.for("better-auth:broadcast-channel");
|
|
3
3
|
const now$1 = () => Math.floor(Date.now() / 1e3);
|
|
4
4
|
var WindowBroadcastChannel = class {
|
|
@@ -205,7 +205,7 @@ let onMount = ($store, initialize) => {
|
|
|
205
205
|
});
|
|
206
206
|
};
|
|
207
207
|
//#endregion
|
|
208
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
208
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/equality.mjs
|
|
209
209
|
function isPlainObject$1(value) {
|
|
210
210
|
if (typeof value !== "object" || value === null) return false;
|
|
211
211
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -233,7 +233,7 @@ function withEquality(store, isEqual) {
|
|
|
233
233
|
});
|
|
234
234
|
}
|
|
235
235
|
//#endregion
|
|
236
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
236
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/focus-manager.mjs
|
|
237
237
|
const kFocusManager = Symbol.for("better-auth:focus-manager");
|
|
238
238
|
var WindowFocusManager = class {
|
|
239
239
|
listeners = new Set();
|
|
@@ -262,7 +262,7 @@ function getGlobalFocusManager() {
|
|
|
262
262
|
return globalThis[kFocusManager];
|
|
263
263
|
}
|
|
264
264
|
//#endregion
|
|
265
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
265
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/online-manager.mjs
|
|
266
266
|
const kOnlineManager = Symbol.for("better-auth:online-manager");
|
|
267
267
|
var WindowOnlineManager = class {
|
|
268
268
|
listeners = new Set();
|
|
@@ -294,7 +294,7 @@ function getGlobalOnlineManager() {
|
|
|
294
294
|
return globalThis[kOnlineManager];
|
|
295
295
|
}
|
|
296
296
|
//#endregion
|
|
297
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
297
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/parser.mjs
|
|
298
298
|
const PROTO_POLLUTION_PATTERNS = {
|
|
299
299
|
proto: /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,
|
|
300
300
|
constructor: /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,
|
|
@@ -363,7 +363,7 @@ function parseJSON(value, options = { strict: true }) {
|
|
|
363
363
|
return betterJSONParse(value, options);
|
|
364
364
|
}
|
|
365
365
|
//#endregion
|
|
366
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
366
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/session-refresh.mjs
|
|
367
367
|
const now = () => Math.floor(Date.now() / 1e3);
|
|
368
368
|
const FOCUS_REFETCH_RATE_LIMIT_SECONDS = 5;
|
|
369
369
|
function createSessionRefreshManager(opts) {
|
|
@@ -660,7 +660,7 @@ var BetterAuthError = class extends Error {
|
|
|
660
660
|
}
|
|
661
661
|
};
|
|
662
662
|
//#endregion
|
|
663
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
663
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/utils/url.mjs
|
|
664
664
|
const SLASH_CHAR_CODE = "/".charCodeAt(0);
|
|
665
665
|
function trimTrailingSlashes(value) {
|
|
666
666
|
let end = value.length;
|
|
@@ -754,7 +754,7 @@ function isSafeUrlScheme(value) {
|
|
|
754
754
|
return !DANGEROUS_URL_SCHEMES.includes(parsed.protocol);
|
|
755
755
|
}
|
|
756
756
|
//#endregion
|
|
757
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
757
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/fetch-plugins.mjs
|
|
758
758
|
const redirectPlugin = {
|
|
759
759
|
id: "redirect",
|
|
760
760
|
name: "Redirect",
|
|
@@ -769,7 +769,7 @@ const redirectPlugin = {
|
|
|
769
769
|
} }
|
|
770
770
|
};
|
|
771
771
|
//#endregion
|
|
772
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
772
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/session-atom.mjs
|
|
773
773
|
const isServer = () => typeof window === "undefined";
|
|
774
774
|
function normalizeSessionResponse(res) {
|
|
775
775
|
if (typeof res === "object" && res !== null && "data" in res && "error" in res) return res;
|
|
@@ -1417,7 +1417,7 @@ var betterFetch = async (url, options) => {
|
|
|
1417
1417
|
};
|
|
1418
1418
|
};
|
|
1419
1419
|
//#endregion
|
|
1420
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
1420
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/config.mjs
|
|
1421
1421
|
const resolvePublicAuthUrl = (basePath) => {
|
|
1422
1422
|
if (typeof process === "undefined") return void 0;
|
|
1423
1423
|
const path = basePath ?? "/api/auth";
|
|
@@ -1515,7 +1515,7 @@ const getClientConfig = (options, loadEnv) => {
|
|
|
1515
1515
|
};
|
|
1516
1516
|
};
|
|
1517
1517
|
//#endregion
|
|
1518
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
1518
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/utils/is-atom.mjs
|
|
1519
1519
|
function isAtom(value) {
|
|
1520
1520
|
return typeof value === "object" && value !== null && "get" in value && typeof value.get === "function" && "lc" in value && typeof value.lc === "number";
|
|
1521
1521
|
}
|
|
@@ -1533,7 +1533,7 @@ function toKebabCase(input) {
|
|
|
1533
1533
|
return splitWords(input).map((word) => word.toLowerCase()).join("-");
|
|
1534
1534
|
}
|
|
1535
1535
|
//#endregion
|
|
1536
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
1536
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/proxy.mjs
|
|
1537
1537
|
function getMethod(path, knownPathMethods, args) {
|
|
1538
1538
|
const method = knownPathMethods[path];
|
|
1539
1539
|
const { fetchOptions, query: _query, ...body } = args || {};
|
|
@@ -1602,7 +1602,7 @@ function createDynamicPathProxy(routes, client, knownPathMethods, atoms, atomLis
|
|
|
1602
1602
|
return createProxy();
|
|
1603
1603
|
}
|
|
1604
1604
|
//#endregion
|
|
1605
|
-
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@
|
|
1605
|
+
//#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_95de1d9b4b5221fcaa380f950243e93e/node_modules/better-auth/dist/client/vanilla.mjs
|
|
1606
1606
|
function createAuthClient$1(options) {
|
|
1607
1607
|
const { pluginPathMethods, pluginsActions, pluginsAtoms, $fetch, atomListeners, $store } = getClientConfig(options);
|
|
1608
1608
|
const resolvedHooks = {};
|
|
@@ -1615,7 +1615,7 @@ function createAuthClient$1(options) {
|
|
|
1615
1615
|
}, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
|
|
1616
1616
|
}
|
|
1617
1617
|
//#endregion
|
|
1618
|
-
//#region ../../node_modules/.pnpm/@chiballc+utils@2.2.22_magic-string@0.30.21_magicast@0.5.3_rolldown@1.2.0_vite@7.3.6_@
|
|
1618
|
+
//#region ../../node_modules/.pnpm/@chiballc+utils@2.2.22_magic-string@0.30.21_magicast@0.5.3_rolldown@1.2.0_vite@7.3.6_@t_7ea103523467af2ecb75df55c94dbb80/node_modules/@chiballc/utils/dist/index.mjs
|
|
1619
1619
|
function isPromise(arg) {
|
|
1620
1620
|
return arg && typeof arg.then === "function";
|
|
1621
1621
|
}
|
|
@@ -1861,7 +1861,12 @@ const messages = {
|
|
|
1861
1861
|
invalid_credentials: "The credentials are invalid.",
|
|
1862
1862
|
authentication_required: "Authentication is required.",
|
|
1863
1863
|
request_origin_denied: "The request origin is not allowed.",
|
|
1864
|
+
invalid_invitation: "The invitation is invalid.",
|
|
1865
|
+
invitation_unavailable: "The invitation is not available.",
|
|
1866
|
+
invitation_recipient_mismatch: "The invitation cannot be accepted by this account.",
|
|
1867
|
+
email_verification_required: "Email verification is required.",
|
|
1864
1868
|
invalid_workspace_selection: "The workspace selection is invalid.",
|
|
1869
|
+
organization_context_too_large: "The organization context is too large.",
|
|
1865
1870
|
credential_rate_limited: "Credential requests are temporarily limited.",
|
|
1866
1871
|
state_conflict: "The authentication state conflicts with the request.",
|
|
1867
1872
|
access_denied: "Access is denied.",
|
|
@@ -2189,6 +2194,37 @@ function normalizeDriveCredential(value, now) {
|
|
|
2189
2194
|
expiresAt: new Date(now + value.expiresIn * 1e3)
|
|
2190
2195
|
};
|
|
2191
2196
|
}
|
|
2197
|
+
function normalizeOrganizations(value) {
|
|
2198
|
+
if (!Array.isArray(value) || value.length >= 100) throw authorityUnavailable();
|
|
2199
|
+
const seen = new Set();
|
|
2200
|
+
return value.map((organization) => {
|
|
2201
|
+
if (!isObject(organization) || !isId(organization.id) || seen.has(organization.id) || typeof organization.name !== "string" || organization.name.length < 1 || typeof organization.slug !== "string" || organization.slug.length < 1) throw authorityUnavailable();
|
|
2202
|
+
seen.add(organization.id);
|
|
2203
|
+
return {
|
|
2204
|
+
id: organization.id,
|
|
2205
|
+
name: organization.name,
|
|
2206
|
+
slug: organization.slug
|
|
2207
|
+
};
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2210
|
+
function normalizeInvitationInput(value) {
|
|
2211
|
+
if (!isObject(value) || Object.keys(value).length !== 1 || !isId(value.invitationId)) throw new AuthError("invalid_invitation", 422);
|
|
2212
|
+
return { invitationId: value.invitationId };
|
|
2213
|
+
}
|
|
2214
|
+
function normalizeInvitationAcceptance(value, invitationId) {
|
|
2215
|
+
if (!isObject(value) || !isObject(value.invitation) || !isObject(value.member) || value.invitation.id !== invitationId || value.invitation.status !== "accepted" || !isId(value.invitation.organizationId) || value.member.organizationId !== value.invitation.organizationId) throw authorityUnavailable();
|
|
2216
|
+
return { organizationId: value.invitation.organizationId };
|
|
2217
|
+
}
|
|
2218
|
+
function normalizeWorkspaceSelection(value) {
|
|
2219
|
+
if (!isObject(value)) throw new AuthError("invalid_workspace_selection", 422);
|
|
2220
|
+
const keys = Object.keys(value);
|
|
2221
|
+
if (value.type === "personal" && keys.length === 1 && keys[0] === "type") return { type: "personal" };
|
|
2222
|
+
if (value.type === "organization" && keys.length === 2 && keys.includes("type") && keys.includes("organizationId") && typeof value.organizationId === "string" && id.test(value.organizationId)) return {
|
|
2223
|
+
type: "organization",
|
|
2224
|
+
organizationId: value.organizationId
|
|
2225
|
+
};
|
|
2226
|
+
throw new AuthError("invalid_workspace_selection", 422);
|
|
2227
|
+
}
|
|
2192
2228
|
function fromAuthorityError(value, fallbackStatus, retryAfter) {
|
|
2193
2229
|
const mapped = mapError(isObject(value) && typeof value.code === "string" ? value.code : void 0, fallbackStatus);
|
|
2194
2230
|
return new AuthError(mapped.code, mapped.status, parseRetryAfter(retryAfter));
|
|
@@ -2196,6 +2232,23 @@ function fromAuthorityError(value, fallbackStatus, retryAfter) {
|
|
|
2196
2232
|
function authorityUnavailable() {
|
|
2197
2233
|
return new AuthError("identity_authority_unavailable", 503);
|
|
2198
2234
|
}
|
|
2235
|
+
function fromOrganizationListError(error) {
|
|
2236
|
+
if (error instanceof AuthError && error.status === 401) return new AuthError("authentication_required", 401);
|
|
2237
|
+
if (error instanceof AuthError) return error;
|
|
2238
|
+
return authorityUnavailable();
|
|
2239
|
+
}
|
|
2240
|
+
function fromInvitationAuthorityError(value, status) {
|
|
2241
|
+
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
|
2242
|
+
if (status === 401 && code === "UNAUTHORIZED") return new AuthError("authentication_required", 401);
|
|
2243
|
+
if (status === 403 && (code === "INVALID_ORIGIN" || code === "MISSING_OR_NULL_ORIGIN")) return new AuthError("request_origin_denied", 403);
|
|
2244
|
+
if (status === 403 && code === "YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION") return new AuthError("invitation_recipient_mismatch", 403);
|
|
2245
|
+
if (status === 403 && code === "EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION") return new AuthError("email_verification_required", 403);
|
|
2246
|
+
if (status === 400 && (code === "INVITATION_NOT_FOUND" || code === "ORGANIZATION_NOT_FOUND" || code === "TEAM_NOT_FOUND")) return new AuthError("invitation_unavailable", 409);
|
|
2247
|
+
return authorityUnavailable();
|
|
2248
|
+
}
|
|
2249
|
+
function fromInvitationError(error) {
|
|
2250
|
+
return error instanceof AuthError ? error : authorityUnavailable();
|
|
2251
|
+
}
|
|
2199
2252
|
function mapError(code, status) {
|
|
2200
2253
|
if (code === "authentication_required") return {
|
|
2201
2254
|
code,
|
|
@@ -2209,6 +2262,10 @@ function mapError(code, status) {
|
|
|
2209
2262
|
code,
|
|
2210
2263
|
status: 422
|
|
2211
2264
|
};
|
|
2265
|
+
if (code === "organization_context_too_large") return {
|
|
2266
|
+
code,
|
|
2267
|
+
status: 422
|
|
2268
|
+
};
|
|
2212
2269
|
if (code === "credential_rate_limited") return {
|
|
2213
2270
|
code,
|
|
2214
2271
|
status: 429
|
|
@@ -2261,6 +2318,9 @@ function isObject(value) {
|
|
|
2261
2318
|
//#region src/http.ts
|
|
2262
2319
|
const MAX_RESPONSE_BYTES = 64 * 1024;
|
|
2263
2320
|
async function requestJson(url, options) {
|
|
2321
|
+
return (await requestJsonResponse(url, options)).value;
|
|
2322
|
+
}
|
|
2323
|
+
async function requestJsonResponse(url, options) {
|
|
2264
2324
|
let response;
|
|
2265
2325
|
try {
|
|
2266
2326
|
response = await createFetch({ fetch: options.fetch }).raw(url, {
|
|
@@ -2271,6 +2331,7 @@ async function requestJson(url, options) {
|
|
|
2271
2331
|
retry: 0,
|
|
2272
2332
|
timeout: options.timeoutMs,
|
|
2273
2333
|
redirect: "manual",
|
|
2334
|
+
signal: options.signal,
|
|
2274
2335
|
responseType: "stream",
|
|
2275
2336
|
ignoreResponseError: true
|
|
2276
2337
|
});
|
|
@@ -2281,9 +2342,12 @@ async function requestJson(url, options) {
|
|
|
2281
2342
|
if (response.status >= 300 || response.status < 200 || contentType !== "application/json") {
|
|
2282
2343
|
const body = contentType === "application/json" ? await readJson(response) : void 0;
|
|
2283
2344
|
await response.body?.cancel();
|
|
2284
|
-
throw fromAuthorityError(body, response.status, response.headers.get("retry-after"));
|
|
2345
|
+
throw (options.mapError ?? fromAuthorityError)(body, response.status, response.headers.get("retry-after"));
|
|
2285
2346
|
}
|
|
2286
|
-
return
|
|
2347
|
+
return {
|
|
2348
|
+
value: await readJson(response),
|
|
2349
|
+
headers: response.headers
|
|
2350
|
+
};
|
|
2287
2351
|
}
|
|
2288
2352
|
async function readJson(response) {
|
|
2289
2353
|
const length = response.headers.get("content-length");
|
|
@@ -2322,6 +2386,685 @@ async function readJson(response) {
|
|
|
2322
2386
|
}
|
|
2323
2387
|
}
|
|
2324
2388
|
//#endregion
|
|
2389
|
+
//#region ../../node_modules/.pnpm/unstorage@1.17.5/node_modules/unstorage/dist/shared/unstorage.zVDD2mZo.mjs
|
|
2390
|
+
function wrapToPromise(value) {
|
|
2391
|
+
if (!value || typeof value.then !== "function") return Promise.resolve(value);
|
|
2392
|
+
return value;
|
|
2393
|
+
}
|
|
2394
|
+
function asyncCall(function_, ...arguments_) {
|
|
2395
|
+
try {
|
|
2396
|
+
return wrapToPromise(function_(...arguments_));
|
|
2397
|
+
} catch (error) {
|
|
2398
|
+
return Promise.reject(error);
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
function isPrimitive(value) {
|
|
2402
|
+
const type = typeof value;
|
|
2403
|
+
return value === null || type !== "object" && type !== "function";
|
|
2404
|
+
}
|
|
2405
|
+
function isPureObject(value) {
|
|
2406
|
+
const proto = Object.getPrototypeOf(value);
|
|
2407
|
+
return !proto || proto.isPrototypeOf(Object);
|
|
2408
|
+
}
|
|
2409
|
+
function stringify(value) {
|
|
2410
|
+
if (isPrimitive(value)) return String(value);
|
|
2411
|
+
if (isPureObject(value) || Array.isArray(value)) return JSON.stringify(value);
|
|
2412
|
+
if (typeof value.toJSON === "function") return stringify(value.toJSON());
|
|
2413
|
+
throw new Error("[unstorage] Cannot stringify value!");
|
|
2414
|
+
}
|
|
2415
|
+
const BASE64_PREFIX = "base64:";
|
|
2416
|
+
function serializeRaw(value) {
|
|
2417
|
+
if (typeof value === "string") return value;
|
|
2418
|
+
return BASE64_PREFIX + base64Encode(value);
|
|
2419
|
+
}
|
|
2420
|
+
function deserializeRaw(value) {
|
|
2421
|
+
if (typeof value !== "string") return value;
|
|
2422
|
+
if (!value.startsWith(BASE64_PREFIX)) return value;
|
|
2423
|
+
return base64Decode(value.slice(7));
|
|
2424
|
+
}
|
|
2425
|
+
function base64Decode(input) {
|
|
2426
|
+
if (globalThis.Buffer) return Buffer.from(input, "base64");
|
|
2427
|
+
return Uint8Array.from(globalThis.atob(input), (c) => c.codePointAt(0));
|
|
2428
|
+
}
|
|
2429
|
+
function base64Encode(input) {
|
|
2430
|
+
if (globalThis.Buffer) return Buffer.from(input).toString("base64");
|
|
2431
|
+
return globalThis.btoa(String.fromCodePoint(...input));
|
|
2432
|
+
}
|
|
2433
|
+
function normalizeKey$1(key) {
|
|
2434
|
+
if (!key) return "";
|
|
2435
|
+
return key.split("?")[0]?.replace(/[/\\]/g, ":").replace(/:+/g, ":").replace(/^:|:$/g, "") || "";
|
|
2436
|
+
}
|
|
2437
|
+
function joinKeys(...keys) {
|
|
2438
|
+
return normalizeKey$1(keys.join(":"));
|
|
2439
|
+
}
|
|
2440
|
+
function normalizeBaseKey(base) {
|
|
2441
|
+
base = normalizeKey$1(base);
|
|
2442
|
+
return base ? base + ":" : "";
|
|
2443
|
+
}
|
|
2444
|
+
function filterKeyByDepth(key, depth) {
|
|
2445
|
+
if (depth === void 0) return true;
|
|
2446
|
+
let substrCount = 0;
|
|
2447
|
+
let index = key.indexOf(":");
|
|
2448
|
+
while (index > -1) {
|
|
2449
|
+
substrCount++;
|
|
2450
|
+
index = key.indexOf(":", index + 1);
|
|
2451
|
+
}
|
|
2452
|
+
return substrCount <= depth;
|
|
2453
|
+
}
|
|
2454
|
+
function filterKeyByBase(key, base) {
|
|
2455
|
+
if (base) return key.startsWith(base) && key[key.length - 1] !== "$";
|
|
2456
|
+
return key[key.length - 1] !== "$";
|
|
2457
|
+
}
|
|
2458
|
+
//#endregion
|
|
2459
|
+
//#region ../../node_modules/.pnpm/unstorage@1.17.5/node_modules/unstorage/dist/index.mjs
|
|
2460
|
+
function defineDriver$1(factory) {
|
|
2461
|
+
return factory;
|
|
2462
|
+
}
|
|
2463
|
+
const DRIVER_NAME$3 = "memory";
|
|
2464
|
+
const memory = defineDriver$1(() => {
|
|
2465
|
+
const data = new Map();
|
|
2466
|
+
return {
|
|
2467
|
+
name: DRIVER_NAME$3,
|
|
2468
|
+
getInstance: () => data,
|
|
2469
|
+
hasItem(key) {
|
|
2470
|
+
return data.has(key);
|
|
2471
|
+
},
|
|
2472
|
+
getItem(key) {
|
|
2473
|
+
return data.get(key) ?? null;
|
|
2474
|
+
},
|
|
2475
|
+
getItemRaw(key) {
|
|
2476
|
+
return data.get(key) ?? null;
|
|
2477
|
+
},
|
|
2478
|
+
setItem(key, value) {
|
|
2479
|
+
data.set(key, value);
|
|
2480
|
+
},
|
|
2481
|
+
setItemRaw(key, value) {
|
|
2482
|
+
data.set(key, value);
|
|
2483
|
+
},
|
|
2484
|
+
removeItem(key) {
|
|
2485
|
+
data.delete(key);
|
|
2486
|
+
},
|
|
2487
|
+
getKeys() {
|
|
2488
|
+
return [...data.keys()];
|
|
2489
|
+
},
|
|
2490
|
+
clear() {
|
|
2491
|
+
data.clear();
|
|
2492
|
+
},
|
|
2493
|
+
dispose() {
|
|
2494
|
+
data.clear();
|
|
2495
|
+
}
|
|
2496
|
+
};
|
|
2497
|
+
});
|
|
2498
|
+
function createStorage(options = {}) {
|
|
2499
|
+
const context = {
|
|
2500
|
+
mounts: { "": options.driver || memory() },
|
|
2501
|
+
mountpoints: [""],
|
|
2502
|
+
watching: false,
|
|
2503
|
+
watchListeners: [],
|
|
2504
|
+
unwatch: {}
|
|
2505
|
+
};
|
|
2506
|
+
const getMount = (key) => {
|
|
2507
|
+
for (const base of context.mountpoints) if (key.startsWith(base)) return {
|
|
2508
|
+
base,
|
|
2509
|
+
relativeKey: key.slice(base.length),
|
|
2510
|
+
driver: context.mounts[base]
|
|
2511
|
+
};
|
|
2512
|
+
return {
|
|
2513
|
+
base: "",
|
|
2514
|
+
relativeKey: key,
|
|
2515
|
+
driver: context.mounts[""]
|
|
2516
|
+
};
|
|
2517
|
+
};
|
|
2518
|
+
const getMounts = (base, includeParent) => {
|
|
2519
|
+
return context.mountpoints.filter((mountpoint) => mountpoint.startsWith(base) || includeParent && base.startsWith(mountpoint)).map((mountpoint) => ({
|
|
2520
|
+
relativeBase: base.length > mountpoint.length ? base.slice(mountpoint.length) : void 0,
|
|
2521
|
+
mountpoint,
|
|
2522
|
+
driver: context.mounts[mountpoint]
|
|
2523
|
+
}));
|
|
2524
|
+
};
|
|
2525
|
+
const onChange = (event, key) => {
|
|
2526
|
+
if (!context.watching) return;
|
|
2527
|
+
key = normalizeKey$1(key);
|
|
2528
|
+
for (const listener of context.watchListeners) listener(event, key);
|
|
2529
|
+
};
|
|
2530
|
+
const startWatch = async () => {
|
|
2531
|
+
if (context.watching) return;
|
|
2532
|
+
context.watching = true;
|
|
2533
|
+
for (const mountpoint in context.mounts) context.unwatch[mountpoint] = await watch(context.mounts[mountpoint], onChange, mountpoint);
|
|
2534
|
+
};
|
|
2535
|
+
const stopWatch = async () => {
|
|
2536
|
+
if (!context.watching) return;
|
|
2537
|
+
for (const mountpoint in context.unwatch) await context.unwatch[mountpoint]();
|
|
2538
|
+
context.unwatch = {};
|
|
2539
|
+
context.watching = false;
|
|
2540
|
+
};
|
|
2541
|
+
const runBatch = (items, commonOptions, cb) => {
|
|
2542
|
+
const batches = new Map();
|
|
2543
|
+
const getBatch = (mount) => {
|
|
2544
|
+
let batch = batches.get(mount.base);
|
|
2545
|
+
if (!batch) {
|
|
2546
|
+
batch = {
|
|
2547
|
+
driver: mount.driver,
|
|
2548
|
+
base: mount.base,
|
|
2549
|
+
items: []
|
|
2550
|
+
};
|
|
2551
|
+
batches.set(mount.base, batch);
|
|
2552
|
+
}
|
|
2553
|
+
return batch;
|
|
2554
|
+
};
|
|
2555
|
+
for (const item of items) {
|
|
2556
|
+
const isStringItem = typeof item === "string";
|
|
2557
|
+
const key = normalizeKey$1(isStringItem ? item : item.key);
|
|
2558
|
+
const value = isStringItem ? void 0 : item.value;
|
|
2559
|
+
const options2 = isStringItem || !item.options ? commonOptions : {
|
|
2560
|
+
...commonOptions,
|
|
2561
|
+
...item.options
|
|
2562
|
+
};
|
|
2563
|
+
const mount = getMount(key);
|
|
2564
|
+
getBatch(mount).items.push({
|
|
2565
|
+
key,
|
|
2566
|
+
value,
|
|
2567
|
+
relativeKey: mount.relativeKey,
|
|
2568
|
+
options: options2
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2571
|
+
return Promise.all([...batches.values()].map((batch) => cb(batch))).then((r) => r.flat());
|
|
2572
|
+
};
|
|
2573
|
+
const storage = {
|
|
2574
|
+
hasItem(key, opts = {}) {
|
|
2575
|
+
key = normalizeKey$1(key);
|
|
2576
|
+
const { relativeKey, driver } = getMount(key);
|
|
2577
|
+
return asyncCall(driver.hasItem, relativeKey, opts);
|
|
2578
|
+
},
|
|
2579
|
+
getItem(key, opts = {}) {
|
|
2580
|
+
key = normalizeKey$1(key);
|
|
2581
|
+
const { relativeKey, driver } = getMount(key);
|
|
2582
|
+
return asyncCall(driver.getItem, relativeKey, opts).then((value) => destr(value));
|
|
2583
|
+
},
|
|
2584
|
+
getItems(items, commonOptions = {}) {
|
|
2585
|
+
return runBatch(items, commonOptions, (batch) => {
|
|
2586
|
+
if (batch.driver.getItems) return asyncCall(batch.driver.getItems, batch.items.map((item) => ({
|
|
2587
|
+
key: item.relativeKey,
|
|
2588
|
+
options: item.options
|
|
2589
|
+
})), commonOptions).then((r) => r.map((item) => ({
|
|
2590
|
+
key: joinKeys(batch.base, item.key),
|
|
2591
|
+
value: destr(item.value)
|
|
2592
|
+
})));
|
|
2593
|
+
return Promise.all(batch.items.map((item) => {
|
|
2594
|
+
return asyncCall(batch.driver.getItem, item.relativeKey, item.options).then((value) => ({
|
|
2595
|
+
key: item.key,
|
|
2596
|
+
value: destr(value)
|
|
2597
|
+
}));
|
|
2598
|
+
}));
|
|
2599
|
+
});
|
|
2600
|
+
},
|
|
2601
|
+
getItemRaw(key, opts = {}) {
|
|
2602
|
+
key = normalizeKey$1(key);
|
|
2603
|
+
const { relativeKey, driver } = getMount(key);
|
|
2604
|
+
if (driver.getItemRaw) return asyncCall(driver.getItemRaw, relativeKey, opts);
|
|
2605
|
+
return asyncCall(driver.getItem, relativeKey, opts).then((value) => deserializeRaw(value));
|
|
2606
|
+
},
|
|
2607
|
+
async setItem(key, value, opts = {}) {
|
|
2608
|
+
if (value === void 0) return storage.removeItem(key);
|
|
2609
|
+
key = normalizeKey$1(key);
|
|
2610
|
+
const { relativeKey, driver } = getMount(key);
|
|
2611
|
+
if (!driver.setItem) return;
|
|
2612
|
+
await asyncCall(driver.setItem, relativeKey, stringify(value), opts);
|
|
2613
|
+
if (!driver.watch) onChange("update", key);
|
|
2614
|
+
},
|
|
2615
|
+
async setItems(items, commonOptions) {
|
|
2616
|
+
await runBatch(items, commonOptions, async (batch) => {
|
|
2617
|
+
if (batch.driver.setItems) return asyncCall(batch.driver.setItems, batch.items.map((item) => ({
|
|
2618
|
+
key: item.relativeKey,
|
|
2619
|
+
value: stringify(item.value),
|
|
2620
|
+
options: item.options
|
|
2621
|
+
})), commonOptions);
|
|
2622
|
+
if (!batch.driver.setItem) return;
|
|
2623
|
+
await Promise.all(batch.items.map((item) => {
|
|
2624
|
+
return asyncCall(batch.driver.setItem, item.relativeKey, stringify(item.value), item.options);
|
|
2625
|
+
}));
|
|
2626
|
+
});
|
|
2627
|
+
},
|
|
2628
|
+
async setItemRaw(key, value, opts = {}) {
|
|
2629
|
+
if (value === void 0) return storage.removeItem(key, opts);
|
|
2630
|
+
key = normalizeKey$1(key);
|
|
2631
|
+
const { relativeKey, driver } = getMount(key);
|
|
2632
|
+
if (driver.setItemRaw) await asyncCall(driver.setItemRaw, relativeKey, value, opts);
|
|
2633
|
+
else if (driver.setItem) await asyncCall(driver.setItem, relativeKey, serializeRaw(value), opts);
|
|
2634
|
+
else return;
|
|
2635
|
+
if (!driver.watch) onChange("update", key);
|
|
2636
|
+
},
|
|
2637
|
+
async removeItem(key, opts = {}) {
|
|
2638
|
+
if (typeof opts === "boolean") opts = { removeMeta: opts };
|
|
2639
|
+
key = normalizeKey$1(key);
|
|
2640
|
+
const { relativeKey, driver } = getMount(key);
|
|
2641
|
+
if (!driver.removeItem) return;
|
|
2642
|
+
await asyncCall(driver.removeItem, relativeKey, opts);
|
|
2643
|
+
if (opts.removeMeta || opts.removeMata) await asyncCall(driver.removeItem, relativeKey + "$", opts);
|
|
2644
|
+
if (!driver.watch) onChange("remove", key);
|
|
2645
|
+
},
|
|
2646
|
+
async getMeta(key, opts = {}) {
|
|
2647
|
+
if (typeof opts === "boolean") opts = { nativeOnly: opts };
|
|
2648
|
+
key = normalizeKey$1(key);
|
|
2649
|
+
const { relativeKey, driver } = getMount(key);
|
|
2650
|
+
const meta = Object.create(null);
|
|
2651
|
+
if (driver.getMeta) Object.assign(meta, await asyncCall(driver.getMeta, relativeKey, opts));
|
|
2652
|
+
if (!opts.nativeOnly) {
|
|
2653
|
+
const value = await asyncCall(driver.getItem, relativeKey + "$", opts).then((value_) => destr(value_));
|
|
2654
|
+
if (value && typeof value === "object") {
|
|
2655
|
+
if (typeof value.atime === "string") value.atime = new Date(value.atime);
|
|
2656
|
+
if (typeof value.mtime === "string") value.mtime = new Date(value.mtime);
|
|
2657
|
+
Object.assign(meta, value);
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
return meta;
|
|
2661
|
+
},
|
|
2662
|
+
setMeta(key, value, opts = {}) {
|
|
2663
|
+
return this.setItem(key + "$", value, opts);
|
|
2664
|
+
},
|
|
2665
|
+
removeMeta(key, opts = {}) {
|
|
2666
|
+
return this.removeItem(key + "$", opts);
|
|
2667
|
+
},
|
|
2668
|
+
async getKeys(base, opts = {}) {
|
|
2669
|
+
base = normalizeBaseKey(base);
|
|
2670
|
+
const mounts = getMounts(base, true);
|
|
2671
|
+
let maskedMounts = [];
|
|
2672
|
+
const allKeys = [];
|
|
2673
|
+
let allMountsSupportMaxDepth = true;
|
|
2674
|
+
for (const mount of mounts) {
|
|
2675
|
+
if (!mount.driver.flags?.maxDepth) allMountsSupportMaxDepth = false;
|
|
2676
|
+
const rawKeys = await asyncCall(mount.driver.getKeys, mount.relativeBase, opts);
|
|
2677
|
+
for (const key of rawKeys) {
|
|
2678
|
+
const fullKey = mount.mountpoint + normalizeKey$1(key);
|
|
2679
|
+
if (!maskedMounts.some((p) => fullKey.startsWith(p))) allKeys.push(fullKey);
|
|
2680
|
+
}
|
|
2681
|
+
maskedMounts = [mount.mountpoint, ...maskedMounts.filter((p) => !p.startsWith(mount.mountpoint))];
|
|
2682
|
+
}
|
|
2683
|
+
const shouldFilterByDepth = opts.maxDepth !== void 0 && !allMountsSupportMaxDepth;
|
|
2684
|
+
return allKeys.filter((key) => (!shouldFilterByDepth || filterKeyByDepth(key, opts.maxDepth)) && filterKeyByBase(key, base));
|
|
2685
|
+
},
|
|
2686
|
+
async clear(base, opts = {}) {
|
|
2687
|
+
base = normalizeBaseKey(base);
|
|
2688
|
+
await Promise.all(getMounts(base, false).map(async (m) => {
|
|
2689
|
+
if (m.driver.clear) return asyncCall(m.driver.clear, m.relativeBase, opts);
|
|
2690
|
+
if (m.driver.removeItem) {
|
|
2691
|
+
const keys = await m.driver.getKeys(m.relativeBase || "", opts);
|
|
2692
|
+
return Promise.all(keys.map((key) => m.driver.removeItem(key, opts)));
|
|
2693
|
+
}
|
|
2694
|
+
}));
|
|
2695
|
+
},
|
|
2696
|
+
async dispose() {
|
|
2697
|
+
await Promise.all(Object.values(context.mounts).map((driver) => dispose(driver)));
|
|
2698
|
+
},
|
|
2699
|
+
async watch(callback) {
|
|
2700
|
+
await startWatch();
|
|
2701
|
+
context.watchListeners.push(callback);
|
|
2702
|
+
return async () => {
|
|
2703
|
+
context.watchListeners = context.watchListeners.filter((listener) => listener !== callback);
|
|
2704
|
+
if (context.watchListeners.length === 0) await stopWatch();
|
|
2705
|
+
};
|
|
2706
|
+
},
|
|
2707
|
+
async unwatch() {
|
|
2708
|
+
context.watchListeners = [];
|
|
2709
|
+
await stopWatch();
|
|
2710
|
+
},
|
|
2711
|
+
mount(base, driver) {
|
|
2712
|
+
base = normalizeBaseKey(base);
|
|
2713
|
+
if (base && context.mounts[base]) throw new Error(`already mounted at ${base}`);
|
|
2714
|
+
if (base) {
|
|
2715
|
+
context.mountpoints.push(base);
|
|
2716
|
+
context.mountpoints.sort((a, b) => b.length - a.length);
|
|
2717
|
+
}
|
|
2718
|
+
context.mounts[base] = driver;
|
|
2719
|
+
if (context.watching) Promise.resolve(watch(driver, onChange, base)).then((unwatcher) => {
|
|
2720
|
+
context.unwatch[base] = unwatcher;
|
|
2721
|
+
}).catch(console.error);
|
|
2722
|
+
return storage;
|
|
2723
|
+
},
|
|
2724
|
+
async unmount(base, _dispose = true) {
|
|
2725
|
+
base = normalizeBaseKey(base);
|
|
2726
|
+
if (!base || !context.mounts[base]) return;
|
|
2727
|
+
if (context.watching && base in context.unwatch) {
|
|
2728
|
+
context.unwatch[base]?.();
|
|
2729
|
+
delete context.unwatch[base];
|
|
2730
|
+
}
|
|
2731
|
+
if (_dispose) await dispose(context.mounts[base]);
|
|
2732
|
+
context.mountpoints = context.mountpoints.filter((key) => key !== base);
|
|
2733
|
+
delete context.mounts[base];
|
|
2734
|
+
},
|
|
2735
|
+
getMount(key = "") {
|
|
2736
|
+
key = normalizeKey$1(key) + ":";
|
|
2737
|
+
const m = getMount(key);
|
|
2738
|
+
return {
|
|
2739
|
+
driver: m.driver,
|
|
2740
|
+
base: m.base
|
|
2741
|
+
};
|
|
2742
|
+
},
|
|
2743
|
+
getMounts(base = "", opts = {}) {
|
|
2744
|
+
base = normalizeKey$1(base);
|
|
2745
|
+
return getMounts(base, opts.parents).map((m) => ({
|
|
2746
|
+
driver: m.driver,
|
|
2747
|
+
base: m.mountpoint
|
|
2748
|
+
}));
|
|
2749
|
+
},
|
|
2750
|
+
keys: (base, opts = {}) => storage.getKeys(base, opts),
|
|
2751
|
+
get: (key, opts = {}) => storage.getItem(key, opts),
|
|
2752
|
+
set: (key, value, opts = {}) => storage.setItem(key, value, opts),
|
|
2753
|
+
has: (key, opts = {}) => storage.hasItem(key, opts),
|
|
2754
|
+
del: (key, opts = {}) => storage.removeItem(key, opts),
|
|
2755
|
+
remove: (key, opts = {}) => storage.removeItem(key, opts)
|
|
2756
|
+
};
|
|
2757
|
+
return storage;
|
|
2758
|
+
}
|
|
2759
|
+
function watch(driver, onChange, base) {
|
|
2760
|
+
return driver.watch ? driver.watch((event, key) => onChange(event, base + key)) : () => {};
|
|
2761
|
+
}
|
|
2762
|
+
async function dispose(driver) {
|
|
2763
|
+
if (typeof driver.dispose === "function") await asyncCall(driver.dispose);
|
|
2764
|
+
}
|
|
2765
|
+
//#endregion
|
|
2766
|
+
//#region ../../node_modules/.pnpm/unstorage@1.17.5/node_modules/unstorage/drivers/utils/index.mjs
|
|
2767
|
+
function defineDriver(factory) {
|
|
2768
|
+
return factory;
|
|
2769
|
+
}
|
|
2770
|
+
function normalizeKey(key, sep = ":") {
|
|
2771
|
+
if (!key) return "";
|
|
2772
|
+
return key.replace(/[:/\\]/g, sep).replace(/^[:/\\]|[:/\\]$/g, "");
|
|
2773
|
+
}
|
|
2774
|
+
function createError(driver, message, opts) {
|
|
2775
|
+
const err = new Error(`[unstorage] [${driver}] ${message}`, opts);
|
|
2776
|
+
if (Error.captureStackTrace) Error.captureStackTrace(err, createError);
|
|
2777
|
+
return err;
|
|
2778
|
+
}
|
|
2779
|
+
function createRequiredError(driver, name) {
|
|
2780
|
+
if (Array.isArray(name)) return createError(driver, `Missing some of the required options ${name.map((n) => "`" + n + "`").join(", ")}`);
|
|
2781
|
+
return createError(driver, `Missing required option \`${name}\`.`);
|
|
2782
|
+
}
|
|
2783
|
+
//#endregion
|
|
2784
|
+
//#region ../../node_modules/.pnpm/unstorage@1.17.5/node_modules/unstorage/drivers/localstorage.mjs
|
|
2785
|
+
const DRIVER_NAME$2 = "localstorage";
|
|
2786
|
+
var localstorage_default = defineDriver((opts = {}) => {
|
|
2787
|
+
const storage = opts.storage || opts.localStorage || opts.sessionStorage || (opts.window || globalThis.window)?.[opts.windowKey || "localStorage"];
|
|
2788
|
+
if (!storage) throw createRequiredError(DRIVER_NAME$2, "localStorage");
|
|
2789
|
+
const base = opts.base ? normalizeKey(opts.base) : "";
|
|
2790
|
+
const r = (key) => (base ? `${base}:` : "") + key;
|
|
2791
|
+
let _storageListener;
|
|
2792
|
+
const _unwatch = () => {
|
|
2793
|
+
if (_storageListener) opts.window?.removeEventListener("storage", _storageListener);
|
|
2794
|
+
_storageListener = void 0;
|
|
2795
|
+
};
|
|
2796
|
+
return {
|
|
2797
|
+
name: DRIVER_NAME$2,
|
|
2798
|
+
options: opts,
|
|
2799
|
+
getInstance: () => storage,
|
|
2800
|
+
hasItem(key) {
|
|
2801
|
+
return Object.prototype.hasOwnProperty.call(storage, r(key));
|
|
2802
|
+
},
|
|
2803
|
+
getItem(key) {
|
|
2804
|
+
return storage.getItem(r(key));
|
|
2805
|
+
},
|
|
2806
|
+
setItem(key, value) {
|
|
2807
|
+
return storage.setItem(r(key), value);
|
|
2808
|
+
},
|
|
2809
|
+
removeItem(key) {
|
|
2810
|
+
return storage.removeItem(r(key));
|
|
2811
|
+
},
|
|
2812
|
+
getKeys() {
|
|
2813
|
+
const allKeys = Object.keys(storage);
|
|
2814
|
+
return base ? allKeys.filter((key) => key.startsWith(`${base}:`)).map((key) => key.slice(base.length + 1)) : allKeys;
|
|
2815
|
+
},
|
|
2816
|
+
clear(prefix) {
|
|
2817
|
+
const _base = [base, prefix].filter(Boolean).join(":");
|
|
2818
|
+
if (_base) {
|
|
2819
|
+
for (const key of Object.keys(storage)) if (key.startsWith(`${_base}:`)) storage?.removeItem(key);
|
|
2820
|
+
} else storage.clear();
|
|
2821
|
+
},
|
|
2822
|
+
dispose() {
|
|
2823
|
+
if (opts.window && _storageListener) opts.window.removeEventListener("storage", _storageListener);
|
|
2824
|
+
},
|
|
2825
|
+
watch(callback) {
|
|
2826
|
+
if (!opts.window) return _unwatch;
|
|
2827
|
+
_storageListener = (ev) => {
|
|
2828
|
+
if (ev.key) callback(ev.newValue ? "update" : "remove", ev.key);
|
|
2829
|
+
};
|
|
2830
|
+
opts.window.addEventListener("storage", _storageListener);
|
|
2831
|
+
return _unwatch;
|
|
2832
|
+
}
|
|
2833
|
+
};
|
|
2834
|
+
});
|
|
2835
|
+
//#endregion
|
|
2836
|
+
//#region ../../node_modules/.pnpm/unstorage@1.17.5/node_modules/unstorage/drivers/memory.mjs
|
|
2837
|
+
const DRIVER_NAME$1 = "memory";
|
|
2838
|
+
var memory_default = defineDriver(() => {
|
|
2839
|
+
const data = new Map();
|
|
2840
|
+
return {
|
|
2841
|
+
name: DRIVER_NAME$1,
|
|
2842
|
+
getInstance: () => data,
|
|
2843
|
+
hasItem(key) {
|
|
2844
|
+
return data.has(key);
|
|
2845
|
+
},
|
|
2846
|
+
getItem(key) {
|
|
2847
|
+
return data.get(key) ?? null;
|
|
2848
|
+
},
|
|
2849
|
+
getItemRaw(key) {
|
|
2850
|
+
return data.get(key) ?? null;
|
|
2851
|
+
},
|
|
2852
|
+
setItem(key, value) {
|
|
2853
|
+
data.set(key, value);
|
|
2854
|
+
},
|
|
2855
|
+
setItemRaw(key, value) {
|
|
2856
|
+
data.set(key, value);
|
|
2857
|
+
},
|
|
2858
|
+
removeItem(key) {
|
|
2859
|
+
data.delete(key);
|
|
2860
|
+
},
|
|
2861
|
+
getKeys() {
|
|
2862
|
+
return [...data.keys()];
|
|
2863
|
+
},
|
|
2864
|
+
clear() {
|
|
2865
|
+
data.clear();
|
|
2866
|
+
},
|
|
2867
|
+
dispose() {
|
|
2868
|
+
data.clear();
|
|
2869
|
+
}
|
|
2870
|
+
};
|
|
2871
|
+
});
|
|
2872
|
+
//#endregion
|
|
2873
|
+
//#region ../../node_modules/.pnpm/unstorage@1.17.5/node_modules/unstorage/drivers/session-storage.mjs
|
|
2874
|
+
const DRIVER_NAME = "session-storage";
|
|
2875
|
+
var session_storage_default = defineDriver((opts = {}) => {
|
|
2876
|
+
return {
|
|
2877
|
+
...localstorage_default({
|
|
2878
|
+
windowKey: "sessionStorage",
|
|
2879
|
+
...opts
|
|
2880
|
+
}),
|
|
2881
|
+
name: DRIVER_NAME
|
|
2882
|
+
};
|
|
2883
|
+
});
|
|
2884
|
+
//#endregion
|
|
2885
|
+
//#region src/persistence.ts
|
|
2886
|
+
const KEY = "finueva-auth:session:v1";
|
|
2887
|
+
const MAX_SNAPSHOT_BYTES = 16 * 1024;
|
|
2888
|
+
const MAX_FUTURE_SKEW_MS = 300 * 1e3;
|
|
2889
|
+
function createSessionPersistence(persistence, authOrigin, now, timeoutMs) {
|
|
2890
|
+
const storage = createStorage({ driver: guardRawValues(selectDriver(persistence)) });
|
|
2891
|
+
let enabled = true;
|
|
2892
|
+
let generation = 0;
|
|
2893
|
+
let queue = Promise.resolve();
|
|
2894
|
+
const operationTimeoutMs = Math.min(timeoutMs, 1e3);
|
|
2895
|
+
function cleanup() {
|
|
2896
|
+
return Promise.resolve().then(() => storage.removeItem(KEY));
|
|
2897
|
+
}
|
|
2898
|
+
async function finishesWithin(work) {
|
|
2899
|
+
let timeout;
|
|
2900
|
+
try {
|
|
2901
|
+
await Promise.race([work, new Promise((_, reject) => {
|
|
2902
|
+
timeout = setTimeout(() => reject(new Error("persistence timeout")), operationTimeoutMs);
|
|
2903
|
+
})]);
|
|
2904
|
+
return true;
|
|
2905
|
+
} catch {
|
|
2906
|
+
return false;
|
|
2907
|
+
} finally {
|
|
2908
|
+
if (timeout) clearTimeout(timeout);
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
function schedule(operation) {
|
|
2912
|
+
const operationGeneration = ++generation;
|
|
2913
|
+
queue = queue.then(async () => {
|
|
2914
|
+
if (!enabled || operationGeneration !== generation) return;
|
|
2915
|
+
const isCurrent = () => enabled && operationGeneration === generation;
|
|
2916
|
+
const work = Promise.resolve().then(() => operation(isCurrent));
|
|
2917
|
+
if (!await finishesWithin(work)) {
|
|
2918
|
+
enabled = false;
|
|
2919
|
+
finishesWithin(cleanup());
|
|
2920
|
+
work.then(cleanup, cleanup).then(() => void 0, () => void 0);
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2923
|
+
if (!isCurrent() && !await finishesWithin(cleanup())) enabled = false;
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
return {
|
|
2927
|
+
hydrate(accept) {
|
|
2928
|
+
schedule(async (isCurrent) => {
|
|
2929
|
+
const value = await storage.getItem(KEY);
|
|
2930
|
+
if (!isCurrent()) return;
|
|
2931
|
+
if (value === null) return;
|
|
2932
|
+
const session = readSnapshot(value, authOrigin, now());
|
|
2933
|
+
if (!session) {
|
|
2934
|
+
await storage.removeItem(KEY);
|
|
2935
|
+
return;
|
|
2936
|
+
}
|
|
2937
|
+
if (isCurrent()) accept(session);
|
|
2938
|
+
});
|
|
2939
|
+
},
|
|
2940
|
+
persist(session) {
|
|
2941
|
+
const expiresAt = session.expiresAt.getTime();
|
|
2942
|
+
const normalizedSession = {
|
|
2943
|
+
id: session.id,
|
|
2944
|
+
expiresAt: session.expiresAt.toISOString(),
|
|
2945
|
+
user: {
|
|
2946
|
+
id: session.user.id,
|
|
2947
|
+
name: session.user.name,
|
|
2948
|
+
email: session.user.email,
|
|
2949
|
+
emailVerified: session.user.emailVerified,
|
|
2950
|
+
image: session.user.image
|
|
2951
|
+
}
|
|
2952
|
+
};
|
|
2953
|
+
schedule(async () => {
|
|
2954
|
+
const cachedAt = now();
|
|
2955
|
+
if (expiresAt <= cachedAt) {
|
|
2956
|
+
await storage.removeItem(KEY);
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
const snapshot = {
|
|
2960
|
+
version: 1,
|
|
2961
|
+
authority: authOrigin,
|
|
2962
|
+
cachedAt,
|
|
2963
|
+
session: normalizedSession
|
|
2964
|
+
};
|
|
2965
|
+
if (byteLength(JSON.stringify(snapshot)) > MAX_SNAPSHOT_BYTES) {
|
|
2966
|
+
await storage.removeItem(KEY);
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
await storage.setItem(KEY, snapshot);
|
|
2970
|
+
if (expiresAt <= now()) await storage.removeItem(KEY);
|
|
2971
|
+
});
|
|
2972
|
+
},
|
|
2973
|
+
remove() {
|
|
2974
|
+
schedule(() => storage.removeItem(KEY));
|
|
2975
|
+
}
|
|
2976
|
+
};
|
|
2977
|
+
}
|
|
2978
|
+
function selectDriver(persistence) {
|
|
2979
|
+
if (typeof persistence === "object" && persistence !== null) return adaptDriver(persistence);
|
|
2980
|
+
if (persistence === "memory") return memory_default();
|
|
2981
|
+
if (persistence === "local" || persistence === "session") {
|
|
2982
|
+
const storage = browserStorage(persistence);
|
|
2983
|
+
return storage ? persistence === "local" ? localstorage_default({ storage }) : session_storage_default({ storage }) : memory_default();
|
|
2984
|
+
}
|
|
2985
|
+
if (persistence !== void 0) throw new TypeError("persistence must be local, session, memory, or a driver");
|
|
2986
|
+
const storage = browserStorage("local");
|
|
2987
|
+
return storage ? localstorage_default({ storage }) : memory_default();
|
|
2988
|
+
}
|
|
2989
|
+
function browserStorage(mode) {
|
|
2990
|
+
try {
|
|
2991
|
+
if (typeof window === "undefined" || typeof document === "undefined") return void 0;
|
|
2992
|
+
const storage = mode === "local" ? window.localStorage : window.sessionStorage;
|
|
2993
|
+
storage.getItem(KEY);
|
|
2994
|
+
return storage;
|
|
2995
|
+
} catch {
|
|
2996
|
+
return;
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
function adaptDriver(driver) {
|
|
3000
|
+
if (typeof driver.getItem !== "function" || typeof driver.setItem !== "function" || typeof driver.removeItem !== "function") throw new TypeError("persistence driver must implement getItem, setItem, and removeItem");
|
|
3001
|
+
return {
|
|
3002
|
+
name: "finueva-auth-custom",
|
|
3003
|
+
hasItem: async (key) => await driver.getItem(key) !== null,
|
|
3004
|
+
getItem: (key) => driver.getItem(key),
|
|
3005
|
+
getKeys: () => [],
|
|
3006
|
+
setItem: (key, value) => driver.setItem(key, value),
|
|
3007
|
+
removeItem: (key) => driver.removeItem(key)
|
|
3008
|
+
};
|
|
3009
|
+
}
|
|
3010
|
+
function guardRawValues(driver) {
|
|
3011
|
+
return {
|
|
3012
|
+
...driver,
|
|
3013
|
+
async getItem(key) {
|
|
3014
|
+
const value = await driver.getItem(key);
|
|
3015
|
+
if (value !== null && typeof value !== "string") throw new Error("invalid persistence value");
|
|
3016
|
+
if (typeof value === "string" && byteLength(value) > MAX_SNAPSHOT_BYTES) throw new Error("oversized persistence value");
|
|
3017
|
+
if (typeof value === "string") JSON.parse(value, (field, nestedValue) => {
|
|
3018
|
+
if (field === "__proto__") throw new Error("invalid persistence field");
|
|
3019
|
+
return nestedValue;
|
|
3020
|
+
});
|
|
3021
|
+
return value;
|
|
3022
|
+
}
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
3025
|
+
function readSnapshot(value, authOrigin, currentTime) {
|
|
3026
|
+
if (!exactObject(value, [
|
|
3027
|
+
"authority",
|
|
3028
|
+
"cachedAt",
|
|
3029
|
+
"session",
|
|
3030
|
+
"version"
|
|
3031
|
+
])) return null;
|
|
3032
|
+
if (value.version !== 1 || value.authority !== authOrigin || !Number.isSafeInteger(value.cachedAt)) return null;
|
|
3033
|
+
if (!exactObject(value.session, [
|
|
3034
|
+
"expiresAt",
|
|
3035
|
+
"id",
|
|
3036
|
+
"user"
|
|
3037
|
+
])) return null;
|
|
3038
|
+
if (!exactObject(value.session.user, [
|
|
3039
|
+
"email",
|
|
3040
|
+
"emailVerified",
|
|
3041
|
+
"id",
|
|
3042
|
+
"image",
|
|
3043
|
+
"name"
|
|
3044
|
+
])) return null;
|
|
3045
|
+
const expiresAt = typeof value.session.expiresAt === "string" ? Date.parse(value.session.expiresAt) : NaN;
|
|
3046
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= currentTime || value.cachedAt > currentTime + MAX_FUTURE_SKEW_MS || value.cachedAt > expiresAt) return null;
|
|
3047
|
+
try {
|
|
3048
|
+
return normalizeSession({
|
|
3049
|
+
session: {
|
|
3050
|
+
id: value.session.id,
|
|
3051
|
+
expiresAt: value.session.expiresAt
|
|
3052
|
+
},
|
|
3053
|
+
user: value.session.user
|
|
3054
|
+
});
|
|
3055
|
+
} catch {
|
|
3056
|
+
return null;
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
function exactObject(value, fields) {
|
|
3060
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
3061
|
+
const keys = Object.keys(value);
|
|
3062
|
+
return keys.length === fields.length && fields.every((field) => keys.includes(field));
|
|
3063
|
+
}
|
|
3064
|
+
function byteLength(value) {
|
|
3065
|
+
return new TextEncoder().encode(value).byteLength;
|
|
3066
|
+
}
|
|
3067
|
+
//#endregion
|
|
2325
3068
|
//#region src/client.ts
|
|
2326
3069
|
const REFRESH_WINDOW_MS = 120 * 1e3;
|
|
2327
3070
|
function createAuthClient(options) {
|
|
@@ -2341,63 +3084,263 @@ function createAuthClient(options) {
|
|
|
2341
3084
|
timeout: timeoutMs
|
|
2342
3085
|
}
|
|
2343
3086
|
});
|
|
3087
|
+
const persistence = createSessionPersistence(options.persistence, authOrigin, now, timeoutMs);
|
|
3088
|
+
const authStateListeners = new Set();
|
|
3089
|
+
let authState = { status: "loading" };
|
|
3090
|
+
let authStateStarted = false;
|
|
2344
3091
|
let credential;
|
|
2345
|
-
|
|
3092
|
+
const credentialRequests = new Map();
|
|
3093
|
+
let selectedWorkspaceKey;
|
|
2346
3094
|
let credentialGeneration = 0;
|
|
3095
|
+
let authorityGeneration = 0;
|
|
3096
|
+
let locallySignedOut = false;
|
|
3097
|
+
let activeSignInGeneration;
|
|
3098
|
+
let invitationAbort;
|
|
3099
|
+
let invitationRequest;
|
|
3100
|
+
let signOutRequest;
|
|
2347
3101
|
let sessionId;
|
|
3102
|
+
function setAuthState(state) {
|
|
3103
|
+
authState = state;
|
|
3104
|
+
for (const listener of authStateListeners) listener(state);
|
|
3105
|
+
}
|
|
3106
|
+
function unavailable() {
|
|
3107
|
+
setAuthState({
|
|
3108
|
+
status: "unavailable",
|
|
3109
|
+
session: "session" in authState ? authState.session : null,
|
|
3110
|
+
authoritative: false
|
|
3111
|
+
});
|
|
3112
|
+
}
|
|
3113
|
+
function acceptAuthoritySession(session, generation = authorityGeneration) {
|
|
3114
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3115
|
+
const normalized = updateSession(session);
|
|
3116
|
+
if (normalized) {
|
|
3117
|
+
persistence.persist(normalized);
|
|
3118
|
+
setAuthState({
|
|
3119
|
+
status: "authenticated",
|
|
3120
|
+
session: normalized,
|
|
3121
|
+
authoritative: true
|
|
3122
|
+
});
|
|
3123
|
+
} else {
|
|
3124
|
+
setAuthState({
|
|
3125
|
+
status: "unauthenticated",
|
|
3126
|
+
session: null,
|
|
3127
|
+
authoritative: true
|
|
3128
|
+
});
|
|
3129
|
+
persistence.remove();
|
|
3130
|
+
}
|
|
3131
|
+
return normalized;
|
|
3132
|
+
}
|
|
3133
|
+
function startAuthState() {
|
|
3134
|
+
if (authStateStarted) return;
|
|
3135
|
+
authStateStarted = true;
|
|
3136
|
+
betterAuth.useSession.subscribe((state) => {
|
|
3137
|
+
if (state.isPending) return;
|
|
3138
|
+
if (state.error) {
|
|
3139
|
+
unavailable();
|
|
3140
|
+
return;
|
|
3141
|
+
}
|
|
3142
|
+
try {
|
|
3143
|
+
const session = normalizeSession(state.data);
|
|
3144
|
+
if (session && (locallySignedOut || signOutRequest)) return;
|
|
3145
|
+
acceptAuthoritySession(session);
|
|
3146
|
+
} catch {
|
|
3147
|
+
unavailable();
|
|
3148
|
+
}
|
|
3149
|
+
});
|
|
3150
|
+
persistence.hydrate((session) => {
|
|
3151
|
+
if (authState.status === "loading") setAuthState({
|
|
3152
|
+
status: "cached",
|
|
3153
|
+
session,
|
|
3154
|
+
authoritative: false
|
|
3155
|
+
});
|
|
3156
|
+
else if (authState.status === "unavailable" && authState.session === null) setAuthState({
|
|
3157
|
+
status: "unavailable",
|
|
3158
|
+
session,
|
|
3159
|
+
authoritative: false
|
|
3160
|
+
});
|
|
3161
|
+
});
|
|
3162
|
+
if (typeof window === "undefined" || typeof document === "undefined") getSession().catch(() => void 0);
|
|
3163
|
+
}
|
|
2348
3164
|
function clearCredential() {
|
|
2349
3165
|
credential = void 0;
|
|
2350
|
-
|
|
3166
|
+
credentialRequests.clear();
|
|
3167
|
+
selectedWorkspaceKey = void 0;
|
|
2351
3168
|
credentialGeneration += 1;
|
|
2352
3169
|
}
|
|
2353
3170
|
function updateSession(session) {
|
|
2354
|
-
|
|
3171
|
+
const unboundCredential = !sessionId && (credential || credentialRequests.size > 0);
|
|
3172
|
+
if (!session || unboundCredential || sessionId && session.id !== sessionId) clearCredential();
|
|
2355
3173
|
sessionId = session?.id;
|
|
2356
3174
|
return session;
|
|
2357
3175
|
}
|
|
2358
3176
|
async function getSession() {
|
|
3177
|
+
if (signOutRequest) throw new AuthError("state_conflict", 409);
|
|
3178
|
+
locallySignedOut = false;
|
|
3179
|
+
const generation = authorityGeneration;
|
|
2359
3180
|
let result;
|
|
2360
3181
|
try {
|
|
2361
3182
|
result = await betterAuth.getSession();
|
|
2362
3183
|
} catch {
|
|
3184
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3185
|
+
unavailable();
|
|
3186
|
+
throw authorityUnavailable();
|
|
3187
|
+
}
|
|
3188
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3189
|
+
if (result.error) {
|
|
3190
|
+
unavailable();
|
|
3191
|
+
throw fromAuthorityError(result.error, result.error.status);
|
|
3192
|
+
}
|
|
3193
|
+
try {
|
|
3194
|
+
return acceptAuthoritySession(normalizeSession(result.data), generation);
|
|
3195
|
+
} catch (error) {
|
|
3196
|
+
if (error instanceof AuthError) throw error;
|
|
3197
|
+
unavailable();
|
|
2363
3198
|
throw authorityUnavailable();
|
|
2364
3199
|
}
|
|
2365
|
-
if (result.error) throw fromAuthorityError(result.error, result.error.status);
|
|
2366
|
-
return updateSession(normalizeSession(result.data));
|
|
2367
3200
|
}
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
3201
|
+
function signOut() {
|
|
3202
|
+
if (signOutRequest) return signOutRequest;
|
|
3203
|
+
const pendingInvitation = invitationRequest;
|
|
3204
|
+
invitationAbort?.abort();
|
|
3205
|
+
const generation = ++authorityGeneration;
|
|
3206
|
+
locallySignedOut = true;
|
|
3207
|
+
clearCredential();
|
|
3208
|
+
sessionId = void 0;
|
|
3209
|
+
persistence.remove();
|
|
3210
|
+
const request = (async () => {
|
|
3211
|
+
await pendingInvitation?.catch(() => void 0);
|
|
2372
3212
|
let result;
|
|
2373
3213
|
try {
|
|
2374
|
-
result = await betterAuth.
|
|
2375
|
-
email: input.email,
|
|
2376
|
-
password: input.password
|
|
2377
|
-
});
|
|
3214
|
+
result = await betterAuth.signOut();
|
|
2378
3215
|
} catch {
|
|
3216
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3217
|
+
locallySignedOut = false;
|
|
3218
|
+
unavailable();
|
|
2379
3219
|
throw authorityUnavailable();
|
|
2380
3220
|
}
|
|
2381
|
-
if (
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
3221
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3222
|
+
if (result.error) {
|
|
3223
|
+
locallySignedOut = false;
|
|
3224
|
+
unavailable();
|
|
3225
|
+
throw fromAuthorityError(result.error, result.error.status);
|
|
3226
|
+
}
|
|
3227
|
+
setAuthState({
|
|
3228
|
+
status: "unauthenticated",
|
|
3229
|
+
session: null,
|
|
3230
|
+
authoritative: true
|
|
3231
|
+
});
|
|
3232
|
+
})().finally(() => {
|
|
3233
|
+
if (signOutRequest === request) signOutRequest = void 0;
|
|
3234
|
+
});
|
|
3235
|
+
signOutRequest = request;
|
|
3236
|
+
return request;
|
|
3237
|
+
}
|
|
3238
|
+
return {
|
|
3239
|
+
acceptInvitation(input) {
|
|
3240
|
+
let invitation;
|
|
3241
|
+
try {
|
|
3242
|
+
invitation = normalizeInvitationInput(input);
|
|
3243
|
+
} catch (error) {
|
|
3244
|
+
return Promise.reject(error);
|
|
3245
|
+
}
|
|
3246
|
+
if (signOutRequest || activeSignInGeneration !== void 0 || invitationRequest) return Promise.reject(new AuthError("state_conflict", 409));
|
|
3247
|
+
const generation = authorityGeneration;
|
|
3248
|
+
const controller = new AbortController();
|
|
2387
3249
|
clearCredential();
|
|
2388
|
-
|
|
2389
|
-
|
|
3250
|
+
const request = (async () => {
|
|
3251
|
+
try {
|
|
3252
|
+
const value = await requestJson(joinURL(authOrigin, "api/v1/auth/organization/accept-invitation"), {
|
|
3253
|
+
fetch: fetchImpl,
|
|
3254
|
+
timeoutMs,
|
|
3255
|
+
method: "POST",
|
|
3256
|
+
headers: { "content-type": "application/json; charset=utf-8" },
|
|
3257
|
+
body: invitation,
|
|
3258
|
+
mapError: fromInvitationAuthorityError,
|
|
3259
|
+
signal: controller.signal
|
|
3260
|
+
});
|
|
3261
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3262
|
+
return normalizeInvitationAcceptance(value, invitation.invitationId);
|
|
3263
|
+
} catch (error) {
|
|
3264
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3265
|
+
throw fromInvitationError(error);
|
|
3266
|
+
}
|
|
3267
|
+
})().finally(() => {
|
|
3268
|
+
if (invitationRequest === request) {
|
|
3269
|
+
invitationAbort = void 0;
|
|
3270
|
+
invitationRequest = void 0;
|
|
3271
|
+
}
|
|
3272
|
+
});
|
|
3273
|
+
invitationAbort = controller;
|
|
3274
|
+
invitationRequest = request;
|
|
3275
|
+
return request;
|
|
3276
|
+
},
|
|
3277
|
+
getSession,
|
|
3278
|
+
async listOrganizations() {
|
|
3279
|
+
if (signOutRequest || activeSignInGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
|
|
3280
|
+
const generation = authorityGeneration;
|
|
2390
3281
|
try {
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
3282
|
+
const value = await requestJson(joinURL(authOrigin, "api/v1/auth/organization/list"), {
|
|
3283
|
+
fetch: fetchImpl,
|
|
3284
|
+
timeoutMs,
|
|
3285
|
+
method: "GET"
|
|
3286
|
+
});
|
|
3287
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3288
|
+
return normalizeOrganizations(value);
|
|
3289
|
+
} catch (error) {
|
|
3290
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3291
|
+
throw fromOrganizationListError(error);
|
|
2394
3292
|
}
|
|
2395
|
-
if (result.error) throw fromAuthorityError(result.error, result.error.status);
|
|
2396
3293
|
},
|
|
3294
|
+
async signIn(input) {
|
|
3295
|
+
if (signOutRequest) throw new AuthError("state_conflict", 409);
|
|
3296
|
+
const pendingInvitation = invitationRequest;
|
|
3297
|
+
invitationAbort?.abort();
|
|
3298
|
+
const generation = ++authorityGeneration;
|
|
3299
|
+
activeSignInGeneration = generation;
|
|
3300
|
+
try {
|
|
3301
|
+
await pendingInvitation?.catch(() => void 0);
|
|
3302
|
+
locallySignedOut = false;
|
|
3303
|
+
clearCredential();
|
|
3304
|
+
let result;
|
|
3305
|
+
try {
|
|
3306
|
+
result = await betterAuth.signIn.email({
|
|
3307
|
+
email: input.email,
|
|
3308
|
+
password: input.password
|
|
3309
|
+
});
|
|
3310
|
+
} catch {
|
|
3311
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3312
|
+
unavailable();
|
|
3313
|
+
throw authorityUnavailable();
|
|
3314
|
+
}
|
|
3315
|
+
if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
|
|
3316
|
+
if (result.error) {
|
|
3317
|
+
unavailable();
|
|
3318
|
+
throw fromAuthorityError(result.error, result.error.status);
|
|
3319
|
+
}
|
|
3320
|
+
const session = await getSession();
|
|
3321
|
+
if (!session) throw new AuthError("authentication_required", 401);
|
|
3322
|
+
return session;
|
|
3323
|
+
} finally {
|
|
3324
|
+
if (activeSignInGeneration === generation) activeSignInGeneration = void 0;
|
|
3325
|
+
}
|
|
3326
|
+
},
|
|
3327
|
+
signOut,
|
|
2397
3328
|
getDriveCredential(input) {
|
|
2398
|
-
|
|
2399
|
-
|
|
3329
|
+
let workspace;
|
|
3330
|
+
try {
|
|
3331
|
+
workspace = normalizeWorkspaceSelection(input?.workspace);
|
|
3332
|
+
} catch (error) {
|
|
3333
|
+
return Promise.reject(error);
|
|
3334
|
+
}
|
|
3335
|
+
if (invitationRequest) return Promise.reject(new AuthError("state_conflict", 409));
|
|
3336
|
+
const workspaceKey = workspace.type === "personal" ? "personal" : `organization:${workspace.organizationId}`;
|
|
3337
|
+
if (selectedWorkspaceKey !== workspaceKey) {
|
|
3338
|
+
credential = void 0;
|
|
3339
|
+
selectedWorkspaceKey = workspaceKey;
|
|
3340
|
+
}
|
|
3341
|
+
if (!input.forceRefresh && credential?.key === workspaceKey && credential.value.expiresAt.getTime() - now() > REFRESH_WINDOW_MS) return Promise.resolve(credential.value);
|
|
2400
3342
|
if (input.forceRefresh) credential = void 0;
|
|
3343
|
+
let credentialRequest = credentialRequests.get(workspaceKey);
|
|
2401
3344
|
if (!credentialRequest) {
|
|
2402
3345
|
const generation = credentialGeneration;
|
|
2403
3346
|
const request = (async () => {
|
|
@@ -2406,20 +3349,30 @@ function createAuthClient(options) {
|
|
|
2406
3349
|
timeoutMs,
|
|
2407
3350
|
method: "POST",
|
|
2408
3351
|
headers: { "content-type": "application/json; charset=utf-8" },
|
|
2409
|
-
body: { workspace
|
|
3352
|
+
body: { workspace }
|
|
2410
3353
|
}));
|
|
2411
3354
|
if (error) throw error;
|
|
2412
3355
|
const nextCredential = normalizeDriveCredential(result, now());
|
|
2413
3356
|
if (generation !== credentialGeneration) throw new AuthError("authentication_required", 401);
|
|
2414
|
-
credential =
|
|
3357
|
+
if (selectedWorkspaceKey === workspaceKey) credential = {
|
|
3358
|
+
key: workspaceKey,
|
|
3359
|
+
value: nextCredential
|
|
3360
|
+
};
|
|
2415
3361
|
return nextCredential;
|
|
2416
3362
|
})().finally(() => {
|
|
2417
|
-
if (
|
|
3363
|
+
if (credentialRequests.get(workspaceKey) === request) credentialRequests.delete(workspaceKey);
|
|
2418
3364
|
});
|
|
3365
|
+
credentialRequests.set(workspaceKey, request);
|
|
2419
3366
|
credentialRequest = request;
|
|
2420
3367
|
}
|
|
2421
3368
|
return credentialRequest;
|
|
2422
3369
|
},
|
|
3370
|
+
onAuthStateChange(listener) {
|
|
3371
|
+
authStateListeners.add(listener);
|
|
3372
|
+
listener(authState);
|
|
3373
|
+
startAuthState();
|
|
3374
|
+
return () => authStateListeners.delete(listener);
|
|
3375
|
+
},
|
|
2423
3376
|
onSessionChange(listener) {
|
|
2424
3377
|
return betterAuth.useSession.subscribe((state) => {
|
|
2425
3378
|
let session;
|