@djangocfg/api 2.1.621 → 2.1.623

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/auth.cjs CHANGED
@@ -240,6 +240,7 @@ __export(auth_exports, {
240
240
  peekSavedRedirect: () => peekSavedRedirect,
241
241
  readAuthTrace: () => readAuthTrace,
242
242
  readOAuthFailure: () => readOAuthFailure,
243
+ resetAuthTraceForTests: () => resetAuthTraceForTests,
243
244
  resolveAuthError: () => resolveAuthError,
244
245
  resolveAuthStatus: () => resolveAuthStatus,
245
246
  resolveGuardIsAuthenticated: () => resolveGuardIsAuthenticated,
@@ -292,7 +293,10 @@ var KEY = "cfg.auth.trace";
292
293
  var MAX = 200;
293
294
  var MAX_STRING = 120;
294
295
  var SENSITIVE = /token|otp|code|email|password|secret|cookie|authorization|key|identifier/i;
295
- var TAB = Math.random().toString(36).slice(2, 6);
296
+ var TAB = (() => {
297
+ const g = globalThis;
298
+ return g.__cfgAuthTab ??= Math.random().toString(36).slice(2, 6);
299
+ })();
296
300
  var hasWindow = typeof window !== "undefined";
297
301
  var memory = [];
298
302
  var loaded = false;
@@ -341,10 +345,30 @@ function clean(fields) {
341
345
  return Object.keys(out).length ? out : void 0;
342
346
  }
343
347
  __name(clean, "clean");
348
+ function refresh() {
349
+ try {
350
+ const raw = backend()?.getItem(KEY);
351
+ const parsed = raw ? JSON.parse(raw) : null;
352
+ if (Array.isArray(parsed)) memory = parsed.filter((e) => typeof e === "object" && e !== null);
353
+ } catch {
354
+ }
355
+ }
356
+ __name(refresh, "refresh");
344
357
  function record(at, ev, fields) {
345
- const entries = load();
358
+ load();
359
+ refresh();
360
+ const entries = memory;
346
361
  const p = hasWindow && typeof performance !== "undefined" ? Math.round(performance.now()) : 0;
347
- entries.push({ t: at, p, tab: TAB, ev, f: clean(fields) });
362
+ const f2 = clean(fields);
363
+ const last = entries[entries.length - 1];
364
+ if (last && last.tab === TAB && last.ev === ev && JSON.stringify(last.f) === JSON.stringify(f2)) {
365
+ last.n = (last.n ?? 1) + 1;
366
+ last.t = at;
367
+ last.p = p;
368
+ persist();
369
+ return;
370
+ }
371
+ entries.push({ t: at, p, tab: TAB, ev, f: f2 });
348
372
  if (entries.length > MAX) entries.splice(0, entries.length - MAX);
349
373
  persist();
350
374
  }
@@ -357,6 +381,11 @@ function authTrace(ev, fields) {
357
381
  }
358
382
  }
359
383
  __name(authTrace, "authTrace");
384
+ function resetAuthTraceForTests() {
385
+ memory = [];
386
+ loaded = true;
387
+ }
388
+ __name(resetAuthTraceForTests, "resetAuthTraceForTests");
360
389
  function readAuthTrace() {
361
390
  return load().slice();
362
391
  }
@@ -372,7 +401,8 @@ function clearAuthTrace() {
372
401
  __name(clearAuthTrace, "clearAuthTrace");
373
402
  function context() {
374
403
  if (!hasWindow) return [];
375
- const lines = [`url: ${window.location.href.split("?")[0]}`, `online: ${navigator.onLine}`, `ua: ${navigator.userAgent}`];
404
+ const copies = globalThis.__cfgAuthCopies ?? 1;
405
+ const lines = [`url: ${window.location.href.split("?")[0]}`, `copies: ${String(copies)}`, `online: ${navigator.onLine}`, `ua: ${navigator.userAgent}`];
376
406
  try {
377
407
  const auth2 = globalThis.__cfgAuthNow;
378
408
  const now = auth2?.();
@@ -388,7 +418,7 @@ function dumpAuthTrace() {
388
418
  const rows = entries.map((e) => {
389
419
  const fields = e.f ? ` ${Object.entries(e.f).map(([k2, v]) => `${k2}=${String(v)}`).join(" ")}` : "";
390
420
  const at = new Date(e.t).toISOString().slice(11, 23);
391
- return `${at} +${String(e.t - first).padStart(6)}ms [${e.tab} p${e.p}] ${e.ev}${fields}`;
421
+ return `${at} +${String(e.t - first).padStart(6)}ms [${e.tab} p${e.p}] ${e.ev}${fields}${e.n && e.n > 1 ? ` x${e.n}` : ""}`;
392
422
  });
393
423
  return [`# cfg auth trace, ${entries.length} events`, ...context(), "", ...rows].join("\n");
394
424
  }
@@ -404,7 +434,21 @@ function installAuthTrace() {
404
434
  console.log(text);
405
435
  return text;
406
436
  }, "dump"),
407
- clear: clearAuthTrace
437
+ clear: clearAuthTrace,
438
+ /** Put the dump on the clipboard (works when the console output is blocked or too long to select). */
439
+ copy: /* @__PURE__ */ __name(() => {
440
+ const text = dumpAuthTrace();
441
+ void navigator.clipboard?.writeText(text);
442
+ return `${text.split("\n").length} lines copied`;
443
+ }, "copy"),
444
+ /** Download the raw trace as a JSON file. */
445
+ download: /* @__PURE__ */ __name(() => {
446
+ const blob = new Blob([JSON.stringify(readAuthTrace(), null, 1)], { type: "application/json" });
447
+ const a = document.createElement("a");
448
+ a.href = URL.createObjectURL(blob);
449
+ a.download = `auth-trace-${Date.now()}.json`;
450
+ a.click();
451
+ }, "download")
408
452
  };
409
453
  const queued = g.__cfgAuthTraceQ;
410
454
  if (Array.isArray(queued)) {
@@ -420,11 +464,25 @@ function installAuthTrace() {
420
464
  }
421
465
  }
422
466
  __name(installAuthTrace, "installAuthTrace");
467
+ function registerCopy() {
468
+ if (!hasWindow) return;
469
+ const g = globalThis;
470
+ const n = (g.__cfgAuthCopies ?? 0) + 1;
471
+ g.__cfgAuthCopies = n;
472
+ if (n > 1) {
473
+ authTrace("dup.copy", { copies: n });
474
+ if (n === 2) {
475
+ console.warn("[@djangocfg/api] more than one copy of the auth package is loaded; see __cfgAuth.dump() (dup.copy). Align the peer set so pnpm installs one instance.");
476
+ }
477
+ }
478
+ }
479
+ __name(registerCopy, "registerCopy");
480
+ registerCopy();
423
481
  installAuthTrace();
424
482
 
425
483
  // src/auth/context/AuthContext.tsx
426
484
  var import_navigation4 = require("next/navigation");
427
- var import_react20 = require("react");
485
+ var import_react21 = require("react");
428
486
 
429
487
  // src/_api/generated/helpers/errors.ts
430
488
  var APIError = class extends Error {
@@ -826,10 +884,10 @@ function adoptLegacySession() {
826
884
  if (_storage.get(ACCESS_KEY) !== null || _storage.get(REFRESH_KEY) !== null) return;
827
885
  const legacy = backendFor("localStorage");
828
886
  const access = legacy.get(ACCESS_KEY);
829
- const refresh = legacy.get(REFRESH_KEY);
830
- if (access === null && refresh === null) return;
887
+ const refresh2 = legacy.get(REFRESH_KEY);
888
+ if (access === null && refresh2 === null) return;
831
889
  if (access !== null) _storage.set(ACCESS_KEY, access);
832
- if (refresh !== null) _storage.set(REFRESH_KEY, refresh);
890
+ if (refresh2 !== null) _storage.set(REFRESH_KEY, refresh2);
833
891
  legacy.set(ACCESS_KEY, null);
834
892
  legacy.set(REFRESH_KEY, null);
835
893
  } catch {
@@ -914,12 +972,12 @@ function jwtExpMs(token) {
914
972
  __name(jwtExpMs, "jwtExpMs");
915
973
  function computeSnapshot() {
916
974
  const access = _storage.get(ACCESS_KEY);
917
- const refresh = _storage.get(REFRESH_KEY);
975
+ const refresh2 = _storage.get(REFRESH_KEY);
918
976
  const now = Date.now();
919
977
  const accessExp = access ? jwtExpMs(access) : null;
920
978
  const accessAlive = access !== null && (accessExp === null || accessExp > now);
921
- const refreshExp = refresh ? jwtExpMs(refresh) : null;
922
- const refreshAlive = refresh !== null && (refreshExp === null || refreshExp > now);
979
+ const refreshExp = refresh2 ? jwtExpMs(refresh2) : null;
980
+ const refreshAlive = refresh2 !== null && (refreshExp === null || refreshExp > now);
923
981
  return {
924
982
  status: accessAlive || refreshAlive ? "authenticated" : "anonymous",
925
983
  accessExpiresAt: accessExp
@@ -942,9 +1000,9 @@ function scheduleExpiryFlip() {
942
1000
  const now = Date.now();
943
1001
  const exps = [];
944
1002
  const access = _storage.get(ACCESS_KEY);
945
- const refresh = _storage.get(REFRESH_KEY);
1003
+ const refresh2 = _storage.get(REFRESH_KEY);
946
1004
  const accessExp = access ? jwtExpMs(access) : null;
947
- const refreshExp = refresh ? jwtExpMs(refresh) : null;
1005
+ const refreshExp = refresh2 ? jwtExpMs(refresh2) : null;
948
1006
  if (accessExp !== null && accessExp > now) exps.push(accessExp);
949
1007
  if (refreshExp !== null && refreshExp > now) exps.push(refreshExp);
950
1008
  if (!exps.length) return;
@@ -1213,9 +1271,9 @@ async function tryRefresh() {
1213
1271
  if (_refreshInflight) return _refreshInflight;
1214
1272
  if (!_refreshHandler) return null;
1215
1273
  const runRefresh = /* @__PURE__ */ __name(async () => {
1216
- const refresh = auth.getRefreshToken();
1217
- if (!refresh) return null;
1218
- const result = await _refreshHandler(refresh);
1274
+ const refresh2 = auth.getRefreshToken();
1275
+ if (!refresh2) return null;
1276
+ const result = await _refreshHandler(refresh2);
1219
1277
  if (!result?.access) {
1220
1278
  trace("refresh", { ok: false, why: "no-access" });
1221
1279
  return null;
@@ -1416,7 +1474,7 @@ function installAuthOnClient(client2) {
1416
1474
  }
1417
1475
  __name(installAuthOnClient, "installAuthOnClient");
1418
1476
  var REFRESH_ENDPOINT = "/cfg/accounts/token/refresh/";
1419
- auth.setRefreshHandler(async (refresh) => {
1477
+ auth.setRefreshHandler(async (refresh2) => {
1420
1478
  try {
1421
1479
  const url = `${auth.getBaseUrl()}${REFRESH_ENDPOINT}`;
1422
1480
  const headers = { "Content-Type": "application/json" };
@@ -1428,11 +1486,11 @@ auth.setRefreshHandler(async (refresh) => {
1428
1486
  method: "POST",
1429
1487
  headers,
1430
1488
  credentials: auth.getWithCredentials() ? "include" : "same-origin",
1431
- body: JSON.stringify({ refresh })
1489
+ body: JSON.stringify({ refresh: refresh2 })
1432
1490
  });
1433
1491
  if (!res.ok) return null;
1434
1492
  const data = await res.json();
1435
- return data?.access ? { access: data.access, refresh: data.refresh ?? refresh } : null;
1493
+ return data?.access ? { access: data.access, refresh: data.refresh ?? refresh2 } : null;
1436
1494
  } catch {
1437
1495
  return null;
1438
1496
  }
@@ -1703,7 +1761,7 @@ function useCfgRouter() {
1703
1761
  const forward = (0, import_react3.useCallback)(() => {
1704
1762
  router.forward();
1705
1763
  }, [router]);
1706
- const refresh = (0, import_react3.useCallback)(() => {
1764
+ const refresh2 = (0, import_react3.useCallback)(() => {
1707
1765
  router.refresh();
1708
1766
  }, [router]);
1709
1767
  return {
@@ -1714,7 +1772,7 @@ function useCfgRouter() {
1714
1772
  prefetch,
1715
1773
  back,
1716
1774
  forward,
1717
- refresh
1775
+ refresh: refresh2
1718
1776
  };
1719
1777
  }
1720
1778
  __name(useCfgRouter, "useCfgRouter");
@@ -4893,7 +4951,7 @@ function resolveAuthStatus(s) {
4893
4951
  __name(resolveAuthStatus, "resolveAuthStatus");
4894
4952
 
4895
4953
  // src/auth/context/AccountsContext.tsx
4896
- var import_react19 = require("react");
4954
+ var import_react20 = require("react");
4897
4955
 
4898
4956
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRegenerateCreate.ts
4899
4957
  var import_mutation = __toESM(require("swr/mutation"), 1);
@@ -5240,6 +5298,15 @@ __name(useCfgAccountsTokenCreate, "useCfgAccountsTokenCreate");
5240
5298
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenRefreshCreate.ts
5241
5299
  var import_mutation19 = __toESM(require("swr/mutation"), 1);
5242
5300
 
5301
+ // src/auth/context/sharedContext.ts
5302
+ var import_react19 = require("react");
5303
+ function sharedContext(key, initial) {
5304
+ const g = globalThis;
5305
+ const registry = g.__cfgAuthContexts ??= {};
5306
+ return registry[key] ??= (0, import_react19.createContext)(initial);
5307
+ }
5308
+ __name(sharedContext, "sharedContext");
5309
+
5243
5310
  // src/auth/context/AccountsContext.tsx
5244
5311
  var import_jsx_runtime = require("react/jsx-runtime");
5245
5312
  function hasApiOrigin() {
@@ -5253,9 +5320,9 @@ function hasApiOrigin() {
5253
5320
  }
5254
5321
  }
5255
5322
  __name(hasApiOrigin, "hasApiOrigin");
5256
- var AccountsContext = (0, import_react19.createContext)(void 0);
5323
+ var AccountsContext = sharedContext("accounts", void 0);
5257
5324
  function AccountsProvider({ children }) {
5258
- const [profile, setProfile] = (0, import_react19.useState)(() => {
5325
+ const [profile, setProfile] = (0, import_react20.useState)(() => {
5259
5326
  if (!auth.isAuthenticated()) {
5260
5327
  clearProfileCache();
5261
5328
  return void 0;
@@ -5263,15 +5330,15 @@ function AccountsProvider({ children }) {
5263
5330
  const cached = getCachedProfile();
5264
5331
  return cached || void 0;
5265
5332
  });
5266
- const [isLoadingProfile, setIsLoadingProfile] = (0, import_react19.useState)(false);
5267
- const [profileError, setProfileError] = (0, import_react19.useState)(null);
5268
- const profileRef = (0, import_react19.useRef)(profile);
5269
- const isLoadingRef = (0, import_react19.useRef)(false);
5270
- const fetchSeqRef = (0, import_react19.useRef)(0);
5271
- (0, import_react19.useEffect)(() => {
5333
+ const [isLoadingProfile, setIsLoadingProfile] = (0, import_react20.useState)(false);
5334
+ const [profileError, setProfileError] = (0, import_react20.useState)(null);
5335
+ const profileRef = (0, import_react20.useRef)(profile);
5336
+ const isLoadingRef = (0, import_react20.useRef)(false);
5337
+ const fetchSeqRef = (0, import_react20.useRef)(0);
5338
+ (0, import_react20.useEffect)(() => {
5272
5339
  profileRef.current = profile;
5273
5340
  }, [profile]);
5274
- (0, import_react19.useEffect)(() => {
5341
+ (0, import_react20.useEffect)(() => {
5275
5342
  isLoadingRef.current = isLoadingProfile;
5276
5343
  }, [isLoadingProfile]);
5277
5344
  const { trigger: triggerProfileUpdate } = useCfgAccountsProfileUpdateUpdate();
@@ -5280,7 +5347,7 @@ function AccountsProvider({ children }) {
5280
5347
  const { trigger: triggerOtpRequest } = useCfgAccountsOtpRequestCreate();
5281
5348
  const { trigger: triggerOtpVerify } = useCfgAccountsOtpVerifyCreate();
5282
5349
  const { trigger: triggerPasswordLogin } = useCfgAccountsTokenCreate();
5283
- const refreshProfile = (0, import_react19.useCallback)(async (options) => {
5350
+ const refreshProfile = (0, import_react20.useCallback)(async (options) => {
5284
5351
  const { callerId, force } = options || {};
5285
5352
  if (!hasApiOrigin()) {
5286
5353
  authLogger.debug(`No API origin configured, skipping profile fetch (caller: ${callerId})`);
@@ -5314,26 +5381,26 @@ function AccountsProvider({ children }) {
5314
5381
  }
5315
5382
  }
5316
5383
  }, []);
5317
- const updateProfile = (0, import_react19.useCallback)(async (data) => {
5384
+ const updateProfile = (0, import_react20.useCallback)(async (data) => {
5318
5385
  await triggerProfileUpdate({ body: data });
5319
5386
  const user = await refreshProfile({ callerId: "updateProfile", force: true });
5320
5387
  return user;
5321
5388
  }, [triggerProfileUpdate, refreshProfile]);
5322
- const partialUpdateProfile = (0, import_react19.useCallback)(async (data) => {
5389
+ const partialUpdateProfile = (0, import_react20.useCallback)(async (data) => {
5323
5390
  await triggerProfilePartialUpdate({ body: data });
5324
5391
  const user = await refreshProfile({ callerId: "partialUpdateProfile", force: true });
5325
5392
  return user;
5326
5393
  }, [triggerProfilePartialUpdate, refreshProfile]);
5327
- const uploadAvatar = (0, import_react19.useCallback)(async (avatar) => {
5394
+ const uploadAvatar = (0, import_react20.useCallback)(async (avatar) => {
5328
5395
  await triggerAvatar({ body: { avatar } });
5329
5396
  const user = await refreshProfile({ callerId: "uploadAvatar", force: true });
5330
5397
  return user;
5331
5398
  }, [triggerAvatar, refreshProfile]);
5332
- const requestOTP = (0, import_react19.useCallback)(async (data) => {
5399
+ const requestOTP = (0, import_react20.useCallback)(async (data) => {
5333
5400
  const result = await triggerOtpRequest({ body: data });
5334
5401
  return result;
5335
5402
  }, [triggerOtpRequest]);
5336
- const settleLoginEnvelope = (0, import_react19.useCallback)(async (result, callerId) => {
5403
+ const settleLoginEnvelope = (0, import_react20.useCallback)(async (result, callerId) => {
5337
5404
  if (result.requires_2fa && result.session_id) {
5338
5405
  authLogger.info("2FA required, session:", result.session_id);
5339
5406
  return;
@@ -5348,20 +5415,20 @@ function AccountsProvider({ children }) {
5348
5415
  }
5349
5416
  }
5350
5417
  }, [refreshProfile]);
5351
- const verifyOTP = (0, import_react19.useCallback)(async (data) => {
5418
+ const verifyOTP = (0, import_react20.useCallback)(async (data) => {
5352
5419
  const result = await triggerOtpVerify({ body: data });
5353
5420
  await settleLoginEnvelope(result, "verifyOTP");
5354
5421
  return result;
5355
5422
  }, [triggerOtpVerify, settleLoginEnvelope]);
5356
- const loginWithPassword = (0, import_react19.useCallback)(async (data) => {
5423
+ const loginWithPassword = (0, import_react20.useCallback)(async (data) => {
5357
5424
  const result = await triggerPasswordLogin({ body: data });
5358
5425
  await settleLoginEnvelope(result, "loginWithPassword");
5359
5426
  return result;
5360
5427
  }, [triggerPasswordLogin, settleLoginEnvelope]);
5361
- const logout = (0, import_react19.useCallback)(() => {
5362
- const refresh = auth.getRefreshToken();
5363
- if (refresh) {
5364
- CfgAccountsAuth.cfgAccountsTokenBlacklistCreate({ body: { refresh } }).catch(() => {
5428
+ const logout = (0, import_react20.useCallback)(() => {
5429
+ const refresh2 = auth.getRefreshToken();
5430
+ if (refresh2) {
5431
+ CfgAccountsAuth.cfgAccountsTokenBlacklistCreate({ body: { refresh: refresh2 } }).catch(() => {
5365
5432
  authLogger.warn("Refresh-token blacklist failed (logged out locally anyway)");
5366
5433
  });
5367
5434
  }
@@ -5371,7 +5438,7 @@ function AccountsProvider({ children }) {
5371
5438
  setProfileError(null);
5372
5439
  clearProfileCache();
5373
5440
  }, []);
5374
- const value = (0, import_react19.useMemo)(() => ({
5441
+ const value = (0, import_react20.useMemo)(() => ({
5375
5442
  profile,
5376
5443
  isLoadingProfile,
5377
5444
  profileError,
@@ -5400,7 +5467,7 @@ function AccountsProvider({ children }) {
5400
5467
  }
5401
5468
  __name(AccountsProvider, "AccountsProvider");
5402
5469
  function useAccountsContext() {
5403
- const context2 = (0, import_react19.useContext)(AccountsContext);
5470
+ const context2 = (0, import_react20.useContext)(AccountsContext);
5404
5471
  if (!context2) {
5405
5472
  throw new Error("useAccountsContext must be used within AccountsProvider");
5406
5473
  }
@@ -5421,7 +5488,7 @@ var resolveAuthRoutes = /* @__PURE__ */ __name((routes) => ({
5421
5488
  defaultAuthCallback: routes?.defaultAuthCallback || routes?.auth || defaultRoutes.defaultAuthCallback
5422
5489
  }), "resolveAuthRoutes");
5423
5490
  var EMAIL_STORAGE_KEY = CFG_KEYS.email.key;
5424
- var AuthContext = (0, import_react20.createContext)(void 0);
5491
+ var AuthContext = sharedContext("auth", void 0);
5425
5492
  var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5426
5493
  const accounts = useAccountsContext();
5427
5494
  const session = useSession();
@@ -5433,28 +5500,28 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5433
5500
  EMAIL_STORAGE_KEY,
5434
5501
  null
5435
5502
  );
5436
- const routes = (0, import_react20.useMemo)(() => resolveAuthRoutes(config?.routes), [config?.routes]);
5437
- const routesRef = (0, import_react20.useRef)(routes);
5438
- (0, import_react20.useEffect)(() => {
5503
+ const routes = (0, import_react21.useMemo)(() => resolveAuthRoutes(config?.routes), [config?.routes]);
5504
+ const routesRef = (0, import_react21.useRef)(routes);
5505
+ (0, import_react21.useEffect)(() => {
5439
5506
  routesRef.current = routes;
5440
5507
  }, [routes]);
5441
5508
  const redirectManager = useAuthRedirectManager({
5442
5509
  fallbackUrl: routes.defaultCallback,
5443
5510
  clearOnUse: true
5444
5511
  });
5445
- const configRef = (0, import_react20.useRef)(config);
5446
- (0, import_react20.useEffect)(() => {
5512
+ const configRef = (0, import_react21.useRef)(config);
5513
+ (0, import_react21.useEffect)(() => {
5447
5514
  configRef.current = config;
5448
5515
  }, [config]);
5449
- const accountsRef = (0, import_react20.useRef)(accounts);
5450
- (0, import_react20.useEffect)(() => {
5516
+ const accountsRef = (0, import_react21.useRef)(accounts);
5517
+ (0, import_react21.useEffect)(() => {
5451
5518
  accountsRef.current = accounts;
5452
5519
  }, [accounts]);
5453
- const pendingManualNavRef = (0, import_react20.useRef)(false);
5454
- const [profileSettled, setProfileSettled] = (0, import_react20.useState)(false);
5520
+ const pendingManualNavRef = (0, import_react21.useRef)(false);
5521
+ const [profileSettled, setProfileSettled] = (0, import_react21.useState)(false);
5455
5522
  const hasProfile = Boolean(accounts.profile);
5456
- const profileAttemptedRef = (0, import_react20.useRef)(false);
5457
- (0, import_react20.useEffect)(() => {
5523
+ const profileAttemptedRef = (0, import_react21.useRef)(false);
5524
+ (0, import_react21.useEffect)(() => {
5458
5525
  if (!isAuthenticated) {
5459
5526
  profileAttemptedRef.current = false;
5460
5527
  const hasTokens = Boolean(auth.getToken() || auth.getRefreshToken());
@@ -5492,9 +5559,9 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5492
5559
  };
5493
5560
  }, [isAuthenticated, hasProfile]);
5494
5561
  const isLoading = !profileSettled;
5495
- const [clientReady, setClientReady] = (0, import_react20.useState)(false);
5496
- const [timedOut, setTimedOut] = (0, import_react20.useState)(false);
5497
- (0, import_react20.useEffect)(() => {
5562
+ const [clientReady, setClientReady] = (0, import_react21.useState)(false);
5563
+ const [timedOut, setTimedOut] = (0, import_react21.useState)(false);
5564
+ (0, import_react21.useEffect)(() => {
5498
5565
  setClientReady(true);
5499
5566
  const timer = setTimeout(() => setTimedOut(true), 8e3);
5500
5567
  return () => clearTimeout(timer);
@@ -5506,8 +5573,8 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5506
5573
  profileSettled,
5507
5574
  timedOut
5508
5575
  });
5509
- const lastStatusRef = (0, import_react20.useRef)("");
5510
- (0, import_react20.useEffect)(() => {
5576
+ const lastStatusRef = (0, import_react21.useRef)("");
5577
+ (0, import_react21.useEffect)(() => {
5511
5578
  if (lastStatusRef.current === status) return;
5512
5579
  lastStatusRef.current = status;
5513
5580
  authTrace("status", {
@@ -5519,7 +5586,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5519
5586
  path: pathname ?? ""
5520
5587
  });
5521
5588
  }, [status, isAuthenticated, profileSettled, timedOut, pathname]);
5522
- (0, import_react20.useEffect)(() => {
5589
+ (0, import_react21.useEffect)(() => {
5523
5590
  globalThis.__cfgAuthNow = () => ({
5524
5591
  status,
5525
5592
  snapshot: isAuthenticated,
@@ -5530,7 +5597,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5530
5597
  timedOut
5531
5598
  });
5532
5599
  }, [status, isAuthenticated, profileSettled, timedOut]);
5533
- (0, import_react20.useEffect)(() => {
5600
+ (0, import_react21.useEffect)(() => {
5534
5601
  const unsubscribe = auth.onSessionExpired(() => {
5535
5602
  authTrace("expired.handler", { path: pathname ?? "" });
5536
5603
  authLogger.warn("Session expired (terminal 401) \u2014 redirecting to login");
@@ -5542,7 +5609,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5542
5609
  });
5543
5610
  return unsubscribe;
5544
5611
  }, [router, pathname]);
5545
- (0, import_react20.useEffect)(() => {
5612
+ (0, import_react21.useEffect)(() => {
5546
5613
  if (!isAuthenticated || pendingManualNavRef.current) return;
5547
5614
  if (pathname === routes.auth && !queryParams.get("flow")) {
5548
5615
  const saved = redirectManager.hasRedirect() ? redirectManager.getRedirect() : null;
@@ -5551,7 +5618,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5551
5618
  router.push(saved || routes.defaultCallback);
5552
5619
  }
5553
5620
  }, [isAuthenticated, pathname, queryParams, routes, router, redirectManager]);
5554
- const loadCurrentProfile = (0, import_react20.useCallback)(async (callerId) => {
5621
+ const loadCurrentProfile = (0, import_react21.useCallback)(async (callerId) => {
5555
5622
  if (!auth.isAuthenticated()) {
5556
5623
  throw new Error("No valid authentication token");
5557
5624
  }
@@ -5559,7 +5626,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5559
5626
  callerId: callerId || "AuthContext.loadCurrentProfile"
5560
5627
  });
5561
5628
  }, []);
5562
- const checkAuthAndRedirect = (0, import_react20.useCallback)(async () => {
5629
+ const checkAuthAndRedirect = (0, import_react21.useCallback)(async () => {
5563
5630
  if (auth.isAuthenticated()) {
5564
5631
  try {
5565
5632
  await loadCurrentProfile("checkAuthAndRedirect");
@@ -5571,7 +5638,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5571
5638
  router.push(routesRef.current.defaultAuthCallback);
5572
5639
  }
5573
5640
  }, [loadCurrentProfile, router]);
5574
- const requestOTP = (0, import_react20.useCallback)(
5641
+ const requestOTP = (0, import_react21.useCallback)(
5575
5642
  async (identifier, sourceUrl, consent) => {
5576
5643
  authTrace("otp.request");
5577
5644
  auth.clearSession();
@@ -5614,7 +5681,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5614
5681
  },
5615
5682
  []
5616
5683
  );
5617
- const verifyOTP = (0, import_react20.useCallback)(
5684
+ const verifyOTP = (0, import_react21.useCallback)(
5618
5685
  async (identifier, otpCode, sourceUrl, redirectUrl, skipRedirect) => {
5619
5686
  try {
5620
5687
  pendingManualNavRef.current = Boolean(skipRedirect);
@@ -5675,7 +5742,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5675
5742
  },
5676
5743
  [setStoredEmail, redirectManager, router]
5677
5744
  );
5678
- const login = (0, import_react20.useCallback)(
5745
+ const login = (0, import_react21.useCallback)(
5679
5746
  async (email, password, options) => {
5680
5747
  const { redirectUrl, skipRedirect } = options || {};
5681
5748
  try {
@@ -5741,7 +5808,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5741
5808
  },
5742
5809
  [setStoredEmail, redirectManager, router]
5743
5810
  );
5744
- const refreshToken = (0, import_react20.useCallback)(async () => {
5811
+ const refreshToken = (0, import_react21.useCallback)(async () => {
5745
5812
  const access = await auth.refreshNow();
5746
5813
  if (access) {
5747
5814
  Analytics.event("auth_token_refresh" /* AUTH_TOKEN_REFRESH */, {
@@ -5754,7 +5821,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5754
5821
  });
5755
5822
  return { success: false, message: "Error refreshing token" };
5756
5823
  }, []);
5757
- const logout = (0, import_react20.useCallback)(() => {
5824
+ const logout = (0, import_react21.useCallback)(() => {
5758
5825
  authTrace("logout");
5759
5826
  Analytics.event("auth_logout" /* AUTH_LOGOUT */, {
5760
5827
  category: "auth" /* AUTH */
@@ -5764,21 +5831,21 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
5764
5831
  }, [router]);
5765
5832
  const user = accounts.profile ?? null;
5766
5833
  const isAdminUser = Boolean(user?.is_staff || user?.is_superuser);
5767
- (0, import_react20.useEffect)(() => {
5834
+ (0, import_react21.useEffect)(() => {
5768
5835
  applyRoleLogPolicy({ isAdmin: isAdminUser });
5769
5836
  }, [isAdminUser]);
5770
- const updateProfile = (0, import_react20.useCallback)(
5837
+ const updateProfile = (0, import_react21.useCallback)(
5771
5838
  async (data) => {
5772
5839
  const result = await accountsRef.current.partialUpdateProfile(data);
5773
5840
  return result;
5774
5841
  },
5775
5842
  []
5776
5843
  );
5777
- const uploadAvatar = (0, import_react20.useCallback)(async (avatar) => {
5844
+ const uploadAvatar = (0, import_react21.useCallback)(async (avatar) => {
5778
5845
  const result = await accountsRef.current.uploadAvatar(avatar);
5779
5846
  return result;
5780
5847
  }, []);
5781
- const value = (0, import_react20.useMemo)(
5848
+ const value = (0, import_react21.useMemo)(
5782
5849
  () => ({
5783
5850
  user,
5784
5851
  isLoading,
@@ -5836,7 +5903,7 @@ function AuthProviderRaw({ children, config, enabled = true }) {
5836
5903
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AccountsProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthProviderInternal, { config, children }) });
5837
5904
  }
5838
5905
  __name(AuthProviderRaw, "AuthProviderRaw");
5839
- var AuthProvider = (0, import_react20.memo)(AuthProviderRaw);
5906
+ var AuthProvider = (0, import_react21.memo)(AuthProviderRaw);
5840
5907
  var defaultAuthState = {
5841
5908
  user: null,
5842
5909
  isLoading: false,
@@ -5893,7 +5960,7 @@ var defaultAuthState = {
5893
5960
  }, "uploadAvatar")
5894
5961
  };
5895
5962
  var useAuth = /* @__PURE__ */ __name(() => {
5896
- const context2 = (0, import_react20.useContext)(AuthContext);
5963
+ const context2 = (0, import_react21.useContext)(AuthContext);
5897
5964
  if (context2 === void 0) {
5898
5965
  if (isBrowser2 && isDev) {
5899
5966
  authLogger.debug("useAuth called outside AuthProvider, returning default state");