@djangocfg/api 2.1.355 → 2.1.357

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 (112) hide show
  1. package/README.md +53 -632
  2. package/dist/auth-server.cjs +717 -200
  3. package/dist/auth-server.cjs.map +1 -1
  4. package/dist/auth-server.mjs +717 -200
  5. package/dist/auth-server.mjs.map +1 -1
  6. package/dist/auth.cjs +843 -783
  7. package/dist/auth.cjs.map +1 -1
  8. package/dist/auth.d.cts +58 -37
  9. package/dist/auth.d.ts +58 -37
  10. package/dist/auth.mjs +846 -784
  11. package/dist/auth.mjs.map +1 -1
  12. package/dist/clients.cjs +1427 -0
  13. package/dist/clients.cjs.map +1 -1
  14. package/dist/clients.d.cts +1686 -0
  15. package/dist/clients.d.ts +1686 -0
  16. package/dist/clients.mjs +1427 -0
  17. package/dist/clients.mjs.map +1 -1
  18. package/dist/hooks.cjs +1277 -1924
  19. package/dist/hooks.cjs.map +1 -1
  20. package/dist/hooks.d.cts +18 -1206
  21. package/dist/hooks.d.ts +18 -1206
  22. package/dist/hooks.mjs +1253 -1900
  23. package/dist/hooks.mjs.map +1 -1
  24. package/dist/index.cjs +545 -1232
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +1389 -1455
  27. package/dist/index.d.ts +1389 -1455
  28. package/dist/index.mjs +545 -1232
  29. package/dist/index.mjs.map +1 -1
  30. package/package.json +7 -2
  31. package/src/_api/generated/_cfg_accounts/api.ts +11 -3
  32. package/src/_api/generated/_cfg_accounts/hooks/index.ts +3 -0
  33. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRegenerateCreate.ts +64 -0
  34. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRetrieve.ts +65 -0
  35. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyTestCreate.ts +64 -0
  36. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthConnectionsList.ts +43 -3
  37. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthDisconnectCreate.ts +43 -3
  38. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthGithubAuthorizeCreate.ts +43 -3
  39. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthGithubCallbackCreate.ts +43 -3
  40. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthProvidersRetrieve.ts +43 -3
  41. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpRequestCreate.ts +43 -3
  42. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpVerifyCreate.ts +43 -3
  43. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileAvatarCreate.ts +43 -3
  44. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileDeleteCreate.ts +43 -3
  45. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfilePartialPartialUpdate.ts +43 -3
  46. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfilePartialUpdate.ts +43 -3
  47. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileRetrieve.ts +43 -3
  48. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileUpdatePartialUpdate.ts +43 -3
  49. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileUpdateUpdate.ts +43 -3
  50. package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenRefreshCreate.ts +43 -3
  51. package/src/_api/generated/_cfg_accounts/index.ts +1 -1
  52. package/src/_api/generated/_cfg_accounts/schemas/APIKey.ts +13 -0
  53. package/src/_api/generated/_cfg_accounts/schemas/APIKeyRegenerate.ts +12 -0
  54. package/src/_api/generated/_cfg_accounts/schemas/APIKeyRequest.ts +13 -0
  55. package/src/_api/generated/{_cfg_totp/schemas/DeviceListStatusEnum.ts → _cfg_accounts/schemas/APIKeyTestRequest.ts} +4 -2
  56. package/src/_api/generated/_cfg_accounts/schemas/APIKeyTestResult.ts +12 -0
  57. package/src/_api/generated/_cfg_accounts/schemas/AccountDeleteResponse.ts +1 -1
  58. package/src/_api/generated/_cfg_accounts/schemas/CentrifugoToken.ts +2 -2
  59. package/src/_api/generated/_cfg_accounts/schemas/CfgUserUpdateRequest.ts +3 -2
  60. package/src/_api/generated/_cfg_accounts/schemas/OAuthCallbackRequestRequest.ts +1 -1
  61. package/src/_api/generated/_cfg_accounts/schemas/OAuthConnection.ts +6 -6
  62. package/src/_api/generated/_cfg_accounts/schemas/OAuthDisconnectRequestRequest.ts +2 -2
  63. package/src/_api/generated/_cfg_accounts/schemas/{ProviderEnum.ts → OAuthProviderEnum.ts} +2 -2
  64. package/src/_api/generated/_cfg_accounts/schemas/OAuthTokenResponse.ts +5 -5
  65. package/src/_api/generated/_cfg_accounts/schemas/OTPVerifyRequest.ts +1 -1
  66. package/src/_api/generated/_cfg_accounts/schemas/OTPVerifyResponse.ts +3 -3
  67. package/src/_api/generated/_cfg_accounts/schemas/PatchedCfgUserUpdateRequest.ts +3 -2
  68. package/src/_api/generated/_cfg_accounts/schemas/User.ts +12 -10
  69. package/src/_api/generated/_cfg_accounts/schemas/cfg_accounts_oauth_connections_response_200_AutoRef.ts +10 -0
  70. package/src/_api/generated/_cfg_accounts/schemas/cfg_accounts_oauth_disconnect_response_200_AutoRef.ts +11 -0
  71. package/src/_api/generated/_cfg_accounts/schemas/index.ts +8 -1
  72. package/src/_api/generated/_cfg_centrifugo/api.ts +3 -3
  73. package/src/_api/generated/_cfg_centrifugo/hooks/useCfgCentrifugoAuthTokenRetrieve.ts +43 -3
  74. package/src/_api/generated/_cfg_centrifugo/index.ts +1 -1
  75. package/src/_api/generated/_cfg_centrifugo/schemas/ConnectionTokenResponse.ts +2 -2
  76. package/src/_api/generated/_cfg_totp/api.ts +9 -3
  77. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpBackupCodesRegenerateCreate.ts +43 -3
  78. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpBackupCodesRetrieve.ts +43 -3
  79. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpDevicesDestroy.ts +7 -3
  80. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpDevicesRetrieve.ts +43 -3
  81. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpDisableCreate.ts +43 -3
  82. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpSetupConfirmCreate.ts +43 -3
  83. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpSetupCreate.ts +43 -3
  84. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpVerifyBackupCreate.ts +43 -3
  85. package/src/_api/generated/_cfg_totp/hooks/useCfgTotpVerifyCreate.ts +43 -3
  86. package/src/_api/generated/_cfg_totp/index.ts +1 -1
  87. package/src/_api/generated/_cfg_totp/schemas/ConfirmSetupRequest.ts +1 -1
  88. package/src/_api/generated/_cfg_totp/schemas/ConfirmSetupResponse.ts +1 -1
  89. package/src/_api/generated/_cfg_totp/schemas/DeviceList.ts +5 -5
  90. package/src/_api/generated/_cfg_totp/schemas/DeviceStatusEnum.ts +9 -0
  91. package/src/_api/generated/_cfg_totp/schemas/SetupResponse.ts +2 -2
  92. package/src/_api/generated/_cfg_totp/schemas/TotpVerifyUser.ts +11 -9
  93. package/src/_api/generated/_cfg_totp/schemas/VerifyBackupRequest.ts +1 -1
  94. package/src/_api/generated/_cfg_totp/schemas/VerifyRequest.ts +1 -1
  95. package/src/_api/generated/_cfg_totp/schemas/VerifyResponse.ts +2 -2
  96. package/src/_api/generated/_cfg_totp/schemas/cfg_totp_disable_response_200_AutoRef.ts +9 -0
  97. package/src/_api/generated/_cfg_totp/schemas/index.ts +2 -1
  98. package/src/_api/generated/index.ts +3 -1
  99. package/src/_api/generated/sdk.gen.ts +80 -813
  100. package/src/_api/generated/types.gen.ts +320 -159
  101. package/src/auth/context/AccountsContext.tsx +18 -6
  102. package/src/auth/context/AuthContext.tsx +11 -3
  103. package/src/auth/hooks/useDeleteAccount.ts +2 -2
  104. package/src/auth/hooks/useGithubAuth.ts +3 -3
  105. package/src/auth/hooks/useTokenRefresh.ts +2 -2
  106. package/src/auth/hooks/useTwoFactor.ts +3 -3
  107. package/src/auth/hooks/useTwoFactorSetup.ts +3 -3
  108. package/src/auth/hooks/useTwoFactorStatus.ts +3 -3
  109. package/src/auth/middlewares/tokenRefresh.ts +2 -2
  110. package/src/hooks/index.ts +1 -0
  111. package/src/hooks/useApiKey.ts +73 -0
  112. package/src/index.ts +12 -16
