enhance-axios 1.0.3 → 1.1.0

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/cjs/index.js CHANGED
@@ -38,6 +38,9 @@ __export(index_exports, {
38
38
  });
39
39
  module.exports = __toCommonJS(index_exports);
40
40
 
41
+ // package.json
42
+ var version = "1.1.0";
43
+
41
44
  // src/core/index.ts
42
45
  var import_axios = __toESM(require("axios"));
43
46
 
@@ -268,52 +271,89 @@ var CONTENT_TYPE_MAP = {
268
271
  form: "application/x-www-form-urlencoded"
269
272
  };
270
273
 
271
- // src/core/index.ts
272
- var DEFAULT_PREVENT_CONFIG = {
273
- enabled: true,
274
- methods: ["POST", "PUT", "PATCH", "DELETE"],
275
- intervalMs: 1e3
276
- };
277
- var DEFAULT_CANCEL_CONFIG = {
278
- enabled: true,
279
- methods: ["GET"]
280
- };
281
- function defaultRetryCondition(error) {
282
- if (!error.response) {
283
- return true;
274
+ // src/core/tokenManager.ts
275
+ function formatHeader(token, fmt) {
276
+ if (typeof fmt === "function") return fmt(token).trim();
277
+ if (typeof fmt === "string") {
278
+ const tpl = fmt.includes("{token}") ? fmt : `${fmt} {token}`;
279
+ return tpl.replace("{token}", token).trim();
280
+ }
281
+ return `Bearer ${token}`;
282
+ }
283
+ function setHeader(config, token, auth) {
284
+ config.headers = config.headers || {};
285
+ config.headers[auth.headerName || "Authorization"] = formatHeader(token, auth.headerFormat);
286
+ }
287
+ function shouldUseToken(config, instanceNeedToken) {
288
+ if (config.needToken !== void 0) return config.needToken;
289
+ if (typeof instanceNeedToken === "function") return instanceNeedToken(config);
290
+ if (instanceNeedToken !== void 0) return instanceNeedToken;
291
+ return true;
292
+ }
293
+ function defaultShouldRefresh(err) {
294
+ return err?.response?.status === 401 || err?.response?.data?.code === 401;
295
+ }
296
+ var TokenManager = class {
297
+ constructor(auth, needTokenDefault) {
298
+ this.auth = auth;
299
+ this.needTokenDefault = needTokenDefault;
300
+ this.pendingRefresh = null;
301
+ }
302
+ /** 请求拦截器:注入 token header */
303
+ async handleRequest(config) {
304
+ if (!shouldUseToken(config, this.needTokenDefault)) return;
305
+ if (this.pendingRefresh) {
306
+ try {
307
+ const info = await this.pendingRefresh;
308
+ setHeader(config, info.accessToken, this.auth);
309
+ return;
310
+ } catch {
311
+ this.pendingRefresh = null;
312
+ }
313
+ }
314
+ try {
315
+ const local = await Promise.resolve(this.auth.getLocalToken());
316
+ if (local) {
317
+ setHeader(config, local.accessToken, this.auth);
318
+ }
319
+ } catch {
320
+ }
284
321
  }
285
- const status = error.response.status;
286
- if (status === 408 || status === 429) {
322
+ /**
323
+ * 响应拦截器(resolve / reject):
324
+ * 检测到 token 过期则刷新并注入新 token。
325
+ * 返回 true 表示调用方需要调用 instance.request(config) 重试。
326
+ * 抛出异常表示刷新失败,调用方应 reject。
327
+ */
328
+ async handleAuthError(responseOrError, config) {
329
+ if (!shouldUseToken(config, this.needTokenDefault)) return false;
330
+ const check = this.auth.shouldRefreshToken || defaultShouldRefresh;
331
+ if (!check(responseOrError)) return false;
332
+ if (!this.pendingRefresh) {
333
+ this.pendingRefresh = this.auth.refreshToken().then(async (info2) => {
334
+ if (this.auth.setLocalToken) {
335
+ await Promise.resolve(this.auth.setLocalToken(info2)).catch(() => {
336
+ });
337
+ }
338
+ return info2;
339
+ });
340
+ }
341
+ const info = await this.pendingRefresh;
342
+ this.pendingRefresh = null;
343
+ setHeader(config, info.accessToken, this.auth);
287
344
  return true;
288
345
  }
289
- if (status >= 500 && status < 600) {
290
- return true;
346
+ /** 刷新失败时调用 */
347
+ handleRefreshFailure(err) {
348
+ this.pendingRefresh = null;
349
+ const handler = this.auth.tokenFailureHandler;
350
+ if (handler) {
351
+ handler("refresh", err);
352
+ }
291
353
  }
292
- return false;
293
- }
294
- var DEFAULT_RETRY_CONFIG = {
295
- enabled: true,
296
- retries: 3,
297
- retryDelay: 1e3,
298
- retryCondition: defaultRetryCondition,
299
- exponential: true,
300
- maxDelay: 3e4
301
354
  };
302
- function shouldApply(method, methods) {
303
- if (methods == null) return true;
304
- if (methods.length === 0) return false;
305
- return methods.includes(method?.toUpperCase() || "GET");
306
- }
307
- function calculateRetryDelay(retryConfig, retryCount) {
308
- let delay = retryConfig.retryDelay;
309
- if (retryConfig.exponential) {
310
- delay = Math.min(
311
- retryConfig.retryDelay * Math.pow(2, retryCount),
312
- retryConfig.maxDelay
313
- );
314
- }
315
- return delay;
316
- }
355
+
356
+ // src/core/dataTransform.ts
317
357
  function getDataFormat(config) {
318
358
  const headers = config.headers || {};
319
359
  const ctKey = Object.keys(headers).find((k) => k.toLowerCase() === "content-type");
@@ -343,9 +383,74 @@ function injectDataTransform(config, format, instance) {
343
383
  }
344
384
  config.transformRequest = [ourTransform, ...chain];
345
385
  }
386
+
387
+ // src/core/helpers.ts
388
+ function shouldApply(method, methods) {
389
+ if (methods == null) return true;
390
+ if (methods.length === 0) return false;
391
+ return methods.includes(method?.toUpperCase() || "GET");
392
+ }
346
393
  function isConfigSet(config) {
347
394
  return config != null;
348
395
  }
396
+
397
+ // src/core/retry.ts
398
+ function defaultRetryCondition(error) {
399
+ if (!error.response) return true;
400
+ const status = error.response.status;
401
+ if (status === 408 || status === 429) return true;
402
+ if (status >= 500 && status < 600) return true;
403
+ return false;
404
+ }
405
+ var DEFAULT_RETRY_CONFIG = {
406
+ enabled: true,
407
+ retries: 3,
408
+ retryDelay: 1e3,
409
+ retryCondition: defaultRetryCondition,
410
+ exponential: true,
411
+ maxDelay: 3e4
412
+ };
413
+ function calculateRetryDelay(config, retryCount) {
414
+ if (!config.exponential) return config.retryDelay;
415
+ return Math.min(config.retryDelay * Math.pow(2, retryCount), config.maxDelay);
416
+ }
417
+ function normalizeRetryConfig(config, defaults) {
418
+ if (!isConfigSet(config)) return defaults;
419
+ if (typeof config === "boolean") return { ...defaults, enabled: config };
420
+ if (typeof config === "number") return { ...defaults, enabled: true, retries: config };
421
+ if (typeof config === "function") return { ...defaults, enabled: true, retryCondition: config };
422
+ if (Array.isArray(config)) {
423
+ const codes = config;
424
+ return {
425
+ ...defaults,
426
+ enabled: true,
427
+ retryCondition: (error) => {
428
+ if (!error.response) return true;
429
+ return codes.includes(error.response.status);
430
+ }
431
+ };
432
+ }
433
+ return {
434
+ enabled: config.enabled ?? true,
435
+ retries: config.retries ?? defaults.retries,
436
+ retryDelay: config.retryDelay ?? defaults.retryDelay,
437
+ retryCondition: config.retryCondition ?? defaults.retryCondition,
438
+ exponential: config.exponential ?? defaults.exponential,
439
+ maxDelay: config.maxDelay ?? defaults.maxDelay,
440
+ methods: config.methods != null ? config.methods : defaults.methods
441
+ };
442
+ }
443
+
444
+ // src/core/index.ts
445
+ var DEFAULT_PREVENT_CONFIG = {
446
+ enabled: true,
447
+ methods: ["POST", "PUT", "PATCH", "DELETE"],
448
+ intervalMs: 1e3
449
+ };
450
+ var DEFAULT_CANCEL_CONFIG = {
451
+ enabled: true,
452
+ methods: ["GET"]
453
+ };
349
454
  function normalizePreventConfig(config, defaults) {
350
455
  if (!isConfigSet(config)) {
351
456
  return defaults;
@@ -394,40 +499,6 @@ function normalizeCancelConfig(config, defaults) {
394
499
  methods: config.methods != null ? config.methods : defaults.methods
395
500
  };
396
501
  }
397
- function normalizeRetryConfig(config, defaults) {
398
- if (!isConfigSet(config)) {
399
- return defaults;
400
- }
401
- if (typeof config === "boolean") {
402
- return { ...defaults, enabled: config };
403
- }
404
- if (typeof config === "number") {
405
- return { ...defaults, enabled: true, retries: config };
406
- }
407
- if (typeof config === "function") {
408
- return { ...defaults, enabled: true, retryCondition: config };
409
- }
410
- if (Array.isArray(config)) {
411
- const codes = config;
412
- return {
413
- ...defaults,
414
- enabled: true,
415
- retryCondition: (error) => {
416
- if (!error.response) return true;
417
- return codes.includes(error.response.status);
418
- }
419
- };
420
- }
421
- return {
422
- enabled: config.enabled ?? true,
423
- retries: config.retries ?? defaults.retries,
424
- retryDelay: config.retryDelay ?? defaults.retryDelay,
425
- retryCondition: config.retryCondition ?? defaults.retryCondition,
426
- exponential: config.exponential ?? defaults.exponential,
427
- maxDelay: config.maxDelay ?? defaults.maxDelay,
428
- methods: config.methods != null ? config.methods : defaults.methods
429
- };
430
- }
431
502
  function getEffectiveConfig(config, instanceDefaults) {
432
503
  const prevent = isConfigSet(config.preventDuplicate) ? normalizePreventConfig(config.preventDuplicate, instanceDefaults.prevent) : { ...instanceDefaults.prevent };
433
504
  const cancel = isConfigSet(config.cancelRequest) ? normalizeCancelConfig(config.cancelRequest, instanceDefaults.cancel) : { ...instanceDefaults.cancel };
@@ -472,7 +543,8 @@ function resolveAndCleanup(config, rm, pr, data) {
472
543
  if (ck && ck !== pk) rm.unregisterRequest(ck, "cancel");
473
544
  }
474
545
  function createEnhanceInstance(options = {}) {
475
- const instance = import_axios.default.create(options);
546
+ const { tokenAuth: _ta, needToken: _nt, ...axiosOptions } = options;
547
+ const instance = import_axios.default.create(axiosOptions);
476
548
  const defaultPrevent = { ...DEFAULT_PREVENT_CONFIG };
477
549
  const defaultCancel = { ...DEFAULT_CANCEL_CONFIG };
478
550
  const defaultRetry = { ...DEFAULT_RETRY_CONFIG };
@@ -489,6 +561,7 @@ function createEnhanceInstance(options = {}) {
489
561
  Object.assign(defaultRetry, normalized);
490
562
  }
491
563
  const needCacheBust = options.needCacheBust ?? true;
564
+ const tokenManager = _ta ? new TokenManager(_ta, _nt) : null;
492
565
  const requestManager = new RequestManager();
493
566
  const pendingReturns = /* @__PURE__ */ new Map();
494
567
  const enhanceInstance = {
@@ -507,9 +580,10 @@ function createEnhanceInstance(options = {}) {
507
580
  getRequestStatus: (key) => requestManager.getRequestStatus(key)
508
581
  };
509
582
  instance.interceptors.request.use(
510
- (config) => {
583
+ async (config) => {
511
584
  const method = config.method?.toUpperCase() || "GET";
512
585
  const { prevent, cancel } = getEffectiveConfig(config, { prevent: defaultPrevent, cancel: defaultCancel });
586
+ if (tokenManager) await tokenManager.handleRequest(config);
513
587
  const headers = config.headers || {};
514
588
  const hasContentType = typeof headers === "object" && Object.keys(headers).some((k) => k.toLowerCase() === "content-type");
515
589
  if (!hasContentType) {
@@ -606,6 +680,18 @@ function createEnhanceInstance(options = {}) {
606
680
  // ─────────────────────────────────────────────────────────────────────────
607
681
  async (response) => {
608
682
  const config = response.config;
683
+ if (tokenManager) {
684
+ try {
685
+ if (await tokenManager.handleAuthError(response, config)) {
686
+ cleanupRegistered(config, requestManager);
687
+ return instance.request(config);
688
+ }
689
+ } catch (err) {
690
+ tokenManager.handleRefreshFailure(err);
691
+ rejectAndCleanup(config, requestManager, pendingReturns, err);
692
+ return Promise.reject(err);
693
+ }
694
+ }
609
695
  const retryConfig = normalizeRetryConfig(config.retry, defaultRetry);
610
696
  if (retryConfig.enabled && shouldApply(config.method, retryConfig.methods)) {
611
697
  const syntheticError = new Error("Business logic error");
@@ -638,6 +724,18 @@ function createEnhanceInstance(options = {}) {
638
724
  rejectAndCleanup(config, requestManager, pendingReturns, error);
639
725
  return Promise.reject(error);
640
726
  }
727
+ if (tokenManager) {
728
+ try {
729
+ if (await tokenManager.handleAuthError(error, config)) {
730
+ cleanupRegistered(config, requestManager);
731
+ return instance.request(config);
732
+ }
733
+ } catch (err) {
734
+ tokenManager.handleRefreshFailure(err);
735
+ rejectAndCleanup(config, requestManager, pendingReturns, err);
736
+ return Promise.reject(err);
737
+ }
738
+ }
641
739
  const retryConfig = normalizeRetryConfig(config.retry, defaultRetry);
642
740
  if (retryConfig.enabled && shouldApply(config.method, retryConfig.methods)) {
643
741
  const retryCount = config.__retryCount || 0;
@@ -672,9 +770,6 @@ function createEnhanceInstance(options = {}) {
672
770
  instance.enhance = enhanceInstance;
673
771
  return instance;
674
772
  }
675
-
676
- // src/version.ts
677
- var version = "1.0.3";
678
773
  // Annotate the CommonJS export names for ESM import in node:
679
774
  0 && (module.exports = {
680
775
  createEnhanceInstance,