@djangocfg/api 2.1.45 → 2.1.47

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/api",
3
- "version": "2.1.45",
3
+ "version": "2.1.47",
4
4
  "description": "Auto-generated TypeScript API client with React hooks, SWR integration, and Zod validation for Django REST Framework backends",
5
5
  "keywords": [
6
6
  "django",
@@ -74,7 +74,7 @@
74
74
  "check": "tsc --noEmit"
75
75
  },
76
76
  "peerDependencies": {
77
- "@djangocfg/ui-nextjs": "^2.1.45",
77
+ "@djangocfg/ui-nextjs": "^2.1.47",
78
78
  "consola": "^3.4.2",
79
79
  "next": "^14 || ^15",
80
80
  "p-retry": "^7.0.0",
@@ -85,7 +85,7 @@
85
85
  "devDependencies": {
86
86
  "@types/node": "^24.7.2",
87
87
  "@types/react": "^19.0.0",
88
- "@djangocfg/typescript-config": "^2.1.45",
88
+ "@djangocfg/typescript-config": "^2.1.47",
89
89
  "next": "^15.0.0",
90
90
  "react": "^19.0.0",
91
91
  "tsup": "^8.5.0",
@@ -10,6 +10,7 @@ import { useCfgRouter, useLocalStorage, useQueryParams } from '@djangocfg/ui-nex
10
10
 
11
11
  import { api as apiAccounts, Enums } from '../../';
12
12
  import { clearProfileCache, getCachedProfile } from '../hooks/useProfileCache';
13
+ import { useAuthRedirectManager } from '../hooks/useAuthRedirect';
13
14
  import { Analytics, AnalyticsCategory, AnalyticsEvent } from '../utils/analytics';
14
15
  import { authLogger } from '../utils/logger';
15
16
  import { AccountsProvider, useAccountsContext } from './AccountsContext';
@@ -38,6 +39,12 @@ const hasValidTokens = (): boolean => {
38
39
  const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config }) => {
39
40
  const accounts = useAccountsContext();
40
41
 
42
+ // Redirect URL manager for saving URL before auth redirect
43
+ const redirectManager = useAuthRedirectManager({
44
+ fallbackUrl: config?.routes?.defaultCallback || defaultRoutes.defaultCallback,
45
+ clearOnUse: true,
46
+ });
47
+
41
48
  // Smart initial loading state: only true if we don't have tokens yet
42
49
  const [isLoading, setIsLoading] = useState(() => {
43
50
  // If we already have tokens and profile, don't show loading
@@ -360,9 +367,11 @@ const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config })
360
367
  Analytics.setUser(String(result.user.id));
361
368
  }
362
369
 
363
- // Handle redirect logic - use provided redirectUrl or fallback to config
370
+ // Handle redirect logic - priority: provided redirectUrl > saved redirect > config default
364
371
  // Use hardPush for full page reload - ensures all React contexts reinitialize
365
- const finalRedirectUrl = redirectUrl || config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
372
+ const savedRedirect = redirectManager.useAndClearRedirect();
373
+ const finalRedirectUrl = redirectUrl || savedRedirect || config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
374
+ authLogger.info('Redirecting after auth to:', finalRedirectUrl);
366
375
  router.hardPush(finalRedirectUrl);
367
376
 
368
377
  return {
@@ -497,6 +506,11 @@ const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config })
497
506
  verifyOTP,
498
507
  refreshToken,
499
508
  logout,
509
+ // Redirect URL methods
510
+ saveRedirectUrl: redirectManager.setRedirect,
511
+ getRedirectUrl: redirectManager.getFinalRedirectUrl,
512
+ clearRedirectUrl: redirectManager.clearRedirect,
513
+ hasRedirectUrl: redirectManager.hasRedirect,
500
514
  }),
501
515
  [
502
516
  user,
@@ -514,6 +528,7 @@ const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config })
514
528
  verifyOTP,
515
529
  refreshToken,
516
530
  logout,
531
+ redirectManager,
517
532
  ],
518
533
  );
519
534
 
@@ -51,6 +51,12 @@ export interface AuthContextType {
51
51
  verifyOTP: (identifier: string, otpCode: string, channel?: 'email' | 'phone', sourceUrl?: string, redirectUrl?: string) => Promise<{ success: boolean; message: string; user?: UserProfile }>;
52
52
  refreshToken: () => Promise<{ success: boolean; message: string }>;
53
53
  logout: () => Promise<void>;
54
+
55
+ // Redirect URL Methods - for saving URL before auth redirect
56
+ saveRedirectUrl: (url: string) => void;
57
+ getRedirectUrl: () => string;
58
+ clearRedirectUrl: () => void;
59
+ hasRedirectUrl: () => boolean;
54
60
  }
55
61
 
56
62
  // Provider props
@@ -1,6 +1,6 @@
1
1
  "use client"
2
2
 
3
- import { useEffect } from 'react';
3
+ import { useEffect, useState } from 'react';
4
4
 
5
5
  import { useCfgRouter } from '@djangocfg/ui-nextjs/hooks';
6
6
 
@@ -9,18 +9,28 @@ import { useAuth } from '../context';
9
9
  interface UseAuthGuardOptions {
10
10
  redirectTo?: string;
11
11
  requireAuth?: boolean;
12
+ /** Whether to save current URL for redirect after auth (default: true) */
13
+ saveRedirectUrl?: boolean;
12
14
  }
13
15
 
14
16
  export const useAuthGuard = (options: UseAuthGuardOptions = {}) => {
15
- const { redirectTo = '/auth', requireAuth = true } = options;
16
- const { isAuthenticated, isLoading } = useAuth();
17
+ const { redirectTo = '/auth', requireAuth = true, saveRedirectUrl: shouldSaveUrl = true } = options;
18
+ const { isAuthenticated, isLoading, saveRedirectUrl } = useAuth();
17
19
  const router = useCfgRouter();
20
+ const [isRedirecting, setIsRedirecting] = useState(false);
18
21
 
19
22
  useEffect(() => {
20
- if (!isLoading && requireAuth && !isAuthenticated) {
23
+ if (!isLoading && requireAuth && !isAuthenticated && !isRedirecting) {
24
+ // Save current URL before redirecting
25
+ if (shouldSaveUrl && typeof window !== 'undefined') {
26
+ const currentUrl = window.location.pathname + window.location.search;
27
+ saveRedirectUrl(currentUrl);
28
+ }
29
+
30
+ setIsRedirecting(true);
21
31
  router.push(redirectTo);
22
32
  }
23
- }, [isAuthenticated, isLoading, router, redirectTo, requireAuth]);
33
+ }, [isAuthenticated, isLoading, router, redirectTo, requireAuth, isRedirecting, shouldSaveUrl, saveRedirectUrl]);
24
34
 
25
- return { isAuthenticated, isLoading };
35
+ return { isAuthenticated, isLoading, isRedirecting };
26
36
  };