@djangocfg/monitor 2.1.333 → 2.1.334

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.mjs CHANGED
@@ -158,6 +158,9 @@ var _apiKeyOverride = null;
158
158
  var _baseUrlOverride = null;
159
159
  var _withCredentials = true;
160
160
  var _onUnauthorized = null;
161
+ var _refreshHandler = null;
162
+ var _refreshInflight = null;
163
+ var RETRY_MARKER = "X-Auth-Retry";
161
164
  var _client = null;
162
165
  function pushClientConfig() {
163
166
  if (!_client) return;
@@ -236,10 +239,53 @@ var auth = {
236
239
  pushClientConfig();
237
240
  },
238
241
  // ── 401 handler ───────────────────────────────────────────────────
242
+ /**
243
+ * Fired when the server returns 401 AND no refresh path recovers it
244
+ * (no refresh token, no refresh handler, refresh failed, or retry
245
+ * still 401). The app should clear local state and redirect to login.
246
+ *
247
+ * NOT fired for 401 that gets transparently recovered by the refresh
248
+ * handler — those are invisible to callers.
249
+ */
239
250
  onUnauthorized(cb) {
240
251
  _onUnauthorized = cb;
252
+ },
253
+ /**
254
+ * Register the refresh strategy. The handler receives the current
255
+ * refresh token and must call your refresh endpoint, returning
256
+ * `{ access, refresh? }` on success or `null` on failure.
257
+ *
258
+ * @example
259
+ * auth.setRefreshHandler(async (refresh) => {
260
+ * const { data } = await Auth.tokenRefreshCreate({ body: { refresh } });
261
+ * return data ? { access: data.access, refresh: data.refresh } : null;
262
+ * });
263
+ */
264
+ setRefreshHandler(fn) {
265
+ _refreshHandler = fn;
241
266
  }
242
267
  };
268
+ async function tryRefresh() {
269
+ if (_refreshInflight) return _refreshInflight;
270
+ if (!_refreshHandler) return null;
271
+ const refresh = auth.getRefreshToken();
272
+ if (!refresh) return null;
273
+ _refreshInflight = (async () => {
274
+ try {
275
+ const result = await _refreshHandler(refresh);
276
+ if (!result?.access) return null;
277
+ auth.setToken(result.access);
278
+ if (result.refresh) auth.setRefreshToken(result.refresh);
279
+ return result.access;
280
+ } catch {
281
+ return null;
282
+ } finally {
283
+ _refreshInflight = null;
284
+ }
285
+ })();
286
+ return _refreshInflight;
287
+ }
288
+ __name(tryRefresh, "tryRefresh");
243
289
  function installAuthOnClient(client2) {
244
290
  if (_client) return;
245
291
  _client = client2;
@@ -256,14 +302,48 @@ function installAuthOnClient(client2) {
256
302
  if (apiKey) request.headers.set("X-API-Key", apiKey);
257
303
  return request;
258
304
  });
259
- client2.interceptors.response.use((response) => {
260
- if (response.status === 401 && _onUnauthorized) {
261
- try {
262
- _onUnauthorized(response);
263
- } catch {
305
+ client2.interceptors.response.use(async (response, request) => {
306
+ if (response.status !== 401) return response;
307
+ if (request.headers.get(RETRY_MARKER)) {
308
+ if (_onUnauthorized) {
309
+ try {
310
+ _onUnauthorized(response);
311
+ } catch {
312
+ }
264
313
  }
314
+ return response;
315
+ }
316
+ const newToken = await tryRefresh();
317
+ if (!newToken) {
318
+ if (_onUnauthorized) {
319
+ try {
320
+ _onUnauthorized(response);
321
+ } catch {
322
+ }
323
+ }
324
+ return response;
325
+ }
326
+ const retry = request.clone();
327
+ retry.headers.set("Authorization", `Bearer ${newToken}`);
328
+ retry.headers.set(RETRY_MARKER, "1");
329
+ try {
330
+ const retried = await fetch(retry);
331
+ if (retried.status === 401 && _onUnauthorized) {
332
+ try {
333
+ _onUnauthorized(retried);
334
+ } catch {
335
+ }
336
+ }
337
+ return retried;
338
+ } catch {
339
+ if (_onUnauthorized) {
340
+ try {
341
+ _onUnauthorized(response);
342
+ } catch {
343
+ }
344
+ }
345
+ return response;
265
346
  }
266
- return response;
267
347
  });
268
348
  }
269
349
  __name(installAuthOnClient, "installAuthOnClient");
@@ -410,6 +490,15 @@ var _API = class _API {
410
490
  setApiKey(key) {
411
491
  auth.setApiKey(key);
412
492
  }
493
+ // ── 401 handling ────────────────────────────────────────────────────────
494
+ /** Fired only on terminal 401 (after refresh+retry path is exhausted). */
495
+ onUnauthorized(cb) {
496
+ auth.onUnauthorized(cb);
497
+ }
498
+ /** Provide a refresh strategy. See `auth.setRefreshHandler` for the contract. */
499
+ setRefreshHandler(fn) {
500
+ auth.setRefreshHandler(fn);
501
+ }
413
502
  };
414
503
  __name(_API, "API");
415
504
  var API = _API;
@@ -1286,7 +1375,7 @@ __name(sendBatch, "sendBatch");
1286
1375
  // src/client/utils/env.ts
1287
1376
  var isDevelopment = process.env.NODE_ENV === "development";
1288
1377
  var isProduction = !isDevelopment;
1289
- var MONITOR_VERSION = "2.1.333";
1378
+ var MONITOR_VERSION = "2.1.334";
1290
1379
 
1291
1380
  // src/client/constants.ts
1292
1381
  var MONITOR_INGEST_PATTERN = /cfg\/monitor\/ingest/;