@djangocfg/api 2.1.332 → 2.1.333
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-server.cjs +1043 -1041
- package/dist/auth-server.cjs.map +1 -1
- package/dist/auth-server.mjs +1043 -1041
- package/dist/auth-server.mjs.map +1 -1
- package/dist/auth.cjs +1053 -1051
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.mjs +1053 -1051
- package/dist/auth.mjs.map +1 -1
- package/dist/clients.cjs +12 -837
- package/dist/clients.cjs.map +1 -1
- package/dist/clients.mjs +12 -837
- package/dist/clients.mjs.map +1 -1
- package/dist/index.cjs +1081 -1079
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -20
- package/dist/index.d.ts +0 -20
- package/dist/index.mjs +1081 -1079
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/_api/generated/client.gen.ts +3 -2
- package/src/_api/generated/helpers/auth.ts +64 -47
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/api",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.333",
|
|
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",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@types/node": "^24.7.2",
|
|
81
81
|
"@types/react": "^19.1.0",
|
|
82
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
82
|
+
"@djangocfg/typescript-config": "^2.1.333",
|
|
83
83
|
"next": "^16.2.2",
|
|
84
84
|
"react": "^19.1.0",
|
|
85
85
|
"tsup": "^8.5.0",
|
|
@@ -15,5 +15,6 @@ export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (over
|
|
|
15
15
|
|
|
16
16
|
export const client = createClient(createConfig<ClientOptions2>({ baseUrl: 'http://localhost:8000' }));
|
|
17
17
|
|
|
18
|
-
// auto-init:
|
|
19
|
-
import './helpers/auth';
|
|
18
|
+
// auto-init: install auth on client
|
|
19
|
+
import { installAuthOnClient } from './helpers/auth';
|
|
20
|
+
installAuthOnClient(client);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// AUTO-GENERATED by django_generator / ts_extras.wrapper
|
|
2
|
-
// Global auth store.
|
|
3
|
-
//
|
|
2
|
+
// Global auth store. Wired into the shared `client` from `client.gen.ts`
|
|
3
|
+
// via `installAuthOnClient(client)` — called synchronously by the
|
|
4
|
+
// post-processed bottom of client.gen.ts. No circular import here.
|
|
4
5
|
// DO NOT EDIT — re-run `make gen`.
|
|
5
6
|
|
|
6
|
-
import { client } from '../client.gen';
|
|
7
|
-
|
|
8
7
|
const ACCESS_KEY = 'cfg.access_token';
|
|
9
8
|
const REFRESH_KEY = 'cfg.refresh_token';
|
|
10
9
|
const API_KEY_KEY = 'cfg.api_key';
|
|
@@ -106,6 +105,30 @@ let _baseUrlOverride: string | null = null;
|
|
|
106
105
|
let _withCredentials = true;
|
|
107
106
|
let _onUnauthorized: ((response: Response) => void) | null = null;
|
|
108
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Captured reference to the shared Hey API client. Set exactly once by
|
|
110
|
+
* `installAuthOnClient(client)` (called from client.gen.ts). All `auth.set*`
|
|
111
|
+
* methods that mutate transport config (baseUrl / credentials) push through
|
|
112
|
+
* this reference. Until installed, those mutations are silently buffered as
|
|
113
|
+
* in-memory state — the next request after install will pick them up.
|
|
114
|
+
*/
|
|
115
|
+
type HeyClient = {
|
|
116
|
+
setConfig(opts: Record<string, unknown>): void;
|
|
117
|
+
interceptors: {
|
|
118
|
+
request: { use(fn: (req: Request) => Request | Promise<Request>): void };
|
|
119
|
+
response: { use(fn: (res: Response, req: Request) => Response | Promise<Response>): void };
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
let _client: HeyClient | null = null;
|
|
123
|
+
|
|
124
|
+
function pushClientConfig(): void {
|
|
125
|
+
if (!_client) return;
|
|
126
|
+
_client.setConfig({
|
|
127
|
+
baseUrl: auth.getBaseUrl(),
|
|
128
|
+
credentials: _withCredentials ? 'include' : 'same-origin',
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
109
132
|
/**
|
|
110
133
|
* Global auth/config store. All getters read live state every call —
|
|
111
134
|
* the interceptor below uses these to attach headers per-request.
|
|
@@ -116,24 +139,13 @@ let _onUnauthorized: ((response: Response) => void) | null = null;
|
|
|
116
139
|
*
|
|
117
140
|
* @example
|
|
118
141
|
* import { auth } from '@your/api';
|
|
119
|
-
*
|
|
120
|
-
* // After login
|
|
121
142
|
* auth.setToken(jwt);
|
|
122
|
-
* auth.setRefreshToken(refresh);
|
|
123
|
-
*
|
|
124
|
-
* // After logout
|
|
125
143
|
* auth.clearTokens();
|
|
126
|
-
*
|
|
127
|
-
* // Switch to cookie storage (call once during app init)
|
|
128
144
|
* auth.setStorageMode('cookie');
|
|
129
145
|
*/
|
|
130
146
|
export const auth = {
|
|
131
147
|
// ── Storage mode ──────────────────────────────────────────────────
|
|
132
148
|
getStorageMode(): StorageMode { return _storageMode; },
|
|
133
|
-
/**
|
|
134
|
-
* Switch the storage backend. Existing values in the *previous*
|
|
135
|
-
* backend are NOT migrated — set fresh values after switching.
|
|
136
|
-
*/
|
|
137
149
|
setStorageMode(mode: StorageMode): void {
|
|
138
150
|
_storageMode = mode;
|
|
139
151
|
_storage = mode === 'cookie' ? cookieBackend : localStorageBackend;
|
|
@@ -148,13 +160,10 @@ export const auth = {
|
|
|
148
160
|
isAuthenticated(): boolean { return _storage.get(ACCESS_KEY) !== null; },
|
|
149
161
|
|
|
150
162
|
// ── API key ───────────────────────────────────────────────────────
|
|
151
|
-
/** In-memory API key. Falls back to storage, then NEXT_PUBLIC_API_KEY. */
|
|
152
163
|
getApiKey(): string | null {
|
|
153
164
|
return _apiKeyOverride ?? _storage.get(API_KEY_KEY) ?? defaultApiKey();
|
|
154
165
|
},
|
|
155
|
-
/** In-memory only (cleared on reload). */
|
|
156
166
|
setApiKey(key: string | null): void { _apiKeyOverride = key; },
|
|
157
|
-
/** Persist to active storage backend (localStorage or cookie). */
|
|
158
167
|
setApiKeyPersist(key: string | null): void {
|
|
159
168
|
_apiKeyOverride = key;
|
|
160
169
|
_storage.set(API_KEY_KEY, key);
|
|
@@ -162,7 +171,6 @@ export const auth = {
|
|
|
162
171
|
clearApiKey(): void { _apiKeyOverride = null; _storage.set(API_KEY_KEY, null); },
|
|
163
172
|
|
|
164
173
|
// ── Locale ────────────────────────────────────────────────────────
|
|
165
|
-
/** Override locale → falls back to NEXT_LOCALE cookie / navigator.language. */
|
|
166
174
|
getLocale(): string | null { return _localeOverride ?? detectLocale(); },
|
|
167
175
|
setLocale(locale: string | null): void { _localeOverride = locale; },
|
|
168
176
|
|
|
@@ -173,51 +181,60 @@ export const auth = {
|
|
|
173
181
|
},
|
|
174
182
|
setBaseUrl(url: string | null): void {
|
|
175
183
|
_baseUrlOverride = url ? url.replace(/\/$/, '') : null;
|
|
176
|
-
|
|
184
|
+
pushClientConfig();
|
|
177
185
|
},
|
|
178
186
|
|
|
179
|
-
// ── Credentials toggle
|
|
187
|
+
// ── Credentials toggle ────────────────────────────────────────────
|
|
180
188
|
getWithCredentials(): boolean { return _withCredentials; },
|
|
181
189
|
setWithCredentials(value: boolean): void {
|
|
182
190
|
_withCredentials = value;
|
|
183
|
-
|
|
191
|
+
pushClientConfig();
|
|
184
192
|
},
|
|
185
193
|
|
|
186
194
|
// ── 401 handler ───────────────────────────────────────────────────
|
|
187
|
-
/**
|
|
188
|
-
* Register a callback fired on every 401 response. Use this to wire
|
|
189
|
-
* a token-refresh flow or a forced logout. Setting `null` removes
|
|
190
|
-
* the handler.
|
|
191
|
-
*/
|
|
192
195
|
onUnauthorized(cb: ((response: Response) => void) | null): void {
|
|
193
196
|
_onUnauthorized = cb;
|
|
194
197
|
},
|
|
195
198
|
};
|
|
196
199
|
|
|
197
|
-
|
|
198
|
-
client.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Wire the shared client to the global auth store. Called exactly
|
|
202
|
+
* once from `client.gen.ts` (post-processed) right after
|
|
203
|
+
* `createClient()`. Synchronous — no microtask, no TDZ races.
|
|
204
|
+
*
|
|
205
|
+
* Safe to call from server / SSR: storage backends short-circuit on
|
|
206
|
+
* non-browser environments, so headers populated by the interceptor
|
|
207
|
+
* are simply absent server-side (which is the correct behaviour
|
|
208
|
+
* unless the caller explicitly sets a server-side token).
|
|
209
|
+
*/
|
|
210
|
+
export function installAuthOnClient(client: HeyClient): void {
|
|
211
|
+
if (_client) return; // idempotent
|
|
212
|
+
_client = client;
|
|
202
213
|
|
|
203
|
-
client.
|
|
204
|
-
|
|
205
|
-
|
|
214
|
+
client.setConfig({
|
|
215
|
+
baseUrl: auth.getBaseUrl(),
|
|
216
|
+
credentials: _withCredentials ? 'include' : 'same-origin',
|
|
217
|
+
});
|
|
206
218
|
|
|
207
|
-
|
|
208
|
-
|
|
219
|
+
client.interceptors.request.use((request) => {
|
|
220
|
+
const token = auth.getToken();
|
|
221
|
+
if (token) request.headers.set('Authorization', `Bearer ${token}`);
|
|
209
222
|
|
|
210
|
-
|
|
211
|
-
|
|
223
|
+
const locale = auth.getLocale();
|
|
224
|
+
if (locale) request.headers.set('Accept-Language', locale);
|
|
212
225
|
|
|
213
|
-
|
|
214
|
-
|
|
226
|
+
const apiKey = auth.getApiKey();
|
|
227
|
+
if (apiKey) request.headers.set('X-API-Key', apiKey);
|
|
215
228
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
229
|
+
return request;
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
client.interceptors.response.use((response) => {
|
|
233
|
+
if (response.status === 401 && _onUnauthorized) {
|
|
234
|
+
try { _onUnauthorized(response); } catch {}
|
|
235
|
+
}
|
|
236
|
+
return response;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
222
239
|
|
|
223
240
|
export type Auth = typeof auth;
|