@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/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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/broadcast-channel.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/equality.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/focus-manager.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/online-manager.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/parser.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/session-refresh.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/utils/url.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/fetch-plugins.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/session-atom.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/config.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/utils/is-atom.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/proxy.mjs
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@0.29.2__vitest@4.1.10/node_modules/better-auth/dist/client/vanilla.mjs
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_@t_bb8aca60aa14bf30011cd038d243a4ee/node_modules/@chiballc/utils/dist/index.mjs
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 readJson(response);
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
- let credentialRequest;
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
- credentialRequest = void 0;
3166
+ credentialRequests.clear();
3167
+ selectedWorkspaceKey = void 0;
2351
3168
  credentialGeneration += 1;
2352
3169
  }
2353
3170
  function updateSession(session) {
2354
- if (!session || !sessionId && (credential || credentialRequest) || sessionId && session.id !== sessionId) clearCredential();
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
- return {
2369
- getSession,
2370
- async signIn(input) {
2371
- clearCredential();
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.signIn.email({
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 (result.error) throw fromAuthorityError(result.error, result.error.status);
2382
- const session = await getSession();
2383
- if (!session) throw new AuthError("authentication_required", 401);
2384
- return session;
2385
- },
2386
- async signOut() {
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
- sessionId = void 0;
2389
- let result;
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
- result = await betterAuth.signOut();
2392
- } catch {
2393
- throw authorityUnavailable();
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
- if (input.workspace.type !== "personal") return Promise.reject(new AuthError("invalid_workspace_selection", 422));
2399
- if (!input.forceRefresh && credential && credential.expiresAt.getTime() - now() > REFRESH_WINDOW_MS) return Promise.resolve(credential);
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: { type: "personal" } }
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 = nextCredential;
3357
+ if (selectedWorkspaceKey === workspaceKey) credential = {
3358
+ key: workspaceKey,
3359
+ value: nextCredential
3360
+ };
2415
3361
  return nextCredential;
2416
3362
  })().finally(() => {
2417
- if (credentialRequest === request) credentialRequest = void 0;
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;