@djangocfg/api 2.1.56 → 2.1.58

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.
Files changed (75) hide show
  1. package/README.md +125 -9
  2. package/dist/auth.cjs +1865 -402
  3. package/dist/auth.cjs.map +1 -1
  4. package/dist/auth.d.cts +352 -76
  5. package/dist/auth.d.ts +352 -76
  6. package/dist/auth.mjs +1867 -404
  7. package/dist/auth.mjs.map +1 -1
  8. package/dist/clients.cjs +1637 -137
  9. package/dist/clients.cjs.map +1 -1
  10. package/dist/clients.d.cts +1394 -282
  11. package/dist/clients.d.ts +1394 -282
  12. package/dist/clients.mjs +1637 -137
  13. package/dist/clients.mjs.map +1 -1
  14. package/dist/hooks.cjs +24 -11
  15. package/dist/hooks.cjs.map +1 -1
  16. package/dist/hooks.d.cts +88 -21
  17. package/dist/hooks.d.ts +88 -21
  18. package/dist/hooks.mjs +24 -11
  19. package/dist/hooks.mjs.map +1 -1
  20. package/dist/index.cjs +38 -17
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +94 -21
  23. package/dist/index.d.ts +94 -21
  24. package/dist/index.mjs +38 -17
  25. package/dist/index.mjs.map +1 -1
  26. package/package.json +3 -3
  27. package/src/auth/context/AccountsContext.tsx +8 -1
  28. package/src/auth/context/AuthContext.tsx +31 -8
  29. package/src/auth/context/types.ts +8 -1
  30. package/src/auth/hooks/index.ts +29 -5
  31. package/src/auth/hooks/useAuthForm.ts +292 -226
  32. package/src/auth/hooks/useAuthFormState.ts +60 -0
  33. package/src/auth/hooks/useAuthValidation.ts +77 -0
  34. package/src/auth/hooks/useGithubAuth.ts +26 -5
  35. package/src/auth/hooks/useTwoFactor.ts +239 -0
  36. package/src/auth/hooks/useTwoFactorSetup.ts +213 -0
  37. package/src/auth/index.ts +3 -0
  38. package/src/auth/types/form.ts +194 -0
  39. package/src/auth/types/index.ts +28 -0
  40. package/src/clients.ts +10 -0
  41. package/src/generated/cfg_accounts/_utils/schemas/OAuthTokenResponse.schema.ts +26 -3
  42. package/src/generated/cfg_accounts/_utils/schemas/OTPVerifyResponse.schema.ts +26 -3
  43. package/src/generated/cfg_accounts/accounts/client.ts +4 -1
  44. package/src/generated/cfg_accounts/accounts/models.ts +15 -6
  45. package/src/generated/cfg_accounts/accounts__oauth/models.ts +16 -7
  46. package/src/generated/cfg_accounts/client.ts +5 -2
  47. package/src/generated/cfg_accounts/http.ts +8 -2
  48. package/src/generated/cfg_accounts/schema.json +47 -19
  49. package/src/generated/cfg_centrifugo/client.ts +5 -2
  50. package/src/generated/cfg_centrifugo/http.ts +8 -2
  51. package/src/generated/cfg_totp/CLAUDE.md +12 -12
  52. package/src/generated/cfg_totp/_utils/fetchers/index.ts +3 -3
  53. package/src/generated/cfg_totp/_utils/fetchers/{totp__2fa_management.ts → totp__totp_management.ts} +3 -3
  54. package/src/generated/cfg_totp/_utils/fetchers/{totp__2fa_setup.ts → totp__totp_setup.ts} +3 -3
  55. package/src/generated/cfg_totp/_utils/fetchers/{totp__2fa_verification.ts → totp__totp_verification.ts} +3 -3
  56. package/src/generated/cfg_totp/_utils/hooks/index.ts +3 -3
  57. package/src/generated/cfg_totp/_utils/hooks/{totp__2fa_management.ts → totp__totp_management.ts} +2 -2
  58. package/src/generated/cfg_totp/_utils/hooks/{totp__2fa_setup.ts → totp__totp_setup.ts} +2 -2
  59. package/src/generated/cfg_totp/_utils/hooks/{totp__2fa_verification.ts → totp__totp_verification.ts} +2 -2
  60. package/src/generated/cfg_totp/_utils/schemas/DeviceList.schema.ts +1 -1
  61. package/src/generated/cfg_totp/client.ts +14 -11
  62. package/src/generated/cfg_totp/http.ts +8 -2
  63. package/src/generated/cfg_totp/index.ts +16 -16
  64. package/src/generated/cfg_totp/schema.json +8 -7
  65. package/src/generated/cfg_totp/{totp__2fa_management → totp__totp_management}/client.ts +2 -2
  66. package/src/generated/cfg_totp/{totp__2fa_management → totp__totp_management}/models.ts +1 -1
  67. package/src/generated/cfg_totp/{totp__2fa_setup → totp__totp_setup}/client.ts +4 -4
  68. package/src/generated/cfg_totp/{totp__2fa_verification → totp__totp_verification}/client.ts +2 -2
  69. package/src/generated/cfg_webpush/client.ts +5 -2
  70. package/src/generated/cfg_webpush/http.ts +8 -2
  71. /package/src/generated/cfg_totp/{totp__2fa_management → totp__totp_management}/index.ts +0 -0
  72. /package/src/generated/cfg_totp/{totp__2fa_setup → totp__totp_setup}/index.ts +0 -0
  73. /package/src/generated/cfg_totp/{totp__2fa_setup → totp__totp_setup}/models.ts +0 -0
  74. /package/src/generated/cfg_totp/{totp__2fa_verification → totp__totp_verification}/index.ts +0 -0
  75. /package/src/generated/cfg_totp/{totp__2fa_verification → totp__totp_verification}/models.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/api",
