@djangocfg/api 2.1.456 → 2.1.459

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 CHANGED
@@ -6,9 +6,6 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
- var __esm = (fn, res) => function __init() {
10
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
- };
12
9
  var __export = (target, all) => {
13
10
  for (var name in all)
14
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -31,1775 +28,552 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
28
  ));
32
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
30
 
34
- // src/_api/generated/helpers/errors.ts
35
- var APIError;
36
- var init_errors = __esm({
37
- "src/_api/generated/helpers/errors.ts"() {
38
- APIError = class extends Error {
39
- constructor(statusCode, statusText, response, url, message) {
40
- super(message || `HTTP ${statusCode}: ${statusText}`);
41
- this.statusCode = statusCode;
42
- this.statusText = statusText;
43
- this.response = response;
44
- this.url = url;
45
- this.name = "APIError";
46
- }
47
- static {
48
- __name(this, "APIError");
49
- }
50
- get details() {
51
- if (typeof this.response === "object" && this.response !== null) {
52
- return this.response;
53
- }
54
- return null;
55
- }
56
- get fieldErrors() {
57
- const details = this.details;
58
- if (!details) return null;
59
- const fieldErrors = {};
60
- for (const [key, value] of Object.entries(details)) {
61
- if (Array.isArray(value)) fieldErrors[key] = value;
62
- }
63
- return Object.keys(fieldErrors).length > 0 ? fieldErrors : null;
64
- }
65
- get errorMessage() {
66
- const details = this.details;
67
- if (!details) return this.message;
68
- if (details.detail) {
69
- return Array.isArray(details.detail) ? details.detail.join(", ") : String(details.detail);
70
- }
71
- if (details.error) return String(details.error);
72
- if (details.message) return String(details.message);
73
- const fieldErrors = this.fieldErrors;
74
- if (fieldErrors) {
75
- const firstField = Object.keys(fieldErrors)[0];
76
- if (firstField) return `${firstField}: ${fieldErrors[firstField]?.join(", ")}`;
77
- }
78
- return this.message;
79
- }
80
- get isValidationError() {
81
- return this.statusCode === 400;
82
- }
83
- get isAuthError() {
84
- return this.statusCode === 401;
85
- }
86
- get isPermissionError() {
87
- return this.statusCode === 403;
88
- }
89
- get isNotFoundError() {
90
- return this.statusCode === 404;
91
- }
92
- get isServerError() {
93
- return this.statusCode >= 500 && this.statusCode < 600;
94
- }
95
- };
96
- }
31
+ // src/auth/index.ts
32
+ var auth_exports = {};
33
+ __export(auth_exports, {
34
+ AUTH_CONSTANTS: () => AUTH_CONSTANTS,
35
+ AccountsProvider: () => AccountsProvider,
36
+ Analytics: () => Analytics,
37
+ AnalyticsCategory: () => AnalyticsCategory,
38
+ AnalyticsEvent: () => AnalyticsEvent,
39
+ AuthContext: () => AuthContext_default,
40
+ AuthProvider: () => AuthProvider,
41
+ PatchedCfgUserUpdateRequestSchema: () => PatchedCfgUserUpdateRequestSchema,
42
+ authLogger: () => authLogger,
43
+ clearProfileCache: () => clearProfileCache,
44
+ consumeSavedRedirect: () => consumeSavedRedirect,
45
+ decodeBase64: () => decodeBase64,
46
+ encodeBase64: () => encodeBase64,
47
+ formatAuthError: () => formatAuthError,
48
+ getCacheMetadata: () => getCacheMetadata,
49
+ getCachedProfile: () => getCachedProfile,
50
+ hasValidCache: () => hasValidCache,
51
+ isAllowedAuthPath: () => isAllowedAuthPath,
52
+ logger: () => logger,
53
+ normalizePath: () => normalizePath,
54
+ peekSavedRedirect: () => peekSavedRedirect,
55
+ resolveGuardIsAuthenticated: () => resolveGuardIsAuthenticated,
56
+ resolveGuardIsLoading: () => resolveGuardIsLoading,
57
+ setCachedProfile: () => setCachedProfile,
58
+ shouldRedirectToAuth: () => shouldRedirectToAuth,
59
+ useAccountsContext: () => useAccountsContext,
60
+ useAuth: () => useAuth,
61
+ useAuthForm: () => useAuthForm,
62
+ useAuthFormState: () => useAuthFormState,
63
+ useAuthRedirectManager: () => useAuthRedirectManager,
64
+ useAuthValidation: () => useAuthValidation,
65
+ useAutoAuth: () => useAutoAuth,
66
+ useBase64: () => useBase64,
67
+ useCfgRouter: () => useCfgRouter,
68
+ useDeleteAccount: () => useDeleteAccount,
69
+ useGithubAuth: () => useGithubAuth,
70
+ useLocalStorage: () => useLocalStorage,
71
+ useQueryParams: () => useQueryParams,
72
+ useSession: () => useSession,
73
+ useSessionStorage: () => useSessionStorage,
74
+ useTwoFactor: () => useTwoFactor,
75
+ useTwoFactorSetup: () => useTwoFactorSetup,
76
+ useTwoFactorStatus: () => useTwoFactorStatus,
77
+ validateEmail: () => validateEmail,
78
+ validateIdentifier: () => validateIdentifier
97
79
  });
80
+ module.exports = __toCommonJS(auth_exports);
98
81
 
99
- // src/_api/generated/core/bodySerializer.gen.ts
100
- var serializeFormDataPair, formDataBodySerializer, jsonBodySerializer;
101
- var init_bodySerializer_gen = __esm({
102
- "src/_api/generated/core/bodySerializer.gen.ts"() {
103
- serializeFormDataPair = /* @__PURE__ */ __name((data, key, value) => {
104
- if (typeof value === "string" || value instanceof Blob) {
105
- data.append(key, value);
106
- } else if (value instanceof Date) {
107
- data.append(key, value.toISOString());
108
- } else {
109
- data.append(key, JSON.stringify(value));
110
- }
111
- }, "serializeFormDataPair");
112
- formDataBodySerializer = {
113
- bodySerializer: /* @__PURE__ */ __name((body) => {
114
- const data = new FormData();
115
- Object.entries(body).forEach(([key, value]) => {
116
- if (value === void 0 || value === null) {
117
- return;
118
- }
119
- if (Array.isArray(value)) {
120
- value.forEach((v) => serializeFormDataPair(data, key, v));
121
- } else {
122
- serializeFormDataPair(data, key, value);
123
- }
124
- });
125
- return data;
126
- }, "bodySerializer")
127
- };
128
- jsonBodySerializer = {
129
- bodySerializer: /* @__PURE__ */ __name((body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value), "bodySerializer")
130
- };
131
- }
132
- });
82
+ // src/auth/constants.ts
83
+ var AUTH_CONSTANTS = {
84
+ /** Email OTP code length (numeric). */
85
+ EMAIL_OTP_LENGTH: 4,
86
+ /** TOTP code length (RFC 6238 — authenticator apps). */
87
+ TOTP_LENGTH: 6,
88
+ /** Backup code max length. */
89
+ BACKUP_CODE_MAX_LENGTH: 12
90
+ };
133
91
 
134
- // src/_api/generated/core/params.gen.ts
135
- var extraPrefixesMap, extraPrefixes;
136
- var init_params_gen = __esm({
137
- "src/_api/generated/core/params.gen.ts"() {
138
- extraPrefixesMap = {
139
- $body_: "body",
140
- $headers_: "headers",
141
- $path_: "path",
142
- $query_: "query"
143
- };
144
- extraPrefixes = Object.entries(extraPrefixesMap);
145
- }
146
- });
92
+ // src/auth/context/AuthContext.tsx
93
+ var import_navigation4 = require("next/navigation");
94
+ var import_react16 = require("react");
147
95
 
148
- // src/_api/generated/core/queryKeySerializer.gen.ts
149
- var init_queryKeySerializer_gen = __esm({
150
- "src/_api/generated/core/queryKeySerializer.gen.ts"() {
96
+ // src/_api/generated/helpers/errors.ts
97
+ var APIError = class extends Error {
98
+ constructor(statusCode, statusText, response, url, message) {
99
+ super(message || `HTTP ${statusCode}: ${statusText}`);
100
+ this.statusCode = statusCode;
101
+ this.statusText = statusText;
102
+ this.response = response;
103
+ this.url = url;
104
+ this.name = "APIError";
151
105
  }
152
- });
153
-
154
- // src/_api/generated/core/serverSentEvents.gen.ts
155
- function createSseClient({
156
- onRequest,
157
- onSseError,
158
- onSseEvent,
159
- responseTransformer,
160
- responseValidator,
161
- sseDefaultRetryDelay,
162
- sseMaxRetryAttempts,
163
- sseMaxRetryDelay,
164
- sseSleepFn,
165
- url,
166
- ...options
167
- }) {
168
- let lastEventId;
169
- const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
170
- const createStream = /* @__PURE__ */ __name(async function* () {
171
- let retryDelay = sseDefaultRetryDelay ?? 3e3;
172
- let attempt = 0;
173
- const signal = options.signal ?? new AbortController().signal;
174
- while (true) {
175
- if (signal.aborted) break;
176
- attempt++;
177
- const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
178
- if (lastEventId !== void 0) {
179
- headers.set("Last-Event-ID", lastEventId);
180
- }
181
- try {
182
- const requestInit = {
183
- redirect: "follow",
184
- ...options,
185
- body: options.serializedBody,
186
- headers,
187
- signal
188
- };
189
- let request = new Request(url, requestInit);
190
- if (onRequest) {
191
- request = await onRequest(url, requestInit);
192
- }
193
- const _fetch = options.fetch ?? globalThis.fetch;
194
- const response = await _fetch(request);
195
- if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
196
- if (!response.body) throw new Error("No body in SSE response");
197
- const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
198
- let buffer = "";
199
- const abortHandler = /* @__PURE__ */ __name(() => {
200
- try {
201
- reader.cancel();
202
- } catch {
203
- }
204
- }, "abortHandler");
205
- signal.addEventListener("abort", abortHandler);
206
- try {
207
- while (true) {
208
- const { done, value } = await reader.read();
209
- if (done) break;
210
- buffer += value;
211
- buffer = buffer.replace(/\r\n?/g, "\n");
212
- const chunks = buffer.split("\n\n");
213
- buffer = chunks.pop() ?? "";
214
- for (const chunk of chunks) {
215
- const lines = chunk.split("\n");
216
- const dataLines = [];
217
- let eventName;
218
- for (const line of lines) {
219
- if (line.startsWith("data:")) {
220
- dataLines.push(line.replace(/^data:\s*/, ""));
221
- } else if (line.startsWith("event:")) {
222
- eventName = line.replace(/^event:\s*/, "");
223
- } else if (line.startsWith("id:")) {
224
- lastEventId = line.replace(/^id:\s*/, "");
225
- } else if (line.startsWith("retry:")) {
226
- const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
227
- if (!Number.isNaN(parsed)) {
228
- retryDelay = parsed;
229
- }
230
- }
231
- }
232
- let data;
233
- let parsedJson = false;
234
- if (dataLines.length) {
235
- const rawData = dataLines.join("\n");
236
- try {
237
- data = JSON.parse(rawData);
238
- parsedJson = true;
239
- } catch {
240
- data = rawData;
241
- }
242
- }
243
- if (parsedJson) {
244
- if (responseValidator) {
245
- await responseValidator(data);
246
- }
247
- if (responseTransformer) {
248
- data = await responseTransformer(data);
249
- }
250
- }
251
- onSseEvent?.({
252
- data,
253
- event: eventName,
254
- id: lastEventId,
255
- retry: retryDelay
256
- });
257
- if (dataLines.length) {
258
- yield data;
259
- }
260
- }
261
- }
262
- } finally {
263
- signal.removeEventListener("abort", abortHandler);
264
- reader.releaseLock();
265
- }
266
- break;
267
- } catch (error) {
268
- onSseError?.(error);
269
- if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
270
- break;
271
- }
272
- const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
273
- await sleep(backoff);
274
- }
106
+ static {
107
+ __name(this, "APIError");
108
+ }
109
+ get details() {
110
+ if (typeof this.response === "object" && this.response !== null) {
111
+ return this.response;
275
112
  }
276
- }, "createStream");
277
- const stream = createStream();
278
- return { stream };
279
- }
280
- var init_serverSentEvents_gen = __esm({
281
- "src/_api/generated/core/serverSentEvents.gen.ts"() {
282
- __name(createSseClient, "createSseClient");
113
+ return null;
283
114
  }
284
- });
115
+ get fieldErrors() {
116
+ const details = this.details;
117
+ if (!details) return null;
118
+ const fieldErrors = {};
119
+ for (const [key, value] of Object.entries(details)) {
120
+ if (Array.isArray(value)) fieldErrors[key] = value;
121
+ }
122
+ return Object.keys(fieldErrors).length > 0 ? fieldErrors : null;
123
+ }
124
+ get errorMessage() {
125
+ const details = this.details;
126
+ if (!details) return this.message;
127
+ if (details.detail) {
128
+ return Array.isArray(details.detail) ? details.detail.join(", ") : String(details.detail);
129
+ }
130
+ if (details.error) return String(details.error);
131
+ if (details.message) return String(details.message);
132
+ const fieldErrors = this.fieldErrors;
133
+ if (fieldErrors) {
134
+ const firstField = Object.keys(fieldErrors)[0];
135
+ if (firstField) return `${firstField}: ${fieldErrors[firstField]?.join(", ")}`;
136
+ }
137
+ return this.message;
138
+ }
139
+ get isValidationError() {
140
+ return this.statusCode === 400;
141
+ }
142
+ get isAuthError() {
143
+ return this.statusCode === 401;
144
+ }
145
+ get isPermissionError() {
146
+ return this.statusCode === 403;
147
+ }
148
+ get isNotFoundError() {
149
+ return this.statusCode === 404;
150
+ }
151
+ get isServerError() {
152
+ return this.statusCode >= 500 && this.statusCode < 600;
153
+ }
154
+ };
285
155
 
286
- // src/_api/generated/core/pathSerializer.gen.ts
287
- var separatorArrayExplode, separatorArrayNoExplode, separatorObjectExplode, serializeArrayParam, serializePrimitiveParam, serializeObjectParam;
288
- var init_pathSerializer_gen = __esm({
289
- "src/_api/generated/core/pathSerializer.gen.ts"() {
290
- separatorArrayExplode = /* @__PURE__ */ __name((style) => {
291
- switch (style) {
292
- case "label":
293
- return ".";
294
- case "matrix":
295
- return ";";
296
- case "simple":
297
- return ",";
298
- default:
299
- return "&";
300
- }
301
- }, "separatorArrayExplode");
302
- separatorArrayNoExplode = /* @__PURE__ */ __name((style) => {
303
- switch (style) {
304
- case "form":
305
- return ",";
306
- case "pipeDelimited":
307
- return "|";
308
- case "spaceDelimited":
309
- return "%20";
310
- default:
311
- return ",";
156
+ // src/_api/generated/helpers/auth.ts
157
+ var ACCESS_KEY = "cfg.access_token";
158
+ var REFRESH_KEY = "cfg.refresh_token";
159
+ var API_KEY_KEY = "cfg.api_key";
160
+ var isBrowser = typeof window !== "undefined";
161
+ var localStorageBackend = {
162
+ get(key) {
163
+ if (!isBrowser) return null;
164
+ try {
165
+ return window.localStorage.getItem(key);
166
+ } catch {
167
+ return null;
168
+ }
169
+ },
170
+ set(key, value) {
171
+ if (!isBrowser) return;
172
+ try {
173
+ if (value === null) window.localStorage.removeItem(key);
174
+ else window.localStorage.setItem(key, value);
175
+ } catch {
176
+ }
177
+ }
178
+ };
179
+ var COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
180
+ var cookieBackend = {
181
+ get(key) {
182
+ if (!isBrowser) return null;
183
+ try {
184
+ const re = new RegExp(`(?:^|;\\s*)${encodeURIComponent(key)}=([^;]*)`);
185
+ const m = document.cookie.match(re);
186
+ return m ? decodeURIComponent(m[1]) : null;
187
+ } catch {
188
+ return null;
189
+ }
190
+ },
191
+ set(key, value) {
192
+ if (!isBrowser) return;
193
+ try {
194
+ const k = encodeURIComponent(key);
195
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
196
+ if (value === null) {
197
+ document.cookie = `${k}=; Path=/; Max-Age=0; SameSite=Lax${secure}`;
198
+ } else {
199
+ const v = encodeURIComponent(value);
200
+ document.cookie = `${k}=${v}; Path=/; Max-Age=${COOKIE_MAX_AGE}; SameSite=Lax${secure}`;
312
201
  }
313
- }, "separatorArrayNoExplode");
314
- separatorObjectExplode = /* @__PURE__ */ __name((style) => {
315
- switch (style) {
316
- case "label":
317
- return ".";
318
- case "matrix":
319
- return ";";
320
- case "simple":
321
- return ",";
322
- default:
323
- return "&";
324
- }
325
- }, "separatorObjectExplode");
326
- serializeArrayParam = /* @__PURE__ */ __name(({
327
- allowReserved,
328
- explode,
329
- name,
330
- style,
331
- value
332
- }) => {
333
- if (!explode) {
334
- const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
335
- switch (style) {
336
- case "label":
337
- return `.${joinedValues2}`;
338
- case "matrix":
339
- return `;${name}=${joinedValues2}`;
340
- case "simple":
341
- return joinedValues2;
342
- default:
343
- return `${name}=${joinedValues2}`;
344
- }
345
- }
346
- const separator = separatorArrayExplode(style);
347
- const joinedValues = value.map((v) => {
348
- if (style === "label" || style === "simple") {
349
- return allowReserved ? v : encodeURIComponent(v);
350
- }
351
- return serializePrimitiveParam({
352
- allowReserved,
353
- name,
354
- value: v
355
- });
356
- }).join(separator);
357
- return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
358
- }, "serializeArrayParam");
359
- serializePrimitiveParam = /* @__PURE__ */ __name(({
360
- allowReserved,
361
- name,
362
- value
363
- }) => {
364
- if (value === void 0 || value === null) {
365
- return "";
366
- }
367
- if (typeof value === "object") {
368
- throw new Error(
369
- "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
370
- );
371
- }
372
- return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
373
- }, "serializePrimitiveParam");
374
- serializeObjectParam = /* @__PURE__ */ __name(({
375
- allowReserved,
376
- explode,
377
- name,
378
- style,
379
- value,
380
- valueOnly
381
- }) => {
382
- if (value instanceof Date) {
383
- return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
384
- }
385
- if (style !== "deepObject" && !explode) {
386
- let values = [];
387
- Object.entries(value).forEach(([key, v]) => {
388
- values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
389
- });
390
- const joinedValues2 = values.join(",");
391
- switch (style) {
392
- case "form":
393
- return `${name}=${joinedValues2}`;
394
- case "label":
395
- return `.${joinedValues2}`;
396
- case "matrix":
397
- return `;${name}=${joinedValues2}`;
398
- default:
399
- return joinedValues2;
400
- }
401
- }
402
- const separator = separatorObjectExplode(style);
403
- const joinedValues = Object.entries(value).map(
404
- ([key, v]) => serializePrimitiveParam({
405
- allowReserved,
406
- name: style === "deepObject" ? `${name}[${key}]` : key,
407
- value: v
408
- })
409
- ).join(separator);
410
- return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
411
- }, "serializeObjectParam");
412
- }
413
- });
414
-
415
- // src/_api/generated/core/utils.gen.ts
416
- function getValidRequestBody(options) {
417
- const hasBody = options.body !== void 0;
418
- const isSerializedBody = hasBody && options.bodySerializer;
419
- if (isSerializedBody) {
420
- if ("serializedBody" in options) {
421
- const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
422
- return hasSerializedBody ? options.serializedBody : null;
202
+ } catch {
423
203
  }
424
- return options.body !== "" ? options.body : null;
425
204
  }
426
- if (hasBody) {
427
- return options.body;
205
+ };
206
+ var _storage = localStorageBackend;
207
+ var _storageMode = "localStorage";
208
+ function detectLocale() {
209
+ try {
210
+ if (typeof document !== "undefined") {
211
+ const m = document.cookie.match(/(?:^|;\s*)NEXT_LOCALE=([^;]*)/);
212
+ if (m) return decodeURIComponent(m[1]);
213
+ }
214
+ if (typeof navigator !== "undefined" && navigator.language) {
215
+ return navigator.language;
216
+ }
217
+ } catch {
428
218
  }
429
- return void 0;
219
+ return null;
430
220
  }
431
- var PATH_PARAM_RE, defaultPathSerializer, getUrl;
432
- var init_utils_gen = __esm({
433
- "src/_api/generated/core/utils.gen.ts"() {
434
- init_pathSerializer_gen();
435
- PATH_PARAM_RE = /\{[^{}]+\}/g;
436
- defaultPathSerializer = /* @__PURE__ */ __name(({ path, url: _url }) => {
437
- let url = _url;
438
- const matches = _url.match(PATH_PARAM_RE);
439
- if (matches) {
440
- for (const match of matches) {
441
- let explode = false;
442
- let name = match.substring(1, match.length - 1);
443
- let style = "simple";
444
- if (name.endsWith("*")) {
445
- explode = true;
446
- name = name.substring(0, name.length - 1);
447
- }
448
- if (name.startsWith(".")) {
449
- name = name.substring(1);
450
- style = "label";
451
- } else if (name.startsWith(";")) {
452
- name = name.substring(1);
453
- style = "matrix";
454
- }
455
- const value = path[name];
456
- if (value === void 0 || value === null) {
457
- continue;
458
- }
459
- if (Array.isArray(value)) {
460
- url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
461
- continue;
462
- }
463
- if (typeof value === "object") {
464
- url = url.replace(
465
- match,
466
- serializeObjectParam({
467
- explode,
468
- name,
469
- style,
470
- value,
471
- valueOnly: true
472
- })
473
- );
474
- continue;
475
- }
476
- if (style === "matrix") {
477
- url = url.replace(
478
- match,
479
- `;${serializePrimitiveParam({
480
- name,
481
- value
482
- })}`
483
- );
484
- continue;
485
- }
486
- const replaceValue = encodeURIComponent(
487
- style === "label" ? `.${value}` : value
488
- );
489
- url = url.replace(match, replaceValue);
490
- }
491
- }
492
- return url;
493
- }, "defaultPathSerializer");
494
- getUrl = /* @__PURE__ */ __name(({
495
- baseUrl,
496
- path,
497
- query,
498
- querySerializer,
499
- url: _url
500
- }) => {
501
- const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
502
- let url = (baseUrl ?? "") + pathUrl;
503
- if (path) {
504
- url = defaultPathSerializer({ path, url });
505
- }
506
- let search = query ? querySerializer(query) : "";
507
- if (search.startsWith("?")) {
508
- search = search.substring(1);
509
- }
510
- if (search) {
511
- url += `?${search}`;
221
+ __name(detectLocale, "detectLocale");
222
+ function defaultBaseUrl() {
223
+ if (typeof window !== "undefined") {
224
+ try {
225
+ if (typeof process !== "undefined" && process.env) {
226
+ if (process.env.NEXT_PUBLIC_STATIC_BUILD === "true") return "";
227
+ if (process.env.NEXT_PUBLIC_API_PROXY_URL !== void 0)
228
+ return process.env.NEXT_PUBLIC_API_PROXY_URL;
229
+ return process.env.NEXT_PUBLIC_API_URL || "";
512
230
  }
513
- return url;
514
- }, "getUrl");
515
- __name(getValidRequestBody, "getValidRequestBody");
231
+ } catch {
232
+ }
233
+ return "";
516
234
  }
517
- });
518
-
519
- // src/_api/generated/core/auth.gen.ts
520
- var getAuthToken;
521
- var init_auth_gen = __esm({
522
- "src/_api/generated/core/auth.gen.ts"() {
523
- getAuthToken = /* @__PURE__ */ __name(async (auth2, callback) => {
524
- const token = typeof callback === "function" ? await callback(auth2) : callback;
525
- if (!token) {
526
- return;
527
- }
528
- if (auth2.scheme === "bearer") {
529
- return `Bearer ${token}`;
530
- }
531
- if (auth2.scheme === "basic") {
532
- return `Basic ${btoa(token)}`;
533
- }
534
- return token;
535
- }, "getAuthToken");
235
+ try {
236
+ if (typeof process !== "undefined" && process.env) {
237
+ if (process.env.NEXT_PUBLIC_STATIC_BUILD === "true") return "";
238
+ return process.env.NEXT_PUBLIC_API_URL || "";
239
+ }
240
+ } catch {
536
241
  }
537
- });
538
-
539
- // src/_api/generated/client/utils.gen.ts
540
- async function setAuthParams(options) {
541
- for (const auth2 of options.security ?? []) {
542
- if (checkForExistence(options, auth2.name)) {
543
- continue;
242
+ return "";
243
+ }
244
+ __name(defaultBaseUrl, "defaultBaseUrl");
245
+ function defaultApiKey() {
246
+ try {
247
+ if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_KEY) {
248
+ return process.env.NEXT_PUBLIC_API_KEY;
544
249
  }
545
- const token = await getAuthToken(auth2, options.auth);
546
- if (!token) {
547
- continue;
250
+ } catch {
251
+ }
252
+ return null;
253
+ }
254
+ __name(defaultApiKey, "defaultApiKey");
255
+ var _localeOverride = null;
256
+ var _apiKeyOverride = null;
257
+ var _baseUrlOverride = null;
258
+ var _withCredentials = true;
259
+ var _onUnauthorized = null;
260
+ var _refreshHandler = null;
261
+ var _refreshInflight = null;
262
+ var RETRY_MARKER = "X-Auth-Retry";
263
+ function jwtExpMs(token) {
264
+ try {
265
+ const payload = token.split(".")[1];
266
+ if (!payload) return null;
267
+ const json = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
268
+ return typeof json.exp === "number" ? json.exp * 1e3 : null;
269
+ } catch {
270
+ return null;
271
+ }
272
+ }
273
+ __name(jwtExpMs, "jwtExpMs");
274
+ function computeSnapshot() {
275
+ const access = _storage.get(ACCESS_KEY);
276
+ const refresh = _storage.get(REFRESH_KEY);
277
+ const now = Date.now();
278
+ const accessExp = access ? jwtExpMs(access) : null;
279
+ const accessAlive = access !== null && (accessExp === null || accessExp > now);
280
+ const refreshExp = refresh ? jwtExpMs(refresh) : null;
281
+ const refreshAlive = refresh !== null && (refreshExp === null || refreshExp > now);
282
+ return {
283
+ status: accessAlive || refreshAlive ? "authenticated" : "anonymous",
284
+ accessExpiresAt: accessExp
285
+ };
286
+ }
287
+ __name(computeSnapshot, "computeSnapshot");
288
+ var SERVER_SNAPSHOT = { status: "anonymous", accessExpiresAt: null };
289
+ var SESSION_SYNC_EVENT = `cfg-auth:changed:${ACCESS_KEY}`;
290
+ var _snapshot = computeSnapshot();
291
+ var _sessionListeners = /* @__PURE__ */ new Set();
292
+ var _expiryTimer = null;
293
+ var _storageListenerInstalled = false;
294
+ function scheduleExpiryFlip() {
295
+ if (!isBrowser) return;
296
+ if (_expiryTimer !== null) {
297
+ clearTimeout(_expiryTimer);
298
+ _expiryTimer = null;
299
+ }
300
+ if (_sessionListeners.size === 0) return;
301
+ const now = Date.now();
302
+ const exps = [];
303
+ const access = _storage.get(ACCESS_KEY);
304
+ const refresh = _storage.get(REFRESH_KEY);
305
+ const accessExp = access ? jwtExpMs(access) : null;
306
+ const refreshExp = refresh ? jwtExpMs(refresh) : null;
307
+ if (accessExp !== null && accessExp > now) exps.push(accessExp);
308
+ if (refreshExp !== null && refreshExp > now) exps.push(refreshExp);
309
+ if (!exps.length) return;
310
+ const delay = Math.min(Math.min(...exps) - now + 250, 2147483647);
311
+ _expiryTimer = setTimeout(notifySessionChanged, delay);
312
+ }
313
+ __name(scheduleExpiryFlip, "scheduleExpiryFlip");
314
+ function notifySessionChanged() {
315
+ const next = computeSnapshot();
316
+ const changed = next.status !== _snapshot.status || next.accessExpiresAt !== _snapshot.accessExpiresAt;
317
+ if (changed) _snapshot = next;
318
+ scheduleExpiryFlip();
319
+ if (!changed) return;
320
+ for (const listener of Array.from(_sessionListeners)) {
321
+ try {
322
+ listener();
323
+ } catch {
548
324
  }
549
- const name = auth2.name ?? "Authorization";
550
- switch (auth2.in) {
551
- case "query":
552
- if (!options.query) {
553
- options.query = {};
554
- }
555
- options.query[name] = token;
556
- break;
557
- case "cookie":
558
- options.headers.append("Cookie", `${name}=${token}`);
559
- break;
560
- case "header":
561
- default:
562
- options.headers.set(name, token);
563
- break;
325
+ }
326
+ if (isBrowser) {
327
+ try {
328
+ window.dispatchEvent(new Event(SESSION_SYNC_EVENT));
329
+ } catch {
564
330
  }
565
331
  }
566
332
  }
567
- var createQuerySerializer, getParseAs, checkForExistence, buildUrl, mergeConfigs, headersEntries, mergeHeaders, Interceptors, createInterceptors, defaultQuerySerializer, defaultHeaders, createConfig;
568
- var init_utils_gen2 = __esm({
569
- "src/_api/generated/client/utils.gen.ts"() {
570
- init_auth_gen();
571
- init_bodySerializer_gen();
572
- init_pathSerializer_gen();
573
- init_utils_gen();
574
- createQuerySerializer = /* @__PURE__ */ __name(({
575
- parameters = {},
576
- ...args
577
- } = {}) => {
578
- const querySerializer = /* @__PURE__ */ __name((queryParams) => {
579
- const search = [];
580
- if (queryParams && typeof queryParams === "object") {
581
- for (const name in queryParams) {
582
- const value = queryParams[name];
583
- if (value === void 0 || value === null) {
584
- continue;
585
- }
586
- const options = parameters[name] || args;
587
- if (Array.isArray(value)) {
588
- const serializedArray = serializeArrayParam({
589
- allowReserved: options.allowReserved,
590
- explode: true,
591
- name,
592
- style: "form",
593
- value,
594
- ...options.array
595
- });
596
- if (serializedArray) search.push(serializedArray);
597
- } else if (typeof value === "object") {
598
- const serializedObject = serializeObjectParam({
599
- allowReserved: options.allowReserved,
600
- explode: true,
601
- name,
602
- style: "deepObject",
603
- value,
604
- ...options.object
605
- });
606
- if (serializedObject) search.push(serializedObject);
607
- } else {
608
- const serializedPrimitive = serializePrimitiveParam({
609
- allowReserved: options.allowReserved,
610
- name,
611
- value
612
- });
613
- if (serializedPrimitive) search.push(serializedPrimitive);
614
- }
615
- }
616
- }
617
- return search.join("&");
618
- }, "querySerializer");
619
- return querySerializer;
620
- }, "createQuerySerializer");
621
- getParseAs = /* @__PURE__ */ __name((contentType) => {
622
- if (!contentType) {
623
- return "stream";
624
- }
625
- const cleanContent = contentType.split(";")[0]?.trim();
626
- if (!cleanContent) {
627
- return;
628
- }
629
- if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
630
- return "json";
631
- }
632
- if (cleanContent === "multipart/form-data") {
633
- return "formData";
634
- }
635
- if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
636
- return "blob";
637
- }
638
- if (cleanContent.startsWith("text/")) {
639
- return "text";
640
- }
641
- return;
642
- }, "getParseAs");
643
- checkForExistence = /* @__PURE__ */ __name((options, name) => {
644
- if (!name) {
645
- return false;
646
- }
647
- if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
648
- return true;
649
- }
650
- return false;
651
- }, "checkForExistence");
652
- __name(setAuthParams, "setAuthParams");
653
- buildUrl = /* @__PURE__ */ __name((options) => getUrl({
654
- baseUrl: options.baseUrl,
655
- path: options.path,
656
- query: options.query,
657
- querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
658
- url: options.url
659
- }), "buildUrl");
660
- mergeConfigs = /* @__PURE__ */ __name((a, b) => {
661
- const config = { ...a, ...b };
662
- if (config.baseUrl?.endsWith("/")) {
663
- config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
664
- }
665
- config.headers = mergeHeaders(a.headers, b.headers);
666
- return config;
667
- }, "mergeConfigs");
668
- headersEntries = /* @__PURE__ */ __name((headers) => {
669
- const entries = [];
670
- headers.forEach((value, key) => {
671
- entries.push([key, value]);
672
- });
673
- return entries;
674
- }, "headersEntries");
675
- mergeHeaders = /* @__PURE__ */ __name((...headers) => {
676
- const mergedHeaders = new Headers();
677
- for (const header of headers) {
678
- if (!header) {
679
- continue;
680
- }
681
- const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
682
- for (const [key, value] of iterator) {
683
- if (value === null) {
684
- mergedHeaders.delete(key);
685
- } else if (Array.isArray(value)) {
686
- for (const v of value) {
687
- mergedHeaders.append(key, v);
688
- }
689
- } else if (value !== void 0) {
690
- mergedHeaders.set(
691
- key,
692
- typeof value === "object" ? JSON.stringify(value) : value
693
- );
694
- }
695
- }
696
- }
697
- return mergedHeaders;
698
- }, "mergeHeaders");
699
- Interceptors = class {
700
- static {
701
- __name(this, "Interceptors");
702
- }
703
- fns = [];
704
- clear() {
705
- this.fns = [];
706
- }
707
- eject(id) {
708
- const index = this.getInterceptorIndex(id);
709
- if (this.fns[index]) {
710
- this.fns[index] = null;
711
- }
712
- }
713
- exists(id) {
714
- const index = this.getInterceptorIndex(id);
715
- return Boolean(this.fns[index]);
716
- }
717
- getInterceptorIndex(id) {
718
- if (typeof id === "number") {
719
- return this.fns[id] ? id : -1;
720
- }
721
- return this.fns.indexOf(id);
722
- }
723
- update(id, fn) {
724
- const index = this.getInterceptorIndex(id);
725
- if (this.fns[index]) {
726
- this.fns[index] = fn;
727
- return id;
728
- }
729
- return false;
730
- }
731
- use(fn) {
732
- this.fns.push(fn);
733
- return this.fns.length - 1;
333
+ __name(notifySessionChanged, "notifySessionChanged");
334
+ function ensureStorageSync() {
335
+ if (!isBrowser || _storageListenerInstalled) return;
336
+ _storageListenerInstalled = true;
337
+ window.addEventListener("storage", (e) => {
338
+ if (e.key === null || e.key === ACCESS_KEY || e.key === REFRESH_KEY) {
339
+ notifySessionChanged();
340
+ }
341
+ });
342
+ window.addEventListener(SESSION_SYNC_EVENT, () => notifySessionChanged());
343
+ }
344
+ __name(ensureStorageSync, "ensureStorageSync");
345
+ var _sessionExpiredHandlers = /* @__PURE__ */ new Set();
346
+ var _client = null;
347
+ function pushClientConfig() {
348
+ if (!_client) return;
349
+ _client.setConfig({
350
+ baseUrl: auth.getBaseUrl(),
351
+ credentials: _withCredentials ? "include" : "same-origin"
352
+ });
353
+ }
354
+ __name(pushClientConfig, "pushClientConfig");
355
+ var auth = {
356
+ // ── Storage mode ──────────────────────────────────────────────────
357
+ getStorageMode() {
358
+ return _storageMode;
359
+ },
360
+ setStorageMode(mode) {
361
+ _storageMode = mode;
362
+ _storage = mode === "cookie" ? cookieBackend : localStorageBackend;
363
+ notifySessionChanged();
364
+ },
365
+ // ── Bearer token ──────────────────────────────────────────────────
366
+ getToken() {
367
+ return _storage.get(ACCESS_KEY);
368
+ },
369
+ setToken(token) {
370
+ _storage.set(ACCESS_KEY, token);
371
+ notifySessionChanged();
372
+ },
373
+ getRefreshToken() {
374
+ return _storage.get(REFRESH_KEY);
375
+ },
376
+ setRefreshToken(token) {
377
+ _storage.set(REFRESH_KEY, token);
378
+ notifySessionChanged();
379
+ },
380
+ clearTokens() {
381
+ _storage.set(ACCESS_KEY, null);
382
+ _storage.set(REFRESH_KEY, null);
383
+ notifySessionChanged();
384
+ },
385
+ /** Session-aware: token PRESENT and not past its `exp` (or a live refresh
386
+ * token exists that can mint one). Prefer `getSnapshot().status` in React. */
387
+ isAuthenticated() {
388
+ return computeSnapshot().status === "authenticated";
389
+ },
390
+ // ── Session (the ONE write path for login/logout flows) ──────────
391
+ /**
392
+ * Persist a token pair atomically. Every login flow (OTP verify, 2FA,
393
+ * OAuth callback) and the refresh handler should end here — do NOT
394
+ * scatter `setToken`/`setRefreshToken` pairs through app code.
395
+ * `refresh: undefined` keeps the current refresh token (access-only
396
+ * rotation); `refresh: null` explicitly drops it.
397
+ */
398
+ setSession(tokens) {
399
+ _storage.set(ACCESS_KEY, tokens.access);
400
+ if (tokens.refresh !== void 0) _storage.set(REFRESH_KEY, tokens.refresh);
401
+ notifySessionChanged();
402
+ },
403
+ clearSession() {
404
+ auth.clearTokens();
405
+ },
406
+ // ── Reactive snapshot (for useSyncExternalStore) ──────────────────
407
+ /**
408
+ * @example React:
409
+ * const session = useSyncExternalStore(
410
+ * auth.subscribe, auth.getSnapshot, auth.getServerSnapshot,
411
+ * );
412
+ * const isAuthenticated = session.status === 'authenticated';
413
+ */
414
+ getSnapshot() {
415
+ return _snapshot;
416
+ },
417
+ getServerSnapshot() {
418
+ return SERVER_SNAPSHOT;
419
+ },
420
+ subscribe(listener) {
421
+ ensureStorageSync();
422
+ _sessionListeners.add(listener);
423
+ notifySessionChanged();
424
+ return () => {
425
+ _sessionListeners.delete(listener);
426
+ if (_sessionListeners.size === 0 && _expiryTimer !== null) {
427
+ clearTimeout(_expiryTimer);
428
+ _expiryTimer = null;
734
429
  }
735
430
  };
736
- createInterceptors = /* @__PURE__ */ __name(() => ({
737
- error: new Interceptors(),
738
- request: new Interceptors(),
739
- response: new Interceptors()
740
- }), "createInterceptors");
741
- defaultQuerySerializer = createQuerySerializer({
742
- allowReserved: false,
743
- array: {
744
- explode: true,
745
- style: "form"
746
- },
747
- object: {
748
- explode: true,
749
- style: "deepObject"
750
- }
751
- });
752
- defaultHeaders = {
753
- "Content-Type": "application/json"
431
+ },
432
+ /**
433
+ * Fired on TERMINAL 401 — after the refresh+retry path is exhausted.
434
+ * The store has already cleared the session before calling back, so
435
+ * handlers only need to route to login (no clear-then-redirect
436
+ * ordering to get wrong). Returns an unsubscribe function; multiple
437
+ * handlers compose (unlike the legacy single-slot `onUnauthorized`).
438
+ */
439
+ onSessionExpired(cb) {
440
+ _sessionExpiredHandlers.add(cb);
441
+ return () => {
442
+ _sessionExpiredHandlers.delete(cb);
754
443
  };
755
- createConfig = /* @__PURE__ */ __name((override = {}) => ({
756
- ...jsonBodySerializer,
757
- headers: defaultHeaders,
758
- parseAs: "auto",
759
- querySerializer: defaultQuerySerializer,
760
- ...override
761
- }), "createConfig");
762
- }
763
- });
764
-
765
- // src/_api/generated/client/client.gen.ts
766
- var createClient;
767
- var init_client_gen = __esm({
768
- "src/_api/generated/client/client.gen.ts"() {
769
- init_serverSentEvents_gen();
770
- init_utils_gen();
771
- init_utils_gen2();
772
- createClient = /* @__PURE__ */ __name((config = {}) => {
773
- let _config = mergeConfigs(createConfig(), config);
774
- const getConfig = /* @__PURE__ */ __name(() => ({ ..._config }), "getConfig");
775
- const setConfig = /* @__PURE__ */ __name((config2) => {
776
- _config = mergeConfigs(_config, config2);
777
- return getConfig();
778
- }, "setConfig");
779
- const interceptors = createInterceptors();
780
- const beforeRequest = /* @__PURE__ */ __name(async (options) => {
781
- const opts = {
782
- ..._config,
783
- ...options,
784
- fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
785
- headers: mergeHeaders(_config.headers, options.headers),
786
- serializedBody: void 0
787
- };
788
- if (opts.security) {
789
- await setAuthParams(opts);
790
- }
791
- if (opts.requestValidator) {
792
- await opts.requestValidator(opts);
793
- }
794
- if (opts.body !== void 0 && opts.bodySerializer) {
795
- opts.serializedBody = opts.bodySerializer(opts.body);
796
- }
797
- if (opts.body === void 0 || opts.serializedBody === "") {
798
- opts.headers.delete("Content-Type");
799
- }
800
- const resolvedOpts = opts;
801
- const url = buildUrl(resolvedOpts);
802
- return { opts: resolvedOpts, url };
803
- }, "beforeRequest");
804
- const request = /* @__PURE__ */ __name(async (options) => {
805
- const throwOnError = options.throwOnError ?? _config.throwOnError;
806
- const responseStyle = options.responseStyle ?? _config.responseStyle;
807
- let request2;
808
- let response;
809
- try {
810
- const { opts, url } = await beforeRequest(options);
811
- const requestInit = {
812
- redirect: "follow",
813
- ...opts,
814
- body: getValidRequestBody(opts)
815
- };
816
- request2 = new Request(url, requestInit);
817
- for (const fn of interceptors.request.fns) {
818
- if (fn) {
819
- request2 = await fn(request2, opts);
820
- }
821
- }
822
- const _fetch = opts.fetch;
823
- response = await _fetch(request2);
824
- for (const fn of interceptors.response.fns) {
825
- if (fn) {
826
- response = await fn(response, request2, opts);
827
- }
828
- }
829
- const result = {
830
- request: request2,
831
- response
832
- };
833
- if (response.ok) {
834
- const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
835
- if (response.status === 204 || response.headers.get("Content-Length") === "0") {
836
- let emptyData;
837
- switch (parseAs) {
838
- case "arrayBuffer":
839
- case "blob":
840
- case "text":
841
- emptyData = await response[parseAs]();
842
- break;
843
- case "formData":
844
- emptyData = new FormData();
845
- break;
846
- case "stream":
847
- emptyData = response.body;
848
- break;
849
- case "json":
850
- default:
851
- emptyData = {};
852
- break;
853
- }
854
- return opts.responseStyle === "data" ? emptyData : {
855
- data: emptyData,
856
- ...result
857
- };
858
- }
859
- let data;
860
- switch (parseAs) {
861
- case "arrayBuffer":
862
- case "blob":
863
- case "formData":
864
- case "text":
865
- data = await response[parseAs]();
866
- break;
867
- case "json": {
868
- const text = await response.text();
869
- data = text ? JSON.parse(text) : {};
870
- break;
871
- }
872
- case "stream":
873
- return opts.responseStyle === "data" ? response.body : {
874
- data: response.body,
875
- ...result
876
- };
877
- }
878
- if (parseAs === "json") {
879
- if (opts.responseValidator) {
880
- await opts.responseValidator(data);
881
- }
882
- if (opts.responseTransformer) {
883
- data = await opts.responseTransformer(data);
884
- }
885
- }
886
- return opts.responseStyle === "data" ? data : {
887
- data,
888
- ...result
889
- };
890
- }
891
- const textError = await response.text();
892
- let jsonError;
893
- try {
894
- jsonError = JSON.parse(textError);
895
- } catch {
896
- }
897
- throw jsonError ?? textError;
898
- } catch (error) {
899
- let finalError = error;
900
- for (const fn of interceptors.error.fns) {
901
- if (fn) {
902
- finalError = await fn(finalError, response, request2, options);
903
- }
904
- }
905
- finalError = finalError || {};
906
- if (throwOnError) {
907
- throw finalError;
908
- }
909
- return responseStyle === "data" ? void 0 : {
910
- error: finalError,
911
- request: request2,
912
- response
913
- };
914
- }
915
- }, "request");
916
- const makeMethodFn = /* @__PURE__ */ __name((method) => (options) => request({ ...options, method }), "makeMethodFn");
917
- const makeSseFn = /* @__PURE__ */ __name((method) => async (options) => {
918
- const { opts, url } = await beforeRequest(options);
919
- return createSseClient({
920
- ...opts,
921
- body: opts.body,
922
- method,
923
- onRequest: /* @__PURE__ */ __name(async (url2, init) => {
924
- let request2 = new Request(url2, init);
925
- for (const fn of interceptors.request.fns) {
926
- if (fn) {
927
- request2 = await fn(request2, opts);
928
- }
929
- }
930
- return request2;
931
- }, "onRequest"),
932
- serializedBody: getValidRequestBody(opts),
933
- url
934
- });
935
- }, "makeSseFn");
936
- const _buildUrl = /* @__PURE__ */ __name((options) => buildUrl({ ..._config, ...options }), "_buildUrl");
937
- return {
938
- buildUrl: _buildUrl,
939
- connect: makeMethodFn("CONNECT"),
940
- delete: makeMethodFn("DELETE"),
941
- get: makeMethodFn("GET"),
942
- getConfig,
943
- head: makeMethodFn("HEAD"),
944
- interceptors,
945
- options: makeMethodFn("OPTIONS"),
946
- patch: makeMethodFn("PATCH"),
947
- post: makeMethodFn("POST"),
948
- put: makeMethodFn("PUT"),
949
- request,
950
- setConfig,
951
- sse: {
952
- connect: makeSseFn("CONNECT"),
953
- delete: makeSseFn("DELETE"),
954
- get: makeSseFn("GET"),
955
- head: makeSseFn("HEAD"),
956
- options: makeSseFn("OPTIONS"),
957
- patch: makeSseFn("PATCH"),
958
- post: makeSseFn("POST"),
959
- put: makeSseFn("PUT"),
960
- trace: makeSseFn("TRACE")
961
- },
962
- trace: makeMethodFn("TRACE")
963
- };
964
- }, "createClient");
965
- }
966
- });
967
-
968
- // src/_api/generated/client/index.ts
969
- var init_client = __esm({
970
- "src/_api/generated/client/index.ts"() {
971
- init_bodySerializer_gen();
972
- init_params_gen();
973
- init_queryKeySerializer_gen();
974
- init_client_gen();
975
- init_utils_gen2();
976
- }
977
- });
978
-
979
- // src/_api/generated/client.gen.ts
980
- var client;
981
- var init_client_gen2 = __esm({
982
- "src/_api/generated/client.gen.ts"() {
983
- init_client();
984
- init_auth();
985
- client = createClient(createConfig({ baseUrl: "http://localhost:8000" }));
986
- installAuthOnClient(client);
444
+ },
445
+ // ── API key ───────────────────────────────────────────────────────
446
+ getApiKey() {
447
+ return _apiKeyOverride ?? _storage.get(API_KEY_KEY) ?? defaultApiKey();
448
+ },
449
+ setApiKey(key) {
450
+ _apiKeyOverride = key;
451
+ },
452
+ setApiKeyPersist(key) {
453
+ _apiKeyOverride = key;
454
+ _storage.set(API_KEY_KEY, key);
455
+ },
456
+ clearApiKey() {
457
+ _apiKeyOverride = null;
458
+ _storage.set(API_KEY_KEY, null);
459
+ },
460
+ // ── Locale ────────────────────────────────────────────────────────
461
+ getLocale() {
462
+ return _localeOverride ?? detectLocale();
463
+ },
464
+ setLocale(locale) {
465
+ _localeOverride = locale;
466
+ },
467
+ // ── Base URL ──────────────────────────────────────────────────────
468
+ getBaseUrl() {
469
+ const url = _baseUrlOverride ?? defaultBaseUrl();
470
+ return url.replace(/\/$/, "");
471
+ },
472
+ setBaseUrl(url) {
473
+ _baseUrlOverride = url ? url.replace(/\/$/, "") : null;
474
+ pushClientConfig();
475
+ },
476
+ // ── Credentials toggle ────────────────────────────────────────────
477
+ getWithCredentials() {
478
+ return _withCredentials;
479
+ },
480
+ setWithCredentials(value) {
481
+ _withCredentials = value;
482
+ pushClientConfig();
483
+ },
484
+ // ── 401 handler ───────────────────────────────────────────────────
485
+ /**
486
+ * Fired when the server returns 401 AND no refresh path recovers it
487
+ * (no refresh token, no refresh handler, refresh failed, or retry
488
+ * still 401). The app should clear local state and redirect to login.
489
+ *
490
+ * NOT fired for 401 that gets transparently recovered by the refresh
491
+ * handler those are invisible to callers.
492
+ */
493
+ onUnauthorized(cb) {
494
+ _onUnauthorized = cb;
495
+ },
496
+ /**
497
+ * Register the refresh strategy. The handler receives the current
498
+ * refresh token and must call your refresh endpoint, returning
499
+ * `{ access, refresh? }` on success or `null` on failure.
500
+ *
501
+ * @example
502
+ * auth.setRefreshHandler(async (refresh) => {
503
+ * const { data } = await Auth.tokenRefreshCreate({ body: { refresh } });
504
+ * return data ? { access: data.access, refresh: data.refresh } : null;
505
+ * });
506
+ */
507
+ setRefreshHandler(fn) {
508
+ _refreshHandler = fn;
509
+ },
510
+ /**
511
+ * Proactively run the registered refresh handler right now, reusing the
512
+ * SAME single-flight promise as the 401-recovery interceptor. Callers
513
+ * (e.g. an expiry timer / focus / reconnect) get token rotation,
514
+ * de-duplication and rotated-token persistence for free — they must NOT
515
+ * re-implement any of it. Returns the fresh access token, or null if
516
+ * there is no handler / no refresh token / the refresh failed.
517
+ */
518
+ refreshNow() {
519
+ return tryRefresh();
987
520
  }
988
- });
989
-
990
- // src/_api/generated/sdk.gen.ts
991
- var sdk_gen_exports = {};
992
- __export(sdk_gen_exports, {
993
- CfgAccounts: () => CfgAccounts,
994
- CfgAccountsApiKey: () => CfgAccountsApiKey,
995
- CfgAccountsAuth: () => CfgAccountsAuth,
996
- CfgAccountsOauth: () => CfgAccountsOauth,
997
- CfgAccountsProfile: () => CfgAccountsProfile,
998
- CfgCentrifugo: () => CfgCentrifugo,
999
- CfgTotp: () => CfgTotp,
1000
- CfgTotpBackupCodes: () => CfgTotpBackupCodes,
1001
- CfgTotpSetup: () => CfgTotpSetup,
1002
- CfgTotpVerify: () => CfgTotpVerify
1003
- });
1004
- var CfgAccountsApiKey, CfgAccountsOauth, CfgAccounts, CfgAccountsProfile, CfgAccountsAuth, CfgCentrifugo, CfgTotpBackupCodes, CfgTotp, CfgTotpSetup, CfgTotpVerify;
1005
- var init_sdk_gen = __esm({
1006
- "src/_api/generated/sdk.gen.ts"() {
1007
- init_client();
1008
- init_client_gen2();
1009
- CfgAccountsApiKey = class {
1010
- static {
1011
- __name(this, "CfgAccountsApiKey");
1012
- }
1013
- /**
1014
- * Get API key details
1015
- *
1016
- * Retrieve the current user's API key (masked) and metadata.
1017
- */
1018
- static cfgAccountsApiKeyRetrieve(options) {
1019
- return (options?.client ?? client).get({
1020
- security: [
1021
- { scheme: "bearer", type: "http" },
1022
- {
1023
- in: "cookie",
1024
- name: "sessionid",
1025
- type: "apiKey"
1026
- },
1027
- { name: "X-API-Key", type: "apiKey" }
1028
- ],
1029
- url: "/cfg/accounts/api-key/",
1030
- ...options
1031
- });
1032
- }
1033
- /**
1034
- * Regenerate API key
1035
- *
1036
- * Generate a new API key. The full key is returned only once.
1037
- */
1038
- static cfgAccountsApiKeyRegenerateCreate(options) {
1039
- return (options.client ?? client).post({
1040
- security: [
1041
- { scheme: "bearer", type: "http" },
1042
- {
1043
- in: "cookie",
1044
- name: "sessionid",
1045
- type: "apiKey"
1046
- },
1047
- { name: "X-API-Key", type: "apiKey" }
1048
- ],
1049
- url: "/cfg/accounts/api-key/regenerate/",
1050
- ...options,
1051
- headers: {
1052
- "Content-Type": "application/json",
1053
- ...options.headers
1054
- }
1055
- });
1056
- }
1057
- /**
1058
- * Reveal API key
1059
- *
1060
- * Return the current full API key WITHOUT rotating it. The same durable value every one of the user's agents uses — for the signed-in user to copy and paste into agent onboarding. Default GET stays masked; this is the explicit reveal action.
1061
- */
1062
- static cfgAccountsApiKeyRevealCreate(options) {
1063
- return (options.client ?? client).post({
1064
- security: [
1065
- { scheme: "bearer", type: "http" },
1066
- {
1067
- in: "cookie",
1068
- name: "sessionid",
1069
- type: "apiKey"
1070
- },
1071
- { name: "X-API-Key", type: "apiKey" }
1072
- ],
1073
- url: "/cfg/accounts/api-key/reveal/",
1074
- ...options,
1075
- headers: {
1076
- "Content-Type": "application/json",
1077
- ...options.headers
1078
- }
1079
- });
1080
- }
1081
- /**
1082
- * Test API key
1083
- *
1084
- * Test whether an API key is valid without consuming it.
1085
- */
1086
- static cfgAccountsApiKeyTestCreate(options) {
1087
- return (options.client ?? client).post({
1088
- security: [
1089
- { scheme: "bearer", type: "http" },
1090
- {
1091
- in: "cookie",
1092
- name: "sessionid",
1093
- type: "apiKey"
1094
- },
1095
- { name: "X-API-Key", type: "apiKey" }
1096
- ],
1097
- url: "/cfg/accounts/api-key/test/",
1098
- ...options,
1099
- headers: {
1100
- "Content-Type": "application/json",
1101
- ...options.headers
1102
- }
1103
- });
1104
- }
1105
- };
1106
- CfgAccountsOauth = class {
1107
- static {
1108
- __name(this, "CfgAccountsOauth");
1109
- }
1110
- /**
1111
- * List OAuth connections
1112
- *
1113
- * Get all OAuth connections for the current user.
1114
- */
1115
- static cfgAccountsOauthConnectionsList(options) {
1116
- return (options?.client ?? client).get({
1117
- security: [
1118
- { name: "X-API-Key", type: "apiKey" },
1119
- { scheme: "bearer", type: "http" },
1120
- { name: "Authorization", type: "apiKey" }
1121
- ],
1122
- url: "/cfg/accounts/oauth/connections/",
1123
- ...options
1124
- });
1125
- }
1126
- /**
1127
- * Disconnect OAuth provider
1128
- *
1129
- * Remove OAuth connection for the specified provider.
1130
- */
1131
- static cfgAccountsOauthDisconnectCreate(options) {
1132
- return (options.client ?? client).post({
1133
- security: [
1134
- { name: "X-API-Key", type: "apiKey" },
1135
- { scheme: "bearer", type: "http" },
1136
- { name: "Authorization", type: "apiKey" }
1137
- ],
1138
- url: "/cfg/accounts/oauth/disconnect/",
1139
- ...options,
1140
- headers: {
1141
- "Content-Type": "application/json",
1142
- ...options.headers
1143
- }
1144
- });
1145
- }
1146
- /**
1147
- * Start GitHub OAuth
1148
- *
1149
- * Generate GitHub OAuth authorization URL. Redirect user to this URL to start authentication.
1150
- */
1151
- static cfgAccountsOauthGithubAuthorizeCreate(options) {
1152
- return (options?.client ?? client).post({
1153
- url: "/cfg/accounts/oauth/github/authorize/",
1154
- ...options,
1155
- headers: {
1156
- "Content-Type": "application/json",
1157
- ...options?.headers
1158
- }
1159
- });
1160
- }
1161
- /**
1162
- * Complete GitHub OAuth
1163
- *
1164
- * Exchange authorization code for JWT tokens. Call this after GitHub redirects back with code.
1165
- */
1166
- static cfgAccountsOauthGithubCallbackCreate(options) {
1167
- return (options.client ?? client).post({
1168
- url: "/cfg/accounts/oauth/github/callback/",
1169
- ...options,
1170
- headers: {
1171
- "Content-Type": "application/json",
1172
- ...options.headers
1173
- }
1174
- });
1175
- }
1176
- /**
1177
- * List OAuth providers
1178
- *
1179
- * Get list of available OAuth providers for authentication.
1180
- */
1181
- static cfgAccountsOauthProvidersRetrieve(options) {
1182
- return (options?.client ?? client).get({ url: "/cfg/accounts/oauth/providers/", ...options });
1183
- }
1184
- };
1185
- CfgAccounts = class {
1186
- static {
1187
- __name(this, "CfgAccounts");
1188
- }
1189
- /**
1190
- * Request OTP code to email.
1191
- */
1192
- static cfgAccountsOtpRequestCreate(options) {
1193
- return (options.client ?? client).post({
1194
- security: [
1195
- { name: "X-API-Key", type: "apiKey" },
1196
- { scheme: "bearer", type: "http" },
1197
- { name: "Authorization", type: "apiKey" }
1198
- ],
1199
- url: "/cfg/accounts/otp/request/",
1200
- ...options,
1201
- headers: {
1202
- "Content-Type": "application/json",
1203
- ...options.headers
1204
- }
1205
- });
1206
- }
1207
- /**
1208
- * Verify OTP code and return JWT tokens or 2FA session.
1209
- *
1210
- * If user has 2FA enabled:
1211
- * - Returns requires_2fa=True with session_id
1212
- * - Client must complete 2FA verification at /cfg/totp/verify/
1213
- *
1214
- * If user has no 2FA:
1215
- * - Returns JWT tokens and user data directly
1216
- */
1217
- static cfgAccountsOtpVerifyCreate(options) {
1218
- return (options.client ?? client).post({
1219
- security: [
1220
- { name: "X-API-Key", type: "apiKey" },
1221
- { scheme: "bearer", type: "http" },
1222
- { name: "Authorization", type: "apiKey" }
1223
- ],
1224
- url: "/cfg/accounts/otp/verify/",
1225
- ...options,
1226
- headers: {
1227
- "Content-Type": "application/json",
1228
- ...options.headers
1229
- }
1230
- });
1231
- }
1232
- };
1233
- CfgAccountsProfile = class {
1234
- static {
1235
- __name(this, "CfgAccountsProfile");
1236
- }
1237
- /**
1238
- * Get current user profile
1239
- *
1240
- * Retrieve the current authenticated user's profile information.
1241
- */
1242
- static cfgAccountsProfileRetrieve(options) {
1243
- return (options?.client ?? client).get({
1244
- security: [{ scheme: "bearer", type: "http" }, {
1245
- in: "cookie",
1246
- name: "sessionid",
1247
- type: "apiKey"
1248
- }],
1249
- url: "/cfg/accounts/profile/",
1250
- ...options
1251
- });
1252
- }
1253
- /**
1254
- * Upload user avatar
1255
- *
1256
- * Upload avatar image for the current authenticated user. Accepts multipart/form-data with 'avatar' field.
1257
- */
1258
- static cfgAccountsProfileAvatarCreate(options) {
1259
- return (options?.client ?? client).post({
1260
- ...formDataBodySerializer,
1261
- security: [
1262
- { name: "X-API-Key", type: "apiKey" },
1263
- { scheme: "bearer", type: "http" },
1264
- { name: "Authorization", type: "apiKey" }
1265
- ],
1266
- url: "/cfg/accounts/profile/avatar/",
1267
- ...options,
1268
- headers: {
1269
- "Content-Type": null,
1270
- ...options?.headers
1271
- }
1272
- });
1273
- }
1274
- /**
1275
- * Delete user account
1276
- *
1277
- *
1278
- * Permanently delete the current user's account.
1279
- *
1280
- * This operation:
1281
- * - Deactivates the account (user cannot log in)
1282
- * - Anonymizes personal data (GDPR compliance)
1283
- * - Frees up the email address for re-registration
1284
- * - Preserves audit trail
1285
- *
1286
- * The account can be restored by an administrator if needed.
1287
- *
1288
- */
1289
- static cfgAccountsProfileDeleteCreate(options) {
1290
- return (options?.client ?? client).post({
1291
- security: [{ scheme: "bearer", type: "http" }, {
1292
- in: "cookie",
1293
- name: "sessionid",
1294
- type: "apiKey"
1295
- }],
1296
- url: "/cfg/accounts/profile/delete/",
1297
- ...options
1298
- });
1299
- }
1300
- /**
1301
- * Partial update user profile
1302
- *
1303
- * Partially update the current authenticated user's profile information. Supports avatar upload.
1304
- */
1305
- static cfgAccountsProfilePartialPartialUpdate(options) {
1306
- return (options?.client ?? client).patch({
1307
- security: [{ scheme: "bearer", type: "http" }, {
1308
- in: "cookie",
1309
- name: "sessionid",
1310
- type: "apiKey"
1311
- }],
1312
- url: "/cfg/accounts/profile/partial/",
1313
- ...options,
1314
- headers: {
1315
- "Content-Type": "application/json",
1316
- ...options?.headers
1317
- }
1318
- });
1319
- }
1320
- /**
1321
- * Partial update user profile
1322
- *
1323
- * Partially update the current authenticated user's profile information. Supports avatar upload.
1324
- */
1325
- static cfgAccountsProfilePartialUpdate(options) {
1326
- return (options?.client ?? client).put({
1327
- security: [{ scheme: "bearer", type: "http" }, {
1328
- in: "cookie",
1329
- name: "sessionid",
1330
- type: "apiKey"
1331
- }],
1332
- url: "/cfg/accounts/profile/partial/",
1333
- ...options,
1334
- headers: {
1335
- "Content-Type": "application/json",
1336
- ...options?.headers
1337
- }
1338
- });
1339
- }
1340
- /**
1341
- * Update user profile
1342
- *
1343
- * Update the current authenticated user's profile information.
1344
- */
1345
- static cfgAccountsProfileUpdatePartialUpdate(options) {
1346
- return (options?.client ?? client).patch({
1347
- security: [{ scheme: "bearer", type: "http" }, {
1348
- in: "cookie",
1349
- name: "sessionid",
1350
- type: "apiKey"
1351
- }],
1352
- url: "/cfg/accounts/profile/update/",
1353
- ...options,
1354
- headers: {
1355
- "Content-Type": "application/json",
1356
- ...options?.headers
1357
- }
1358
- });
1359
- }
1360
- /**
1361
- * Update user profile
1362
- *
1363
- * Update the current authenticated user's profile information.
1364
- */
1365
- static cfgAccountsProfileUpdateUpdate(options) {
1366
- return (options?.client ?? client).put({
1367
- security: [{ scheme: "bearer", type: "http" }, {
1368
- in: "cookie",
1369
- name: "sessionid",
1370
- type: "apiKey"
1371
- }],
1372
- url: "/cfg/accounts/profile/update/",
1373
- ...options,
1374
- headers: {
1375
- "Content-Type": "application/json",
1376
- ...options?.headers
1377
- }
1378
- });
1379
- }
1380
- };
1381
- CfgAccountsAuth = class {
1382
- static {
1383
- __name(this, "CfgAccountsAuth");
1384
- }
1385
- /**
1386
- * Revoke a refresh token (logout).
1387
- *
1388
- * Blacklists the posted refresh token so it can never mint another access
1389
- * token. Called best-effort by the client's logout — without it, "logout"
1390
- * is purely client-side and a stolen refresh token survives until expiry.
1391
- */
1392
- static cfgAccountsTokenBlacklistCreate(options) {
1393
- return (options.client ?? client).post({
1394
- url: "/cfg/accounts/token/blacklist/",
1395
- ...options,
1396
- headers: {
1397
- "Content-Type": "application/json",
1398
- ...options.headers
1399
- }
1400
- });
1401
- }
1402
- /**
1403
- * Refresh JWT token.
1404
- *
1405
- * DPoP-aware: when the incoming refresh token is key-bound (`cnf.jkt`), the
1406
- * rotated access/refresh in the response are re-stamped with the same `cnf`
1407
- * (stock SimpleJWT drops it from the derived access), and a matching DPoP
1408
- * proof is required on the refresh request — so a stolen refresh token can't
1409
- * be used to mint fresh tokens.
1410
- */
1411
- static cfgAccountsTokenRefreshCreate(options) {
1412
- return (options.client ?? client).post({
1413
- url: "/cfg/accounts/token/refresh/",
1414
- ...options,
1415
- headers: {
1416
- "Content-Type": "application/json",
1417
- ...options.headers
1418
- }
1419
- });
1420
- }
1421
- };
1422
- CfgCentrifugo = class {
1423
- static {
1424
- __name(this, "CfgCentrifugo");
1425
- }
1426
- /**
1427
- * Get Centrifugo connection token
1428
- *
1429
- * Generate JWT token for WebSocket connection to Centrifugo. Token includes user's allowed channels based on their permissions. Requires authentication.
1430
- */
1431
- static cfgCentrifugoAuthTokenRetrieve(options) {
1432
- return (options?.client ?? client).get({
1433
- security: [
1434
- { name: "X-API-Key", type: "apiKey" },
1435
- { scheme: "bearer", type: "http" },
1436
- { name: "Authorization", type: "apiKey" }
1437
- ],
1438
- url: "/cfg/centrifugo/auth/token/",
1439
- ...options
1440
- });
1441
- }
1442
- };
1443
- CfgTotpBackupCodes = class {
1444
- static {
1445
- __name(this, "CfgTotpBackupCodes");
1446
- }
1447
- /**
1448
- * Get backup codes status for user.
1449
- */
1450
- static cfgTotpBackupCodesRetrieve(options) {
1451
- return (options?.client ?? client).get({
1452
- security: [
1453
- { name: "X-API-Key", type: "apiKey" },
1454
- { scheme: "bearer", type: "http" },
1455
- { name: "Authorization", type: "apiKey" }
1456
- ],
1457
- url: "/cfg/totp/backup-codes/",
1458
- ...options
1459
- });
1460
- }
1461
- /**
1462
- * Regenerate backup codes.
1463
- *
1464
- * Requires TOTP code for verification.
1465
- * Invalidates all existing codes.
1466
- */
1467
- static cfgTotpBackupCodesRegenerateCreate(options) {
1468
- return (options.client ?? client).post({
1469
- security: [
1470
- { name: "X-API-Key", type: "apiKey" },
1471
- { scheme: "bearer", type: "http" },
1472
- { name: "Authorization", type: "apiKey" }
1473
- ],
1474
- url: "/cfg/totp/backup-codes/regenerate/",
1475
- ...options,
1476
- headers: {
1477
- "Content-Type": "application/json",
1478
- ...options.headers
1479
- }
1480
- });
1481
- }
1482
- };
1483
- CfgTotp = class {
1484
- static {
1485
- __name(this, "CfgTotp");
1486
- }
1487
- /**
1488
- * List all TOTP devices for user.
1489
- */
1490
- static cfgTotpDevicesRetrieve(options) {
1491
- return (options?.client ?? client).get({
1492
- security: [
1493
- { name: "X-API-Key", type: "apiKey" },
1494
- { scheme: "bearer", type: "http" },
1495
- { name: "Authorization", type: "apiKey" }
1496
- ],
1497
- url: "/cfg/totp/devices/",
1498
- ...options
1499
- });
1500
- }
1501
- /**
1502
- * Delete a TOTP device.
1503
- *
1504
- * Requires verification code if removing the last/primary device.
1505
- */
1506
- static cfgTotpDevicesDestroy(options) {
1507
- return (options.client ?? client).delete({
1508
- security: [
1509
- { name: "X-API-Key", type: "apiKey" },
1510
- { scheme: "bearer", type: "http" },
1511
- { name: "Authorization", type: "apiKey" }
1512
- ],
1513
- url: "/cfg/totp/devices/{id}/",
1514
- ...options
1515
- });
1516
- }
1517
- /**
1518
- * Completely disable 2FA for account.
1519
- *
1520
- * Requires verification code.
1521
- */
1522
- static cfgTotpDisableCreate(options) {
1523
- return (options.client ?? client).post({
1524
- security: [
1525
- { name: "X-API-Key", type: "apiKey" },
1526
- { scheme: "bearer", type: "http" },
1527
- { name: "Authorization", type: "apiKey" }
1528
- ],
1529
- url: "/cfg/totp/disable/",
1530
- ...options,
1531
- headers: {
1532
- "Content-Type": "application/json",
1533
- ...options.headers
1534
- }
1535
- });
1536
- }
1537
- };
1538
- CfgTotpSetup = class {
1539
- static {
1540
- __name(this, "CfgTotpSetup");
1541
- }
1542
- /**
1543
- * Start 2FA setup process.
1544
- *
1545
- * Creates a new TOTP device and returns QR code for scanning.
1546
- */
1547
- static cfgTotpSetupCreate(options) {
1548
- return (options?.client ?? client).post({
1549
- security: [
1550
- { name: "X-API-Key", type: "apiKey" },
1551
- { scheme: "bearer", type: "http" },
1552
- { name: "Authorization", type: "apiKey" }
1553
- ],
1554
- url: "/cfg/totp/setup/",
1555
- ...options,
1556
- headers: {
1557
- "Content-Type": "application/json",
1558
- ...options?.headers
1559
- }
1560
- });
1561
- }
1562
- /**
1563
- * Confirm 2FA setup with first valid code.
1564
- *
1565
- * Activates the device and generates backup codes.
1566
- */
1567
- static cfgTotpSetupConfirmCreate(options) {
1568
- return (options.client ?? client).post({
1569
- security: [
1570
- { name: "X-API-Key", type: "apiKey" },
1571
- { scheme: "bearer", type: "http" },
1572
- { name: "Authorization", type: "apiKey" }
1573
- ],
1574
- url: "/cfg/totp/setup/confirm/",
1575
- ...options,
1576
- headers: {
1577
- "Content-Type": "application/json",
1578
- ...options.headers
1579
- }
1580
- });
1581
- }
1582
- };
1583
- CfgTotpVerify = class {
1584
- static {
1585
- __name(this, "CfgTotpVerify");
1586
- }
1587
- /**
1588
- * Verify TOTP code for 2FA session.
1589
- *
1590
- * Completes authentication and returns JWT tokens on success.
1591
- */
1592
- static cfgTotpVerifyCreate(options) {
1593
- return (options.client ?? client).post({
1594
- security: [
1595
- { name: "X-API-Key", type: "apiKey" },
1596
- { scheme: "bearer", type: "http" },
1597
- { name: "Authorization", type: "apiKey" }
1598
- ],
1599
- url: "/cfg/totp/verify/",
1600
- ...options,
1601
- headers: {
1602
- "Content-Type": "application/json",
1603
- ...options.headers
1604
- }
1605
- });
1606
- }
1607
- /**
1608
- * Verify backup recovery code for 2FA session.
1609
- *
1610
- * Alternative verification method when TOTP device unavailable.
1611
- */
1612
- static cfgTotpVerifyBackupCreate(options) {
1613
- return (options.client ?? client).post({
1614
- security: [
1615
- { name: "X-API-Key", type: "apiKey" },
1616
- { scheme: "bearer", type: "http" },
1617
- { name: "Authorization", type: "apiKey" }
1618
- ],
1619
- url: "/cfg/totp/verify/backup/",
1620
- ...options,
1621
- headers: {
1622
- "Content-Type": "application/json",
1623
- ...options.headers
1624
- }
1625
- });
521
+ };
522
+ async function tryRefresh() {
523
+ if (_refreshInflight) return _refreshInflight;
524
+ if (!_refreshHandler) return null;
525
+ const runRefresh = /* @__PURE__ */ __name(async () => {
526
+ const refresh = auth.getRefreshToken();
527
+ if (!refresh) return null;
528
+ const result = await _refreshHandler(refresh);
529
+ if (!result?.access) return null;
530
+ auth.setToken(result.access);
531
+ if (result.refresh) auth.setRefreshToken(result.refresh);
532
+ return result.access;
533
+ }, "runRefresh");
534
+ _refreshInflight = (async () => {
535
+ try {
536
+ const locks = typeof navigator !== "undefined" ? navigator.locks : void 0;
537
+ if (locks?.request) {
538
+ return await locks.request(`${REFRESH_KEY}:refresh`, runRefresh);
1626
539
  }
1627
- };
1628
- }
1629
- });
1630
-
1631
- // src/_api/generated/helpers/auth.ts
1632
- function detectLocale() {
1633
- try {
1634
- if (typeof document !== "undefined") {
1635
- const m = document.cookie.match(/(?:^|;\s*)NEXT_LOCALE=([^;]*)/);
1636
- if (m) return decodeURIComponent(m[1]);
1637
- }
1638
- if (typeof navigator !== "undefined" && navigator.language) {
1639
- return navigator.language;
540
+ return await runRefresh();
541
+ } catch {
542
+ return null;
543
+ } finally {
544
+ _refreshInflight = null;
1640
545
  }
1641
- } catch {
1642
- }
1643
- return null;
546
+ })();
547
+ return _refreshInflight;
1644
548
  }
1645
- function defaultBaseUrl() {
1646
- if (typeof window !== "undefined") {
549
+ __name(tryRefresh, "tryRefresh");
550
+ function expireSession(response) {
551
+ auth.clearTokens();
552
+ for (const cb of Array.from(_sessionExpiredHandlers)) {
1647
553
  try {
1648
- if (typeof process !== "undefined" && process.env) {
1649
- if (process.env.NEXT_PUBLIC_STATIC_BUILD === "true") return "";
1650
- if (process.env.NEXT_PUBLIC_API_PROXY_URL !== void 0)
1651
- return process.env.NEXT_PUBLIC_API_PROXY_URL;
1652
- return process.env.NEXT_PUBLIC_API_URL || "";
1653
- }
554
+ cb(response);
1654
555
  } catch {
1655
556
  }
1656
- return "";
1657
557
  }
1658
- try {
1659
- if (typeof process !== "undefined" && process.env) {
1660
- if (process.env.NEXT_PUBLIC_STATIC_BUILD === "true") return "";
1661
- return process.env.NEXT_PUBLIC_API_URL || "";
558
+ if (_onUnauthorized) {
559
+ try {
560
+ _onUnauthorized(response);
561
+ } catch {
1662
562
  }
1663
- } catch {
1664
563
  }
1665
- return "";
1666
564
  }
1667
- function defaultApiKey() {
1668
- try {
1669
- if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_KEY) {
1670
- return process.env.NEXT_PUBLIC_API_KEY;
1671
- }
1672
- } catch {
1673
- }
1674
- return null;
1675
- }
1676
- function jwtExpMs(token) {
1677
- try {
1678
- const payload = token.split(".")[1];
1679
- if (!payload) return null;
1680
- const json = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
1681
- return typeof json.exp === "number" ? json.exp * 1e3 : null;
1682
- } catch {
1683
- return null;
1684
- }
1685
- }
1686
- function computeSnapshot() {
1687
- const access = _storage.get(ACCESS_KEY);
1688
- const refresh = _storage.get(REFRESH_KEY);
1689
- const now = Date.now();
1690
- const accessExp = access ? jwtExpMs(access) : null;
1691
- const accessAlive = access !== null && (accessExp === null || accessExp > now);
1692
- const refreshExp = refresh ? jwtExpMs(refresh) : null;
1693
- const refreshAlive = refresh !== null && (refreshExp === null || refreshExp > now);
1694
- return {
1695
- status: accessAlive || refreshAlive ? "authenticated" : "anonymous",
1696
- accessExpiresAt: accessExp
1697
- };
1698
- }
1699
- function scheduleExpiryFlip() {
1700
- if (!isBrowser) return;
1701
- if (_expiryTimer !== null) {
1702
- clearTimeout(_expiryTimer);
1703
- _expiryTimer = null;
1704
- }
1705
- if (_sessionListeners.size === 0) return;
1706
- const now = Date.now();
1707
- const exps = [];
1708
- const access = _storage.get(ACCESS_KEY);
1709
- const refresh = _storage.get(REFRESH_KEY);
1710
- const accessExp = access ? jwtExpMs(access) : null;
1711
- const refreshExp = refresh ? jwtExpMs(refresh) : null;
1712
- if (accessExp !== null && accessExp > now) exps.push(accessExp);
1713
- if (refreshExp !== null && refreshExp > now) exps.push(refreshExp);
1714
- if (!exps.length) return;
1715
- const delay = Math.min(Math.min(...exps) - now + 250, 2147483647);
1716
- _expiryTimer = setTimeout(notifySessionChanged, delay);
1717
- }
1718
- function notifySessionChanged() {
1719
- const next = computeSnapshot();
1720
- const changed = next.status !== _snapshot.status || next.accessExpiresAt !== _snapshot.accessExpiresAt;
1721
- if (changed) _snapshot = next;
1722
- scheduleExpiryFlip();
1723
- if (!changed) return;
1724
- for (const listener of Array.from(_sessionListeners)) {
1725
- try {
1726
- listener();
1727
- } catch {
1728
- }
1729
- }
1730
- if (isBrowser) {
1731
- try {
1732
- window.dispatchEvent(new Event(SESSION_SYNC_EVENT));
1733
- } catch {
1734
- }
1735
- }
1736
- }
1737
- function ensureStorageSync() {
1738
- if (!isBrowser || _storageListenerInstalled) return;
1739
- _storageListenerInstalled = true;
1740
- window.addEventListener("storage", (e) => {
1741
- if (e.key === null || e.key === ACCESS_KEY || e.key === REFRESH_KEY) {
1742
- notifySessionChanged();
1743
- }
1744
- });
1745
- window.addEventListener(SESSION_SYNC_EVENT, () => notifySessionChanged());
1746
- }
1747
- function pushClientConfig() {
1748
- if (!_client) return;
1749
- _client.setConfig({
1750
- baseUrl: auth.getBaseUrl(),
1751
- credentials: _withCredentials ? "include" : "same-origin"
1752
- });
1753
- }
1754
- async function tryRefresh() {
1755
- if (_refreshInflight) return _refreshInflight;
1756
- if (!_refreshHandler) return null;
1757
- const runRefresh = /* @__PURE__ */ __name(async () => {
1758
- const refresh = auth.getRefreshToken();
1759
- if (!refresh) return null;
1760
- const result = await _refreshHandler(refresh);
1761
- if (!result?.access) return null;
1762
- auth.setToken(result.access);
1763
- if (result.refresh) auth.setRefreshToken(result.refresh);
1764
- return result.access;
1765
- }, "runRefresh");
1766
- _refreshInflight = (async () => {
1767
- try {
1768
- const locks = typeof navigator !== "undefined" ? navigator.locks : void 0;
1769
- if (locks?.request) {
1770
- return await locks.request(`${REFRESH_KEY}:refresh`, runRefresh);
1771
- }
1772
- return await runRefresh();
1773
- } catch {
1774
- return null;
1775
- } finally {
1776
- _refreshInflight = null;
1777
- }
1778
- })();
1779
- return _refreshInflight;
1780
- }
1781
- function expireSession(response) {
1782
- auth.clearTokens();
1783
- for (const cb of Array.from(_sessionExpiredHandlers)) {
1784
- try {
1785
- cb(response);
1786
- } catch {
1787
- }
1788
- }
1789
- if (_onUnauthorized) {
1790
- try {
1791
- _onUnauthorized(response);
1792
- } catch {
1793
- }
1794
- }
1795
- }
1796
- function dpopEnabled() {
565
+ __name(expireSession, "expireSession");
566
+ function dpopEnabled() {
1797
567
  try {
1798
568
  return typeof process !== "undefined" && process.env?.NEXT_PUBLIC_DPOP_ENABLED === "true";
1799
569
  } catch {
1800
570
  return false;
1801
571
  }
1802
572
  }
573
+ __name(dpopEnabled, "dpopEnabled");
574
+ var _DPOP_DB = "cfg-auth";
575
+ var _DPOP_STORE = "keys";
576
+ var _DPOP_KEY_ID = "dpop-ec-p256";
1803
577
  function _idbOpen() {
1804
578
  return new Promise((resolve, reject) => {
1805
579
  const req = indexedDB.open(_DPOP_DB, 1);
@@ -1808,6 +582,7 @@ function _idbOpen() {
1808
582
  req.onerror = () => reject(req.error);
1809
583
  });
1810
584
  }
585
+ __name(_idbOpen, "_idbOpen");
1811
586
  function _idbGet(key) {
1812
587
  return _idbOpen().then((db) => new Promise((resolve, reject) => {
1813
588
  const tx = db.transaction(_DPOP_STORE, "readonly");
@@ -1816,6 +591,7 @@ function _idbGet(key) {
1816
591
  req.onerror = () => reject(req.error);
1817
592
  }));
1818
593
  }
594
+ __name(_idbGet, "_idbGet");
1819
595
  function _idbPut(key, value) {
1820
596
  return _idbOpen().then((db) => new Promise((resolve, reject) => {
1821
597
  const tx = db.transaction(_DPOP_STORE, "readwrite");
@@ -1824,6 +600,8 @@ function _idbPut(key, value) {
1824
600
  tx.onerror = () => reject(tx.error);
1825
601
  }));
1826
602
  }
603
+ __name(_idbPut, "_idbPut");
604
+ var _dpopKeyPromise = null;
1827
605
  function _getDpopKeyPair() {
1828
606
  if (_dpopKeyPromise) return _dpopKeyPromise;
1829
607
  _dpopKeyPromise = (async () => {
@@ -1841,19 +619,23 @@ function _getDpopKeyPair() {
1841
619
  })();
1842
620
  return _dpopKeyPromise;
1843
621
  }
622
+ __name(_getDpopKeyPair, "_getDpopKeyPair");
1844
623
  function _b64urlFromBytes(bytes) {
1845
624
  const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
1846
625
  let s = "";
1847
626
  for (let i = 0; i < arr.length; i++) s += String.fromCharCode(arr[i]);
1848
627
  return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1849
628
  }
629
+ __name(_b64urlFromBytes, "_b64urlFromBytes");
1850
630
  function _b64urlFromString(str) {
1851
631
  return _b64urlFromBytes(new TextEncoder().encode(str));
1852
632
  }
633
+ __name(_b64urlFromString, "_b64urlFromString");
1853
634
  async function _publicJwk(pub) {
1854
635
  const jwk = await crypto.subtle.exportKey("jwk", pub);
1855
636
  return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y };
1856
637
  }
638
+ __name(_publicJwk, "_publicJwk");
1857
639
  async function _makeDpopProof(method, url) {
1858
640
  try {
1859
641
  const pair = await _getDpopKeyPair();
@@ -1873,6 +655,7 @@ async function _makeDpopProof(method, url) {
1873
655
  return null;
1874
656
  }
1875
657
  }
658
+ __name(_makeDpopProof, "_makeDpopProof");
1876
659
  function installAuthOnClient(client2) {
1877
660
  if (_client) return;
1878
661
  _client = client2;
@@ -1933,356 +716,30 @@ function installAuthOnClient(client2) {
1933
716
  }
1934
717
  });
1935
718
  }
1936
- var ACCESS_KEY, REFRESH_KEY, API_KEY_KEY, isBrowser, localStorageBackend, COOKIE_MAX_AGE, cookieBackend, _storage, _storageMode, _localeOverride, _apiKeyOverride, _baseUrlOverride, _withCredentials, _onUnauthorized, _refreshHandler, _refreshInflight, RETRY_MARKER, SERVER_SNAPSHOT, SESSION_SYNC_EVENT, _snapshot, _sessionListeners, _expiryTimer, _storageListenerInstalled, _sessionExpiredHandlers, _client, auth, _DPOP_DB, _DPOP_STORE, _DPOP_KEY_ID, _dpopKeyPromise;
1937
- var init_auth = __esm({
1938
- "src/_api/generated/helpers/auth.ts"() {
1939
- init_errors();
1940
- ACCESS_KEY = "cfg.access_token";
1941
- REFRESH_KEY = "cfg.refresh_token";
1942
- API_KEY_KEY = "cfg.api_key";
1943
- isBrowser = typeof window !== "undefined";
1944
- localStorageBackend = {
1945
- get(key) {
1946
- if (!isBrowser) return null;
1947
- try {
1948
- return window.localStorage.getItem(key);
1949
- } catch {
1950
- return null;
1951
- }
1952
- },
1953
- set(key, value) {
1954
- if (!isBrowser) return;
1955
- try {
1956
- if (value === null) window.localStorage.removeItem(key);
1957
- else window.localStorage.setItem(key, value);
1958
- } catch {
1959
- }
1960
- }
1961
- };
1962
- COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
1963
- cookieBackend = {
1964
- get(key) {
1965
- if (!isBrowser) return null;
1966
- try {
1967
- const re = new RegExp(`(?:^|;\\s*)${encodeURIComponent(key)}=([^;]*)`);
1968
- const m = document.cookie.match(re);
1969
- return m ? decodeURIComponent(m[1]) : null;
1970
- } catch {
1971
- return null;
1972
- }
1973
- },
1974
- set(key, value) {
1975
- if (!isBrowser) return;
1976
- try {
1977
- const k = encodeURIComponent(key);
1978
- const secure = window.location.protocol === "https:" ? "; Secure" : "";
1979
- if (value === null) {
1980
- document.cookie = `${k}=; Path=/; Max-Age=0; SameSite=Lax${secure}`;
1981
- } else {
1982
- const v = encodeURIComponent(value);
1983
- document.cookie = `${k}=${v}; Path=/; Max-Age=${COOKIE_MAX_AGE}; SameSite=Lax${secure}`;
1984
- }
1985
- } catch {
1986
- }
1987
- }
1988
- };
1989
- _storage = localStorageBackend;
1990
- _storageMode = "localStorage";
1991
- __name(detectLocale, "detectLocale");
1992
- __name(defaultBaseUrl, "defaultBaseUrl");
1993
- __name(defaultApiKey, "defaultApiKey");
1994
- _localeOverride = null;
1995
- _apiKeyOverride = null;
1996
- _baseUrlOverride = null;
1997
- _withCredentials = true;
1998
- _onUnauthorized = null;
1999
- _refreshHandler = null;
2000
- _refreshInflight = null;
2001
- RETRY_MARKER = "X-Auth-Retry";
2002
- __name(jwtExpMs, "jwtExpMs");
2003
- __name(computeSnapshot, "computeSnapshot");
2004
- SERVER_SNAPSHOT = { status: "anonymous", accessExpiresAt: null };
2005
- SESSION_SYNC_EVENT = `cfg-auth:changed:${ACCESS_KEY}`;
2006
- _snapshot = computeSnapshot();
2007
- _sessionListeners = /* @__PURE__ */ new Set();
2008
- _expiryTimer = null;
2009
- _storageListenerInstalled = false;
2010
- __name(scheduleExpiryFlip, "scheduleExpiryFlip");
2011
- __name(notifySessionChanged, "notifySessionChanged");
2012
- __name(ensureStorageSync, "ensureStorageSync");
2013
- _sessionExpiredHandlers = /* @__PURE__ */ new Set();
2014
- _client = null;
2015
- __name(pushClientConfig, "pushClientConfig");
2016
- auth = {
2017
- // ── Storage mode ──────────────────────────────────────────────────
2018
- getStorageMode() {
2019
- return _storageMode;
2020
- },
2021
- setStorageMode(mode) {
2022
- _storageMode = mode;
2023
- _storage = mode === "cookie" ? cookieBackend : localStorageBackend;
2024
- notifySessionChanged();
2025
- },
2026
- // ── Bearer token ──────────────────────────────────────────────────
2027
- getToken() {
2028
- return _storage.get(ACCESS_KEY);
2029
- },
2030
- setToken(token) {
2031
- _storage.set(ACCESS_KEY, token);
2032
- notifySessionChanged();
2033
- },
2034
- getRefreshToken() {
2035
- return _storage.get(REFRESH_KEY);
2036
- },
2037
- setRefreshToken(token) {
2038
- _storage.set(REFRESH_KEY, token);
2039
- notifySessionChanged();
2040
- },
2041
- clearTokens() {
2042
- _storage.set(ACCESS_KEY, null);
2043
- _storage.set(REFRESH_KEY, null);
2044
- notifySessionChanged();
2045
- },
2046
- /** Session-aware: token PRESENT and not past its `exp` (or a live refresh
2047
- * token exists that can mint one). Prefer `getSnapshot().status` in React. */
2048
- isAuthenticated() {
2049
- return computeSnapshot().status === "authenticated";
2050
- },
2051
- // ── Session (the ONE write path for login/logout flows) ──────────
2052
- /**
2053
- * Persist a token pair atomically. Every login flow (OTP verify, 2FA,
2054
- * OAuth callback) and the refresh handler should end here — do NOT
2055
- * scatter `setToken`/`setRefreshToken` pairs through app code.
2056
- * `refresh: undefined` keeps the current refresh token (access-only
2057
- * rotation); `refresh: null` explicitly drops it.
2058
- */
2059
- setSession(tokens) {
2060
- _storage.set(ACCESS_KEY, tokens.access);
2061
- if (tokens.refresh !== void 0) _storage.set(REFRESH_KEY, tokens.refresh);
2062
- notifySessionChanged();
2063
- },
2064
- clearSession() {
2065
- auth.clearTokens();
2066
- },
2067
- // ── Reactive snapshot (for useSyncExternalStore) ──────────────────
2068
- /**
2069
- * @example React:
2070
- * const session = useSyncExternalStore(
2071
- * auth.subscribe, auth.getSnapshot, auth.getServerSnapshot,
2072
- * );
2073
- * const isAuthenticated = session.status === 'authenticated';
2074
- */
2075
- getSnapshot() {
2076
- return _snapshot;
2077
- },
2078
- getServerSnapshot() {
2079
- return SERVER_SNAPSHOT;
2080
- },
2081
- subscribe(listener) {
2082
- ensureStorageSync();
2083
- _sessionListeners.add(listener);
2084
- notifySessionChanged();
2085
- return () => {
2086
- _sessionListeners.delete(listener);
2087
- if (_sessionListeners.size === 0 && _expiryTimer !== null) {
2088
- clearTimeout(_expiryTimer);
2089
- _expiryTimer = null;
2090
- }
2091
- };
2092
- },
2093
- /**
2094
- * Fired on TERMINAL 401 — after the refresh+retry path is exhausted.
2095
- * The store has already cleared the session before calling back, so
2096
- * handlers only need to route to login (no clear-then-redirect
2097
- * ordering to get wrong). Returns an unsubscribe function; multiple
2098
- * handlers compose (unlike the legacy single-slot `onUnauthorized`).
2099
- */
2100
- onSessionExpired(cb) {
2101
- _sessionExpiredHandlers.add(cb);
2102
- return () => {
2103
- _sessionExpiredHandlers.delete(cb);
2104
- };
2105
- },
2106
- // ── API key ───────────────────────────────────────────────────────
2107
- getApiKey() {
2108
- return _apiKeyOverride ?? _storage.get(API_KEY_KEY) ?? defaultApiKey();
2109
- },
2110
- setApiKey(key) {
2111
- _apiKeyOverride = key;
2112
- },
2113
- setApiKeyPersist(key) {
2114
- _apiKeyOverride = key;
2115
- _storage.set(API_KEY_KEY, key);
2116
- },
2117
- clearApiKey() {
2118
- _apiKeyOverride = null;
2119
- _storage.set(API_KEY_KEY, null);
2120
- },
2121
- // ── Locale ────────────────────────────────────────────────────────
2122
- getLocale() {
2123
- return _localeOverride ?? detectLocale();
2124
- },
2125
- setLocale(locale) {
2126
- _localeOverride = locale;
2127
- },
2128
- // ── Base URL ──────────────────────────────────────────────────────
2129
- getBaseUrl() {
2130
- const url = _baseUrlOverride ?? defaultBaseUrl();
2131
- return url.replace(/\/$/, "");
2132
- },
2133
- setBaseUrl(url) {
2134
- _baseUrlOverride = url ? url.replace(/\/$/, "") : null;
2135
- pushClientConfig();
2136
- },
2137
- // ── Credentials toggle ────────────────────────────────────────────
2138
- getWithCredentials() {
2139
- return _withCredentials;
2140
- },
2141
- setWithCredentials(value) {
2142
- _withCredentials = value;
2143
- pushClientConfig();
2144
- },
2145
- // ── 401 handler ───────────────────────────────────────────────────
2146
- /**
2147
- * Fired when the server returns 401 AND no refresh path recovers it
2148
- * (no refresh token, no refresh handler, refresh failed, or retry
2149
- * still 401). The app should clear local state and redirect to login.
2150
- *
2151
- * NOT fired for 401 that gets transparently recovered by the refresh
2152
- * handler — those are invisible to callers.
2153
- */
2154
- onUnauthorized(cb) {
2155
- _onUnauthorized = cb;
2156
- },
2157
- /**
2158
- * Register the refresh strategy. The handler receives the current
2159
- * refresh token and must call your refresh endpoint, returning
2160
- * `{ access, refresh? }` on success or `null` on failure.
2161
- *
2162
- * @example
2163
- * auth.setRefreshHandler(async (refresh) => {
2164
- * const { data } = await Auth.tokenRefreshCreate({ body: { refresh } });
2165
- * return data ? { access: data.access, refresh: data.refresh } : null;
2166
- * });
2167
- */
2168
- setRefreshHandler(fn) {
2169
- _refreshHandler = fn;
2170
- },
2171
- /**
2172
- * Proactively run the registered refresh handler right now, reusing the
2173
- * SAME single-flight promise as the 401-recovery interceptor. Callers
2174
- * (e.g. an expiry timer / focus / reconnect) get token rotation,
2175
- * de-duplication and rotated-token persistence for free — they must NOT
2176
- * re-implement any of it. Returns the fresh access token, or null if
2177
- * there is no handler / no refresh token / the refresh failed.
2178
- */
2179
- refreshNow() {
2180
- return tryRefresh();
2181
- }
2182
- };
2183
- __name(tryRefresh, "tryRefresh");
2184
- __name(expireSession, "expireSession");
2185
- __name(dpopEnabled, "dpopEnabled");
2186
- _DPOP_DB = "cfg-auth";
2187
- _DPOP_STORE = "keys";
2188
- _DPOP_KEY_ID = "dpop-ec-p256";
2189
- __name(_idbOpen, "_idbOpen");
2190
- __name(_idbGet, "_idbGet");
2191
- __name(_idbPut, "_idbPut");
2192
- _dpopKeyPromise = null;
2193
- __name(_getDpopKeyPair, "_getDpopKeyPair");
2194
- __name(_b64urlFromBytes, "_b64urlFromBytes");
2195
- __name(_b64urlFromString, "_b64urlFromString");
2196
- __name(_publicJwk, "_publicJwk");
2197
- __name(_makeDpopProof, "_makeDpopProof");
2198
- __name(installAuthOnClient, "installAuthOnClient");
2199
- auth.setRefreshHandler(async (refresh) => {
2200
- try {
2201
- const { CfgAccountsAuth: CfgAccountsAuth2 } = await Promise.resolve().then(() => (init_sdk_gen(), sdk_gen_exports));
2202
- const { data } = await CfgAccountsAuth2.cfgAccountsTokenRefreshCreate({
2203
- body: { refresh },
2204
- throwOnError: true
2205
- });
2206
- return data?.access ? { access: data.access, refresh: data.refresh ?? refresh } : null;
2207
- } catch {
2208
- return null;
2209
- }
719
+ __name(installAuthOnClient, "installAuthOnClient");
720
+ var REFRESH_ENDPOINT = "/cfg/accounts/token/refresh/";
721
+ auth.setRefreshHandler(async (refresh) => {
722
+ try {
723
+ const url = `${auth.getBaseUrl()}${REFRESH_ENDPOINT}`;
724
+ const headers = { "Content-Type": "application/json" };
725
+ if (dpopEnabled() && typeof window !== "undefined") {
726
+ const proof = await _makeDpopProof("POST", url);
727
+ if (proof) headers["DPoP"] = proof;
728
+ }
729
+ const res = await fetch(url, {
730
+ method: "POST",
731
+ headers,
732
+ credentials: auth.getWithCredentials() ? "include" : "same-origin",
733
+ body: JSON.stringify({ refresh })
2210
734
  });
735
+ if (!res.ok) return null;
736
+ const data = await res.json();
737
+ return data?.access ? { access: data.access, refresh: data.refresh ?? refresh } : null;
738
+ } catch {
739
+ return null;
2211
740
  }
2212
741
  });
2213
742
 
2214
- // src/auth/index.ts
2215
- var auth_exports = {};
2216
- __export(auth_exports, {
2217
- AUTH_CONSTANTS: () => AUTH_CONSTANTS,
2218
- AccountsProvider: () => AccountsProvider,
2219
- Analytics: () => Analytics,
2220
- AnalyticsCategory: () => AnalyticsCategory,
2221
- AnalyticsEvent: () => AnalyticsEvent,
2222
- AuthContext: () => AuthContext_default,
2223
- AuthProvider: () => AuthProvider,
2224
- DEFAULT_AUTH_PATH: () => DEFAULT_AUTH_PATH,
2225
- DEFAULT_CALLBACK_PATH: () => DEFAULT_CALLBACK_PATH,
2226
- PatchedCfgUserUpdateRequestSchema: () => PatchedCfgUserUpdateRequestSchema,
2227
- authLogger: () => authLogger,
2228
- clearProfileCache: () => clearProfileCache,
2229
- decodeBase64: () => decodeBase64,
2230
- encodeBase64: () => encodeBase64,
2231
- formatAuthError: () => formatAuthError,
2232
- getCacheMetadata: () => getCacheMetadata,
2233
- getCachedProfile: () => getCachedProfile,
2234
- hasValidCache: () => hasValidCache,
2235
- isAllowedAuthPath: () => isAllowedAuthPath,
2236
- logger: () => logger,
2237
- normalizePath: () => normalizePath,
2238
- resolveGuardIsAuthenticated: () => resolveGuardIsAuthenticated,
2239
- resolveGuardIsLoading: () => resolveGuardIsLoading,
2240
- setCachedProfile: () => setCachedProfile,
2241
- shouldRedirectToAuth: () => shouldRedirectToAuth,
2242
- useAccountsContext: () => useAccountsContext,
2243
- useAuth: () => useAuth,
2244
- useAuthForm: () => useAuthForm,
2245
- useAuthFormState: () => useAuthFormState,
2246
- useAuthRedirectManager: () => useAuthRedirectManager,
2247
- useAuthValidation: () => useAuthValidation,
2248
- useAutoAuth: () => useAutoAuth,
2249
- useBase64: () => useBase64,
2250
- useCfgRouter: () => useCfgRouter,
2251
- useDeleteAccount: () => useDeleteAccount,
2252
- useGithubAuth: () => useGithubAuth,
2253
- useLocalStorage: () => useLocalStorage,
2254
- useQueryParams: () => useQueryParams,
2255
- useSession: () => useSession,
2256
- useSessionStorage: () => useSessionStorage,
2257
- useTwoFactor: () => useTwoFactor,
2258
- useTwoFactorSetup: () => useTwoFactorSetup,
2259
- useTwoFactorStatus: () => useTwoFactorStatus,
2260
- validateEmail: () => validateEmail,
2261
- validateIdentifier: () => validateIdentifier
2262
- });
2263
- module.exports = __toCommonJS(auth_exports);
2264
-
2265
- // src/auth/constants.ts
2266
- var AUTH_CONSTANTS = {
2267
- /** Email OTP code length (numeric). */
2268
- EMAIL_OTP_LENGTH: 4,
2269
- /** TOTP code length (RFC 6238 — authenticator apps). */
2270
- TOTP_LENGTH: 6,
2271
- /** Backup code max length. */
2272
- BACKUP_CODE_MAX_LENGTH: 12
2273
- };
2274
- var DEFAULT_AUTH_PATH = "/auth";
2275
- var DEFAULT_CALLBACK_PATH = "/dashboard";
2276
-
2277
- // src/auth/context/AuthContext.tsx
2278
- var import_navigation4 = require("next/navigation");
2279
- var import_react16 = require("react");
2280
- init_auth();
2281
-
2282
- // src/_api/generated/helpers/index.ts
2283
- init_auth();
2284
- init_errors();
2285
-
2286
743
  // src/_api/generated/helpers/logger.ts
2287
744
  var import_consola = require("consola");
2288
745
  var DEFAULT_CONFIG = {
@@ -2423,7 +880,6 @@ __name(applyRoleLogPolicy, "applyRoleLogPolicy");
2423
880
 
2424
881
  // src/auth/hooks/useSession.ts
2425
882
  var import_react = require("react");
2426
- init_auth();
2427
883
  function useSession() {
2428
884
  return (0, import_react.useSyncExternalStore)(auth.subscribe, auth.getSnapshot, auth.getServerSnapshot);
2429
885
  }
@@ -2628,7 +1084,7 @@ var useAuthValidation = /* @__PURE__ */ __name(() => {
2628
1084
  var validateIdentifier = /* @__PURE__ */ __name((id) => EMAIL_REGEX.test(id), "validateIdentifier");
2629
1085
 
2630
1086
  // src/auth/hooks/useAuthForm.ts
2631
- var import_react8 = require("react");
1087
+ var import_react9 = require("react");
2632
1088
 
2633
1089
  // src/auth/utils/logger.ts
2634
1090
  var import_consola2 = require("consola");
@@ -2694,9 +1150,1290 @@ var useAutoAuth = /* @__PURE__ */ __name((options = {}) => {
2694
1150
  }, "useAutoAuth");
2695
1151
 
2696
1152
  // src/auth/hooks/useTwoFactor.ts
2697
- var import_react7 = require("react");
2698
- init_auth();
2699
- init_sdk_gen();
1153
+ var import_react8 = require("react");
1154
+
1155
+ // src/_api/generated/core/bodySerializer.gen.ts
1156
+ var serializeFormDataPair = /* @__PURE__ */ __name((data, key, value) => {
1157
+ if (typeof value === "string" || value instanceof Blob) {
1158
+ data.append(key, value);
1159
+ } else if (value instanceof Date) {
1160
+ data.append(key, value.toISOString());
1161
+ } else {
1162
+ data.append(key, JSON.stringify(value));
1163
+ }
1164
+ }, "serializeFormDataPair");
1165
+ var formDataBodySerializer = {
1166
+ bodySerializer: /* @__PURE__ */ __name((body) => {
1167
+ const data = new FormData();
1168
+ Object.entries(body).forEach(([key, value]) => {
1169
+ if (value === void 0 || value === null) {
1170
+ return;
1171
+ }
1172
+ if (Array.isArray(value)) {
1173
+ value.forEach((v) => serializeFormDataPair(data, key, v));
1174
+ } else {
1175
+ serializeFormDataPair(data, key, value);
1176
+ }
1177
+ });
1178
+ return data;
1179
+ }, "bodySerializer")
1180
+ };
1181
+ var jsonBodySerializer = {
1182
+ bodySerializer: /* @__PURE__ */ __name((body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value), "bodySerializer")
1183
+ };
1184
+
1185
+ // src/_api/generated/core/params.gen.ts
1186
+ var extraPrefixesMap = {
1187
+ $body_: "body",
1188
+ $headers_: "headers",
1189
+ $path_: "path",
1190
+ $query_: "query"
1191
+ };
1192
+ var extraPrefixes = Object.entries(extraPrefixesMap);
1193
+
1194
+ // src/_api/generated/core/serverSentEvents.gen.ts
1195
+ function createSseClient({
1196
+ onRequest,
1197
+ onSseError,
1198
+ onSseEvent,
1199
+ responseTransformer,
1200
+ responseValidator,
1201
+ sseDefaultRetryDelay,
1202
+ sseMaxRetryAttempts,
1203
+ sseMaxRetryDelay,
1204
+ sseSleepFn,
1205
+ url,
1206
+ ...options
1207
+ }) {
1208
+ let lastEventId;
1209
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1210
+ const createStream = /* @__PURE__ */ __name(async function* () {
1211
+ let retryDelay = sseDefaultRetryDelay ?? 3e3;
1212
+ let attempt = 0;
1213
+ const signal = options.signal ?? new AbortController().signal;
1214
+ while (true) {
1215
+ if (signal.aborted) break;
1216
+ attempt++;
1217
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
1218
+ if (lastEventId !== void 0) {
1219
+ headers.set("Last-Event-ID", lastEventId);
1220
+ }
1221
+ try {
1222
+ const requestInit = {
1223
+ redirect: "follow",
1224
+ ...options,
1225
+ body: options.serializedBody,
1226
+ headers,
1227
+ signal
1228
+ };
1229
+ let request = new Request(url, requestInit);
1230
+ if (onRequest) {
1231
+ request = await onRequest(url, requestInit);
1232
+ }
1233
+ const _fetch = options.fetch ?? globalThis.fetch;
1234
+ const response = await _fetch(request);
1235
+ if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
1236
+ if (!response.body) throw new Error("No body in SSE response");
1237
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
1238
+ let buffer = "";
1239
+ const abortHandler = /* @__PURE__ */ __name(() => {
1240
+ try {
1241
+ reader.cancel();
1242
+ } catch {
1243
+ }
1244
+ }, "abortHandler");
1245
+ signal.addEventListener("abort", abortHandler);
1246
+ try {
1247
+ while (true) {
1248
+ const { done, value } = await reader.read();
1249
+ if (done) break;
1250
+ buffer += value;
1251
+ buffer = buffer.replace(/\r\n?/g, "\n");
1252
+ const chunks = buffer.split("\n\n");
1253
+ buffer = chunks.pop() ?? "";
1254
+ for (const chunk of chunks) {
1255
+ const lines = chunk.split("\n");
1256
+ const dataLines = [];
1257
+ let eventName;
1258
+ for (const line of lines) {
1259
+ if (line.startsWith("data:")) {
1260
+ dataLines.push(line.replace(/^data:\s*/, ""));
1261
+ } else if (line.startsWith("event:")) {
1262
+ eventName = line.replace(/^event:\s*/, "");
1263
+ } else if (line.startsWith("id:")) {
1264
+ lastEventId = line.replace(/^id:\s*/, "");
1265
+ } else if (line.startsWith("retry:")) {
1266
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
1267
+ if (!Number.isNaN(parsed)) {
1268
+ retryDelay = parsed;
1269
+ }
1270
+ }
1271
+ }
1272
+ let data;
1273
+ let parsedJson = false;
1274
+ if (dataLines.length) {
1275
+ const rawData = dataLines.join("\n");
1276
+ try {
1277
+ data = JSON.parse(rawData);
1278
+ parsedJson = true;
1279
+ } catch {
1280
+ data = rawData;
1281
+ }
1282
+ }
1283
+ if (parsedJson) {
1284
+ if (responseValidator) {
1285
+ await responseValidator(data);
1286
+ }
1287
+ if (responseTransformer) {
1288
+ data = await responseTransformer(data);
1289
+ }
1290
+ }
1291
+ onSseEvent?.({
1292
+ data,
1293
+ event: eventName,
1294
+ id: lastEventId,
1295
+ retry: retryDelay
1296
+ });
1297
+ if (dataLines.length) {
1298
+ yield data;
1299
+ }
1300
+ }
1301
+ }
1302
+ } finally {
1303
+ signal.removeEventListener("abort", abortHandler);
1304
+ reader.releaseLock();
1305
+ }
1306
+ break;
1307
+ } catch (error) {
1308
+ onSseError?.(error);
1309
+ if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
1310
+ break;
1311
+ }
1312
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
1313
+ await sleep(backoff);
1314
+ }
1315
+ }
1316
+ }, "createStream");
1317
+ const stream = createStream();
1318
+ return { stream };
1319
+ }
1320
+ __name(createSseClient, "createSseClient");
1321
+
1322
+ // src/_api/generated/core/pathSerializer.gen.ts
1323
+ var separatorArrayExplode = /* @__PURE__ */ __name((style) => {
1324
+ switch (style) {
1325
+ case "label":
1326
+ return ".";
1327
+ case "matrix":
1328
+ return ";";
1329
+ case "simple":
1330
+ return ",";
1331
+ default:
1332
+ return "&";
1333
+ }
1334
+ }, "separatorArrayExplode");
1335
+ var separatorArrayNoExplode = /* @__PURE__ */ __name((style) => {
1336
+ switch (style) {
1337
+ case "form":
1338
+ return ",";
1339
+ case "pipeDelimited":
1340
+ return "|";
1341
+ case "spaceDelimited":
1342
+ return "%20";
1343
+ default:
1344
+ return ",";
1345
+ }
1346
+ }, "separatorArrayNoExplode");
1347
+ var separatorObjectExplode = /* @__PURE__ */ __name((style) => {
1348
+ switch (style) {
1349
+ case "label":
1350
+ return ".";
1351
+ case "matrix":
1352
+ return ";";
1353
+ case "simple":
1354
+ return ",";
1355
+ default:
1356
+ return "&";
1357
+ }
1358
+ }, "separatorObjectExplode");
1359
+ var serializeArrayParam = /* @__PURE__ */ __name(({
1360
+ allowReserved,
1361
+ explode,
1362
+ name,
1363
+ style,
1364
+ value
1365
+ }) => {
1366
+ if (!explode) {
1367
+ const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
1368
+ switch (style) {
1369
+ case "label":
1370
+ return `.${joinedValues2}`;
1371
+ case "matrix":
1372
+ return `;${name}=${joinedValues2}`;
1373
+ case "simple":
1374
+ return joinedValues2;
1375
+ default:
1376
+ return `${name}=${joinedValues2}`;
1377
+ }
1378
+ }
1379
+ const separator = separatorArrayExplode(style);
1380
+ const joinedValues = value.map((v) => {
1381
+ if (style === "label" || style === "simple") {
1382
+ return allowReserved ? v : encodeURIComponent(v);
1383
+ }
1384
+ return serializePrimitiveParam({
1385
+ allowReserved,
1386
+ name,
1387
+ value: v
1388
+ });
1389
+ }).join(separator);
1390
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
1391
+ }, "serializeArrayParam");
1392
+ var serializePrimitiveParam = /* @__PURE__ */ __name(({
1393
+ allowReserved,
1394
+ name,
1395
+ value
1396
+ }) => {
1397
+ if (value === void 0 || value === null) {
1398
+ return "";
1399
+ }
1400
+ if (typeof value === "object") {
1401
+ throw new Error(
1402
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
1403
+ );
1404
+ }
1405
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
1406
+ }, "serializePrimitiveParam");
1407
+ var serializeObjectParam = /* @__PURE__ */ __name(({
1408
+ allowReserved,
1409
+ explode,
1410
+ name,
1411
+ style,
1412
+ value,
1413
+ valueOnly
1414
+ }) => {
1415
+ if (value instanceof Date) {
1416
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
1417
+ }
1418
+ if (style !== "deepObject" && !explode) {
1419
+ let values = [];
1420
+ Object.entries(value).forEach(([key, v]) => {
1421
+ values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
1422
+ });
1423
+ const joinedValues2 = values.join(",");
1424
+ switch (style) {
1425
+ case "form":
1426
+ return `${name}=${joinedValues2}`;
1427
+ case "label":
1428
+ return `.${joinedValues2}`;
1429
+ case "matrix":
1430
+ return `;${name}=${joinedValues2}`;
1431
+ default:
1432
+ return joinedValues2;
1433
+ }
1434
+ }
1435
+ const separator = separatorObjectExplode(style);
1436
+ const joinedValues = Object.entries(value).map(
1437
+ ([key, v]) => serializePrimitiveParam({
1438
+ allowReserved,
1439
+ name: style === "deepObject" ? `${name}[${key}]` : key,
1440
+ value: v
1441
+ })
1442
+ ).join(separator);
1443
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
1444
+ }, "serializeObjectParam");
1445
+
1446
+ // src/_api/generated/core/utils.gen.ts
1447
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
1448
+ var defaultPathSerializer = /* @__PURE__ */ __name(({ path, url: _url }) => {
1449
+ let url = _url;
1450
+ const matches = _url.match(PATH_PARAM_RE);
1451
+ if (matches) {
1452
+ for (const match of matches) {
1453
+ let explode = false;
1454
+ let name = match.substring(1, match.length - 1);
1455
+ let style = "simple";
1456
+ if (name.endsWith("*")) {
1457
+ explode = true;
1458
+ name = name.substring(0, name.length - 1);
1459
+ }
1460
+ if (name.startsWith(".")) {
1461
+ name = name.substring(1);
1462
+ style = "label";
1463
+ } else if (name.startsWith(";")) {
1464
+ name = name.substring(1);
1465
+ style = "matrix";
1466
+ }
1467
+ const value = path[name];
1468
+ if (value === void 0 || value === null) {
1469
+ continue;
1470
+ }
1471
+ if (Array.isArray(value)) {
1472
+ url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
1473
+ continue;
1474
+ }
1475
+ if (typeof value === "object") {
1476
+ url = url.replace(
1477
+ match,
1478
+ serializeObjectParam({
1479
+ explode,
1480
+ name,
1481
+ style,
1482
+ value,
1483
+ valueOnly: true
1484
+ })
1485
+ );
1486
+ continue;
1487
+ }
1488
+ if (style === "matrix") {
1489
+ url = url.replace(
1490
+ match,
1491
+ `;${serializePrimitiveParam({
1492
+ name,
1493
+ value
1494
+ })}`
1495
+ );
1496
+ continue;
1497
+ }
1498
+ const replaceValue = encodeURIComponent(
1499
+ style === "label" ? `.${value}` : value
1500
+ );
1501
+ url = url.replace(match, replaceValue);
1502
+ }
1503
+ }
1504
+ return url;
1505
+ }, "defaultPathSerializer");
1506
+ var getUrl = /* @__PURE__ */ __name(({
1507
+ baseUrl,
1508
+ path,
1509
+ query,
1510
+ querySerializer,
1511
+ url: _url
1512
+ }) => {
1513
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
1514
+ let url = (baseUrl ?? "") + pathUrl;
1515
+ if (path) {
1516
+ url = defaultPathSerializer({ path, url });
1517
+ }
1518
+ let search = query ? querySerializer(query) : "";
1519
+ if (search.startsWith("?")) {
1520
+ search = search.substring(1);
1521
+ }
1522
+ if (search) {
1523
+ url += `?${search}`;
1524
+ }
1525
+ return url;
1526
+ }, "getUrl");
1527
+ function getValidRequestBody(options) {
1528
+ const hasBody = options.body !== void 0;
1529
+ const isSerializedBody = hasBody && options.bodySerializer;
1530
+ if (isSerializedBody) {
1531
+ if ("serializedBody" in options) {
1532
+ const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
1533
+ return hasSerializedBody ? options.serializedBody : null;
1534
+ }
1535
+ return options.body !== "" ? options.body : null;
1536
+ }
1537
+ if (hasBody) {
1538
+ return options.body;
1539
+ }
1540
+ return void 0;
1541
+ }
1542
+ __name(getValidRequestBody, "getValidRequestBody");
1543
+
1544
+ // src/_api/generated/core/auth.gen.ts
1545
+ var getAuthToken = /* @__PURE__ */ __name(async (auth2, callback) => {
1546
+ const token = typeof callback === "function" ? await callback(auth2) : callback;
1547
+ if (!token) {
1548
+ return;
1549
+ }
1550
+ if (auth2.scheme === "bearer") {
1551
+ return `Bearer ${token}`;
1552
+ }
1553
+ if (auth2.scheme === "basic") {
1554
+ return `Basic ${btoa(token)}`;
1555
+ }
1556
+ return token;
1557
+ }, "getAuthToken");
1558
+
1559
+ // src/_api/generated/client/utils.gen.ts
1560
+ var createQuerySerializer = /* @__PURE__ */ __name(({
1561
+ parameters = {},
1562
+ ...args
1563
+ } = {}) => {
1564
+ const querySerializer = /* @__PURE__ */ __name((queryParams) => {
1565
+ const search = [];
1566
+ if (queryParams && typeof queryParams === "object") {
1567
+ for (const name in queryParams) {
1568
+ const value = queryParams[name];
1569
+ if (value === void 0 || value === null) {
1570
+ continue;
1571
+ }
1572
+ const options = parameters[name] || args;
1573
+ if (Array.isArray(value)) {
1574
+ const serializedArray = serializeArrayParam({
1575
+ allowReserved: options.allowReserved,
1576
+ explode: true,
1577
+ name,
1578
+ style: "form",
1579
+ value,
1580
+ ...options.array
1581
+ });
1582
+ if (serializedArray) search.push(serializedArray);
1583
+ } else if (typeof value === "object") {
1584
+ const serializedObject = serializeObjectParam({
1585
+ allowReserved: options.allowReserved,
1586
+ explode: true,
1587
+ name,
1588
+ style: "deepObject",
1589
+ value,
1590
+ ...options.object
1591
+ });
1592
+ if (serializedObject) search.push(serializedObject);
1593
+ } else {
1594
+ const serializedPrimitive = serializePrimitiveParam({
1595
+ allowReserved: options.allowReserved,
1596
+ name,
1597
+ value
1598
+ });
1599
+ if (serializedPrimitive) search.push(serializedPrimitive);
1600
+ }
1601
+ }
1602
+ }
1603
+ return search.join("&");
1604
+ }, "querySerializer");
1605
+ return querySerializer;
1606
+ }, "createQuerySerializer");
1607
+ var getParseAs = /* @__PURE__ */ __name((contentType) => {
1608
+ if (!contentType) {
1609
+ return "stream";
1610
+ }
1611
+ const cleanContent = contentType.split(";")[0]?.trim();
1612
+ if (!cleanContent) {
1613
+ return;
1614
+ }
1615
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
1616
+ return "json";
1617
+ }
1618
+ if (cleanContent === "multipart/form-data") {
1619
+ return "formData";
1620
+ }
1621
+ if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
1622
+ return "blob";
1623
+ }
1624
+ if (cleanContent.startsWith("text/")) {
1625
+ return "text";
1626
+ }
1627
+ return;
1628
+ }, "getParseAs");
1629
+ var checkForExistence = /* @__PURE__ */ __name((options, name) => {
1630
+ if (!name) {
1631
+ return false;
1632
+ }
1633
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
1634
+ return true;
1635
+ }
1636
+ return false;
1637
+ }, "checkForExistence");
1638
+ async function setAuthParams(options) {
1639
+ for (const auth2 of options.security ?? []) {
1640
+ if (checkForExistence(options, auth2.name)) {
1641
+ continue;
1642
+ }
1643
+ const token = await getAuthToken(auth2, options.auth);
1644
+ if (!token) {
1645
+ continue;
1646
+ }
1647
+ const name = auth2.name ?? "Authorization";
1648
+ switch (auth2.in) {
1649
+ case "query":
1650
+ if (!options.query) {
1651
+ options.query = {};
1652
+ }
1653
+ options.query[name] = token;
1654
+ break;
1655
+ case "cookie":
1656
+ options.headers.append("Cookie", `${name}=${token}`);
1657
+ break;
1658
+ case "header":
1659
+ default:
1660
+ options.headers.set(name, token);
1661
+ break;
1662
+ }
1663
+ }
1664
+ }
1665
+ __name(setAuthParams, "setAuthParams");
1666
+ var buildUrl = /* @__PURE__ */ __name((options) => getUrl({
1667
+ baseUrl: options.baseUrl,
1668
+ path: options.path,
1669
+ query: options.query,
1670
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
1671
+ url: options.url
1672
+ }), "buildUrl");
1673
+ var mergeConfigs = /* @__PURE__ */ __name((a, b) => {
1674
+ const config = { ...a, ...b };
1675
+ if (config.baseUrl?.endsWith("/")) {
1676
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
1677
+ }
1678
+ config.headers = mergeHeaders(a.headers, b.headers);
1679
+ return config;
1680
+ }, "mergeConfigs");
1681
+ var headersEntries = /* @__PURE__ */ __name((headers) => {
1682
+ const entries = [];
1683
+ headers.forEach((value, key) => {
1684
+ entries.push([key, value]);
1685
+ });
1686
+ return entries;
1687
+ }, "headersEntries");
1688
+ var mergeHeaders = /* @__PURE__ */ __name((...headers) => {
1689
+ const mergedHeaders = new Headers();
1690
+ for (const header of headers) {
1691
+ if (!header) {
1692
+ continue;
1693
+ }
1694
+ const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
1695
+ for (const [key, value] of iterator) {
1696
+ if (value === null) {
1697
+ mergedHeaders.delete(key);
1698
+ } else if (Array.isArray(value)) {
1699
+ for (const v of value) {
1700
+ mergedHeaders.append(key, v);
1701
+ }
1702
+ } else if (value !== void 0) {
1703
+ mergedHeaders.set(
1704
+ key,
1705
+ typeof value === "object" ? JSON.stringify(value) : value
1706
+ );
1707
+ }
1708
+ }
1709
+ }
1710
+ return mergedHeaders;
1711
+ }, "mergeHeaders");
1712
+ var Interceptors = class {
1713
+ static {
1714
+ __name(this, "Interceptors");
1715
+ }
1716
+ fns = [];
1717
+ clear() {
1718
+ this.fns = [];
1719
+ }
1720
+ eject(id) {
1721
+ const index = this.getInterceptorIndex(id);
1722
+ if (this.fns[index]) {
1723
+ this.fns[index] = null;
1724
+ }
1725
+ }
1726
+ exists(id) {
1727
+ const index = this.getInterceptorIndex(id);
1728
+ return Boolean(this.fns[index]);
1729
+ }
1730
+ getInterceptorIndex(id) {
1731
+ if (typeof id === "number") {
1732
+ return this.fns[id] ? id : -1;
1733
+ }
1734
+ return this.fns.indexOf(id);
1735
+ }
1736
+ update(id, fn) {
1737
+ const index = this.getInterceptorIndex(id);
1738
+ if (this.fns[index]) {
1739
+ this.fns[index] = fn;
1740
+ return id;
1741
+ }
1742
+ return false;
1743
+ }
1744
+ use(fn) {
1745
+ this.fns.push(fn);
1746
+ return this.fns.length - 1;
1747
+ }
1748
+ };
1749
+ var createInterceptors = /* @__PURE__ */ __name(() => ({
1750
+ error: new Interceptors(),
1751
+ request: new Interceptors(),
1752
+ response: new Interceptors()
1753
+ }), "createInterceptors");
1754
+ var defaultQuerySerializer = createQuerySerializer({
1755
+ allowReserved: false,
1756
+ array: {
1757
+ explode: true,
1758
+ style: "form"
1759
+ },
1760
+ object: {
1761
+ explode: true,
1762
+ style: "deepObject"
1763
+ }
1764
+ });
1765
+ var defaultHeaders = {
1766
+ "Content-Type": "application/json"
1767
+ };
1768
+ var createConfig = /* @__PURE__ */ __name((override = {}) => ({
1769
+ ...jsonBodySerializer,
1770
+ headers: defaultHeaders,
1771
+ parseAs: "auto",
1772
+ querySerializer: defaultQuerySerializer,
1773
+ ...override
1774
+ }), "createConfig");
1775
+
1776
+ // src/_api/generated/client/client.gen.ts
1777
+ var createClient = /* @__PURE__ */ __name((config = {}) => {
1778
+ let _config = mergeConfigs(createConfig(), config);
1779
+ const getConfig = /* @__PURE__ */ __name(() => ({ ..._config }), "getConfig");
1780
+ const setConfig = /* @__PURE__ */ __name((config2) => {
1781
+ _config = mergeConfigs(_config, config2);
1782
+ return getConfig();
1783
+ }, "setConfig");
1784
+ const interceptors = createInterceptors();
1785
+ const beforeRequest = /* @__PURE__ */ __name(async (options) => {
1786
+ const opts = {
1787
+ ..._config,
1788
+ ...options,
1789
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
1790
+ headers: mergeHeaders(_config.headers, options.headers),
1791
+ serializedBody: void 0
1792
+ };
1793
+ if (opts.security) {
1794
+ await setAuthParams(opts);
1795
+ }
1796
+ if (opts.requestValidator) {
1797
+ await opts.requestValidator(opts);
1798
+ }
1799
+ if (opts.body !== void 0 && opts.bodySerializer) {
1800
+ opts.serializedBody = opts.bodySerializer(opts.body);
1801
+ }
1802
+ if (opts.body === void 0 || opts.serializedBody === "") {
1803
+ opts.headers.delete("Content-Type");
1804
+ }
1805
+ const resolvedOpts = opts;
1806
+ const url = buildUrl(resolvedOpts);
1807
+ return { opts: resolvedOpts, url };
1808
+ }, "beforeRequest");
1809
+ const request = /* @__PURE__ */ __name(async (options) => {
1810
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
1811
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
1812
+ let request2;
1813
+ let response;
1814
+ try {
1815
+ const { opts, url } = await beforeRequest(options);
1816
+ const requestInit = {
1817
+ redirect: "follow",
1818
+ ...opts,
1819
+ body: getValidRequestBody(opts)
1820
+ };
1821
+ request2 = new Request(url, requestInit);
1822
+ for (const fn of interceptors.request.fns) {
1823
+ if (fn) {
1824
+ request2 = await fn(request2, opts);
1825
+ }
1826
+ }
1827
+ const _fetch = opts.fetch;
1828
+ response = await _fetch(request2);
1829
+ for (const fn of interceptors.response.fns) {
1830
+ if (fn) {
1831
+ response = await fn(response, request2, opts);
1832
+ }
1833
+ }
1834
+ const result = {
1835
+ request: request2,
1836
+ response
1837
+ };
1838
+ if (response.ok) {
1839
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
1840
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
1841
+ let emptyData;
1842
+ switch (parseAs) {
1843
+ case "arrayBuffer":
1844
+ case "blob":
1845
+ case "text":
1846
+ emptyData = await response[parseAs]();
1847
+ break;
1848
+ case "formData":
1849
+ emptyData = new FormData();
1850
+ break;
1851
+ case "stream":
1852
+ emptyData = response.body;
1853
+ break;
1854
+ case "json":
1855
+ default:
1856
+ emptyData = {};
1857
+ break;
1858
+ }
1859
+ return opts.responseStyle === "data" ? emptyData : {
1860
+ data: emptyData,
1861
+ ...result
1862
+ };
1863
+ }
1864
+ let data;
1865
+ switch (parseAs) {
1866
+ case "arrayBuffer":
1867
+ case "blob":
1868
+ case "formData":
1869
+ case "text":
1870
+ data = await response[parseAs]();
1871
+ break;
1872
+ case "json": {
1873
+ const text = await response.text();
1874
+ data = text ? JSON.parse(text) : {};
1875
+ break;
1876
+ }
1877
+ case "stream":
1878
+ return opts.responseStyle === "data" ? response.body : {
1879
+ data: response.body,
1880
+ ...result
1881
+ };
1882
+ }
1883
+ if (parseAs === "json") {
1884
+ if (opts.responseValidator) {
1885
+ await opts.responseValidator(data);
1886
+ }
1887
+ if (opts.responseTransformer) {
1888
+ data = await opts.responseTransformer(data);
1889
+ }
1890
+ }
1891
+ return opts.responseStyle === "data" ? data : {
1892
+ data,
1893
+ ...result
1894
+ };
1895
+ }
1896
+ const textError = await response.text();
1897
+ let jsonError;
1898
+ try {
1899
+ jsonError = JSON.parse(textError);
1900
+ } catch {
1901
+ }
1902
+ throw jsonError ?? textError;
1903
+ } catch (error) {
1904
+ let finalError = error;
1905
+ for (const fn of interceptors.error.fns) {
1906
+ if (fn) {
1907
+ finalError = await fn(finalError, response, request2, options);
1908
+ }
1909
+ }
1910
+ finalError = finalError || {};
1911
+ if (throwOnError) {
1912
+ throw finalError;
1913
+ }
1914
+ return responseStyle === "data" ? void 0 : {
1915
+ error: finalError,
1916
+ request: request2,
1917
+ response
1918
+ };
1919
+ }
1920
+ }, "request");
1921
+ const makeMethodFn = /* @__PURE__ */ __name((method) => (options) => request({ ...options, method }), "makeMethodFn");
1922
+ const makeSseFn = /* @__PURE__ */ __name((method) => async (options) => {
1923
+ const { opts, url } = await beforeRequest(options);
1924
+ return createSseClient({
1925
+ ...opts,
1926
+ body: opts.body,
1927
+ method,
1928
+ onRequest: /* @__PURE__ */ __name(async (url2, init) => {
1929
+ let request2 = new Request(url2, init);
1930
+ for (const fn of interceptors.request.fns) {
1931
+ if (fn) {
1932
+ request2 = await fn(request2, opts);
1933
+ }
1934
+ }
1935
+ return request2;
1936
+ }, "onRequest"),
1937
+ serializedBody: getValidRequestBody(opts),
1938
+ url
1939
+ });
1940
+ }, "makeSseFn");
1941
+ const _buildUrl = /* @__PURE__ */ __name((options) => buildUrl({ ..._config, ...options }), "_buildUrl");
1942
+ return {
1943
+ buildUrl: _buildUrl,
1944
+ connect: makeMethodFn("CONNECT"),
1945
+ delete: makeMethodFn("DELETE"),
1946
+ get: makeMethodFn("GET"),
1947
+ getConfig,
1948
+ head: makeMethodFn("HEAD"),
1949
+ interceptors,
1950
+ options: makeMethodFn("OPTIONS"),
1951
+ patch: makeMethodFn("PATCH"),
1952
+ post: makeMethodFn("POST"),
1953
+ put: makeMethodFn("PUT"),
1954
+ request,
1955
+ setConfig,
1956
+ sse: {
1957
+ connect: makeSseFn("CONNECT"),
1958
+ delete: makeSseFn("DELETE"),
1959
+ get: makeSseFn("GET"),
1960
+ head: makeSseFn("HEAD"),
1961
+ options: makeSseFn("OPTIONS"),
1962
+ patch: makeSseFn("PATCH"),
1963
+ post: makeSseFn("POST"),
1964
+ put: makeSseFn("PUT"),
1965
+ trace: makeSseFn("TRACE")
1966
+ },
1967
+ trace: makeMethodFn("TRACE")
1968
+ };
1969
+ }, "createClient");
1970
+
1971
+ // src/_api/generated/client.gen.ts
1972
+ var client = createClient(createConfig({ baseUrl: "http://localhost:8000" }));
1973
+ installAuthOnClient(client);
1974
+
1975
+ // src/_api/generated/sdk.gen.ts
1976
+ var CfgAccountsOauth = class {
1977
+ static {
1978
+ __name(this, "CfgAccountsOauth");
1979
+ }
1980
+ /**
1981
+ * List OAuth connections
1982
+ *
1983
+ * Get all OAuth connections for the current user.
1984
+ */
1985
+ static cfgAccountsOauthConnectionsList(options) {
1986
+ return (options?.client ?? client).get({
1987
+ security: [
1988
+ { name: "X-API-Key", type: "apiKey" },
1989
+ { scheme: "bearer", type: "http" },
1990
+ { name: "Authorization", type: "apiKey" }
1991
+ ],
1992
+ url: "/cfg/accounts/oauth/connections/",
1993
+ ...options
1994
+ });
1995
+ }
1996
+ /**
1997
+ * Disconnect OAuth provider
1998
+ *
1999
+ * Remove OAuth connection for the specified provider.
2000
+ */
2001
+ static cfgAccountsOauthDisconnectCreate(options) {
2002
+ return (options.client ?? client).post({
2003
+ security: [
2004
+ { name: "X-API-Key", type: "apiKey" },
2005
+ { scheme: "bearer", type: "http" },
2006
+ { name: "Authorization", type: "apiKey" }
2007
+ ],
2008
+ url: "/cfg/accounts/oauth/disconnect/",
2009
+ ...options,
2010
+ headers: {
2011
+ "Content-Type": "application/json",
2012
+ ...options.headers
2013
+ }
2014
+ });
2015
+ }
2016
+ /**
2017
+ * Start GitHub OAuth
2018
+ *
2019
+ * Generate GitHub OAuth authorization URL. Redirect user to this URL to start authentication.
2020
+ */
2021
+ static cfgAccountsOauthGithubAuthorizeCreate(options) {
2022
+ return (options?.client ?? client).post({
2023
+ url: "/cfg/accounts/oauth/github/authorize/",
2024
+ ...options,
2025
+ headers: {
2026
+ "Content-Type": "application/json",
2027
+ ...options?.headers
2028
+ }
2029
+ });
2030
+ }
2031
+ /**
2032
+ * Complete GitHub OAuth
2033
+ *
2034
+ * Exchange authorization code for JWT tokens. Call this after GitHub redirects back with code.
2035
+ */
2036
+ static cfgAccountsOauthGithubCallbackCreate(options) {
2037
+ return (options.client ?? client).post({
2038
+ url: "/cfg/accounts/oauth/github/callback/",
2039
+ ...options,
2040
+ headers: {
2041
+ "Content-Type": "application/json",
2042
+ ...options.headers
2043
+ }
2044
+ });
2045
+ }
2046
+ /**
2047
+ * List OAuth providers
2048
+ *
2049
+ * Get list of available OAuth providers for authentication.
2050
+ */
2051
+ static cfgAccountsOauthProvidersRetrieve(options) {
2052
+ return (options?.client ?? client).get({ url: "/cfg/accounts/oauth/providers/", ...options });
2053
+ }
2054
+ };
2055
+ var CfgAccounts = class {
2056
+ static {
2057
+ __name(this, "CfgAccounts");
2058
+ }
2059
+ /**
2060
+ * Request OTP code to email.
2061
+ */
2062
+ static cfgAccountsOtpRequestCreate(options) {
2063
+ return (options.client ?? client).post({
2064
+ security: [
2065
+ { name: "X-API-Key", type: "apiKey" },
2066
+ { scheme: "bearer", type: "http" },
2067
+ { name: "Authorization", type: "apiKey" }
2068
+ ],
2069
+ url: "/cfg/accounts/otp/request/",
2070
+ ...options,
2071
+ headers: {
2072
+ "Content-Type": "application/json",
2073
+ ...options.headers
2074
+ }
2075
+ });
2076
+ }
2077
+ /**
2078
+ * Verify OTP code and return JWT tokens or 2FA session.
2079
+ *
2080
+ * If user has 2FA enabled:
2081
+ * - Returns requires_2fa=True with session_id
2082
+ * - Client must complete 2FA verification at /cfg/totp/verify/
2083
+ *
2084
+ * If user has no 2FA:
2085
+ * - Returns JWT tokens and user data directly
2086
+ */
2087
+ static cfgAccountsOtpVerifyCreate(options) {
2088
+ return (options.client ?? client).post({
2089
+ security: [
2090
+ { name: "X-API-Key", type: "apiKey" },
2091
+ { scheme: "bearer", type: "http" },
2092
+ { name: "Authorization", type: "apiKey" }
2093
+ ],
2094
+ url: "/cfg/accounts/otp/verify/",
2095
+ ...options,
2096
+ headers: {
2097
+ "Content-Type": "application/json",
2098
+ ...options.headers
2099
+ }
2100
+ });
2101
+ }
2102
+ };
2103
+ var CfgAccountsProfile = class {
2104
+ static {
2105
+ __name(this, "CfgAccountsProfile");
2106
+ }
2107
+ /**
2108
+ * Get current user profile
2109
+ *
2110
+ * Retrieve the current authenticated user's profile information.
2111
+ */
2112
+ static cfgAccountsProfileRetrieve(options) {
2113
+ return (options?.client ?? client).get({
2114
+ security: [{ scheme: "bearer", type: "http" }, {
2115
+ in: "cookie",
2116
+ name: "sessionid",
2117
+ type: "apiKey"
2118
+ }],
2119
+ url: "/cfg/accounts/profile/",
2120
+ ...options
2121
+ });
2122
+ }
2123
+ /**
2124
+ * Upload user avatar
2125
+ *
2126
+ * Upload avatar image for the current authenticated user. Accepts multipart/form-data with 'avatar' field.
2127
+ */
2128
+ static cfgAccountsProfileAvatarCreate(options) {
2129
+ return (options?.client ?? client).post({
2130
+ ...formDataBodySerializer,
2131
+ security: [
2132
+ { name: "X-API-Key", type: "apiKey" },
2133
+ { scheme: "bearer", type: "http" },
2134
+ { name: "Authorization", type: "apiKey" }
2135
+ ],
2136
+ url: "/cfg/accounts/profile/avatar/",
2137
+ ...options,
2138
+ headers: {
2139
+ "Content-Type": null,
2140
+ ...options?.headers
2141
+ }
2142
+ });
2143
+ }
2144
+ /**
2145
+ * Delete user account
2146
+ *
2147
+ *
2148
+ * Permanently delete the current user's account.
2149
+ *
2150
+ * This operation:
2151
+ * - Deactivates the account (user cannot log in)
2152
+ * - Anonymizes personal data (GDPR compliance)
2153
+ * - Frees up the email address for re-registration
2154
+ * - Preserves audit trail
2155
+ *
2156
+ * The account can be restored by an administrator if needed.
2157
+ *
2158
+ */
2159
+ static cfgAccountsProfileDeleteCreate(options) {
2160
+ return (options?.client ?? client).post({
2161
+ security: [{ scheme: "bearer", type: "http" }, {
2162
+ in: "cookie",
2163
+ name: "sessionid",
2164
+ type: "apiKey"
2165
+ }],
2166
+ url: "/cfg/accounts/profile/delete/",
2167
+ ...options
2168
+ });
2169
+ }
2170
+ /**
2171
+ * Partial update user profile
2172
+ *
2173
+ * Partially update the current authenticated user's profile information. Supports avatar upload.
2174
+ */
2175
+ static cfgAccountsProfilePartialPartialUpdate(options) {
2176
+ return (options?.client ?? client).patch({
2177
+ security: [{ scheme: "bearer", type: "http" }, {
2178
+ in: "cookie",
2179
+ name: "sessionid",
2180
+ type: "apiKey"
2181
+ }],
2182
+ url: "/cfg/accounts/profile/partial/",
2183
+ ...options,
2184
+ headers: {
2185
+ "Content-Type": "application/json",
2186
+ ...options?.headers
2187
+ }
2188
+ });
2189
+ }
2190
+ /**
2191
+ * Partial update user profile
2192
+ *
2193
+ * Partially update the current authenticated user's profile information. Supports avatar upload.
2194
+ */
2195
+ static cfgAccountsProfilePartialUpdate(options) {
2196
+ return (options?.client ?? client).put({
2197
+ security: [{ scheme: "bearer", type: "http" }, {
2198
+ in: "cookie",
2199
+ name: "sessionid",
2200
+ type: "apiKey"
2201
+ }],
2202
+ url: "/cfg/accounts/profile/partial/",
2203
+ ...options,
2204
+ headers: {
2205
+ "Content-Type": "application/json",
2206
+ ...options?.headers
2207
+ }
2208
+ });
2209
+ }
2210
+ /**
2211
+ * Update user profile
2212
+ *
2213
+ * Update the current authenticated user's profile information.
2214
+ */
2215
+ static cfgAccountsProfileUpdatePartialUpdate(options) {
2216
+ return (options?.client ?? client).patch({
2217
+ security: [{ scheme: "bearer", type: "http" }, {
2218
+ in: "cookie",
2219
+ name: "sessionid",
2220
+ type: "apiKey"
2221
+ }],
2222
+ url: "/cfg/accounts/profile/update/",
2223
+ ...options,
2224
+ headers: {
2225
+ "Content-Type": "application/json",
2226
+ ...options?.headers
2227
+ }
2228
+ });
2229
+ }
2230
+ /**
2231
+ * Update user profile
2232
+ *
2233
+ * Update the current authenticated user's profile information.
2234
+ */
2235
+ static cfgAccountsProfileUpdateUpdate(options) {
2236
+ return (options?.client ?? client).put({
2237
+ security: [{ scheme: "bearer", type: "http" }, {
2238
+ in: "cookie",
2239
+ name: "sessionid",
2240
+ type: "apiKey"
2241
+ }],
2242
+ url: "/cfg/accounts/profile/update/",
2243
+ ...options,
2244
+ headers: {
2245
+ "Content-Type": "application/json",
2246
+ ...options?.headers
2247
+ }
2248
+ });
2249
+ }
2250
+ };
2251
+ var CfgAccountsAuth = class {
2252
+ static {
2253
+ __name(this, "CfgAccountsAuth");
2254
+ }
2255
+ /**
2256
+ * Revoke a refresh token (logout).
2257
+ *
2258
+ * Blacklists the posted refresh token so it can never mint another access
2259
+ * token. Called best-effort by the client's logout — without it, "logout"
2260
+ * is purely client-side and a stolen refresh token survives until expiry.
2261
+ */
2262
+ static cfgAccountsTokenBlacklistCreate(options) {
2263
+ return (options.client ?? client).post({
2264
+ url: "/cfg/accounts/token/blacklist/",
2265
+ ...options,
2266
+ headers: {
2267
+ "Content-Type": "application/json",
2268
+ ...options.headers
2269
+ }
2270
+ });
2271
+ }
2272
+ /**
2273
+ * Refresh JWT token.
2274
+ *
2275
+ * DPoP-aware: when the incoming refresh token is key-bound (`cnf.jkt`), the
2276
+ * rotated access/refresh in the response are re-stamped with the same `cnf`
2277
+ * (stock SimpleJWT drops it from the derived access), and a matching DPoP
2278
+ * proof is required on the refresh request — so a stolen refresh token can't
2279
+ * be used to mint fresh tokens.
2280
+ */
2281
+ static cfgAccountsTokenRefreshCreate(options) {
2282
+ return (options.client ?? client).post({
2283
+ url: "/cfg/accounts/token/refresh/",
2284
+ ...options,
2285
+ headers: {
2286
+ "Content-Type": "application/json",
2287
+ ...options.headers
2288
+ }
2289
+ });
2290
+ }
2291
+ };
2292
+ var CfgTotp = class {
2293
+ static {
2294
+ __name(this, "CfgTotp");
2295
+ }
2296
+ /**
2297
+ * List all TOTP devices for user.
2298
+ */
2299
+ static cfgTotpDevicesRetrieve(options) {
2300
+ return (options?.client ?? client).get({
2301
+ security: [
2302
+ { name: "X-API-Key", type: "apiKey" },
2303
+ { scheme: "bearer", type: "http" },
2304
+ { name: "Authorization", type: "apiKey" }
2305
+ ],
2306
+ url: "/cfg/totp/devices/",
2307
+ ...options
2308
+ });
2309
+ }
2310
+ /**
2311
+ * Delete a TOTP device.
2312
+ *
2313
+ * Requires verification code if removing the last/primary device.
2314
+ */
2315
+ static cfgTotpDevicesDestroy(options) {
2316
+ return (options.client ?? client).delete({
2317
+ security: [
2318
+ { name: "X-API-Key", type: "apiKey" },
2319
+ { scheme: "bearer", type: "http" },
2320
+ { name: "Authorization", type: "apiKey" }
2321
+ ],
2322
+ url: "/cfg/totp/devices/{id}/",
2323
+ ...options
2324
+ });
2325
+ }
2326
+ /**
2327
+ * Completely disable 2FA for account.
2328
+ *
2329
+ * Requires verification code.
2330
+ */
2331
+ static cfgTotpDisableCreate(options) {
2332
+ return (options.client ?? client).post({
2333
+ security: [
2334
+ { name: "X-API-Key", type: "apiKey" },
2335
+ { scheme: "bearer", type: "http" },
2336
+ { name: "Authorization", type: "apiKey" }
2337
+ ],
2338
+ url: "/cfg/totp/disable/",
2339
+ ...options,
2340
+ headers: {
2341
+ "Content-Type": "application/json",
2342
+ ...options.headers
2343
+ }
2344
+ });
2345
+ }
2346
+ };
2347
+ var CfgTotpSetup = class {
2348
+ static {
2349
+ __name(this, "CfgTotpSetup");
2350
+ }
2351
+ /**
2352
+ * Start 2FA setup process.
2353
+ *
2354
+ * Creates a new TOTP device and returns QR code for scanning.
2355
+ */
2356
+ static cfgTotpSetupCreate(options) {
2357
+ return (options?.client ?? client).post({
2358
+ security: [
2359
+ { name: "X-API-Key", type: "apiKey" },
2360
+ { scheme: "bearer", type: "http" },
2361
+ { name: "Authorization", type: "apiKey" }
2362
+ ],
2363
+ url: "/cfg/totp/setup/",
2364
+ ...options,
2365
+ headers: {
2366
+ "Content-Type": "application/json",
2367
+ ...options?.headers
2368
+ }
2369
+ });
2370
+ }
2371
+ /**
2372
+ * Confirm 2FA setup with first valid code.
2373
+ *
2374
+ * Activates the device and generates backup codes.
2375
+ */
2376
+ static cfgTotpSetupConfirmCreate(options) {
2377
+ return (options.client ?? client).post({
2378
+ security: [
2379
+ { name: "X-API-Key", type: "apiKey" },
2380
+ { scheme: "bearer", type: "http" },
2381
+ { name: "Authorization", type: "apiKey" }
2382
+ ],
2383
+ url: "/cfg/totp/setup/confirm/",
2384
+ ...options,
2385
+ headers: {
2386
+ "Content-Type": "application/json",
2387
+ ...options.headers
2388
+ }
2389
+ });
2390
+ }
2391
+ };
2392
+ var CfgTotpVerify = class {
2393
+ static {
2394
+ __name(this, "CfgTotpVerify");
2395
+ }
2396
+ /**
2397
+ * Verify TOTP code for 2FA session.
2398
+ *
2399
+ * Completes authentication and returns JWT tokens on success.
2400
+ */
2401
+ static cfgTotpVerifyCreate(options) {
2402
+ return (options.client ?? client).post({
2403
+ security: [
2404
+ { name: "X-API-Key", type: "apiKey" },
2405
+ { scheme: "bearer", type: "http" },
2406
+ { name: "Authorization", type: "apiKey" }
2407
+ ],
2408
+ url: "/cfg/totp/verify/",
2409
+ ...options,
2410
+ headers: {
2411
+ "Content-Type": "application/json",
2412
+ ...options.headers
2413
+ }
2414
+ });
2415
+ }
2416
+ /**
2417
+ * Verify backup recovery code for 2FA session.
2418
+ *
2419
+ * Alternative verification method when TOTP device unavailable.
2420
+ */
2421
+ static cfgTotpVerifyBackupCreate(options) {
2422
+ return (options.client ?? client).post({
2423
+ security: [
2424
+ { name: "X-API-Key", type: "apiKey" },
2425
+ { scheme: "bearer", type: "http" },
2426
+ { name: "Authorization", type: "apiKey" }
2427
+ ],
2428
+ url: "/cfg/totp/verify/backup/",
2429
+ ...options,
2430
+ headers: {
2431
+ "Content-Type": "application/json",
2432
+ ...options.headers
2433
+ }
2434
+ });
2435
+ }
2436
+ };
2700
2437
 
2701
2438
  // src/auth/utils/analytics.ts
2702
2439
  var AnalyticsEvent = /* @__PURE__ */ ((AnalyticsEvent2) => {
@@ -2731,22 +2468,228 @@ var Analytics = {
2731
2468
  if (isDev) {
2732
2469
  console.log("[Analytics] Set user:", userId);
2733
2470
  }
2734
- }
2735
- };
2471
+ }
2472
+ };
2473
+
2474
+ // src/auth/hooks/useSessionStorage.ts
2475
+ var import_react7 = require("react");
2476
+ function useSessionStorage(key, initialValue) {
2477
+ const [storedValue, setStoredValue] = (0, import_react7.useState)(() => {
2478
+ if (typeof window === "undefined") {
2479
+ return initialValue;
2480
+ }
2481
+ try {
2482
+ const item = window.sessionStorage.getItem(key);
2483
+ return item ? JSON.parse(item) : initialValue;
2484
+ } catch (error) {
2485
+ authLogger.error(`Error reading sessionStorage key "${key}":`, error);
2486
+ return initialValue;
2487
+ }
2488
+ });
2489
+ const checkDataSize = /* @__PURE__ */ __name((data) => {
2490
+ try {
2491
+ const jsonString = JSON.stringify(data);
2492
+ const sizeInBytes = new Blob([jsonString]).size;
2493
+ const sizeInKB = sizeInBytes / 1024;
2494
+ if (sizeInKB > 1024) {
2495
+ authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
2496
+ return false;
2497
+ }
2498
+ return true;
2499
+ } catch (error) {
2500
+ authLogger.error(`Error checking data size for key "${key}":`, error);
2501
+ return false;
2502
+ }
2503
+ }, "checkDataSize");
2504
+ const clearOldData = /* @__PURE__ */ __name(() => {
2505
+ try {
2506
+ const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
2507
+ if (keys.length > 50) {
2508
+ const itemsToRemove = Math.ceil(keys.length * 0.2);
2509
+ for (let i = 0; i < itemsToRemove; i++) {
2510
+ try {
2511
+ const key2 = keys[i];
2512
+ if (key2) {
2513
+ sessionStorage.removeItem(key2);
2514
+ sessionStorage.removeItem(`${key2}_timestamp`);
2515
+ }
2516
+ } catch {
2517
+ }
2518
+ }
2519
+ }
2520
+ } catch (error) {
2521
+ authLogger.error("Error clearing old sessionStorage data:", error);
2522
+ }
2523
+ }, "clearOldData");
2524
+ const forceClearAll = /* @__PURE__ */ __name(() => {
2525
+ try {
2526
+ const keys = Object.keys(sessionStorage);
2527
+ for (const key2 of keys) {
2528
+ try {
2529
+ sessionStorage.removeItem(key2);
2530
+ } catch {
2531
+ }
2532
+ }
2533
+ } catch (error) {
2534
+ authLogger.error("Error force clearing sessionStorage:", error);
2535
+ }
2536
+ }, "forceClearAll");
2537
+ const setValue = /* @__PURE__ */ __name((value) => {
2538
+ try {
2539
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
2540
+ if (!checkDataSize(valueToStore)) {
2541
+ authLogger.warn(`Data size too large for key "${key}", removing key`);
2542
+ try {
2543
+ window.sessionStorage.removeItem(key);
2544
+ window.sessionStorage.removeItem(`${key}_timestamp`);
2545
+ } catch {
2546
+ }
2547
+ setStoredValue(valueToStore);
2548
+ return;
2549
+ }
2550
+ setStoredValue(valueToStore);
2551
+ if (typeof window !== "undefined") {
2552
+ try {
2553
+ window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
2554
+ window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
2555
+ } catch (storageError) {
2556
+ if (storageError.name === "QuotaExceededError" || storageError.code === 22 || storageError.message?.includes("quota")) {
2557
+ authLogger.warn("sessionStorage quota exceeded, clearing old data...");
2558
+ clearOldData();
2559
+ try {
2560
+ window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
2561
+ window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
2562
+ } catch (retryError) {
2563
+ authLogger.error(`Failed to set sessionStorage key "${key}" after clearing old data:`, retryError);
2564
+ try {
2565
+ forceClearAll();
2566
+ window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
2567
+ window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
2568
+ } catch (finalError) {
2569
+ authLogger.error(`Failed to set sessionStorage key "${key}" after force clearing:`, finalError);
2570
+ setStoredValue(valueToStore);
2571
+ }
2572
+ }
2573
+ } else {
2574
+ throw storageError;
2575
+ }
2576
+ }
2577
+ }
2578
+ } catch (error) {
2579
+ authLogger.error(`Error setting sessionStorage key "${key}":`, error);
2580
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
2581
+ setStoredValue(valueToStore);
2582
+ }
2583
+ }, "setValue");
2584
+ const removeValue = /* @__PURE__ */ __name(() => {
2585
+ try {
2586
+ setStoredValue(initialValue);
2587
+ if (typeof window !== "undefined") {
2588
+ try {
2589
+ window.sessionStorage.removeItem(key);
2590
+ window.sessionStorage.removeItem(`${key}_timestamp`);
2591
+ } catch (removeError) {
2592
+ if (removeError.name === "QuotaExceededError" || removeError.code === 22 || removeError.message?.includes("quota")) {
2593
+ authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
2594
+ clearOldData();
2595
+ try {
2596
+ window.sessionStorage.removeItem(key);
2597
+ window.sessionStorage.removeItem(`${key}_timestamp`);
2598
+ } catch (retryError) {
2599
+ authLogger.error(`Failed to remove sessionStorage key "${key}" after clearing:`, retryError);
2600
+ forceClearAll();
2601
+ }
2602
+ } else {
2603
+ throw removeError;
2604
+ }
2605
+ }
2606
+ }
2607
+ } catch (error) {
2608
+ authLogger.error(`Error removing sessionStorage key "${key}":`, error);
2609
+ }
2610
+ }, "removeValue");
2611
+ return [storedValue, setValue, removeValue];
2612
+ }
2613
+ __name(useSessionStorage, "useSessionStorage");
2614
+
2615
+ // src/auth/hooks/useAuthRedirect.ts
2616
+ var AUTH_REDIRECT_KEY = "auth_redirect_url";
2617
+ var getRedirectFromStorage = /* @__PURE__ */ __name(() => {
2618
+ if (typeof window === "undefined") return "";
2619
+ try {
2620
+ const item = window.sessionStorage.getItem(AUTH_REDIRECT_KEY);
2621
+ return item ? JSON.parse(item) : "";
2622
+ } catch {
2623
+ return "";
2624
+ }
2625
+ }, "getRedirectFromStorage");
2626
+ var clearRedirectFromStorage = /* @__PURE__ */ __name(() => {
2627
+ if (typeof window === "undefined") return;
2628
+ try {
2629
+ window.sessionStorage.removeItem(AUTH_REDIRECT_KEY);
2630
+ window.sessionStorage.removeItem(`${AUTH_REDIRECT_KEY}_timestamp`);
2631
+ } catch {
2632
+ }
2633
+ }, "clearRedirectFromStorage");
2634
+ var peekSavedRedirect = /* @__PURE__ */ __name(() => getRedirectFromStorage() || null, "peekSavedRedirect");
2635
+ var consumeSavedRedirect = /* @__PURE__ */ __name(() => {
2636
+ const stored = getRedirectFromStorage();
2637
+ if (stored) clearRedirectFromStorage();
2638
+ return stored || null;
2639
+ }, "consumeSavedRedirect");
2640
+ var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
2641
+ const { fallbackUrl = "/dashboard", clearOnUse = true } = options;
2642
+ const [redirectUrl, setRedirectUrl, removeRedirectUrl] = useSessionStorage(AUTH_REDIRECT_KEY, "");
2643
+ const setRedirect = /* @__PURE__ */ __name((url) => {
2644
+ setRedirectUrl(url);
2645
+ }, "setRedirect");
2646
+ const getRedirect = /* @__PURE__ */ __name(() => {
2647
+ return getRedirectFromStorage() || redirectUrl;
2648
+ }, "getRedirect");
2649
+ const clearRedirect = /* @__PURE__ */ __name(() => {
2650
+ removeRedirectUrl();
2651
+ clearRedirectFromStorage();
2652
+ }, "clearRedirect");
2653
+ const hasRedirect = /* @__PURE__ */ __name(() => {
2654
+ const stored = getRedirectFromStorage();
2655
+ return stored.length > 0 || redirectUrl.length > 0;
2656
+ }, "hasRedirect");
2657
+ const getFinalRedirectUrl = /* @__PURE__ */ __name(() => {
2658
+ const stored = getRedirectFromStorage();
2659
+ return stored || redirectUrl || fallbackUrl;
2660
+ }, "getFinalRedirectUrl");
2661
+ const useAndClearRedirect = /* @__PURE__ */ __name(() => {
2662
+ const stored = getRedirectFromStorage();
2663
+ const finalUrl = stored || redirectUrl || fallbackUrl;
2664
+ if (clearOnUse) {
2665
+ clearRedirect();
2666
+ }
2667
+ return finalUrl;
2668
+ }, "useAndClearRedirect");
2669
+ return {
2670
+ redirectUrl,
2671
+ setRedirect,
2672
+ getRedirect,
2673
+ clearRedirect,
2674
+ hasRedirect,
2675
+ getFinalRedirectUrl,
2676
+ useAndClearRedirect
2677
+ };
2678
+ }, "useAuthRedirectManager");
2736
2679
 
2737
2680
  // src/auth/hooks/useTwoFactor.ts
2738
2681
  var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
2739
2682
  const { onSuccess, onError, redirectUrl, skipRedirect = false } = options;
2740
2683
  const router = useCfgRouter();
2741
- const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
2742
- const [error, setError] = (0, import_react7.useState)(null);
2743
- const [warning, setWarning] = (0, import_react7.useState)(null);
2744
- const [remainingBackupCodes, setRemainingBackupCodes] = (0, import_react7.useState)(null);
2745
- const [attemptsRemaining, setAttemptsRemaining] = (0, import_react7.useState)(null);
2746
- const clearError = (0, import_react7.useCallback)(() => {
2684
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
2685
+ const [error, setError] = (0, import_react8.useState)(null);
2686
+ const [warning, setWarning] = (0, import_react8.useState)(null);
2687
+ const [remainingBackupCodes, setRemainingBackupCodes] = (0, import_react8.useState)(null);
2688
+ const [attemptsRemaining, setAttemptsRemaining] = (0, import_react8.useState)(null);
2689
+ const clearError = (0, import_react8.useCallback)(() => {
2747
2690
  setError(null);
2748
2691
  }, []);
2749
- const handleSuccess = (0, import_react7.useCallback)((response) => {
2692
+ const handleSuccess = (0, import_react8.useCallback)((response) => {
2750
2693
  auth.setSession({ access: response.access_token, refresh: response.refresh_token });
2751
2694
  if (response.warning) {
2752
2695
  setWarning(response.warning);
@@ -2763,12 +2706,12 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
2763
2706
  }
2764
2707
  onSuccess?.(response.user);
2765
2708
  if (!skipRedirect) {
2766
- const finalRedirectUrl = redirectUrl || "/dashboard";
2709
+ const finalRedirectUrl = consumeSavedRedirect() || redirectUrl || "/";
2767
2710
  authLogger.info("2FA successful, redirecting to:", finalRedirectUrl);
2768
2711
  router.hardPush(finalRedirectUrl);
2769
2712
  }
2770
2713
  }, [onSuccess, redirectUrl, router, skipRedirect]);
2771
- const verifyTOTP = (0, import_react7.useCallback)(async (sessionId, code) => {
2714
+ const verifyTOTP = (0, import_react8.useCallback)(async (sessionId, code) => {
2772
2715
  if (!sessionId) {
2773
2716
  const msg = "Missing 2FA session ID";
2774
2717
  setError(msg);
@@ -2812,7 +2755,7 @@ var useTwoFactor = /* @__PURE__ */ __name((options = {}) => {
2812
2755
  setIsLoading(false);
2813
2756
  }
2814
2757
  }, [handleSuccess, onError]);
2815
- const verifyBackupCode = (0, import_react7.useCallback)(async (sessionId, backupCode) => {
2758
+ const verifyBackupCode = (0, import_react8.useCallback)(async (sessionId, backupCode) => {
2816
2759
  if (!sessionId) {
2817
2760
  const msg = "Missing 2FA session ID";
2818
2761
  setError(msg);
@@ -2884,8 +2827,8 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
2884
2827
  } = options;
2885
2828
  const formState = useAuthFormState();
2886
2829
  const validation = useAuthValidation();
2887
- const isAutoSubmitFromUrlRef = (0, import_react8.useRef)(false);
2888
- const processedOtpKeyRef = (0, import_react8.useRef)(null);
2830
+ const isAutoSubmitFromUrlRef = (0, import_react9.useRef)(false);
2831
+ const processedOtpKeyRef = (0, import_react9.useRef)(null);
2889
2832
  const {
2890
2833
  requestOTP,
2891
2834
  verifyOTP,
@@ -2928,16 +2871,16 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
2928
2871
  // We handle navigation via success step
2929
2872
  });
2930
2873
  const { validateIdentifier: validateIdentifier2 } = validation;
2931
- const saveIdentifierToStorage = (0, import_react8.useCallback)((id) => {
2874
+ const saveIdentifierToStorage = (0, import_react9.useCallback)((id) => {
2932
2875
  saveEmail(id);
2933
2876
  }, [saveEmail]);
2934
- (0, import_react8.useEffect)(() => {
2877
+ (0, import_react9.useEffect)(() => {
2935
2878
  const savedEmail = getSavedEmail();
2936
2879
  if (savedEmail) {
2937
2880
  setIdentifier(savedEmail);
2938
2881
  }
2939
2882
  }, []);
2940
- const handleIdentifierSubmit = (0, import_react8.useCallback)(async (e) => {
2883
+ const handleIdentifierSubmit = (0, import_react9.useCallback)(async (e) => {
2941
2884
  e.preventDefault();
2942
2885
  if (!identifier) {
2943
2886
  const msg = "Please enter your email address";
@@ -2999,7 +2942,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
2999
2942
  onError,
3000
2943
  sourceUrl
3001
2944
  ]);
3002
- const submitOTP = (0, import_react8.useCallback)(async (submitIdentifier, submitOtp) => {
2945
+ const submitOTP = (0, import_react9.useCallback)(async (submitIdentifier, submitOtp) => {
3003
2946
  if (!submitOtp || submitOtp.length < AUTH_CONSTANTS.EMAIL_OTP_LENGTH) {
3004
2947
  const msg = `Please enter the ${AUTH_CONSTANTS.EMAIL_OTP_LENGTH}-digit verification code`;
3005
2948
  setError(msg);
@@ -3038,11 +2981,11 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
3038
2981
  setIsLoading(false);
3039
2982
  }
3040
2983
  }, [verifyOTP, saveIdentifierToStorage, setError, setIsLoading, clearError, onOTPSuccess, onError, sourceUrl, redirectUrl, setTwoFactorSessionId, setShouldPrompt2FA, setStep]);
3041
- const handleOTPSubmit = (0, import_react8.useCallback)(async (e) => {
2984
+ const handleOTPSubmit = (0, import_react9.useCallback)(async (e) => {
3042
2985
  e.preventDefault();
3043
2986
  await submitOTP(identifier, otp);
3044
2987
  }, [identifier, otp, submitOTP]);
3045
- const handleResendOTP = (0, import_react8.useCallback)(async () => {
2988
+ const handleResendOTP = (0, import_react9.useCallback)(async () => {
3046
2989
  setIsLoading(true);
3047
2990
  clearError();
3048
2991
  try {
@@ -3068,15 +3011,15 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
3068
3011
  setIsLoading(false);
3069
3012
  }
3070
3013
  }, [identifier, requestOTP, saveIdentifierToStorage, setOtp, setError, setIsLoading, clearError, startRateLimitCountdown, setWebmail, onError, sourceUrl]);
3071
- const handleBackToIdentifier = (0, import_react8.useCallback)(() => {
3014
+ const handleBackToIdentifier = (0, import_react9.useCallback)(() => {
3072
3015
  setStep("identifier");
3073
3016
  clearError();
3074
3017
  }, [setStep, clearError]);
3075
- const forceOTPStep = (0, import_react8.useCallback)(() => {
3018
+ const forceOTPStep = (0, import_react9.useCallback)(() => {
3076
3019
  setStep("otp");
3077
3020
  clearError();
3078
3021
  }, [setStep, clearError]);
3079
- const handle2FASubmit = (0, import_react8.useCallback)(async (e) => {
3022
+ const handle2FASubmit = (0, import_react9.useCallback)(async (e) => {
3080
3023
  e.preventDefault();
3081
3024
  if (!twoFactorSessionId) {
3082
3025
  const msg = "Missing 2FA session";
@@ -3090,17 +3033,17 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
3090
3033
  await twoFactor.verifyTOTP(twoFactorSessionId, twoFactorCode);
3091
3034
  }
3092
3035
  }, [twoFactorSessionId, twoFactorCode, useBackupCode, twoFactor, setError, onError]);
3093
- const handleUseBackupCode = (0, import_react8.useCallback)(() => {
3036
+ const handleUseBackupCode = (0, import_react9.useCallback)(() => {
3094
3037
  setUseBackupCode(true);
3095
3038
  setTwoFactorCode("");
3096
3039
  clearError();
3097
3040
  }, [setUseBackupCode, setTwoFactorCode, clearError]);
3098
- const handleUseTOTP = (0, import_react8.useCallback)(() => {
3041
+ const handleUseTOTP = (0, import_react9.useCallback)(() => {
3099
3042
  setUseBackupCode(false);
3100
3043
  setTwoFactorCode("");
3101
3044
  clearError();
3102
3045
  }, [setUseBackupCode, setTwoFactorCode, clearError]);
3103
- const handleOTPFromUrl = (0, import_react8.useCallback)((detectedOtp, detectedEmail) => {
3046
+ const handleOTPFromUrl = (0, import_react9.useCallback)((detectedOtp, detectedEmail) => {
3104
3047
  const autoIdentifier = detectedEmail || getSavedEmail() || "";
3105
3048
  if (!autoIdentifier) {
3106
3049
  authLogger.warn("No identifier found for auto-submit (no email in URL or storage)");
@@ -3153,15 +3096,13 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
3153
3096
  }, "useAuthForm");
3154
3097
 
3155
3098
  // src/auth/hooks/useGithubAuth.ts
3156
- var import_react9 = require("react");
3157
- init_auth();
3158
- init_sdk_gen();
3099
+ var import_react10 = require("react");
3159
3100
  var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
3160
3101
  const { sourceUrl, onSuccess, onError, onRequires2FA, redirectUrl, skipRedirect = false } = options;
3161
3102
  const router = useCfgRouter();
3162
- const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
3163
- const [error, setError] = (0, import_react9.useState)(null);
3164
- const startGithubAuth = (0, import_react9.useCallback)(async () => {
3103
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
3104
+ const [error, setError] = (0, import_react10.useState)(null);
3105
+ const startGithubAuth = (0, import_react10.useCallback)(async () => {
3165
3106
  setIsLoading(true);
3166
3107
  setError(null);
3167
3108
  try {
@@ -3199,7 +3140,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
3199
3140
  setIsLoading(false);
3200
3141
  }
3201
3142
  }, [sourceUrl, onError]);
3202
- const handleGithubCallback = (0, import_react9.useCallback)(async (code, state) => {
3143
+ const handleGithubCallback = (0, import_react10.useCallback)(async (code, state) => {
3203
3144
  setIsLoading(true);
3204
3145
  setError(null);
3205
3146
  try {
@@ -3265,27 +3206,26 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
3265
3206
  }, "useGithubAuth");
3266
3207
 
3267
3208
  // src/auth/hooks/useTwoFactorSetup.ts
3268
- var import_react10 = require("react");
3269
- init_sdk_gen();
3209
+ var import_react11 = require("react");
3270
3210
  var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
3271
3211
  const { onComplete, onError } = options;
3272
- const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
3273
- const [error, setError] = (0, import_react10.useState)(null);
3274
- const [setupData, setSetupData] = (0, import_react10.useState)(null);
3275
- const [backupCodes, setBackupCodes] = (0, import_react10.useState)(null);
3276
- const [backupCodesWarning, setBackupCodesWarning] = (0, import_react10.useState)(null);
3277
- const [setupStep, setSetupStep] = (0, import_react10.useState)("idle");
3278
- const clearError = (0, import_react10.useCallback)(() => {
3212
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
3213
+ const [error, setError] = (0, import_react11.useState)(null);
3214
+ const [setupData, setSetupData] = (0, import_react11.useState)(null);
3215
+ const [backupCodes, setBackupCodes] = (0, import_react11.useState)(null);
3216
+ const [backupCodesWarning, setBackupCodesWarning] = (0, import_react11.useState)(null);
3217
+ const [setupStep, setSetupStep] = (0, import_react11.useState)("idle");
3218
+ const clearError = (0, import_react11.useCallback)(() => {
3279
3219
  setError(null);
3280
3220
  }, []);
3281
- const resetSetup = (0, import_react10.useCallback)(() => {
3221
+ const resetSetup = (0, import_react11.useCallback)(() => {
3282
3222
  setSetupData(null);
3283
3223
  setBackupCodes(null);
3284
3224
  setBackupCodesWarning(null);
3285
3225
  setSetupStep("idle");
3286
3226
  setError(null);
3287
3227
  }, []);
3288
- const startSetup = (0, import_react10.useCallback)(async (deviceName) => {
3228
+ const startSetup = (0, import_react11.useCallback)(async (deviceName) => {
3289
3229
  setIsLoading(true);
3290
3230
  setError(null);
3291
3231
  setSetupStep("scanning");
@@ -3317,7 +3257,7 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
3317
3257
  setIsLoading(false);
3318
3258
  }
3319
3259
  }, [onError]);
3320
- const confirmSetup = (0, import_react10.useCallback)(async (code) => {
3260
+ const confirmSetup = (0, import_react11.useCallback)(async (code) => {
3321
3261
  if (!setupData) {
3322
3262
  const msg = "Setup not started. Call startSetup() first.";
3323
3263
  setError(msg);
@@ -3373,8 +3313,7 @@ var useTwoFactorSetup = /* @__PURE__ */ __name((options = {}) => {
3373
3313
  }, "useTwoFactorSetup");
3374
3314
 
3375
3315
  // src/auth/hooks/useTwoFactorStatus.ts
3376
- var import_react11 = require("react");
3377
- init_sdk_gen();
3316
+ var import_react12 = require("react");
3378
3317
  function extractErrorMessage(err, fallback) {
3379
3318
  if (err instanceof APIError) {
3380
3319
  const body = err.response;
@@ -3387,14 +3326,14 @@ function extractErrorMessage(err, fallback) {
3387
3326
  }
3388
3327
  __name(extractErrorMessage, "extractErrorMessage");
3389
3328
  var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
3390
- const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
3391
- const [error, setError] = (0, import_react11.useState)(null);
3392
- const [has2FAEnabled, setHas2FAEnabled] = (0, import_react11.useState)(null);
3393
- const [devices, setDevices] = (0, import_react11.useState)([]);
3394
- const clearError = (0, import_react11.useCallback)(() => {
3329
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
3330
+ const [error, setError] = (0, import_react12.useState)(null);
3331
+ const [has2FAEnabled, setHas2FAEnabled] = (0, import_react12.useState)(null);
3332
+ const [devices, setDevices] = (0, import_react12.useState)([]);
3333
+ const clearError = (0, import_react12.useCallback)(() => {
3395
3334
  setError(null);
3396
3335
  }, []);
3397
- const fetchStatus = (0, import_react11.useCallback)(async () => {
3336
+ const fetchStatus = (0, import_react12.useCallback)(async () => {
3398
3337
  setIsLoading(true);
3399
3338
  setError(null);
3400
3339
  try {
@@ -3419,7 +3358,7 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
3419
3358
  setIsLoading(false);
3420
3359
  }
3421
3360
  }, []);
3422
- const disable2FA = (0, import_react11.useCallback)(async (code) => {
3361
+ const disable2FA = (0, import_react12.useCallback)(async (code) => {
3423
3362
  if (!code || code.length !== 6) {
3424
3363
  setError("Please enter a 6-digit code");
3425
3364
  return false;
@@ -3453,206 +3392,6 @@ var useTwoFactorStatus = /* @__PURE__ */ __name(() => {
3453
3392
  };
3454
3393
  }, "useTwoFactorStatus");
3455
3394
 
3456
- // src/auth/hooks/useSessionStorage.ts
3457
- var import_react12 = require("react");
3458
- function useSessionStorage(key, initialValue) {
3459
- const [storedValue, setStoredValue] = (0, import_react12.useState)(() => {
3460
- if (typeof window === "undefined") {
3461
- return initialValue;
3462
- }
3463
- try {
3464
- const item = window.sessionStorage.getItem(key);
3465
- return item ? JSON.parse(item) : initialValue;
3466
- } catch (error) {
3467
- authLogger.error(`Error reading sessionStorage key "${key}":`, error);
3468
- return initialValue;
3469
- }
3470
- });
3471
- const checkDataSize = /* @__PURE__ */ __name((data) => {
3472
- try {
3473
- const jsonString = JSON.stringify(data);
3474
- const sizeInBytes = new Blob([jsonString]).size;
3475
- const sizeInKB = sizeInBytes / 1024;
3476
- if (sizeInKB > 1024) {
3477
- authLogger.warn(`Data size (${sizeInKB.toFixed(2)}KB) exceeds 1MB limit for key "${key}"`);
3478
- return false;
3479
- }
3480
- return true;
3481
- } catch (error) {
3482
- authLogger.error(`Error checking data size for key "${key}":`, error);
3483
- return false;
3484
- }
3485
- }, "checkDataSize");
3486
- const clearOldData = /* @__PURE__ */ __name(() => {
3487
- try {
3488
- const keys = Object.keys(sessionStorage).filter((key2) => key2 && typeof key2 === "string");
3489
- if (keys.length > 50) {
3490
- const itemsToRemove = Math.ceil(keys.length * 0.2);
3491
- for (let i = 0; i < itemsToRemove; i++) {
3492
- try {
3493
- const key2 = keys[i];
3494
- if (key2) {
3495
- sessionStorage.removeItem(key2);
3496
- sessionStorage.removeItem(`${key2}_timestamp`);
3497
- }
3498
- } catch {
3499
- }
3500
- }
3501
- }
3502
- } catch (error) {
3503
- authLogger.error("Error clearing old sessionStorage data:", error);
3504
- }
3505
- }, "clearOldData");
3506
- const forceClearAll = /* @__PURE__ */ __name(() => {
3507
- try {
3508
- const keys = Object.keys(sessionStorage);
3509
- for (const key2 of keys) {
3510
- try {
3511
- sessionStorage.removeItem(key2);
3512
- } catch {
3513
- }
3514
- }
3515
- } catch (error) {
3516
- authLogger.error("Error force clearing sessionStorage:", error);
3517
- }
3518
- }, "forceClearAll");
3519
- const setValue = /* @__PURE__ */ __name((value) => {
3520
- try {
3521
- const valueToStore = value instanceof Function ? value(storedValue) : value;
3522
- if (!checkDataSize(valueToStore)) {
3523
- authLogger.warn(`Data size too large for key "${key}", removing key`);
3524
- try {
3525
- window.sessionStorage.removeItem(key);
3526
- window.sessionStorage.removeItem(`${key}_timestamp`);
3527
- } catch {
3528
- }
3529
- setStoredValue(valueToStore);
3530
- return;
3531
- }
3532
- setStoredValue(valueToStore);
3533
- if (typeof window !== "undefined") {
3534
- try {
3535
- window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
3536
- window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
3537
- } catch (storageError) {
3538
- if (storageError.name === "QuotaExceededError" || storageError.code === 22 || storageError.message?.includes("quota")) {
3539
- authLogger.warn("sessionStorage quota exceeded, clearing old data...");
3540
- clearOldData();
3541
- try {
3542
- window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
3543
- window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
3544
- } catch (retryError) {
3545
- authLogger.error(`Failed to set sessionStorage key "${key}" after clearing old data:`, retryError);
3546
- try {
3547
- forceClearAll();
3548
- window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
3549
- window.sessionStorage.setItem(`${key}_timestamp`, Date.now().toString());
3550
- } catch (finalError) {
3551
- authLogger.error(`Failed to set sessionStorage key "${key}" after force clearing:`, finalError);
3552
- setStoredValue(valueToStore);
3553
- }
3554
- }
3555
- } else {
3556
- throw storageError;
3557
- }
3558
- }
3559
- }
3560
- } catch (error) {
3561
- authLogger.error(`Error setting sessionStorage key "${key}":`, error);
3562
- const valueToStore = value instanceof Function ? value(storedValue) : value;
3563
- setStoredValue(valueToStore);
3564
- }
3565
- }, "setValue");
3566
- const removeValue = /* @__PURE__ */ __name(() => {
3567
- try {
3568
- setStoredValue(initialValue);
3569
- if (typeof window !== "undefined") {
3570
- try {
3571
- window.sessionStorage.removeItem(key);
3572
- window.sessionStorage.removeItem(`${key}_timestamp`);
3573
- } catch (removeError) {
3574
- if (removeError.name === "QuotaExceededError" || removeError.code === 22 || removeError.message?.includes("quota")) {
3575
- authLogger.warn("sessionStorage quota exceeded during removal, clearing old data...");
3576
- clearOldData();
3577
- try {
3578
- window.sessionStorage.removeItem(key);
3579
- window.sessionStorage.removeItem(`${key}_timestamp`);
3580
- } catch (retryError) {
3581
- authLogger.error(`Failed to remove sessionStorage key "${key}" after clearing:`, retryError);
3582
- forceClearAll();
3583
- }
3584
- } else {
3585
- throw removeError;
3586
- }
3587
- }
3588
- }
3589
- } catch (error) {
3590
- authLogger.error(`Error removing sessionStorage key "${key}":`, error);
3591
- }
3592
- }, "removeValue");
3593
- return [storedValue, setValue, removeValue];
3594
- }
3595
- __name(useSessionStorage, "useSessionStorage");
3596
-
3597
- // src/auth/hooks/useAuthRedirect.ts
3598
- var AUTH_REDIRECT_KEY = "auth_redirect_url";
3599
- var getRedirectFromStorage = /* @__PURE__ */ __name(() => {
3600
- if (typeof window === "undefined") return "";
3601
- try {
3602
- const item = window.sessionStorage.getItem(AUTH_REDIRECT_KEY);
3603
- return item ? JSON.parse(item) : "";
3604
- } catch {
3605
- return "";
3606
- }
3607
- }, "getRedirectFromStorage");
3608
- var clearRedirectFromStorage = /* @__PURE__ */ __name(() => {
3609
- if (typeof window === "undefined") return;
3610
- try {
3611
- window.sessionStorage.removeItem(AUTH_REDIRECT_KEY);
3612
- window.sessionStorage.removeItem(`${AUTH_REDIRECT_KEY}_timestamp`);
3613
- } catch {
3614
- }
3615
- }, "clearRedirectFromStorage");
3616
- var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
3617
- const { fallbackUrl = "/dashboard", clearOnUse = true } = options;
3618
- const [redirectUrl, setRedirectUrl, removeRedirectUrl] = useSessionStorage(AUTH_REDIRECT_KEY, "");
3619
- const setRedirect = /* @__PURE__ */ __name((url) => {
3620
- setRedirectUrl(url);
3621
- }, "setRedirect");
3622
- const getRedirect = /* @__PURE__ */ __name(() => {
3623
- return getRedirectFromStorage() || redirectUrl;
3624
- }, "getRedirect");
3625
- const clearRedirect = /* @__PURE__ */ __name(() => {
3626
- removeRedirectUrl();
3627
- clearRedirectFromStorage();
3628
- }, "clearRedirect");
3629
- const hasRedirect = /* @__PURE__ */ __name(() => {
3630
- const stored = getRedirectFromStorage();
3631
- return stored.length > 0 || redirectUrl.length > 0;
3632
- }, "hasRedirect");
3633
- const getFinalRedirectUrl = /* @__PURE__ */ __name(() => {
3634
- const stored = getRedirectFromStorage();
3635
- return stored || redirectUrl || fallbackUrl;
3636
- }, "getFinalRedirectUrl");
3637
- const useAndClearRedirect = /* @__PURE__ */ __name(() => {
3638
- const stored = getRedirectFromStorage();
3639
- const finalUrl = stored || redirectUrl || fallbackUrl;
3640
- if (clearOnUse) {
3641
- clearRedirect();
3642
- }
3643
- return finalUrl;
3644
- }, "useAndClearRedirect");
3645
- return {
3646
- redirectUrl,
3647
- setRedirect,
3648
- getRedirect,
3649
- clearRedirect,
3650
- hasRedirect,
3651
- getFinalRedirectUrl,
3652
- useAndClearRedirect
3653
- };
3654
- }, "useAuthRedirectManager");
3655
-
3656
3395
  // src/auth/hooks/useLocalStorage.ts
3657
3396
  var import_react13 = require("react");
3658
3397
  function useLocalStorage(key, initialValue) {
@@ -3953,7 +3692,6 @@ __name(getCacheMetadata, "getCacheMetadata");
3953
3692
 
3954
3693
  // src/auth/hooks/useDeleteAccount.ts
3955
3694
  var import_react14 = require("react");
3956
- init_sdk_gen();
3957
3695
  var useDeleteAccount = /* @__PURE__ */ __name(() => {
3958
3696
  const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
3959
3697
  const [error, setError] = (0, import_react14.useState)(null);
@@ -3992,14 +3730,9 @@ var useDeleteAccount = /* @__PURE__ */ __name(() => {
3992
3730
 
3993
3731
  // src/auth/context/AccountsContext.tsx
3994
3732
  var import_react15 = require("react");
3995
- init_auth();
3996
-
3997
- // src/_api/generated/_cfg_accounts/sdk.gen.ts
3998
- init_sdk_gen();
3999
3733
 
4000
3734
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRegenerateCreate.ts
4001
3735
  var import_mutation = __toESM(require("swr/mutation"), 1);
4002
- init_sdk_gen();
4003
3736
 
4004
3737
  // src/_api/generated/_cfg_accounts/schemas/APIKeyRegenerate.ts
4005
3738
  var import_zod = require("zod");
@@ -4010,7 +3743,6 @@ var APIKeyRegenerateSchema = import_zod.z.object({
4010
3743
 
4011
3744
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRetrieve.ts
4012
3745
  var import_swr = __toESM(require("swr"), 1);
4013
- init_sdk_gen();
4014
3746
 
4015
3747
  // src/_api/generated/_cfg_accounts/schemas/APIKey.ts
4016
3748
  var import_zod2 = require("zod");
@@ -4022,7 +3754,6 @@ var APIKeySchema = import_zod2.z.object({
4022
3754
 
4023
3755
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRevealCreate.ts
4024
3756
  var import_mutation2 = __toESM(require("swr/mutation"), 1);
4025
- init_sdk_gen();
4026
3757
 
4027
3758
  // src/_api/generated/_cfg_accounts/schemas/APIKeyReveal.ts
4028
3759
  var import_zod3 = require("zod");
@@ -4034,7 +3765,6 @@ var APIKeyRevealSchema = import_zod3.z.object({
4034
3765
 
4035
3766
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyTestCreate.ts
4036
3767
  var import_mutation3 = __toESM(require("swr/mutation"), 1);
4037
- init_sdk_gen();
4038
3768
 
4039
3769
  // src/_api/generated/_cfg_accounts/schemas/APIKeyTestResult.ts
4040
3770
  var import_zod4 = require("zod");
@@ -4045,7 +3775,6 @@ var APIKeyTestResultSchema = import_zod4.z.object({
4045
3775
 
4046
3776
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthConnectionsList.ts
4047
3777
  var import_swr2 = __toESM(require("swr"), 1);
4048
- init_sdk_gen();
4049
3778
 
4050
3779
  // src/_api/generated/_cfg_accounts/schemas/cfg_accounts_oauth_connections_response_200_AutoRef.ts
4051
3780
  var import_zod7 = require("zod");
@@ -4074,7 +3803,6 @@ var cfg_accounts_oauth_connections_response_200_AutoRefSchema = import_zod7.z.ar
4074
3803
 
4075
3804
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthDisconnectCreate.ts
4076
3805
  var import_mutation4 = __toESM(require("swr/mutation"), 1);
4077
- init_sdk_gen();
4078
3806
 
4079
3807
  // src/_api/generated/_cfg_accounts/schemas/cfg_accounts_oauth_disconnect_response_200_AutoRef.ts
4080
3808
  var import_zod8 = require("zod");
@@ -4084,7 +3812,6 @@ var cfg_accounts_oauth_disconnect_response_200_AutoRefSchema = import_zod8.z.obj
4084
3812
 
4085
3813
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthGithubAuthorizeCreate.ts
4086
3814
  var import_mutation5 = __toESM(require("swr/mutation"), 1);
4087
- init_sdk_gen();
4088
3815
 
4089
3816
  // src/_api/generated/_cfg_accounts/schemas/OAuthAuthorizeResponse.ts
4090
3817
  var import_zod9 = require("zod");
@@ -4095,7 +3822,6 @@ var OAuthAuthorizeResponseSchema = import_zod9.z.object({
4095
3822
 
4096
3823
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthGithubCallbackCreate.ts
4097
3824
  var import_mutation6 = __toESM(require("swr/mutation"), 1);
4098
- init_sdk_gen();
4099
3825
 
4100
3826
  // src/_api/generated/_cfg_accounts/schemas/OAuthTokenResponse.ts
4101
3827
  var import_zod10 = require("zod");
@@ -4112,7 +3838,6 @@ var OAuthTokenResponseSchema = import_zod10.z.object({
4112
3838
 
4113
3839
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthProvidersRetrieve.ts
4114
3840
  var import_swr3 = __toESM(require("swr"), 1);
4115
- init_sdk_gen();
4116
3841
 
4117
3842
  // src/_api/generated/_cfg_accounts/schemas/OAuthProvidersResponse.ts
4118
3843
  var import_zod11 = require("zod");
@@ -4122,7 +3847,6 @@ var OAuthProvidersResponseSchema = import_zod11.z.object({
4122
3847
 
4123
3848
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpRequestCreate.ts
4124
3849
  var import_mutation7 = __toESM(require("swr/mutation"), 1);
4125
- init_sdk_gen();
4126
3850
 
4127
3851
  // src/_api/generated/_cfg_accounts/schemas/OTPRequestResponse.ts
4128
3852
  var import_zod14 = require("zod");
@@ -4197,7 +3921,6 @@ __name(useCfgAccountsOtpRequestCreate, "useCfgAccountsOtpRequestCreate");
4197
3921
 
4198
3922
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpVerifyCreate.ts
4199
3923
  var import_mutation8 = __toESM(require("swr/mutation"), 1);
4200
- init_sdk_gen();
4201
3924
 
4202
3925
  // src/_api/generated/_cfg_accounts/schemas/OTPVerifyResponse.ts
4203
3926
  var import_zod17 = require("zod");
@@ -4297,7 +4020,6 @@ __name(useCfgAccountsOtpVerifyCreate, "useCfgAccountsOtpVerifyCreate");
4297
4020
 
4298
4021
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileAvatarCreate.ts
4299
4022
  var import_mutation9 = __toESM(require("swr/mutation"), 1);
4300
- init_sdk_gen();
4301
4023
  function useCfgAccountsProfileAvatarCreate(config) {
4302
4024
  return (0, import_mutation9.default)(
4303
4025
  ["cfg_accounts_profile_avatar_create"],
@@ -4346,7 +4068,6 @@ __name(useCfgAccountsProfileAvatarCreate, "useCfgAccountsProfileAvatarCreate");
4346
4068
 
4347
4069
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileDeleteCreate.ts
4348
4070
  var import_mutation10 = __toESM(require("swr/mutation"), 1);
4349
- init_sdk_gen();
4350
4071
 
4351
4072
  // src/_api/generated/_cfg_accounts/schemas/AccountDeleteResponse.ts
4352
4073
  var import_zod18 = require("zod");
@@ -4357,11 +4078,9 @@ var AccountDeleteResponseSchema = import_zod18.z.object({
4357
4078
 
4358
4079
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfilePartialPartialUpdate.ts
4359
4080
  var import_mutation11 = __toESM(require("swr/mutation"), 1);
4360
- init_sdk_gen();
4361
4081
 
4362
4082
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfilePartialUpdate.ts
4363
4083
  var import_mutation12 = __toESM(require("swr/mutation"), 1);
4364
- init_sdk_gen();
4365
4084
  function useCfgAccountsProfilePartialUpdate(config) {
4366
4085
  return (0, import_mutation12.default)(
4367
4086
  ["cfg_accounts_profile_partial_update"],
@@ -4410,15 +4129,12 @@ __name(useCfgAccountsProfilePartialUpdate, "useCfgAccountsProfilePartialUpdate")
4410
4129
 
4411
4130
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileRetrieve.ts
4412
4131
  var import_swr4 = __toESM(require("swr"), 1);
4413
- init_sdk_gen();
4414
4132
 
4415
4133
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileUpdatePartialUpdate.ts
4416
4134
  var import_mutation13 = __toESM(require("swr/mutation"), 1);
4417
- init_sdk_gen();
4418
4135
 
4419
4136
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsProfileUpdateUpdate.ts
4420
4137
  var import_mutation14 = __toESM(require("swr/mutation"), 1);
4421
- init_sdk_gen();
4422
4138
  function useCfgAccountsProfileUpdateUpdate(config) {
4423
4139
  return (0, import_mutation14.default)(
4424
4140
  ["cfg_accounts_profile_update_update"],
@@ -4467,11 +4183,9 @@ __name(useCfgAccountsProfileUpdateUpdate, "useCfgAccountsProfileUpdateUpdate");
4467
4183
 
4468
4184
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenBlacklistCreate.ts
4469
4185
  var import_mutation15 = __toESM(require("swr/mutation"), 1);
4470
- init_sdk_gen();
4471
4186
 
4472
4187
  // src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenRefreshCreate.ts
4473
4188
  var import_mutation16 = __toESM(require("swr/mutation"), 1);
4474
- init_sdk_gen();
4475
4189
 
4476
4190
  // src/_api/generated/_cfg_accounts/schemas/TokenRefresh.ts
4477
4191
  var import_zod19 = require("zod");
@@ -4715,10 +4429,15 @@ __name(useAccountsContext, "useAccountsContext");
4715
4429
  // src/auth/context/AuthContext.tsx
4716
4430
  var import_jsx_runtime2 = require("react/jsx-runtime");
4717
4431
  var defaultRoutes = {
4718
- auth: DEFAULT_AUTH_PATH,
4719
- defaultCallback: DEFAULT_CALLBACK_PATH,
4720
- defaultAuthCallback: DEFAULT_AUTH_PATH
4432
+ auth: "/auth",
4433
+ defaultCallback: "/",
4434
+ defaultAuthCallback: "/auth"
4721
4435
  };
4436
+ var resolveAuthRoutes = /* @__PURE__ */ __name((routes) => ({
4437
+ auth: routes?.auth || defaultRoutes.auth,
4438
+ defaultCallback: routes?.defaultCallback || defaultRoutes.defaultCallback,
4439
+ defaultAuthCallback: routes?.defaultAuthCallback || routes?.auth || defaultRoutes.defaultAuthCallback
4440
+ }), "resolveAuthRoutes");
4722
4441
  var EMAIL_STORAGE_KEY = "auth_email";
4723
4442
  var AuthContext = (0, import_react16.createContext)(void 0);
4724
4443
  var apiErrorMessage = /* @__PURE__ */ __name((error) => {
@@ -4736,8 +4455,13 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4736
4455
  EMAIL_STORAGE_KEY,
4737
4456
  null
4738
4457
  );
4458
+ const routes = (0, import_react16.useMemo)(() => resolveAuthRoutes(config?.routes), [config?.routes]);
4459
+ const routesRef = (0, import_react16.useRef)(routes);
4460
+ (0, import_react16.useEffect)(() => {
4461
+ routesRef.current = routes;
4462
+ }, [routes]);
4739
4463
  const redirectManager = useAuthRedirectManager({
4740
- fallbackUrl: config?.routes?.defaultCallback || defaultRoutes.defaultCallback,
4464
+ fallbackUrl: routes.defaultCallback,
4741
4465
  clearOnUse: true
4742
4466
  });
4743
4467
  const configRef = (0, import_react16.useRef)(config);
@@ -4748,13 +4472,15 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4748
4472
  (0, import_react16.useEffect)(() => {
4749
4473
  accountsRef.current = accounts;
4750
4474
  }, [accounts]);
4475
+ const pendingManualNavRef = (0, import_react16.useRef)(false);
4751
4476
  const [profileSettled, setProfileSettled] = (0, import_react16.useState)(false);
4752
4477
  const hasProfile = Boolean(accounts.profile);
4753
4478
  const profileAttemptedRef = (0, import_react16.useRef)(false);
4754
4479
  (0, import_react16.useEffect)(() => {
4755
4480
  if (!isAuthenticated) {
4756
4481
  profileAttemptedRef.current = false;
4757
- if (auth.getToken() || auth.getRefreshToken()) {
4482
+ const hasTokens = Boolean(auth.getToken() || auth.getRefreshToken());
4483
+ if (hasTokens && !auth.isAuthenticated()) {
4758
4484
  authLogger.warn("Dead session in storage \u2014 clearing");
4759
4485
  auth.clearSession();
4760
4486
  clearProfileCache();
@@ -4788,18 +4514,18 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4788
4514
  Analytics.event("auth_session_expired" /* AUTH_SESSION_EXPIRED */, {
4789
4515
  category: "auth" /* AUTH */
4790
4516
  });
4791
- const authCallbackUrl = configRef.current?.routes?.defaultAuthCallback || defaultRoutes.defaultAuthCallback;
4792
- router.hardReplace(authCallbackUrl);
4517
+ router.hardReplace(routesRef.current.defaultAuthCallback);
4793
4518
  });
4794
4519
  return unsubscribe;
4795
4520
  }, [router]);
4796
4521
  (0, import_react16.useEffect)(() => {
4797
- if (!isAuthenticated) return;
4798
- const authRoute = config?.routes?.auth || defaultRoutes.auth;
4799
- if (pathname === authRoute && !queryParams.get("flow")) {
4800
- router.push(config?.routes?.defaultCallback || defaultRoutes.defaultCallback);
4522
+ if (!isAuthenticated || pendingManualNavRef.current) return;
4523
+ if (pathname === routes.auth && !queryParams.get("flow")) {
4524
+ const saved = redirectManager.hasRedirect() ? redirectManager.getRedirect() : null;
4525
+ if (saved) redirectManager.clearRedirect();
4526
+ router.push(saved || routes.defaultCallback);
4801
4527
  }
4802
- }, [isAuthenticated, pathname, queryParams, config?.routes, router]);
4528
+ }, [isAuthenticated, pathname, queryParams, routes, router, redirectManager]);
4803
4529
  const loadCurrentProfile = (0, import_react16.useCallback)(async (callerId) => {
4804
4530
  if (!auth.isAuthenticated()) {
4805
4531
  throw new Error("No valid authentication token");
@@ -4809,16 +4535,15 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4809
4535
  });
4810
4536
  }, []);
4811
4537
  const checkAuthAndRedirect = (0, import_react16.useCallback)(async () => {
4812
- const routes = configRef.current?.routes;
4813
4538
  if (auth.isAuthenticated()) {
4814
4539
  try {
4815
4540
  await loadCurrentProfile("checkAuthAndRedirect");
4816
4541
  } catch (error) {
4817
4542
  authLogger.warn("checkAuthAndRedirect: profile load failed", error);
4818
4543
  }
4819
- router.push(routes?.defaultCallback || defaultRoutes.defaultCallback);
4544
+ router.push(routesRef.current.defaultCallback);
4820
4545
  } else {
4821
- router.push(routes?.defaultAuthCallback || defaultRoutes.defaultAuthCallback);
4546
+ router.push(routesRef.current.defaultAuthCallback);
4822
4547
  }
4823
4548
  }, [loadCurrentProfile, router]);
4824
4549
  const requestOTP = (0, import_react16.useCallback)(
@@ -4858,6 +4583,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4858
4583
  const verifyOTP = (0, import_react16.useCallback)(
4859
4584
  async (identifier, otpCode, sourceUrl, redirectUrl, skipRedirect) => {
4860
4585
  try {
4586
+ pendingManualNavRef.current = Boolean(skipRedirect);
4861
4587
  const result = await accountsRef.current.verifyOTP({
4862
4588
  identifier,
4863
4589
  otp: otpCode,
@@ -4888,8 +4614,9 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4888
4614
  Analytics.setUser(String(result.user.id));
4889
4615
  }
4890
4616
  if (!skipRedirect) {
4891
- const savedRedirect = redirectManager.useAndClearRedirect();
4892
- const finalRedirectUrl = redirectUrl || savedRedirect || configRef.current?.routes?.defaultCallback || defaultRoutes.defaultCallback;
4617
+ const saved = redirectManager.hasRedirect() ? redirectManager.getRedirect() : null;
4618
+ if (saved) redirectManager.clearRedirect();
4619
+ const finalRedirectUrl = saved || redirectUrl || routesRef.current.defaultCallback;
4893
4620
  authLogger.info("Redirecting after auth to:", finalRedirectUrl);
4894
4621
  router.hardPush(finalRedirectUrl);
4895
4622
  }
@@ -4931,8 +4658,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4931
4658
  category: "auth" /* AUTH */
4932
4659
  });
4933
4660
  accountsRef.current.logout();
4934
- const authCallbackUrl = configRef.current?.routes?.defaultAuthCallback || defaultRoutes.defaultAuthCallback;
4935
- router.hardReplace(authCallbackUrl);
4661
+ router.hardReplace(routesRef.current.defaultAuthCallback);
4936
4662
  }, [router]);
4937
4663
  const user = accounts.profile ?? null;
4938
4664
  const isAdminUser = Boolean(user?.is_staff || user?.is_superuser);
@@ -4958,6 +4684,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4958
4684
  // expiry timer, cross-tab/cross-store sync) — no ticks, no polling.
4959
4685
  isAuthenticated,
4960
4686
  isAdminUser,
4687
+ routes,
4961
4688
  loadCurrentProfile,
4962
4689
  checkAuthAndRedirect,
4963
4690
  getToken: /* @__PURE__ */ __name(() => auth.getToken(), "getToken"),
@@ -4981,6 +4708,7 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
4981
4708
  isLoading,
4982
4709
  isAuthenticated,
4983
4710
  isAdminUser,
4711
+ routes,
4984
4712
  loadCurrentProfile,
4985
4713
  checkAuthAndRedirect,
4986
4714
  storedEmail,
@@ -5008,6 +4736,7 @@ var defaultAuthState = {
5008
4736
  isLoading: false,
5009
4737
  isAuthenticated: false,
5010
4738
  isAdminUser: false,
4739
+ routes: resolveAuthRoutes(),
5011
4740
  loadCurrentProfile: /* @__PURE__ */ __name(async () => {
5012
4741
  authLogger.warn("useAuth: loadCurrentProfile called outside AuthProvider");
5013
4742
  }, "loadCurrentProfile"),