@djangocfg/monitor 2.1.333 → 2.1.335

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/client.cjs CHANGED
@@ -192,6 +192,9 @@ var _apiKeyOverride = null;
192
192
  var _baseUrlOverride = null;
193
193
  var _withCredentials = true;
194
194
  var _onUnauthorized = null;
195
+ var _refreshHandler = null;
196
+ var _refreshInflight = null;
197
+ var RETRY_MARKER = "X-Auth-Retry";
195
198
  var _client = null;
196
199
  function pushClientConfig() {
197
200
  if (!_client) return;
@@ -270,10 +273,53 @@ var auth = {
270
273
  pushClientConfig();
271
274
  },
272
275
  // ── 401 handler ───────────────────────────────────────────────────
276
+ /**
277
+ * Fired when the server returns 401 AND no refresh path recovers it
278
+ * (no refresh token, no refresh handler, refresh failed, or retry
279
+ * still 401). The app should clear local state and redirect to login.
280
+ *
281
+ * NOT fired for 401 that gets transparently recovered by the refresh
282
+ * handler — those are invisible to callers.
283
+ */
273
284
  onUnauthorized(cb) {
274
285
  _onUnauthorized = cb;
286
+ },
287
+ /**
288
+ * Register the refresh strategy. The handler receives the current
289
+ * refresh token and must call your refresh endpoint, returning
290
+ * `{ access, refresh? }` on success or `null` on failure.
291
+ *
292
+ * @example
293
+ * auth.setRefreshHandler(async (refresh) => {
294
+ * const { data } = await Auth.tokenRefreshCreate({ body: { refresh } });
295
+ * return data ? { access: data.access, refresh: data.refresh } : null;
296
+ * });
297
+ */
298
+ setRefreshHandler(fn) {
299
+ _refreshHandler = fn;
275
300
  }
276
301
  };
302
+ async function tryRefresh() {
303
+ if (_refreshInflight) return _refreshInflight;
304
+ if (!_refreshHandler) return null;
305
+ const refresh = auth.getRefreshToken();
306
+ if (!refresh) return null;
307
+ _refreshInflight = (async () => {
308
+ try {
309
+ const result = await _refreshHandler(refresh);
310
+ if (!result?.access) return null;
311
+ auth.setToken(result.access);
312
+ if (result.refresh) auth.setRefreshToken(result.refresh);
313
+ return result.access;
314
+ } catch {
315
+ return null;
316
+ } finally {
317
+ _refreshInflight = null;
318
+ }
319
+ })();
320
+ return _refreshInflight;
321
+ }
322
+ __name(tryRefresh, "tryRefresh");
277
323
  function installAuthOnClient(client2) {
278
324
  if (_client) return;
279
325
  _client = client2;
@@ -290,14 +336,48 @@ function installAuthOnClient(client2) {
290
336
  if (apiKey) request.headers.set("X-API-Key", apiKey);
291
337
  return request;
292
338
  });
293
- client2.interceptors.response.use((response) => {
294
- if (response.status === 401 && _onUnauthorized) {
295
- try {
296
- _onUnauthorized(response);
297
- } catch {
339
+ client2.interceptors.response.use(async (response, request) => {
340
+ if (response.status !== 401) return response;
341
+ if (request.headers.get(RETRY_MARKER)) {
342
+ if (_onUnauthorized) {
343
+ try {
344
+ _onUnauthorized(response);
345
+ } catch {
346
+ }
298
347
  }
348
+ return response;
349
+ }
350
+ const newToken = await tryRefresh();
351
+ if (!newToken) {
352
+ if (_onUnauthorized) {
353
+ try {
354
+ _onUnauthorized(response);
355
+ } catch {
356
+ }
357
+ }
358
+ return response;
359
+ }
360
+ const retry = request.clone();
361
+ retry.headers.set("Authorization", `Bearer ${newToken}`);
362
+ retry.headers.set(RETRY_MARKER, "1");
363
+ try {
364
+ const retried = await fetch(retry);
365
+ if (retried.status === 401 && _onUnauthorized) {
366
+ try {
367
+ _onUnauthorized(retried);
368
+ } catch {
369
+ }
370
+ }
371
+ return retried;
372
+ } catch {
373
+ if (_onUnauthorized) {
374
+ try {
375
+ _onUnauthorized(response);
376
+ } catch {
377
+ }
378
+ }
379
+ return response;
299
380
  }
300
- return response;
301
381
  });
302
382
  }
303
383
  __name(installAuthOnClient, "installAuthOnClient");
@@ -444,6 +524,15 @@ var _API = class _API {
444
524
  setApiKey(key) {
445
525
  auth.setApiKey(key);
446
526
  }
527
+ // ── 401 handling ────────────────────────────────────────────────────────
528
+ /** Fired only on terminal 401 (after refresh+retry path is exhausted). */
529
+ onUnauthorized(cb) {
530
+ auth.onUnauthorized(cb);
531
+ }
532
+ /** Provide a refresh strategy. See `auth.setRefreshHandler` for the contract. */
533
+ setRefreshHandler(fn) {
534
+ auth.setRefreshHandler(fn);
535
+ }
447
536
  };
448
537
  __name(_API, "API");
449
538
  var API = _API;
@@ -1320,7 +1409,7 @@ __name(sendBatch, "sendBatch");
1320
1409
  // src/client/utils/env.ts
1321
1410
  var isDevelopment = process.env.NODE_ENV === "development";
1322
1411
  var isProduction = !isDevelopment;
1323
- var MONITOR_VERSION = "2.1.333";
1412
+ var MONITOR_VERSION = "2.1.335";
1324
1413
 
1325
1414
  // src/client/constants.ts
1326
1415
  var MONITOR_INGEST_PATTERN = /cfg\/monitor\/ingest/;