3
- "version": "2.1.56",
3
+ "version": "2.1.58",
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.56",
77
+ "@djangocfg/ui-nextjs": "^2.1.58",
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.56",
88
+ "@djangocfg/typescript-config": "^2.1.58",
89
89
  "next": "^15.0.0",
90
90
  "react": "^19.0.0",
91
91
  "tsup": "^8.5.0",
@@ -181,7 +181,14 @@ export function AccountsProvider({ children }: AccountsProviderProps) {
181
181
  const verifyOTP = async (data: OTPVerifyRequest): Promise<OTPVerifyResponse> => {
182
182
  const result = await otpVerifyMutation(data, apiAccounts);
183
183
 
184
- // Automatically save tokens after successful verification
184
+ // Check if 2FA is required - don't save tokens yet
185
+ if (result.requires_2fa && result.session_id) {
186
+ authLogger.info('2FA required, session:', result.session_id);
187
+ // Return result without saving tokens - caller handles 2FA step
188
+ return result as OTPVerifyResponse;
189
+ }
190
+
191
+ // Normal flow - save tokens after successful verification
185
192
  if (result.access && result.refresh) {
186
193
  apiAccounts.setToken(result.access, result.refresh);
187
194
  // Refresh profile to load user data with new token
@@ -323,7 +323,14 @@ const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config })
323
323
  );
324
324
 
325
325
  const verifyOTP = useCallback(
326
- async (identifier: string, otpCode: string, channel?: 'email' | 'phone', sourceUrl?: string, redirectUrl?: string): Promise<{ success: boolean; message: string; user?: UserProfile }> => {
326
+ async (identifier: string, otpCode: string, channel?: 'email' | 'phone', sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean): Promise<{
327
+ success: boolean;
328
+ message: string;
329
+ user?: UserProfile;
330
+ requires_2fa?: boolean;
331
+ session_id?: string | null;
332
+ should_prompt_2fa?: boolean;
333
+ }> => {
327
334
  try {
328
335
  const channelValue = channel === 'phone'
329
336
  ? Enums.OTPVerifyRequestChannel.PHONE
@@ -335,7 +342,19 @@ const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config })
335
342
  channel: channelValue,
336
343
  });
337
344
 