package/README.md CHANGED
@@ -1,14 +1,6 @@
1
- <div align="center">
2
-
3
- ![@djangocfg/api](https://raw.githubusercontent.com/markolofsen/assets/main/libs/djangocfg/api.webp)
4
-
5
- </div>
6
-
7
1
  # @djangocfg/api
8
2
 
9
- Core authentication API client and auth system for DjangoCFG applications.
10
-
11
- **Part of [DjangoCFG](https://djangocfg.com)** — modern Django framework for production-ready SaaS applications.
3
+ Type-safe API client and auth system for DjangoCFG applications.
12
4
 
13
5
  ## Install
14
6
 
@@ -16,504 +8,92 @@ Core authentication API client and auth system for DjangoCFG applications.
16
8
  pnpm add @djangocfg/api
17
9
  ```
18
10
 
19
- ## What's Inside
20
-
21
- This package provides everything needed for authentication and user management:
22
-
23
- - **API Client** - Type-safe client for Django `cfg_accounts` API
24
- - **Auth System** - Complete authentication module with contexts, hooks, and utilities
25
- - **JWT Management** - Automatic token refresh and storage
26
- - **OAuth Integration** - GitHub OAuth with callback handling
27
- - **Two-Factor Authentication** - TOTP-based 2FA setup and verification
28
- - **Server Middleware** - Proxy middleware for Next.js
29
- - **Shared Storage** - Authentication storage used by all extensions
30
-
31
- ## Package Structure
32
-
33
- ```
34
- src/
35
- ├── generated/
36
- │ ├── cfg_accounts/ # Generated API client (accounts, profiles, OAuth)
37
- │ │ ├── api/ # API class with all endpoints
38
- │ │ ├── schemas/ # Zod validation schemas
39
- │ │ └── types/ # TypeScript types
40
- │ ├── cfg_totp/ # Generated TOTP/2FA client
41
- │ │ ├── api/ # TOTP device, setup, verification endpoints
42
- │ │ ├── schemas/ # TOTP-specific schemas
43
- │ │ └── types/ # TOTP types
44
- │ └── cfg_centrifugo/ # Generated Centrifugo auth client
45
- │ ├── api/ # Token endpoint (GET /auth/token/)
46
- │ ├── schemas/ # Centrifugo response schemas
47
- │ └── types/ # Centrifugo types
48
- └── auth/
49
- ├── context/ # AuthProvider, AccountsProvider
50
- ├── hooks/ # useAuth, useAuthGuard, useGithubAuth, useTwoFactor, etc.
51
- ├── middlewares/ # Next.js proxy middleware
52
- └── utils/ # Validation, errors, logger, analytics
53
- ```
54
-
55
11
  ## Entry Points
56
12
 
57
13
  | Entry | Import | Description |
58
14
  |-------|--------|-------------|
59
- | **Main** | `@djangocfg/api` | Server-safe exports (API client, fetchers, schemas, types) |
60
- | **Hooks** | `@djangocfg/api/hooks` | Client-only SWR hooks for data fetching |
61
- | **Auth** | `@djangocfg/api/auth` | Client-only auth system (providers, hooks) |
62
- | **Auth Server** | `@djangocfg/api/auth/server` | Server-safe auth utilities (middleware) |
15
+ | **Main** | `@djangocfg/api` | API classes, types, fetchers, schemas |
16
+ | **Auth** | `@djangocfg/api/auth` | Auth providers, hooks, utilities |
17
+ | **Auth Server** | `@djangocfg/api/auth/server` | Next.js proxy middleware |
18
+ | **Clients** | `@djangocfg/api/clients` | Pre-configured API instances |
63
19
 
64
- ## API Client
20
+ ## Generated API Classes
65
21
 
66
- Pre-configured API instance with automatic JWT token management:
22
+ One class per OpenAPI tag. Import directly and call static methods:
67
23
 
68
24
  ```typescript
69
- import { api } from '@djangocfg/api';
25
+ import {
26
+ CfgAccounts, // OTP login
27
+ CfgAccountsProfile, // Profile CRUD
28
+ CfgAccountsOauth, // GitHub OAuth
29
+ CfgAccountsAuth, // Token refresh
30
+ CfgAccountsApiKey, // API key management
31
+ CfgTotp, // TOTP devices / disable
32
+ CfgTotpSetup, // TOTP setup / confirm
33
+ CfgTotpVerify, // TOTP verify / backup
34
+ CfgTotpBackupCodes, // Backup codes
35
+ CfgCentrifugo, // Centrifugo token
36
+ } from '@djangocfg/api';
70
37
 
71
- // Authentication
72
- await api.accounts.login({ email, password });
73
- await api.accounts.logout();
74
- await api.accounts.register({ email, password, username });
38
+ // OTP login
39
+ const result = await CfgAccounts.cfgAccountsOtpVerifyCreate({
40
+ body: { identifier, otp },
41
+ });
75
42
 
76
43
  // Profile
77
- const profile = await api.accounts.profileRetrieve();
78
- await api.accounts.profileUpdate({ first_name: 'John' });
79
-
80
- // Password
81
- await api.accounts.passwordChange({ old_password, new_password });
82
- await api.accounts.passwordReset({ email });
83
- await api.accounts.passwordResetConfirm({ token, password });
84
-
85
- // OAuth
86
- await api.accounts.oauthCallback({ provider: 'github', code });
87
- ```
88
-
89
- ### Centrifugo Token
90
-
91
- Fetch a JWT connection token for Centrifugo WebSocket (used by `@djangocfg/centrifugo` provider):
92
-
93
- ```typescript
94
- import { getCentrifugoAuthTokenRetrieve } from '@djangocfg/api';
95
-
96
- const { token, centrifugo_url, channels, expires_at } =
97
- await getCentrifugoAuthTokenRetrieve();
98
- ```
99
-
100
- ### Shared Authentication Storage
101
-
102
- All DjangoCFG extensions use shared authentication storage from this package:
44
+ const profile = await CfgAccountsProfile.cfgAccountsProfileRetrieve();
103
45
 
104
- ```typescript
105
- // Extensions automatically access the same auth tokens
106
- import { apiSupport } from '@djangocfg/ext-support';
107
- import { apiPayments } from '@djangocfg/ext-payments';
108
-
109
- // All API clients share the same authentication state
110
- // Login once, authenticated everywhere
46
+ // Token refresh
47
+ const tokens = await CfgAccountsAuth.cfgAccountsTokenRefreshCreate({
48
+ body: { refresh },
49
+ });
111
50
  ```
112
51
 
113
- This is handled automatically by `createExtensionAPI()` from `@djangocfg/ext-base`.
114
-
115
52
  ## Auth Module
116
53
 
117
- Complete authentication system with OTP, OAuth, and Two-Factor Authentication (2FA) support.
118
-
119
- ### Authentication Flow
120
-
121
- ```
122
- 1. User enters email → OTP sent
123
- 2. User enters OTP code → Verify
124
- ├── If 2FA enabled → Show TOTP verification
125
- │ └── User enters 6-digit TOTP → Verify
126
- └── If no 2FA → Continue
127
- 3. Success screen with logo → Auto-redirect to dashboard
128
- ```
129
-
130
- All authentication methods (OTP, OAuth, 2FA) show a success screen with your logo before redirecting.
131
-
132
- ### Setup
133
-
134
54
  ```tsx
135
- // app/layout.tsx
136
- import { AuthProvider } from '@djangocfg/api/auth';
55
+ import { AuthProvider, useAuth } from '@djangocfg/api/auth';
137
56
 
138
- export default function RootLayout({ children }) {
139
- return (
140
- <html lang="en">
141
- <body>
142
- <AuthProvider
143
- config={{
144
- routes: {
145
- auth: '/auth',
146
- defaultCallback: '/dashboard'
147
- }
148
- }}
149
- >
150
- {children}
151
- </AuthProvider>
152
- </body>
153
- </html>
154
- );
155
- }
57
+ // Provider
58
+ <AuthProvider config={{ routes: { auth: '/auth', defaultCallback: '/dashboard' } }}>
59
+ {children}
60
+ </AuthProvider>
61
+
62
+ // Hook
63
+ const { user, isAuthenticated, requestOTP, verifyOTP, logout } = useAuth();
156
64
  ```
157
65
 
158
- ### Available Hooks
66
+ ### Auth Hooks
159
67
 
160
68
  ```typescript
161
69
  import {
162
- useAuth, // Main auth context (user, isAuthenticated, OTP methods)
163
- useAuthGuard, // Protect routes (redirect if not authenticated)
164
- useAuthForm, // Auth form state management (OTP + 2FA steps)
165
- useGithubAuth, // GitHub OAuth integration
166
- useTwoFactor, // 2FA verification (verify TOTP code)
167
- useTwoFactorSetup, // 2FA setup flow (generate QR, verify, enable)
168
- useTwoFactorStatus, // 2FA status check and disable
169
- useAutoAuth, // Auto-authentication on mount
170
- useLocalStorage, // localStorage helper
171
- useSessionStorage, // sessionStorage helper
70
+ useAuth, // Main auth context
71
+ useAuthGuard, // Route protection
72
+ useAuthForm, // OTP form state machine
73
+ useGithubAuth, // GitHub OAuth
74
+ useTwoFactor, // 2FA verification
75
+ useTwoFactorSetup, // 2FA setup flow
76
+ useTwoFactorStatus, // 2FA status / disable
77
+ useDeleteAccount, // Account deletion
172
78
  } from '@djangocfg/api/auth';
173
79
  ```
174
80
 
175
- ### useAuth
176
-
177
- Main authentication hook with OTP support:
178
-
179
- ```tsx
180
- 'use client';
181
- import { useAuth } from '@djangocfg/api/auth';
182
-
183
- export function UserProfile() {
184
- const {
185
- user, // UserProfile | null
186
- isAuthenticated, // boolean
187
- isLoading, // boolean
188
- requestOTP, // (identifier, sourceUrl?) => Promise<{ success, message }>
189
- verifyOTP, // (identifier, otp, sourceUrl?, redirectUrl?) => Promise<{ success, message, user? }>
190
- logout, // () => void
191
- } = useAuth();
192
-
193
- if (isLoading) return <div>Loading...</div>;
194
-
195
- if (!isAuthenticated) {
196
- return <div>Please sign in</div>;
197
- }
198
-
199
- return (
200
- <div>
201
- <p>Welcome, {user?.email}!</p>
202
- <button onClick={logout}>Logout</button>
203
- </div>
204
- );
205
- }
206
- ```
207
-
208
- ### useAuthGuard
209
-
210
- Protect routes from unauthenticated access:
211
-
212
- ```tsx
213
- 'use client';
214
- import { useAuthGuard } from '@djangocfg/api/auth';
215
-
216
- export default function DashboardPage() {
217
- const { isAllowed } = useAuthGuard({
218
- redirectTo: '/auth',
219
- requireAuth: true,
220
- });
221
-
222
- if (!isAllowed) return null;
223
-
224
- return <div>Protected Dashboard Content</div>;
225
- }
226
- ```
227
-
228
- ### useAuthForm
229
-
230
- Manage authentication form state with OTP and 2FA support:
231
-
232
- ```tsx
233
- 'use client';
234
- import { useAuthForm } from '@djangocfg/api/auth';
235
-
236
- export function OTPLoginForm() {
237
- const {
238
- // State
239
- identifier, // Email address
240
- otp, // 6-digit OTP code
241
- step, // 'identifier' | 'otp' | '2fa' | '2fa-setup' | 'success'
242
- isLoading,
243
- error,
244
- acceptedTerms,
245
- isRateLimited, // boolean - true when rate limited
246
- rateLimitLabel, // string - formatted countdown e.g. "1:30" or "45s"
247
-
248
- // Setters
249
- setIdentifier,
250
- setOtp,
251
- setAcceptedTerms,
252
-
253
- // Handlers
254
- handleIdentifierSubmit, // Request OTP
255
- handleOTPSubmit, // Verify OTP
256
- handleResendOTP, // Resend OTP
257
- handleBackToIdentifier, // Go back to step 1
258
-
259
- // Utilities
260
- validateIdentifier,
261
- } = useAuthForm({
262
- sourceUrl: window.location.origin,
263
- requireTermsAcceptance: false, // Set true if terms/privacy links provided
264
- onIdentifierSuccess: (identifier) => {
265
- console.log('OTP sent to', identifier);
266
- },
267
- onOTPSuccess: () => {
268
- console.log('Login successful');
269
- },
270
- });
271
-
272
- if (step === 'identifier') {
273
- return (
274
- <form onSubmit={handleIdentifierSubmit}>
275
- <input
276
- type="email"
277
- value={identifier}
278
- onChange={(e) => setIdentifier(e.target.value)}
279
- placeholder="Enter email"
280
- />
281
- {error && <p className="text-red-500">{error}</p>}
282
- <button type="submit" disabled={isLoading}>
283
- {isLoading ? 'Sending...' : 'Send verification code'}
284
- </button>
285
- </form>
286
- );
287
- }
288
-
289
- return (
290
- <form onSubmit={handleOTPSubmit}>
291
- <p>Enter the code sent to {identifier}</p>
292
- <input
293
- type="text"
294
- value={otp}
295
- onChange={(e) => setOtp(e.target.value)}
296
- placeholder="000000"
297
- maxLength={6}
298
- />
299
- {error && <p className="text-red-500">{error}</p>}
300
- <button type="submit" disabled={isLoading || otp.length < 6}>
301
- {isLoading ? 'Verifying...' : 'Verify'}
302
- </button>
303
- <button type="button" onClick={handleResendOTP}>Resend</button>
304
- <button type="button" onClick={handleBackToIdentifier}>Back</button>
305
- </form>
306
- );
307
- }
308
- ```
309
-
310
- #### useAuthForm Options
311
-
312
- | Option | Type | Default | Description |
313
- |--------|------|---------|-------------|
314
- | `sourceUrl` | `string` | required | Application URL for OTP emails |
315
- | `redirectUrl` | `string` | - | URL to redirect after successful OTP verification |
316
- | `requireTermsAcceptance` | `boolean` | `false` | Require terms acceptance before submit |
317
- | `onIdentifierSuccess` | `function` | - | Callback after OTP sent |
318
- | `onOTPSuccess` | `function` | - | Callback after successful verification |
319
- | `onError` | `function` | - | Callback on error |
320
-
321
- ### useGithubAuth
322
-
323
- GitHub OAuth integration:
324
-
325
- ```tsx
326
- 'use client';
327
- import { useGithubAuth } from '@djangocfg/api/auth';
328
-
329
- export function GithubLoginButton() {
330
- const {
331
- startGithubAuth, // () => void - redirects to GitHub
332
- isLoading, // boolean
333
- error, // string | null
334
- } = useGithubAuth({
335
- sourceUrl: window.location.origin,
336
- });
337
-
338
- return (
339
- <button onClick={startGithubAuth} disabled={isLoading}>
340
- {isLoading ? 'Connecting...' : 'Continue with GitHub'}
341
- </button>
342
- );
343
- }
344
- ```
345
-
346
- OAuth callback is handled automatically by `@djangocfg/layouts` AuthLayout component.
347
-
348
- ### useTwoFactor
349
-
350
- Verify 2FA code during authentication:
351
-
352
- ```tsx
353
- 'use client';
354
- import { useTwoFactor } from '@djangocfg/api/auth';
355
-
356
- export function TwoFactorVerify({ sessionId }: { sessionId: string }) {
357
- const {
358
- verify, // (code: string) => Promise<void>
359
- isLoading, // boolean
360
- error, // string | null
361
- } = useTwoFactor({
362
- sessionId,
363
- onSuccess: (user) => console.log('2FA verified:', user),
364
- onError: (error) => console.error('2FA failed:', error),
365
- redirectUrl: '/dashboard',
366
- skipRedirect: false, // Set true if handling navigation manually
367
- });
368
-
369
- const [code, setCode] = useState('');
370
-
371
- return (
372
- <form onSubmit={(e) => { e.preventDefault(); verify(code); }}>
373
- <input
374
- type="text"
375
- value={code}
376
- onChange={(e) => setCode(e.target.value)}
377
- placeholder="000000"
378
- maxLength={6}
379
- />
380
- <button type="submit" disabled={isLoading || code.length < 6}>
381
- {isLoading ? 'Verifying...' : 'Verify'}
382
- </button>
383
- </form>
384
- );
385
- }
386
- ```
387
-
388
- ### useTwoFactorSetup
389
-
390
- Setup 2FA for authenticated users:
391
-
392
- ```tsx
393
- 'use client';
394
- import { useTwoFactorSetup } from '@djangocfg/api/auth';
395
-
396
- export function TwoFactorSetup() {
397
- const {
398
- // State
399
- qrCode, // Base64 QR code image
400
- secret, // Manual entry secret
401
- isEnabled, // Current 2FA status
402
- isLoading,
403
- error,
404
-
405
- // Actions
406
- startSetup, // () => Promise<void> - generates QR code
407
- verifySetup, // (code: string) => Promise<void> - enables 2FA
408
- disable, // () => Promise<void> - disables 2FA
409
- checkStatus, // () => Promise<boolean> - refresh status
410
- } = useTwoFactorSetup({
411
- onSetupComplete: () => console.log('2FA enabled successfully'),
412
- onDisabled: () => console.log('2FA disabled'),
413
- onError: (error) => console.error('2FA setup error:', error),
414
- });
415
-
416
- if (isEnabled) {
417
- return (
418
- <div>
419
- <p>Two-factor authentication is enabled</p>
420
- <button onClick={disable}>Disable 2FA</button>
421
- </div>
422
- );
423
- }
424
-
425
- if (qrCode) {
426
- return (
427
- <div>
428
- <img src={qrCode} alt="2FA QR Code" />
429
- <p>Secret: {secret}</p>
430
- <input placeholder="Enter code from app" />
431
- <button onClick={() => verifySetup('123456')}>Verify & Enable</button>
432
- </div>
433
- );
434
- }
435
-
436
- return <button onClick={startSetup}>Set up 2FA</button>;
437
- }
438
- ```
439
-
440
- ### useTwoFactorStatus
441
-
442
- Check 2FA status and disable 2FA for authenticated users:
443
-
444
- ```tsx
445
- 'use client';
446
- import { useTwoFactorStatus } from '@djangocfg/api/auth';
447
-
448
- export function TwoFactorStatus() {
449
- const {
450
- // State
451
- has2FAEnabled, // boolean | null - current 2FA status
452
- devices, // TwoFactorDevice[] - list of TOTP devices
453
- isLoading,
454
- error,
455
-
456
- // Actions
457
- fetchStatus, // () => Promise<void> - refresh status
458
- disable2FA, // (code: string) => Promise<boolean> - disable with TOTP code
459
- clearError, // () => void
460
- } = useTwoFactorStatus();
461
-
462
- useEffect(() => {
463
- fetchStatus();
464
- }, [fetchStatus]);
465
-
466
- if (has2FAEnabled) {
467
- return (
468
- <div>
469
- <p>2FA is enabled</p>
470
- <p>Devices: {devices.length}</p>
471
- <button onClick={() => disable2FA('123456')}>Disable 2FA</button>
472
- </div>
473
- );
474
- }
475
-
476
- return <p>2FA is not enabled</p>;
477
- }
478
- ```
479
-
480
- ## Server Components & API Routes
481
-
482
- Use fetchers for server-side data fetching:
81
+ ## Type Namespaces
483
82
 
484
83
  ```typescript
485
- import { Fetchers, api } from '@djangocfg/api';
486
-
487
- // Server Component
488
- export default async function ProfilePage() {
489
- const profile = await Fetchers.getAccountsProfileRetrieve(api);
490
-
491
- return <div>{profile.email}</div>;
492
- }
84
+ import type { AccountsTypes, TotpTypes, CentrifugoTypes } from '@djangocfg/api';
493
85
 
494
- // API Route
495
- export async function GET() {
496
- try {
497
- const profile = await Fetchers.getAccountsProfileRetrieve(api);
498
- return Response.json(profile);
499
- } catch (error) {
500
- return Response.json({ error: 'Failed to fetch profile' }, { status: 500 });
501
- }
502
- }
86
+ type User = AccountsTypes.User;
87
+ type Device = TotpTypes.TotpDevice;
503
88
  ```
504
89
 
505
90
  ## Server Middleware
506
91
 
507
- Proxy middleware for Django backend:
508
-
509
92
  ```typescript
510
93
  // middleware.ts
511
94
  import { proxyMiddleware } from '@djangocfg/api/auth/server';
512
- import { NextRequest } from 'next/server';
513
95
 
514
96
  export function middleware(request: NextRequest) {
515
- // Proxies /media/* and /api/* to Django backend
516
- // Automatically forwards cookies and headers
517
97
  return proxyMiddleware(request);
518
98
  }
519
99
 
@@ -522,174 +102,15 @@ export const config = {
522
102
  };
523
103
  ```
524
104
 
525
- ## Client Hooks (SWR)
526
-
527
- Use SWR hooks for reactive data fetching in client components:
528
-
529
- ```tsx
530
- 'use client';
531
- import { useAccountsProfileRetrieve, useAccountsProfileUpdate } from '@djangocfg/api/hooks';
532
-
533
- export function Profile() {
534
- const { data: profile, isLoading, error, mutate } = useAccountsProfileRetrieve();
535
- const { trigger: updateProfile } = useAccountsProfileUpdate();
536
-
537
- const handleUpdate = async () => {
538
- await updateProfile({ first_name: 'John' });
539
- mutate(); // Revalidate data
540
- };
541
-
542
- if (isLoading) return <div>Loading...</div>;
543
- if (error) return <div>Error: {error.message}</div>;
544
-
545
- return (
546
- <div>
547
- <p>Email: {profile?.email}</p>
548
- <button onClick={handleUpdate}>Update Profile</button>
549
- </div>
550
- );
551
- }
552
- ```
553
-
554
- ## Validation Schemas
555
-
556
- Zod schemas for runtime validation:
557
-
558
- ```typescript
559
- import { Schemas } from '@djangocfg/api';
560
-
561
- // Validate API responses
562
- const profile = Schemas.UserProfileSchema.parse(data);
563
-
564
- // Validate form data
565
- const loginData = Schemas.LoginRequestSchema.parse({
566
- email: 'user@example.com',
567
- password: 'password123',
568
- });
569
- ```
570
-
571
- ## TypeScript Types
572
-
573
- Full type safety for all API operations:
574
-
575
- ```typescript
576
- import type {
577
- UserProfile,
578
- LoginRequest,
579
- RegisterRequest,
580
- OAuthProvider,
581
- OAuthCallbackRequest,
582
- } from '@djangocfg/api';
583
-
584
- // Or use namespace
585
- import type { CfgAccountsTypes } from '@djangocfg/api';
586
- type Profile = CfgAccountsTypes.UserProfile;
587
- type LoginReq = CfgAccountsTypes.LoginRequest;
588
- ```
589
-
590
- ## Extension Packages
591
-
592
- Extensions are now in **separate packages** with their own API clients that share authentication:
593
-
594
- | Extension | Package | Description |
595
- |-----------|---------|-------------|
596
- | **Newsletter** | `@djangocfg/ext-newsletter` | Newsletter subscription and campaigns |
597
- | **Knowledge Base** | `@djangocfg/ext-knowbase` | Documentation, chat, RAG-powered AI |
598
- | **Leads** | `@djangocfg/ext-leads` | Lead capture and contact forms |
599
- | **Payments** | `@djangocfg/ext-payments` | Payment processing and subscriptions |
600
- | **Support** | `@djangocfg/ext-support` | Support tickets and helpdesk |
601
-
602
- ### Extension Usage
603
-
604
- ```typescript
605
- // Extensions automatically use shared auth from @djangocfg/api
606
- import { apiSupport } from '@djangocfg/ext-support';
607
- import { apiPayments } from '@djangocfg/ext-payments';
608
- import { apiLeads } from '@djangocfg/ext-leads';
609
-
610
- // All authenticated automatically if user is logged in
611
- const tickets = await apiSupport.tickets.list();
612
- const payments = await apiPayments.payments.list();
613
- const leads = await apiLeads.leads.list();
614
- ```
615
-
616
- See individual extension documentation for details.
617
-
618
- ## Error Handling
619
-
620
- ```typescript
621
- import { handleError, formatError } from '@djangocfg/api/auth';
622
-
623
- try {
624
- await api.accounts.login({ email, password });
625
- } catch (error) {
626
- handleError(error, (formattedError) => {
627
- console.error('Login failed:', formattedError);
628
- // formattedError has consistent structure:
629
- // { message: string, code?: string, details?: any }
630
- });
631
- }
632
- ```
633
-
634
- ## Analytics Integration
635
-
636
- Auth events are automatically tracked when analytics is enabled:
637
-
638
- ```typescript
639
- // Automatic tracking for:
640
- // - AUTH_LOGIN_SUCCESS
641
- // - AUTH_LOGOUT
642
- // - AUTH_SESSION_EXPIRED
643
- // - AUTH_TOKEN_REFRESH
644
- // - AUTH_OAUTH_START
645
- // - AUTH_OAUTH_SUCCESS
646
- // - AUTH_OAUTH_FAIL
647
- // - AUTH_2FA_SETUP_START
648
- // - AUTH_2FA_SETUP_COMPLETE
649
- // - AUTH_2FA_VERIFY_SUCCESS
650
- // - AUTH_2FA_VERIFY_FAIL
651
- ```
652
-
653
- Analytics setup is handled by `@djangocfg/layouts` package.
654
-
655
- ## Environment Variables
105
+ ## Environment
656
106
 
657
107
  ```bash
658
- # Required
659
108
  NEXT_PUBLIC_API_URL=http://localhost:8000
660
-
661
- # OAuth (optional)
662
- NEXT_PUBLIC_GITHUB_CLIENT_ID=your_github_client_id
663
-
664
- # Static build (optional)
665
- NEXT_PUBLIC_STATIC_BUILD=false
666
109
  ```
667
110
 
668
- ## Development
111
+ ## Regenerate Client
669
112
 
670
113
  ```bash
671
- # Generate API client from Django OpenAPI schema
672
- make generate
673
-
674
- # Build package
675
- make build
676
-
677
- # Watch mode
678
- pnpm dev
114
+ # From django solution directory
115
+ make api
679
116
  ```
680
-
681
- ## Requirements
682
-
683
- - Next.js >= 15
684
- - React >= 19
685
- - SWR (peer dependency)
686
- - Zod (bundled for validation)
687
-
688
- ## License
689
-
690
- MIT
691
-
692
- ## Links
693
-
694
- - [DjangoCFG Documentation](https://djangocfg.com)
695
- - [GitHub](https://github.com/markolofsen/django-cfg)