@djangocfg/api 2.1.47 → 2.1.48
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 +11 -7
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +5 -0
- package/dist/auth.d.ts +5 -0
- package/dist/auth.mjs +11 -7
- package/dist/auth.mjs.map +1 -1
- package/package.json +3 -3
- package/src/auth/hooks/useAuthForm.ts +9 -6
- package/src/auth/hooks/useAutoAuth.ts +14 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/api",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.48",
|
|
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.
|
|
77
|
+
"@djangocfg/ui-nextjs": "^2.1.48",
|
|
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.
|
|
88
|
+
"@djangocfg/typescript-config": "^2.1.48",
|
|
89
89
|
"next": "^15.0.0",
|
|
90
90
|
"react": "^19.0.0",
|
|
91
91
|
"tsup": "^8.5.0",
|
|
@@ -43,10 +43,12 @@ export interface UseAuthFormOptions {
|
|
|
43
43
|
redirectUrl?: string;
|
|
44
44
|
/** If true, user must accept terms before submitting. Default: false */
|
|
45
45
|
requireTermsAcceptance?: boolean;
|
|
46
|
+
/** Path to auth page for auto-OTP detection. Default: '/auth' */
|
|
47
|
+
authPath?: string;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
export const useAuthForm = (options: UseAuthFormOptions): AuthFormState & AuthFormHandlers => {
|
|
49
|
-
const { onIdentifierSuccess, onOTPSuccess, onError, sourceUrl, redirectUrl, requireTermsAcceptance = false } = options;
|
|
51
|
+
const { onIdentifierSuccess, onOTPSuccess, onError, sourceUrl, redirectUrl, requireTermsAcceptance = false, authPath = '/auth' } = options;
|
|
50
52
|
|
|
51
53
|
// Form state
|
|
52
54
|
const [identifier, setIdentifier] = useState('');
|
|
@@ -273,15 +275,16 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormState & AuthFo
|
|
|
273
275
|
setSavedTermsAccepted(checked);
|
|
274
276
|
}, [setSavedTermsAccepted]);
|
|
275
277
|
|
|
276
|
-
// Auto-detect OTP from URL query parameters
|
|
278
|
+
// Auto-detect OTP from URL query parameters (only on auth page)
|
|
277
279
|
useAutoAuth({
|
|
280
|
+
allowedPaths: [authPath],
|
|
278
281
|
onOTPDetected: (otp: string) => {
|
|
279
282
|
authLogger.info('OTP detected, auto-submitting');
|
|
280
|
-
|
|
283
|
+
|
|
281
284
|
// Get saved identifier from auth context
|
|
282
285
|
const savedEmail = getSavedEmail();
|
|
283
286
|
const savedPhone = getSavedPhone();
|
|
284
|
-
|
|
287
|
+
|
|
285
288
|
// Prioritize phone over email if both exist
|
|
286
289
|
if (savedPhone) {
|
|
287
290
|
setIdentifier(savedPhone);
|
|
@@ -290,11 +293,11 @@ export const useAuthForm = (options: UseAuthFormOptions): AuthFormState & AuthFo
|
|
|
290
293
|
setIdentifier(savedEmail);
|
|
291
294
|
setChannel('email');
|
|
292
295
|
}
|
|
293
|
-
|
|
296
|
+
|
|
294
297
|
// Set OTP and force OTP step
|
|
295
298
|
setOtp(otp);
|
|
296
299
|
setStep('otp');
|
|
297
|
-
|
|
300
|
+
|
|
298
301
|
// Auto-submit after a short delay to ensure state is updated
|
|
299
302
|
setTimeout(() => {
|
|
300
303
|
const fakeEvent = { preventDefault: () => {} } as React.FormEvent;
|
|
@@ -10,6 +10,8 @@ import { authLogger } from '../utils/logger';
|
|
|
10
10
|
export interface UseAutoAuthOptions {
|
|
11
11
|
onOTPDetected?: (otp: string) => void;
|
|
12
12
|
cleanupUrl?: boolean;
|
|
13
|
+
/** Paths where auto-auth should be active. Default: ['/auth'] */
|
|
14
|
+
allowedPaths?: string[];
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -17,22 +19,26 @@ export interface UseAutoAuthOptions {
|
|
|
17
19
|
* Detects OTP from URL and triggers callback
|
|
18
20
|
*/
|
|
19
21
|
export const useAutoAuth = (options: UseAutoAuthOptions = {}) => {
|
|
20
|
-
const { onOTPDetected, cleanupUrl = true } = options;
|
|
22
|
+
const { onOTPDetected, cleanupUrl = true, allowedPaths = ['/auth'] } = options;
|
|
21
23
|
const queryParams = useQueryParams();
|
|
22
24
|
const pathname = usePathname();
|
|
23
25
|
const router = useCfgRouter();
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
// Check if current path is in allowed paths
|
|
28
|
+
const isAllowedPath = allowedPaths.some(path => pathname === path || pathname?.startsWith(path + '/'));
|
|
29
|
+
|
|
26
30
|
const hasOTP = !!(queryParams.get('otp'));
|
|
31
|
+
const isReady = !!pathname && hasOTP && isAllowedPath;
|
|
27
32
|
|
|
28
33
|
useEffect(() => {
|
|
29
34
|
if (!isReady) return;
|
|
30
35
|
|
|
31
36
|
const queryOtp = queryParams.get('otp') as string;
|
|
32
37
|
|
|
33
|
-
// Handle OTP detection
|
|
38
|
+
// Handle OTP detection - only on allowed paths to avoid conflicts with other pages
|
|
39
|
+
// (e.g., /dashboard/device uses ?otp= for device authorization, not user auth)
|
|
34
40
|
if (queryOtp && typeof queryOtp === 'string' && queryOtp.length === 6) {
|
|
35
|
-
authLogger.info('OTP detected in URL:', queryOtp);
|
|
41
|
+
authLogger.info('OTP detected in URL on auth page:', queryOtp);
|
|
36
42
|
onOTPDetected?.(queryOtp);
|
|
37
43
|
}
|
|
38
44
|
|
|
@@ -40,12 +46,14 @@ export const useAutoAuth = (options: UseAutoAuthOptions = {}) => {
|
|
|
40
46
|
if (cleanupUrl && queryOtp) {
|
|
41
47
|
const cleanQuery = Object.fromEntries(queryParams.entries());
|
|
42
48
|
delete cleanQuery.otp;
|
|
43
|
-
|
|
49
|
+
const queryString = new URLSearchParams(cleanQuery).toString();
|
|
50
|
+
router.push(queryString ? `${pathname}?${queryString}` : pathname);
|
|
44
51
|
}
|
|
45
|
-
}, [pathname, queryParams, onOTPDetected, cleanupUrl, router]);
|
|
52
|
+
}, [pathname, queryParams, onOTPDetected, cleanupUrl, router, isReady]);
|
|
46
53
|
|
|
47
54
|
return {
|
|
48
55
|
isReady,
|
|
49
56
|
hasOTP,
|
|
57
|
+
isAllowedPath,
|
|
50
58
|
};
|
|
51
59
|
};
|