enhance-axios 1.0.4 → 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 +173 -78
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/esm/index.d.mts +49 -21
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.mjs +173 -78
- package/dist/esm/index.mjs.map +1 -1
- package/dist/umd/index.global.js +173 -78
- package/dist/umd/index.global.js.map +1 -1
- package/dist/umd/index.min.global.js +1 -1
- package/dist/umd.bundle/index.axios.global.js +176 -81
- package/dist/umd.bundle/index.axios.global.js.map +1 -1
- package/dist/umd.bundle/index.axios.min.global.js +9 -9
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -39,7 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
module.exports = __toCommonJS(index_exports);
|
|
40
40
|
|
|
41
41
|
// package.json
|
|
42
|
-
var version = "1.0
|
|
42
|
+
var version = "1.1.0";
|
|
43
43
|
|
|
44
44
|
// src/core/index.ts
|
|
45
45
|
var import_axios = __toESM(require("axios"));
|
|
@@ -271,52 +271,89 @@ var CONTENT_TYPE_MAP = {
|
|
|
271
271
|
form: "application/x-www-form-urlencoded"
|
|
272
272
|
};
|
|
273
273
|
|
|
274
|
-
// src/core/
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
+
}
|
|
287
321
|
}
|
|
288
|
-
|
|
289
|
-
|
|
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);
|
|
290
344
|
return true;
|
|
291
345
|
}
|
|
292
|
-
|
|
293
|
-
|
|
346
|
+
/** 刷新失败时调用 */
|
|
347
|
+
handleRefreshFailure(err) {
|
|
348
|
+
this.pendingRefresh = null;
|
|
349
|
+
const handler = this.auth.tokenFailureHandler;
|
|
350
|
+
if (handler) {
|
|
351
|
+
handler("refresh", err);
|
|
352
|
+
}
|
|
294
353
|
}
|
|
295
|
-
return false;
|
|
296
|
-
}
|
|
297
|
-
var DEFAULT_RETRY_CONFIG = {
|
|
298
|
-
enabled: true,
|
|
299
|
-
retries: 3,
|
|
300
|
-
retryDelay: 1e3,
|
|
301
|
-
retryCondition: defaultRetryCondition,
|
|
302
|
-
exponential: true,
|
|
303
|
-
maxDelay: 3e4
|
|
304
354
|
};
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (methods.length === 0) return false;
|
|
308
|
-
return methods.includes(method?.toUpperCase() || "GET");
|
|
309
|
-
}
|
|
310
|
-
function calculateRetryDelay(retryConfig, retryCount) {
|
|
311
|
-
let delay = retryConfig.retryDelay;
|
|
312
|
-
if (retryConfig.exponential) {
|
|
313
|
-
delay = Math.min(
|
|
314
|
-
retryConfig.retryDelay * Math.pow(2, retryCount),
|
|
315
|
-
retryConfig.maxDelay
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
return delay;
|
|
319
|
-
}
|
|
355
|
+
|
|
356
|
+
// src/core/dataTransform.ts
|
|
320
357
|
function getDataFormat(config) {
|
|
321
358
|
const headers = config.headers || {};
|
|
322
359
|
const ctKey = Object.keys(headers).find((k) => k.toLowerCase() === "content-type");
|
|
@@ -346,9 +383,74 @@ function injectDataTransform(config, format, instance) {
|
|
|
346
383
|
}
|
|
347
384
|
config.transformRequest = [ourTransform, ...chain];
|
|
348
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
|
+
}
|
|
349
393
|
function isConfigSet(config) {
|
|
350
394
|
return config != null;
|
|
351
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
|
+
};
|
|
352
454
|
function normalizePreventConfig(config, defaults) {
|
|
353
455
|
if (!isConfigSet(config)) {
|
|
354
456
|
return defaults;
|
|
@@ -397,40 +499,6 @@ function normalizeCancelConfig(config, defaults) {
|
|
|
397
499
|
methods: config.methods != null ? config.methods : defaults.methods
|
|
398
500
|
};
|
|
399
501
|
}
|
|
400
|
-
function normalizeRetryConfig(config, defaults) {
|
|
401
|
-
if (!isConfigSet(config)) {
|
|
402
|
-
return defaults;
|
|
403
|
-
}
|
|
404
|
-
if (typeof config === "boolean") {
|
|
405
|
-
return { ...defaults, enabled: config };
|
|
406
|
-
}
|
|
407
|
-
if (typeof config === "number") {
|
|
408
|
-
return { ...defaults, enabled: true, retries: config };
|
|
409
|
-
}
|
|
410
|
-
if (typeof config === "function") {
|
|
411
|
-
return { ...defaults, enabled: true, retryCondition: config };
|
|
412
|
-
}
|
|
413
|
-
if (Array.isArray(config)) {
|
|
414
|
-
const codes = config;
|
|
415
|
-
return {
|
|
416
|
-
...defaults,
|
|
417
|
-
enabled: true,
|
|
418
|
-
retryCondition: (error) => {
|
|
419
|
-
if (!error.response) return true;
|
|
420
|
-
return codes.includes(error.response.status);
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
return {
|
|
425
|
-
enabled: config.enabled ?? true,
|
|
426
|
-
retries: config.retries ?? defaults.retries,
|
|
427
|
-
retryDelay: config.retryDelay ?? defaults.retryDelay,
|
|
428
|
-
retryCondition: config.retryCondition ?? defaults.retryCondition,
|
|
429
|
-
exponential: config.exponential ?? defaults.exponential,
|
|
430
|
-
maxDelay: config.maxDelay ?? defaults.maxDelay,
|
|
431
|
-
methods: config.methods != null ? config.methods : defaults.methods
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
502
|
function getEffectiveConfig(config, instanceDefaults) {
|
|
435
503
|
const prevent = isConfigSet(config.preventDuplicate) ? normalizePreventConfig(config.preventDuplicate, instanceDefaults.prevent) : { ...instanceDefaults.prevent };
|
|
436
504
|
const cancel = isConfigSet(config.cancelRequest) ? normalizeCancelConfig(config.cancelRequest, instanceDefaults.cancel) : { ...instanceDefaults.cancel };
|
|
@@ -475,7 +543,8 @@ function resolveAndCleanup(config, rm, pr, data) {
|
|
|
475
543
|
if (ck && ck !== pk) rm.unregisterRequest(ck, "cancel");
|
|
476
544
|
}
|
|
477
545
|
function createEnhanceInstance(options = {}) {
|
|
478
|
-
const
|
|
546
|
+
const { tokenAuth: _ta, needToken: _nt, ...axiosOptions } = options;
|
|
547
|
+
const instance = import_axios.default.create(axiosOptions);
|
|
479
548
|
const defaultPrevent = { ...DEFAULT_PREVENT_CONFIG };
|
|
480
549
|
const defaultCancel = { ...DEFAULT_CANCEL_CONFIG };
|
|
481
550
|
const defaultRetry = { ...DEFAULT_RETRY_CONFIG };
|
|
@@ -492,6 +561,7 @@ function createEnhanceInstance(options = {}) {
|
|
|
492
561
|
Object.assign(defaultRetry, normalized);
|
|
493
562
|
}
|
|
494
563
|
const needCacheBust = options.needCacheBust ?? true;
|
|
564
|
+
const tokenManager = _ta ? new TokenManager(_ta, _nt) : null;
|
|
495
565
|
const requestManager = new RequestManager();
|
|
496
566
|
const pendingReturns = /* @__PURE__ */ new Map();
|
|
497
567
|
const enhanceInstance = {
|
|
@@ -510,9 +580,10 @@ function createEnhanceInstance(options = {}) {
|
|
|
510
580
|
getRequestStatus: (key) => requestManager.getRequestStatus(key)
|
|
511
581
|
};
|
|
512
582
|
instance.interceptors.request.use(
|
|
513
|
-
(config) => {
|
|
583
|
+
async (config) => {
|
|
514
584
|
const method = config.method?.toUpperCase() || "GET";
|
|
515
585
|
const { prevent, cancel } = getEffectiveConfig(config, { prevent: defaultPrevent, cancel: defaultCancel });
|
|
586
|
+
if (tokenManager) await tokenManager.handleRequest(config);
|
|
516
587
|
const headers = config.headers || {};
|
|
517
588
|
const hasContentType = typeof headers === "object" && Object.keys(headers).some((k) => k.toLowerCase() === "content-type");
|
|
518
589
|
if (!hasContentType) {
|
|
@@ -609,6 +680,18 @@ function createEnhanceInstance(options = {}) {
|
|
|
609
680
|
// ─────────────────────────────────────────────────────────────────────────
|
|
610
681
|
async (response) => {
|
|
611
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
|
+
}
|
|
612
695
|
const retryConfig = normalizeRetryConfig(config.retry, defaultRetry);
|
|
613
696
|
if (retryConfig.enabled && shouldApply(config.method, retryConfig.methods)) {
|
|
614
697
|
const syntheticError = new Error("Business logic error");
|
|
@@ -641,6 +724,18 @@ function createEnhanceInstance(options = {}) {
|
|
|
641
724
|
rejectAndCleanup(config, requestManager, pendingReturns, error);
|
|
642
725
|
return Promise.reject(error);
|
|
643
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
|
+
}
|
|
644
739
|
const retryConfig = normalizeRetryConfig(config.retry, defaultRetry);
|
|
645
740
|
if (retryConfig.enabled && shouldApply(config.method, retryConfig.methods)) {
|
|
646
741
|
const retryCount = config.__retryCount || 0;
|