338
- // Verify that we got valid tokens
345
+ // Check if 2FA is required - return early with session info
346
+ if (result.requires_2fa && result.session_id) {
347
+ authLogger.info('2FA required, session:', result.session_id);
348
+ return {
349
+ success: true,
350
+ message: 'OTP verified, 2FA required',
351
+ requires_2fa: true,
352
+ session_id: result.session_id,
353
+ should_prompt_2fa: result.should_prompt_2fa,
354
+ };
355
+ }
356
+
357
+ // Verify that we got valid tokens (only required when 2FA is not needed)
339
358
  if (!result.access || !result.refresh) {
340
359
  authLogger.error('Verify OTP returned invalid response:', result);
341
360
  return {
@@ -367,17 +386,21 @@ const AuthProviderInternal: React.FC<AuthProviderProps> = ({ children, config })
367
386
  Analytics.setUser(String(result.user.id));
368
387
  }
369
388
 
370
- // Handle redirect logic - priority: provided redirectUrl > saved redirect > config default
371
- // Use hardPush for full page reload - ensures all React contexts reinitialize
372
- const savedRedirect = redirectManager.useAndClearRedirect();
373
- const finalRedirectUrl = redirectUrl || savedRedirect || config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
374
- authLogger.info('Redirecting after auth to:', finalRedirectUrl);
375
- router.hardPush(finalRedirectUrl);
389
+ // Handle redirect logic (unless skipRedirect is true)
390
+ if (!skipRedirect) {
391
+ // Priority: provided redirectUrl > saved redirect > config default
392
+ // Use hardPush for full page reload - ensures all React contexts reinitialize
393
+ const savedRedirect = redirectManager.useAndClearRedirect();
394
+ const finalRedirectUrl = redirectUrl || savedRedirect || config?.routes?.defaultCallback || defaultRoutes.defaultCallback;
395
+ authLogger.info('Redirecting after auth to:', finalRedirectUrl);
396
+ router.hardPush(finalRedirectUrl);
397
+ }
376
398
 
377
399
  return {
378
400
  success: true,
379
401
  message: 'Login successful',
380
402
  user: result.user as UserProfile,
403
+ should_prompt_2fa: result.should_prompt_2fa,
381
404
  };
382
405
  } catch (error) {
383
406
  authLogger.error('Verify OTP error:', error);
@@ -48,7 +48,14 @@ export interface AuthContextType {
48
48
 
49
49
  // OTP Methods - Multi-channel support
50
50
  requestOTP: (identifier: string, channel?: 'email' | 'phone', sourceUrl?: string) => Promise<{ success: boolean; message: string }>;
51
- verifyOTP: (identifier: string, otpCode: string, channel?: 'email' | 'phone', sourceUrl?: string, redirectUrl?: string) => Promise<{ success: boolean; message: string; user?: UserProfile }>;
51
+ verifyOTP: (identifier: string, otpCode: string, channel?: 'email' | 'phone', sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean) => Promise<{
52
+ success: boolean;
53
+ message: string;
54
+ user?: UserProfile;
55
+ requires_2fa?: boolean;
56
+ session_id?: string | null;
57
+ should_prompt_2fa?: boolean;
58
+ }>;
52
59
  refreshToken: () => Promise<{ success: boolean; message: string }>;
53
60
  logout: () => Promise<void>;
54
61
 
@@ -1,18 +1,42 @@
1
1
  'use client';
2
2
 
3
+ // Core form hooks (decomposed)
4
+ export { useAuthFormState, type UseAuthFormStateReturn } from './useAuthFormState';
5
+ export { useAuthValidation, detectChannelFromIdentifier, validateIdentifier } from './useAuthValidation';
6
+
7
+ // Complete form hook (composes the above)
8
+ export { useAuthForm, type AuthFormReturn, type UseAuthFormOptions } from './useAuthForm';
9
+
10
+ // Auto-auth from URL
11
+ export { useAutoAuth, type UseAutoAuthOptions } from './useAutoAuth';
12
+
13
+ // OAuth
14
+ export { useGithubAuth, type UseGithubAuthOptions, type UseGithubAuthReturn } from './useGithubAuth';
15
+
16
+ // 2FA hooks
17
+ export { useTwoFactor, type UseTwoFactorOptions, type UseTwoFactorReturn } from './useTwoFactor';
18
+ export {
19
+ useTwoFactorSetup,
20
+ type UseTwoFactorSetupOptions,
21
+ type UseTwoFactorSetupReturn,
22
+ type TwoFactorSetupData,
23
+ } from './useTwoFactorSetup';
24
+
25
+ // Auth guards and redirects
3
26
  export { useAuthRedirectManager } from './useAuthRedirect';
4
27
  export { useAuthGuard } from './useAuthGuard';
28
+
29
+ // Storage hooks
5
30
  export { useSessionStorage } from './useSessionStorage';
6
31
  export { useLocalStorage } from './useLocalStorage';
7
- export { useAuthForm } from './useAuthForm';
8
- export { useAutoAuth } from './useAutoAuth';
9
- export { useGithubAuth, type UseGithubAuthOptions, type UseGithubAuthReturn } from './useGithubAuth';
32
+ export { useBase64, encodeBase64, decodeBase64 } from './useBase64';
33
+
34
+ // Profile cache
10
35
  export {
11
36
  getCachedProfile,
12
37
  setCachedProfile,
13
38
  clearProfileCache,
14
39
  hasValidCache,
15
40
  getCacheMetadata,
16
- type ProfileCacheOptions
41
+ type ProfileCacheOptions,
17
42
  } from './useProfileCache';
18
- export { useBase64, encodeBase64, decodeBase64 } from './useBase64';