@djangocfg/api 2.1.86 → 2.1.88

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.mjs CHANGED
@@ -9,11 +9,11 @@ var __export = (target, all) => {
9
9
  import { usePathname } from "next/navigation";
10
10
  import {
11
11
  createContext as createContext2,
12
- useCallback as useCallback2,
12
+ useCallback as useCallback3,
13
13
  useContext as useContext2,
14
- useEffect as useEffect2,
14
+ useEffect as useEffect3,
15
15
  useMemo,
16
- useRef as useRef2,
16
+ useRef as useRef3,
17
17
  useState as useState3
18
18
  } from "react";
19
19
  import { useCfgRouter, useLocalStorage, useQueryParams } from "@djangocfg/ui-nextjs/hooks";
@@ -3618,7 +3618,7 @@ __name(useBase64, "useBase64");
3618
3618
  // src/auth/hooks/useProfileCache.ts
3619
3619
  var CACHE_KEY = "user_profile_cache";
3620
3620
  var CACHE_VERSION = 1;
3621
- var DEFAULT_TTL = 36e5;
3621
+ var DEFAULT_TTL = 144e5;
3622
3622
  function getCachedProfile() {
3623
3623
  try {
3624
3624
  if (typeof window === "undefined") return null;
@@ -3904,6 +3904,106 @@ var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
3904
3904
  };
3905
3905
  }, "useAuthRedirectManager");
3906
3906
 
3907
+ // src/auth/hooks/useTokenRefresh.ts
3908
+ import { useCallback, useEffect, useRef } from "react";
3909
+ var TOKEN_REFRESH_THRESHOLD_MS = 10 * 60 * 1e3;
3910
+ var CHECK_INTERVAL_MS = 5 * 60 * 1e3;
3911
+ function getTokenExpiry(token) {
3912
+ try {
3913
+ const payload = JSON.parse(atob(token.split(".")[1]));
3914
+ return payload.exp * 1e3;
3915
+ } catch {
3916
+ return null;
3917
+ }
3918
+ }
3919
+ __name(getTokenExpiry, "getTokenExpiry");
3920
+ function isTokenExpiringSoon(token, thresholdMs) {
3921
+ const expiry = getTokenExpiry(token);
3922
+ if (!expiry) return false;
3923
+ const timeUntilExpiry = expiry - Date.now();
3924
+ return timeUntilExpiry < thresholdMs;
3925
+ }
3926
+ __name(isTokenExpiringSoon, "isTokenExpiringSoon");
3927
+ function useTokenRefresh(options = {}) {
3928
+ const { enabled = true, onRefresh, onRefreshError } = options;
3929
+ const isRefreshingRef = useRef(false);
3930
+ const refreshToken = useCallback(async () => {
3931
+ if (isRefreshingRef.current) {
3932
+ authLogger.debug("Token refresh already in progress");
3933
+ return false;
3934
+ }
3935
+ const refreshTokenValue = api.getRefreshToken();
3936
+ if (!refreshTokenValue) {
3937
+ authLogger.warn("No refresh token available");
3938
+ return false;
3939
+ }
3940
+ isRefreshingRef.current = true;
3941
+ authLogger.info("Refreshing token...");
3942
+ try {
3943
+ const response = await fetch("/api/accounts/token/refresh/", {
3944
+ method: "POST",
3945
+ headers: { "Content-Type": "application/json" },
3946
+ body: JSON.stringify({ refresh: refreshTokenValue })
3947
+ });
3948
+ if (!response.ok) {
3949
+ throw new Error(`Token refresh failed: ${response.status}`);
3950
+ }
3951
+ const data = await response.json();
3952
+ const newAccessToken = data.access;
3953
+ if (!newAccessToken) {
3954
+ throw new Error("No access token in refresh response");
3955
+ }
3956
+ api.setToken(newAccessToken, refreshTokenValue);
3957
+ authLogger.info("Token refreshed successfully");
3958
+ onRefresh?.(newAccessToken);
3959
+ return true;
3960
+ } catch (error) {
3961
+ authLogger.error("Token refresh error:", error);
3962
+ onRefreshError?.(error instanceof Error ? error : new Error(String(error)));
3963
+ return false;
3964
+ } finally {
3965
+ isRefreshingRef.current = false;
3966
+ }
3967
+ }, [onRefresh, onRefreshError]);
3968
+ const checkAndRefresh = useCallback(async () => {
3969
+ const token = api.getToken();
3970
+ if (!token) return;
3971
+ if (isTokenExpiringSoon(token, TOKEN_REFRESH_THRESHOLD_MS)) {
3972
+ authLogger.info("Token expiring soon, refreshing proactively");
3973
+ await refreshToken();
3974
+ }
3975
+ }, [refreshToken]);
3976
+ useEffect(() => {
3977
+ if (!enabled) return;
3978
+ checkAndRefresh();
3979
+ const intervalId = setInterval(checkAndRefresh, CHECK_INTERVAL_MS);
3980
+ return () => clearInterval(intervalId);
3981
+ }, [enabled, checkAndRefresh]);
3982
+ useEffect(() => {
3983
+ if (!enabled) return;
3984
+ const handleFocus = /* @__PURE__ */ __name(() => {
3985
+ authLogger.debug("Window focused, checking token...");
3986
+ checkAndRefresh();
3987
+ }, "handleFocus");
3988
+ window.addEventListener("focus", handleFocus);
3989
+ return () => window.removeEventListener("focus", handleFocus);
3990
+ }, [enabled, checkAndRefresh]);
3991
+ useEffect(() => {
3992
+ if (!enabled) return;
3993
+ const handleOnline = /* @__PURE__ */ __name(() => {
3994
+ authLogger.info("Network reconnected, checking token...");
3995
+ checkAndRefresh();
3996
+ }, "handleOnline");
3997
+ window.addEventListener("online", handleOnline);
3998
+ return () => window.removeEventListener("online", handleOnline);
3999
+ }, [enabled, checkAndRefresh]);
4000
+ return {
4001
+ refreshToken,
4002
+ checkAndRefresh
4003
+ };
4004
+ }
4005
+ __name(useTokenRefresh, "useTokenRefresh");
4006
+
3907
4007
  // src/auth/utils/analytics.ts
