@djangocfg/api 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/auth.cjs CHANGED
@@ -404,6 +404,9 @@ var _apiKeyOverride = null;
404
404
  var _baseUrlOverride = null;
405
405
  var _withCredentials = true;
406
406
  var _onUnauthorized = null;
407
+ var _refreshHandler = null;
408
+ var _refreshInflight = null;
409
+ var RETRY_MARKER = "X-Auth-Retry";
407
410
  var _client = null;
408
411
  function pushClientConfig() {
409
412
  if (!_client) return;
@@ -482,10 +485,53 @@ var auth = {
482
485
  pushClientConfig();
483
486
  },
484
487
  // ── 401 handler ───────────────────────────────────────────────────
488
+ /**
489
+ * Fired when the server returns 401 AND no refresh path recovers it
490
+ * (no refresh token, no refresh handler, refresh failed, or retry
491
+ * still 401). The app should clear local state and redirect to login.
492
+ *
493
+ * NOT fired for 401 that gets transparently recovered by the refresh
494
+ * handler — those are invisible to callers.
495
+ */
485
496
  onUnauthorized(cb) {
486
497
  _onUnauthorized = cb;
498
+ },
499
+ /**
500
+ * Register the refresh strategy. The handler receives the current
501
+ * refresh token and must call your refresh endpoint, returning
502
+ * `{ access, refresh? }` on success or `null` on failure.
503
+ *
504
+ * @example
505
+ * auth.setRefreshHandler(async (refresh) => {
506
+ * const { data } = await Auth.tokenRefreshCreate({ body: { refresh } });
507
+ * return data ? { access: data.access, refresh: data.refresh } : null;
508
+ * });
509
+ */
510
+ setRefreshHandler(fn) {
511
+ _refreshHandler = fn;
487
512
  }
488
513
  };
514
+ async function tryRefresh() {
515
+ if (_refreshInflight) return _refreshInflight;
516
+ if (!_refreshHandler) return null;
517
+ const refresh = auth.getRefreshToken();
518
+ if (!refresh) return null;
519
+ _refreshInflight = (async () => {
520
+ try {
521
+ const result = await _refreshHandler(refresh);
522
+ if (!result?.access) return null;
523
+ auth.setToken(result.access);
524
+ if (result.refresh) auth.setRefreshToken(result.refresh);
525
+ return result.access;
526
+ } catch {
527
+ return null;
528
+ } finally {
529
+ _refreshInflight = null;
530
+ }
531
+ })();
532
+ return _refreshInflight;
533
+ }
534
+ __name(tryRefresh, "tryRefresh");
489
535
  function installAuthOnClient(client2) {
490
536
  if (_client) return;
491
537
  _client = client2;
@@ -502,14 +548,48 @@ function installAuthOnClient(client2) {
502
548
  if (apiKey) request.headers.set("X-API-Key", apiKey);
503
549
  return request;
504
550
  });
505
- client2.interceptors.response.use((response) => {
506
- if (response.status === 401 && _onUnauthorized) {
507
- try {
508
- _onUnauthorized(response);
509
- } catch {
551
+ client2.interceptors.response.use(async (response, request) => {
552
+ if (response.status !== 401) return response;
553
+ if (request.headers.get(RETRY_MARKER)) {
554
+ if (_onUnauthorized) {
555
+ try {
556
+ _onUnauthorized(response);
557
+ } catch {
558
+ }
510
559
  }
560
+ return response;
561
+ }
562
+ const newToken = await tryRefresh();
563
+ if (!newToken) {
564
+ if (_onUnauthorized) {
565
+ try {
566
+ _onUnauthorized(response);
567
+ } catch {
568
+ }
569
+ }
570
+ return response;
571
+ }
572
+ const retry = request.clone();
573
+ retry.headers.set("Authorization", `Bearer ${newToken}`);
574
+ retry.headers.set(RETRY_MARKER, "1");
575
+ try {
576
+ const retried = await fetch(retry);
577
+ if (retried.status === 401 && _onUnauthorized) {
578
+ try {
579
+ _onUnauthorized(retried);
580
+ } catch {
581
+ }
582
+ }
583
+ return retried;
584
+ } catch {
585
+ if (_onUnauthorized) {
586
+ try {
587
+ _onUnauthorized(response);
588
+ } catch {
589
+ }
590
+ }
591
+ return response;
511
592
  }
512
- return response;
513
593
  });
514
594
  }
515
595
  __name(installAuthOnClient, "installAuthOnClient");
@@ -660,6 +740,15 @@ var API = class {
660
740
  setApiKey(key) {
661
741
  auth.setApiKey(key);
662
742
  }
743
+ // ── 401 handling ────────────────────────────────────────────────────────
744
+ /** Fired only on terminal 401 (after refresh+retry path is exhausted). */
745
+ onUnauthorized(cb) {
746
+ auth.onUnauthorized(cb);
747
+ }
748
+ /** Provide a refresh strategy. See `auth.setRefreshHandler` for the contract. */
749
+ setRefreshHandler(fn) {
750
+ auth.setRefreshHandler(fn);
751
+ }
663
752
  };
664
753
 
665
754
  // src/_api/generated/helpers/errors.ts
@@ -774,6 +863,15 @@ var API2 = class {
774
863
  setApiKey(key) {
775
864
  auth.setApiKey(key);
776
865
  }
866
+ // ── 401 handling ────────────────────────────────────────────────────────
867
+ /** Fired only on terminal 401 (after refresh+retry path is exhausted). */
868
+ onUnauthorized(cb) {
869
+ auth.onUnauthorized(cb);
870
+ }
871
+ /** Provide a refresh strategy. See `auth.setRefreshHandler` for the contract. */
872
+ setRefreshHandler(fn) {
873
+ auth.setRefreshHandler(fn);
874
+ }
777
875
  };
778
876
 
779
877
  // src/_api/generated/_cfg_totp/api.ts
@@ -828,6 +926,15 @@ var API3 = class {
828
926
  setApiKey(key) {
829
927
  auth.setApiKey(key);
830
928
  }
929
+ // ── 401 handling ────────────────────────────────────────────────────────
930
+ /** Fired only on terminal 401 (after refresh+retry path is exhausted). */
931
+ onUnauthorized(cb) {
932
+ auth.onUnauthorized(cb);
933
+ }
934
+ /** Provide a refresh strategy. See `auth.setRefreshHandler` for the contract. */
935
+ setRefreshHandler(fn) {
936
+ auth.setRefreshHandler(fn);
937
+ }
831
938
  };
832
939
 
833
940
  // src/_api/generated/index.ts