3908
4008
  var AnalyticsEvent = /* @__PURE__ */ ((AnalyticsEvent2) => {
3909
4009
  AnalyticsEvent2["AUTH_OTP_REQUEST"] = "auth_otp_request";
@@ -3943,10 +4043,10 @@ var Analytics = {
3943
4043
  // src/auth/context/AccountsContext.tsx
3944
4044
  import {
3945
4045
  createContext,
3946
- useCallback,
4046
+ useCallback as useCallback2,
3947
4047
  useContext,
3948
- useEffect,
3949
- useRef,
4048
+ useEffect as useEffect2,
4049
+ useRef as useRef2,
3950
4050
  useState as useState2
3951
4051
  } from "react";
3952
4052
 
@@ -4028,12 +4128,12 @@ function AccountsProvider({ children }) {
4028
4128
  });
4029
4129
  const [isLoadingProfile, setIsLoadingProfile] = useState2(false);
4030
4130
  const [profileError, setProfileError] = useState2(null);
4031
- const profileRef = useRef(profile);
4032
- const isLoadingRef = useRef(false);
4033
- useEffect(() => {
4131
+ const profileRef = useRef2(profile);
4132
+ const isLoadingRef = useRef2(false);
4133
+ useEffect2(() => {
4034
4134
  profileRef.current = profile;
4035
4135
  }, [profile]);
4036
- useEffect(() => {
4136
+ useEffect2(() => {
4037
4137
  isLoadingRef.current = isLoadingProfile;
4038
4138
  }, [isLoadingProfile]);
4039
4139
  const updateMutation = useUpdateAccountsProfileUpdateUpdate();
@@ -4042,7 +4142,7 @@ function AccountsProvider({ children }) {
4042
4142
  const otpRequestMutation = useCreateAccountsOtpRequestCreate();
4043
4143
  const otpVerifyMutation = useCreateAccountsOtpVerifyCreate();
4044
4144
  const tokenRefreshMutation = useCreateAccountsTokenRefreshCreate();
4045
- const refreshProfile = useCallback(async (callerId) => {
4145
+ const refreshProfile = useCallback2(async (callerId) => {
4046
4146
  const currentProfile = profileRef.current;
4047
4147
  const currentLoading = isLoadingRef.current;
4048
4148
  if (currentProfile && !currentLoading) {
@@ -4108,7 +4208,7 @@ function AccountsProvider({ children }) {
4108
4208
  }
4109
4209
  return result;
4110
4210
  }, "refreshToken");
4111
- const logout = useCallback(() => {
4211
+ const logout = useCallback2(() => {
4112
4212
  api.clearTokens();
4113
4213
  setProfile(void 0);
4114
4214
  setProfileError(null);
@@ -4172,32 +4272,45 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4172
4272
  const queryParams = useQueryParams();
4173
4273
  const [storedEmail, setStoredEmail, clearStoredEmail] = useLocalStorage(EMAIL_STORAGE_KEY, null);
4174
4274
  const [storedPhone, setStoredPhone, clearStoredPhone] = useLocalStorage(PHONE_STORAGE_KEY, null);
4275
+ useTokenRefresh({
4276
+ enabled: true,
4277
+ onRefresh: /* @__PURE__ */ __name((newToken) => {
4278
+ authLogger.info("Token auto-refreshed successfully");
4279
+ }, "onRefresh"),
4280
+ onRefreshError: /* @__PURE__ */ __name((error) => {
4281
+ authLogger.warn("Token auto-refresh failed:", error.message);
4282
+ }, "onRefreshError")
4283
+ });
4175
4284
  const user = accounts.profile;
4176
- const userRef = useRef2(user);
4177
- const configRef = useRef2(config);
4178
- const isLoadingProfileRef = useRef2(false);
4179
- useEffect2(() => {
4285
+ const userRef = useRef3(user);
4286
+ const configRef = useRef3(config);
4287
+ const isLoadingProfileRef = useRef3(false);
4288
+ useEffect3(() => {
4180
4289
  userRef.current = user;
4181
4290
  }, [user]);
4182
- useEffect2(() => {
4291
+ useEffect3(() => {
4183
4292
  configRef.current = config;
4184
4293
  }, [config]);
4185
- const clearAuthState = useCallback2((caller) => {
4294
+ const clearAuthState = useCallback3((caller) => {
4186
4295
  authLogger.info("clearAuthState >> caller", caller);
4187
4296
  api.clearTokens();
4188
4297
  clearProfileCache();
4189
4298
  setInitialized(true);
4190
4299
  setIsLoading(false);
4191
4300
  }, []);
4192
- const handleGlobalAuthError = useCallback2((error, context = "API Request") => {
4193
- if (error?.success === false) {
4194
- authLogger.warn(`Error detected in ${context}, clearing tokens`);
4301
+ const handleGlobalAuthError = useCallback3((error, context = "API Request") => {
4302
+ const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
4303
+ if (isAuthError) {
4304
+ authLogger.warn(`Authentication error in ${context}, clearing tokens`);
4195
4305
  clearAuthState(`globalAuthError:${context}`);
4196
4306
  return true;
4197
4307
  }
4308
+ if (error?.success === false) {
4309
+ authLogger.warn(`Non-auth error in ${context} (not clearing session):`, error?.message || error);
4310
+ }
4198
4311
  return false;
4199
4312
  }, [clearAuthState]);
4200
- const loadCurrentProfile = useCallback2(async (callerId) => {
4313
+ const loadCurrentProfile = useCallback3(async (callerId) => {
4201
4314
  const finalCallerId = callerId || "AuthContext.loadCurrentProfile";
4202
4315
  if (isLoadingProfileRef.current) {
4203
4316
  authLogger.debug(`Profile loading already in progress, skipping duplicate call from: ${finalCallerId}`);
@@ -4226,14 +4339,19 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4226
4339
  setInitialized(true);
4227
4340
  } catch (error) {
4228
4341
  authLogger.error("Failed to load profile:", error);
4229
- if (!handleGlobalAuthError(error, "loadCurrentProfile")) {
4230
- clearAuthState("loadCurrentProfile:error");
4342
+ const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
4343
+ if (isAuthError) {
4344
+ authLogger.warn("Authentication error, clearing session");
4345
+ clearAuthState("loadCurrentProfile:authError");
4346
+ } else {
4347
+ authLogger.warn("Profile load failed but keeping session (non-auth error)");
4348
+ setInitialized(true);
4231
4349
  }
4232
4350
  } finally {
4233
4351
  isLoadingProfileRef.current = false;
4234
4352
  }
4235
4353
  }, [clearAuthState, handleGlobalAuthError, accounts]);
4236
- useEffect2(() => {
4354
+ useEffect3(() => {
4237
4355
  if (initialized) return;
4238
4356
  const initializeAuth = /* @__PURE__ */ __name(async () => {
4239
4357
  authLogger.info("Initializing auth...");
@@ -4273,7 +4391,13 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4273
4391
  await loadCurrentProfile("AuthContext.initializeAuth");
4274
4392
  } catch (error) {
4275
4393
  authLogger.error("Failed to load profile during initialization:", error);
4276
- clearAuthState("initializeAuth:loadProfileFailed");
4394
+ const isAuthError = error?.status === 401 || error?.statusCode === 401 || error?.code === "token_not_valid" || error?.code === "authentication_failed";
4395
+ if (isAuthError) {
4396
+ clearAuthState("initializeAuth:authError");
4397
+ } else {
4398
+ authLogger.warn("Init profile load failed but keeping session");
4399
+ setInitialized(true);
4400
+ }
4277
4401
  }
4278
4402
  setIsLoading(false);
4279
4403
  } else {
@@ -4283,7 +4407,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4283
4407
  }, "initializeAuth");
4284
4408
  initializeAuth();
4285
4409
  }, [initialized]);
4286
- useEffect2(() => {
4410
+ useEffect3(() => {
4287
4411
  if (!initialized) return;
4288
4412
  const isAuthenticated = api.isAuthenticated();
4289
4413
  const authRoute = config?.routes?.auth || defaultRoutes.auth;
@@ -4294,15 +4418,15 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4294
4418
  router.push(callbackUrl);
4295
4419
  }
4296
4420
  }, [initialized, pathname, queryParams, config?.routes]);
4297
- const pushToDefaultCallbackUrl = useCallback2(() => {
4421
+ const pushToDefaultCallbackUrl = useCallback3(() => {
4298
4422
  const callbackUrl = config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
4299
4423
  router.push(callbackUrl);
4300
4424
  }, [config?.routes, router]);
4301
- const pushToDefaultAuthCallbackUrl = useCallback2(() => {
4425
+ const pushToDefaultAuthCallbackUrl = useCallback3(() => {
4302
4426
  const authCallbackUrl = config?.routes?.defaultAuthCallback || defaultRoutes.defaultAuthCallback;
4303
4427
  router.push(authCallbackUrl);
4304
4428
  }, [config?.routes, router]);
4305
- const checkAuthAndRedirect = useCallback2(async () => {
4429
+ const checkAuthAndRedirect = useCallback3(async () => {
4306
4430
  try {
4307
4431
  setIsLoading(true);
4308
4432
  const isAuthenticated = api.isAuthenticated();
@@ -4324,7 +4448,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4324
4448
  setIsLoading(false);
4325
4449
  }
4326
4450
  }, [loadCurrentProfile, clearAuthState, pushToDefaultCallbackUrl, pushToDefaultAuthCallbackUrl, handleGlobalAuthError]);
4327
- const requestOTP = useCallback2(
4451
+ const requestOTP = useCallback3(
4328
4452
  async (identifier, channel, sourceUrl) => {
4329
4453
  api.clearTokens();
4330
4454
  try {
@@ -4352,7 +4476,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4352
4476
  },
4353
4477
  [accounts]
4354
4478
  );
4355
- const verifyOTP = useCallback2(
4479
+ const verifyOTP = useCallback3(
4356
4480
  async (identifier, otpCode, channel, sourceUrl, redirectUrl, skipRedirect) => {
4357
4481
  try {
4358
4482
  const channelValue = channel === "phone" ? enums_exports.OTPVerifyRequestChannel.PHONE : enums_exports.OTPVerifyRequestChannel.EMAIL;
@@ -4419,7 +4543,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4419
4543
  },
4420
4544
  [setStoredEmail, setStoredPhone, clearStoredEmail, clearStoredPhone, config?.routes?.defaultCallback, accounts, router]
4421
4545
  );
4422
- const refreshToken = useCallback2(async () => {
4546
+ const refreshToken = useCallback3(async () => {
4423
4547
  try {
4424
4548
  const refreshTokenValue = api.getRefreshToken();
4425
4549
  if (!refreshTokenValue) {
@@ -4452,7 +4576,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4452
4576
  };
4453
4577
  }
4454
4578
  }, [clearAuthState, accounts]);
4455
- const logout = useCallback2(async () => {
4579
+ const logout = useCallback3(async () => {
4456
4580
  const performLogout = /* @__PURE__ */ __name(() => {
4457
4581
  Analytics.event("auth_logout" /* AUTH_LOGOUT */, {
4458
4582
  category: "auth" /* AUTH */
@@ -4544,7 +4668,7 @@ var useAuth = /* @__PURE__ */ __name(() => {
4544
4668
  }, "useAuth");
4545
4669
 
4546
4670
  // src/auth/hooks/useAuthFormState.ts
4547
- import { useCallback as useCallback3, useState as useState4 } from "react";
4671
+ import { useCallback as useCallback4, useState as useState4 } from "react";
4548
4672
  var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialChannel = "email") => {
4549
4673
  const [identifier, setIdentifier] = useState4(initialIdentifier);
4550
4674
  const [channel, setChannel] = useState4(initialChannel);
@@ -4557,7 +4681,7 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialCh
4557
4681
  const [shouldPrompt2FA, setShouldPrompt2FA] = useState4(false);
4558
4682
  const [twoFactorCode, setTwoFactorCode] = useState4("");
4559
4683
  const [useBackupCode, setUseBackupCode] = useState4(false);
4560
- const clearError = useCallback3(() => setError(""), []);
4684
+ const clearError = useCallback4(() => setError(""), []);
4561
4685
  return {
4562
4686
  // State
4563
4687
  identifier,
@@ -4588,11 +4712,11 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "", initialCh
4588
4712
  }, "useAuthFormState");
4589
4713
 
4590
4714
  // src/auth/hooks/useAuthValidation.ts
4591
- import { useCallback as useCallback4 } from "react";
4715
+ import { useCallback as useCallback5 } from "react";
4592
4716
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4593
4717
  var PHONE_REGEX = /^\+[1-9]\d{6,14}$/;
4594
4718
  var useAuthValidation = /* @__PURE__ */ __name(() => {
4595
- const detectChannelFromIdentifier2 = useCallback4((id) => {
4719
+ const detectChannelFromIdentifier2 = useCallback5((id) => {
4596
4720
  if (!id) return null;
4597
4721
  if (id.includes("@")) {
4598
4722
  return "email";
@@ -4602,7 +4726,7 @@ var useAuthValidation = /* @__PURE__ */ __name(() => {
4602
4726
  }
4603
4727
  return null;
4604
4728
  }, []);
4605
- const validateIdentifier2 = useCallback4((id, channelType) => {
4729
+ const validateIdentifier2 = useCallback5((id, channelType) => {
4606
4730
  if (!id) return false;
4607
4731
  const channel = channelType || detectChannelFromIdentifier2(id);
4608
4732
  if (channel === "email") {
@@ -4633,11 +4757,11 @@ var validateIdentifier = /* @__PURE__ */ __name((id, channelType) => {
4633
4757
  }, "validateIdentifier");
4634
4758
 
4635
4759
  // src/auth/hooks/useAuthForm.ts
4636
- import { useCallback as useCallback6, useEffect as useEffect4, useRef as useRef3 } from "react";
4760
+ import { useCallback as useCallback7, useEffect as useEffect5, useRef as useRef4 } from "react";
4637
4761
 
4638
4762
  // src/auth/hooks/useAutoAuth.ts
4639
4763
  import { usePathname as usePathname2 } from "next/navigation";
4640
- import { useEffect as useEffect3 } from "react";
4764
+ import { useEffect as useEffect4 } from "react";
4641
4765
  import { useCfgRouter as useCfgRouter2, useQueryParams as useQueryParams2 } from "@djangocfg/ui-nextjs/hooks";
4642
4766
  var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
4643
4767
  const { onOTPDetected, cleanupUrl = true, allowedPaths = ["/auth"] } = options;
@@ -4647,7 +4771,7 @@ var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
4647
4771
  const isAllowedPath = allowedPaths.some((path) => pathname === path || pathname?.startsWith(path + "/"));
4648
4772
  const hasOTP = !!queryParams.get("otp");
4649
4773
  const isReady = !!pathname && hasOTP && isAllowedPath;
4650
- useEffect3(() => {
4774
+ useEffect4(() => {
4651
4775
  if (!isReady) return;
4652
4776
  const queryOtp = queryParams.get("otp");
4653
4777
  if (queryOtp && typeof queryOtp === "string" && queryOtp.length === 6) {
@@ -4669,7 +4793,7 @@ var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
4669
4793
  }, "useAutoAuth");
4670
4794
 
4671
4795
  // src/auth/hooks/useTwoFactor.ts
4672
- import { useCallback as useCallback5, useState as useState5 } from "react";
4796
+ import { useCallback as useCallback6, useState as useState5 } from "react";
4673
4797
  import { useCfgRouter as useCfgRouter3 } from "@djangocfg/ui-nextjs/hooks";
4674
4798
 
4675
4799
  // src/generated/cfg_totp/totp__backup_codes/client.ts
@@ -5714,10 +5838,10 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
5714
5838
  const [error, setError] = useState5(null);
5715
5839
  const [warning, setWarning] = useState5(null);
5716
5840
  const [remainingBackupCodes, setRemainingBackupCodes] = useState5(null);
5717
- const clearError = useCallback5(() => {
5841
+ const clearError = useCallback6(() => {
5718
5842
  setError(null);
5719
5843
  }, []);
5720
- const handleSuccess = useCallback5((response) => {
5844
+ const handleSuccess = useCallback6((response) => {
5721
5845
  apiAccounts.setToken(response.access_token, response.refresh_token);
5722
5846
  if (response.warning) {
5723
5847
  setWarning(response.warning);
@@ -5739,7 +5863,7 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
5739
5863
  router.hardPush(finalRedirectUrl);
5740
5864
  }
5741
5865
  }, [onSuccess, redirectUrl, router, skipRedirect]);
5742
- const verifyTOTP = useCallback5(async (sessionId, code) => {
5866
+ const verifyTOTP = useCallback6(async (sessionId, code) => {
5743
5867
  if (!sessionId) {
5744
5868
  const msg = "Missing 2FA session ID";
5745
5869
  setError(msg);
@@ -5779,7 +5903,7 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
5779
5903
  setIsLoading(false);
5780
5904
  }
5781
5905
  }, [handleSuccess, onError]);
5782
- const verifyBackupCode = useCallback5(async (sessionId, backupCode) => {
5906
+ const verifyBackupCode = useCallback6(async (sessionId, backupCode) => {
5783
5907
  if (!sessionId) {
5784
5908
  const msg = "Missing 2FA session ID";
5785
5909
  setError(msg);
@@ -5845,7 +5969,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5845
5969
  } = options;
5846
5970
  const formState = useAuthFormState();
5847
5971
  const validation = useAuthValidation();
5848
- const isAutoSubmitFromUrlRef = useRef3(false);
5972
+ const isAutoSubmitFromUrlRef = useRef4(false);
5849
5973
  const {
5850
5974
  requestOTP,
5851
5975
  verifyOTP,
@@ -5892,7 +6016,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5892
6016
  // We handle navigation via success step
5893
6017
  });
5894
6018
  const { detectChannelFromIdentifier: detectChannelFromIdentifier2, validateIdentifier: validateIdentifier2 } = validation;
5895
- const saveIdentifierToStorage = useCallback6((id, ch) => {
6019
+ const saveIdentifierToStorage = useCallback7((id, ch) => {
5896
6020
  if (ch === "email") {
5897
6021
  saveEmail(id);
5898
6022
  clearSavedPhone();
@@ -5901,7 +6025,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5901
6025
  clearSavedEmail();
5902
6026
  }
5903
6027
  }, [saveEmail, savePhone, clearSavedEmail, clearSavedPhone]);
5904
- useEffect4(() => {
6028
+ useEffect5(() => {
5905
6029
  const savedPhone = getSavedPhone();
5906
6030
  const savedEmail = getSavedEmail();
5907
6031
  if (savedPhone) {
@@ -5912,7 +6036,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5912
6036
  setChannel("email");
5913
6037
  }
5914
6038
  }, [getSavedEmail, getSavedPhone, setIdentifier, setChannel]);
5915
- useEffect4(() => {
6039
+ useEffect5(() => {
5916
6040
  if (identifier) {
5917
6041
  const detected = detectChannelFromIdentifier2(identifier);
5918
6042
  if (detected && detected !== channel) {
@@ -5920,7 +6044,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5920
6044
  }
5921
6045
  }
5922
6046
  }, [identifier, channel, detectChannelFromIdentifier2, setChannel]);
5923
- const handleIdentifierSubmit = useCallback6(async (e) => {
6047
+ const handleIdentifierSubmit = useCallback7(async (e) => {
5924
6048
  e.preventDefault();
5925
6049
  if (!identifier) {
5926
6050
  const msg = channel === "phone" ? "Please enter your phone number" : "Please enter your email address";
@@ -5975,7 +6099,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
5975
6099
  onError,
5976
6100
  sourceUrl
5977
6101
  ]);
5978
- const submitOTP = useCallback6(async (submitIdentifier, submitOtp, submitChannel) => {
6102
+ const submitOTP = useCallback7(async (submitIdentifier, submitOtp, submitChannel) => {
5979
6103
  if (!submitOtp || submitOtp.length < 6) {
5980
6104
  const msg = "Please enter the 6-digit verification code";
5981
6105
  setError(msg);
@@ -6025,11 +6149,11 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6025
6149
  setIsLoading(false);
6026
6150
  }
6027
6151
  }, [verifyOTP, saveIdentifierToStorage, setError, setIsLoading, clearError, onOTPSuccess, onError, sourceUrl, redirectUrl, setTwoFactorSessionId, setShouldPrompt2FA, setStep, enable2FASetup]);
6028
- const handleOTPSubmit = useCallback6(async (e) => {
6152
+ const handleOTPSubmit = useCallback7(async (e) => {
6029
6153
  e.preventDefault();
6030
6154
  await submitOTP(identifier, otp, channel);
6031
6155
  }, [identifier, otp, channel, submitOTP]);
6032
- const handleResendOTP = useCallback6(async () => {
6156
+ const handleResendOTP = useCallback7(async () => {
6033
6157
  setIsLoading(true);
6034
6158
  clearError();
6035
6159
  try {
@@ -6049,15 +6173,15 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6049
6173
  setIsLoading(false);
6050
6174
  }
6051
6175
  }, [identifier, channel, requestOTP, saveIdentifierToStorage, setOtp, setError, setIsLoading, clearError, onError, sourceUrl]);
6052
- const handleBackToIdentifier = useCallback6(() => {
6176
+ const handleBackToIdentifier = useCallback7(() => {
6053
6177
  setStep("identifier");
6054
6178
  clearError();
6055
6179
  }, [setStep, clearError]);
6056
- const forceOTPStep = useCallback6(() => {
6180
+ const forceOTPStep = useCallback7(() => {
6057
6181
  setStep("otp");
6058
6182
  clearError();
6059
6183
  }, [setStep, clearError]);
6060
- const handle2FASubmit = useCallback6(async (e) => {
6184
+ const handle2FASubmit = useCallback7(async (e) => {
6061
6185
  e.preventDefault();
6062
6186
  if (!twoFactorSessionId) {
6063
6187
  const msg = "Missing 2FA session";
@@ -6071,12 +6195,12 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6071
6195
  await twoFactor.verifyTOTP(twoFactorSessionId, twoFactorCode);
6072
6196
  }
6073
6197
  }, [twoFactorSessionId, twoFactorCode, useBackupCode, twoFactor, setError, onError]);
6074
- const handleUseBackupCode = useCallback6(() => {
6198
+ const handleUseBackupCode = useCallback7(() => {
6075
6199
  setUseBackupCode(true);
6076
6200
  setTwoFactorCode("");
6077
6201
  clearError();
6078
6202
  }, [setUseBackupCode, setTwoFactorCode, clearError]);
6079
- const handleUseTOTP = useCallback6(() => {
6203
+ const handleUseTOTP = useCallback7(() => {
6080
6204
  setUseBackupCode(false);
6081
6205
  setTwoFactorCode("");
6082
6206
  clearError();
@@ -6141,14 +6265,14 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
6141
6265
  }, "useAuthForm");
6142
6266
 
6143
6267
  // src/auth/hooks/useGithubAuth.ts
6144
- import { useCallback as useCallback7, useState as useState6 } from "react";
6268
+ import { useCallback as useCallback8, useState as useState6 } from "react";
6145
6269
  import { useCfgRouter as useCfgRouter4 } from "@djangocfg/ui-nextjs/hooks";
6146
6270
  var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
6147
6271
  const { sourceUrl, onSuccess, onError, onRequires2FA, redirectUrl, skipRedirect = false } = options;
6148
6272
  const router = useCfgRouter4();
6149
6273
  const [isLoading, setIsLoading] = useState6(false);
6150
6274
  const [error, setError] = useState6(null);
6151
- const startGithubAuth = useCallback7(async () => {
6275
+ const startGithubAuth = useCallback8(async () => {
6152
6276
  setIsLoading(true);
6153
6277
  setError(null);
6154
6278
  try {
@@ -6182,7 +6306,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
6182
6306
  setIsLoading(false);
6183
6307
  }
6184
6308
  }, [sourceUrl, onError]);
6185
- const handleGithubCallback = useCallback7(async (code, state) => {
6309
+ const handleGithubCallback = useCallback8(async (code, state) => {
6186
6310
  setIsLoading(true);
6187
6311
  setError(null);
6188
6312
  try {
@@ -6247,7 +6371,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
6247
6371
  }, "useGithubAuth");
6248
6372
 
6249
6373
  // src/auth/hooks/useTwoFactorSetup.ts
6250
- import { useCallback as useCallback8, useState as useState7 } from "react";
6374
+ import { useCallback as useCallback9, useState as useState7 } from "react";
6251
6375
  var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
6252
6376
  const { onComplete, onError } = options;
6253
6377
  const [isLoading, setIsLoading] = useState7(false);
@@ -6256,17 +6380,17 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
6256
6380
  const [backupCodes, setBackupCodes] = useState7(null);
6257
6381
  const [backupCodesWarning, setBackupCodesWarning] = useState7(null);
6258
6382
  const [setupStep, setSetupStep] = useState7("idle");
6259
- const clearError = useCallback8(() => {
6383
+ const clearError = useCallback9(() => {
6260
6384
  setError(null);
6261
6385
  }, []);
6262
- const resetSetup = useCallback8(() => {
6386
+ const resetSetup = useCallback9(() => {
6263
6387
  setSetupData(null);
6264
6388
  setBackupCodes(null);
6265
6389
  setBackupCodesWarning(null);
6266
6390
  setSetupStep("idle");
6267
6391
  setError(null);
6268
6392
  }, []);
6269
- const startSetup = useCallback8(async (deviceName) => {
6393
+ const startSetup = useCallback9(async (deviceName) => {
6270
6394
  setIsLoading(true);
6271
6395
  setError(null);
6272
6396
  setSetupStep("scanning");
@@ -6296,7 +6420,7 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
6296
6420
  setIsLoading(false);
6297
6421
  }
6298
6422
  }, [onError]);
6299
- const confirmSetup = useCallback8(async (code) => {
6423
+ const confirmSetup = useCallback9(async (code) => {
6300
6424
  if (!setupData) {
6301
6425
  const msg = "Setup not started. Call startSetup() first.";
6302
6426
  setError(msg);
@@ -6351,16 +6475,16 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
6351
6475
  }, "useTwoFactorSetup");
6352
6476
 
6353
6477
  // src/auth/hooks/useTwoFactorStatus.ts
6354
- import { useCallback as useCallback9, useState as useState8 } from "react";
6478
+ import { useCallback as useCallback10, useState as useState8 } from "react";
6355
6479
  var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
6356
6480
  const [isLoading, setIsLoading] = useState8(false);
6357
6481
  const [error, setError] = useState8(null);
6358
6482
  const [has2FAEnabled, setHas2FAEnabled] = useState8(null);
6359
6483
  const [devices, setDevices] = useState8([]);
6360
- const clearError = useCallback9(() => {
6484
+ const clearError = useCallback10(() => {
6361
6485
  setError(null);
6362
6486
  }, []);
6363
- const fetchStatus = useCallback9(async () => {
6487
+ const fetchStatus = useCallback10(async () => {
6364
6488
  setIsLoading(true);
6365
6489
  setError(null);
6366
6490
  try {
@@ -6385,7 +6509,7 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
6385
6509
  setIsLoading(false);
6386
6510
  }
6387
6511
  }, []);
6388
- const disable2FA = useCallback9(async (code) => {
6512
+ const disable2FA = useCallback10(async (code) => {
6389
6513
  if (!code || code.length !== 6) {
6390
6514
  setError("Please enter a 6-digit code");
6391
6515
  return false;
@@ -6420,14 +6544,14 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
6420
6544
  }, "useTwoFactorStatus");
6421
6545
 
6422
6546
  // src/auth/hooks/useAuthGuard.ts
6423
- import { useEffect as useEffect5, useState as useState9 } from "react";
6547
+ import { useEffect as useEffect6, useState as useState9 } from "react";
6424
6548
  import { useCfgRouter as useCfgRouter5 } from "@djangocfg/ui-nextjs/hooks";
6425
6549
  var useAuthGuard = /* @__PURE__ */ __name((options = {}) => {
6426
6550
  const { redirectTo = "/auth", requireAuth = true, saveRedirectUrl: shouldSaveUrl = true } = options;
6427
6551
  const { isAuthenticated, isLoading, saveRedirectUrl } = useAuth();
6428
6552
  const router = useCfgRouter5();
6429
6553
  const [isRedirecting, setIsRedirecting] = useState9(false);
6430
- useEffect5(() => {
6554
+ useEffect6(() => {
6431
6555
  if (!isLoading && requireAuth && !isAuthenticated && !isRedirecting) {
6432
6556
  if (shouldSaveUrl && typeof window !== "undefined") {
6433
6557
  const currentUrl = window.location.pathname + window.location.search;
@@ -6652,6 +6776,7 @@ export {
6652
6776
  useGithubAuth,
6653
6777
  useLocalStorage2 as useLocalStorage,
6654
6778
  useSessionStorage,
6779
+ useTokenRefresh,
6655
6780
  useTwoFactor,
6656
6781
  useTwoFactorSetup,
6657
6782
  useTwoFactorStatus,