@boo-dreamer/request 0.0.4 → 0.0.5
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/index.cjs +125 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +73 -0
- package/dist/index.mjs +126 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,109 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
6
|
const axios = require("axios");
|
|
7
|
+
const DEFAULT_TOKEN_CONFIG = {
|
|
8
|
+
storageKey: "token",
|
|
9
|
+
storageType: "localStorage",
|
|
10
|
+
headerName: "Authorization",
|
|
11
|
+
tokenPrefix: "Bearer"
|
|
12
|
+
};
|
|
13
|
+
class TokenManager {
|
|
14
|
+
constructor() {
|
|
15
|
+
__publicField(this, "config");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 设置配置
|
|
19
|
+
*/
|
|
20
|
+
setConfig(config) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 获取配置
|
|
25
|
+
*/
|
|
26
|
+
getConfig() {
|
|
27
|
+
return this.config;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 是否启用
|
|
31
|
+
*/
|
|
32
|
+
isEnabled() {
|
|
33
|
+
var _a;
|
|
34
|
+
return ((_a = this.config) == null ? void 0 : _a.enable) ?? false;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 获取 token
|
|
38
|
+
*/
|
|
39
|
+
async getToken() {
|
|
40
|
+
var _a;
|
|
41
|
+
if (!((_a = this.config) == null ? void 0 : _a.enable)) return null;
|
|
42
|
+
if (this.config.getToken) {
|
|
43
|
+
try {
|
|
44
|
+
return await this.config.getToken();
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;
|
|
50
|
+
try {
|
|
51
|
+
const storage = storageType === "sessionStorage" ? sessionStorage : localStorage;
|
|
52
|
+
return storage.getItem(storageKey);
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 设置 token
|
|
59
|
+
*/
|
|
60
|
+
setToken(token) {
|
|
61
|
+
var _a;
|
|
62
|
+
if (!((_a = this.config) == null ? void 0 : _a.enable)) return;
|
|
63
|
+
const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;
|
|
64
|
+
try {
|
|
65
|
+
const storage = storageType === "sessionStorage" ? sessionStorage : localStorage;
|
|
66
|
+
storage.setItem(storageKey, token);
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 清除 token
|
|
72
|
+
*/
|
|
73
|
+
removeToken() {
|
|
74
|
+
var _a;
|
|
75
|
+
if (!((_a = this.config) == null ? void 0 : _a.enable)) return;
|
|
76
|
+
const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;
|
|
77
|
+
try {
|
|
78
|
+
const storage = storageType === "sessionStorage" ? sessionStorage : localStorage;
|
|
79
|
+
storage.removeItem(storageKey);
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 检查 URL 是否在白名单中
|
|
85
|
+
*/
|
|
86
|
+
isInWhiteList(url) {
|
|
87
|
+
var _a, _b;
|
|
88
|
+
if (!((_b = (_a = this.config) == null ? void 0 : _a.whiteList) == null ? void 0 : _b.length)) return false;
|
|
89
|
+
return this.config.whiteList.some((pattern) => {
|
|
90
|
+
if (typeof pattern === "string") {
|
|
91
|
+
return url.includes(pattern);
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 构建 Authorization 头
|
|
98
|
+
*/
|
|
99
|
+
async buildAuthHeader() {
|
|
100
|
+
var _a, _b;
|
|
101
|
+
const token = await this.getToken();
|
|
102
|
+
if (!token) return null;
|
|
103
|
+
const headerName = ((_a = this.config) == null ? void 0 : _a.headerName) ?? DEFAULT_TOKEN_CONFIG.headerName;
|
|
104
|
+
const tokenPrefix = ((_b = this.config) == null ? void 0 : _b.tokenPrefix) ?? DEFAULT_TOKEN_CONFIG.tokenPrefix;
|
|
105
|
+
const value = tokenPrefix ? `${tokenPrefix} ${token}` : token;
|
|
106
|
+
return { key: headerName, value };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const tokenManager = new TokenManager();
|
|
7
110
|
const DEFAULT_CODE_MESSAGE_MAP = {
|
|
8
111
|
200: "操作成功",
|
|
9
112
|
201: "创建成功",
|
|
@@ -40,7 +143,8 @@ class ConfigManager {
|
|
|
40
143
|
httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },
|
|
41
144
|
timeout: DEFAULT_TIMEOUT,
|
|
42
145
|
interceptors: {},
|
|
43
|
-
onError: void 0
|
|
146
|
+
onError: void 0,
|
|
147
|
+
tokenConfig: void 0
|
|
44
148
|
});
|
|
45
149
|
}
|
|
46
150
|
/**
|
|
@@ -71,6 +175,9 @@ class ConfigManager {
|
|
|
71
175
|
...config.interceptors
|
|
72
176
|
}
|
|
73
177
|
};
|
|
178
|
+
if (config.tokenConfig !== void 0) {
|
|
179
|
+
tokenManager.setConfig(config.tokenConfig);
|
|
180
|
+
}
|
|
74
181
|
}
|
|
75
182
|
/**
|
|
76
183
|
* 获取成功状态码
|
|
@@ -128,8 +235,16 @@ class ConfigManager {
|
|
|
128
235
|
httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },
|
|
129
236
|
timeout: DEFAULT_TIMEOUT,
|
|
130
237
|
interceptors: {},
|
|
131
|
-
onError: void 0
|
|
238
|
+
onError: void 0,
|
|
239
|
+
tokenConfig: void 0
|
|
132
240
|
};
|
|
241
|
+
tokenManager.setConfig(void 0);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 获取 Token 配置
|
|
245
|
+
*/
|
|
246
|
+
getTokenConfig() {
|
|
247
|
+
return this.config.tokenConfig;
|
|
133
248
|
}
|
|
134
249
|
}
|
|
135
250
|
const configManager = new ConfigManager();
|
|
@@ -294,7 +409,13 @@ class RequestClass {
|
|
|
294
409
|
setupInterceptors() {
|
|
295
410
|
const interceptors = configManager.getInterceptors();
|
|
296
411
|
this.instance.interceptors.request.use(
|
|
297
|
-
(config) => {
|
|
412
|
+
async (config) => {
|
|
413
|
+
if (tokenManager.isEnabled() && !tokenManager.isInWhiteList(config.url || "")) {
|
|
414
|
+
const authHeader = await tokenManager.buildAuthHeader();
|
|
415
|
+
if (authHeader) {
|
|
416
|
+
config.headers[authHeader.key] = authHeader.value;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
298
419
|
if (interceptors.request) {
|
|
299
420
|
return interceptors.request(config);
|
|
300
421
|
}
|
|
@@ -441,4 +562,5 @@ exports.RequestError = RequestError;
|
|
|
441
562
|
exports.configManager = configManager;
|
|
442
563
|
exports.handleError = handleError;
|
|
443
564
|
exports.isSuccessResponse = isSuccessResponse;
|
|
565
|
+
exports.tokenManager = tokenManager;
|
|
444
566
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/config.ts","../src/types.ts","../src/error-handler.ts","../src/request.ts"],"sourcesContent":["import type { GlobalConfig, CodeMessageMap, HttpStatusMessageMap, InterceptorConfig } from './types.js';\n\n/**\n * 默认 Code 提示映射表\n */\nexport const DEFAULT_CODE_MESSAGE_MAP: CodeMessageMap = {\n 200: '操作成功',\n 201: '创建成功',\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 500: '服务器内部错误',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认 HTTP 状态码提示映射表\n */\nexport const DEFAULT_HTTP_STATUS_MESSAGE_MAP: HttpStatusMessageMap = {\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 405: '请求方法不允许',\n 408: '请求超时',\n 500: '服务器内部错误',\n 501: '服务未实现',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认成功状态码\n */\nexport const DEFAULT_SUCCESS_CODE: number[] = [200, 0];\n\n/**\n * 默认超时时间(10秒)\n */\nexport const DEFAULT_TIMEOUT = 10000;\n\n/**\n * 配置管理类\n */\nclass ConfigManager {\n private config: GlobalConfig = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n };\n\n /**\n * 获取当前配置\n */\n getConfig(): GlobalConfig {\n return { ...this.config };\n }\n\n /**\n * 设置全局配置\n */\n setConfig(config: GlobalConfig): void {\n this.config = {\n ...this.config,\n ...config,\n // 深度合并映射表\n codeMessageMap: {\n ...this.config.codeMessageMap,\n ...config.codeMessageMap,\n },\n httpStatusMessageMap: {\n ...this.config.httpStatusMessageMap,\n ...config.httpStatusMessageMap,\n },\n // 合并拦截器配置\n interceptors: {\n ...this.config.interceptors,\n ...config.interceptors,\n },\n };\n }\n\n /**\n * 获取成功状态码\n */\n getSuccessCodes(): number[] {\n const codes = this.config.successCode ?? DEFAULT_SUCCESS_CODE;\n return Array.isArray(codes) ? codes : [codes];\n }\n\n /**\n * 检查是否为成功状态码\n */\n isSuccessCode(code: number): boolean {\n return this.getSuccessCodes().includes(code);\n }\n\n /**\n * 根据 Code 获取提示消息\n */\n getMessageByCode(code: number | string): string | undefined {\n return this.config.codeMessageMap?.[code];\n }\n\n /**\n * 根据 HTTP 状态码获取提示消息\n */\n getMessageByHttpStatus(status: number): string | undefined {\n return this.config.httpStatusMessageMap?.[status];\n }\n\n /**\n * 获取超时时间\n */\n getTimeout(): number {\n return this.config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * 获取拦截器配置\n */\n getInterceptors(): InterceptorConfig {\n return this.config.interceptors ?? {};\n }\n\n /**\n * 获取错误处理钩子\n */\n getErrorHandler(): ((error: unknown) => void) | undefined {\n return this.config.onError ?? undefined;\n }\n\n /**\n * 重置为默认配置\n */\n reset(): void {\n this.config = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n };\n }\n}\n\n/**\n * 全局配置管理器实例\n */\nexport const configManager = new ConfigManager();\n","import type { AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, Canceler } from 'axios';\n\n/**\n * 默认响应数据格式\n * @template T - data 字段的数据类型\n */\nexport interface BaseResponse<T = unknown> {\n /** 业务状态码 */\n code: number;\n /** 响应数据 */\n data: T;\n /** 提示消息 */\n msg: string;\n /** 是否成功 */\n success: boolean;\n}\n\n/**\n * 自定义响应数据格式接口\n * 用户可通过继承此接口实现自定义响应格式\n */\nexport interface CustomResponse<T = unknown> {\n [key: string]: unknown;\n data?: T;\n}\n\n/**\n * 请求配置选项\n */\nexport interface RequestConfig extends AxiosRequestConfig {\n /** 是否显示错误提示 */\n showError?: boolean;\n /** 自定义错误提示消息 */\n errorMessage?: string;\n /** 是否携带 token */\n withToken?: boolean;\n}\n\n/**\n * 请求拦截器函数类型\n */\nexport type RequestInterceptor = (\n config: InternalAxiosRequestConfig\n) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;\n\n/**\n * 响应拦截器函数类型\n */\nexport type ResponseInterceptor<T = unknown> = (\n response: AxiosResponse<T>\n) => AxiosResponse<T> | Promise<AxiosResponse<T>>;\n\n/**\n * 错误拦截器函数类型\n */\nexport type ErrorInterceptor = (error: unknown) => unknown;\n\n/**\n * 拦截器配置\n */\nexport interface InterceptorConfig {\n /** 请求拦截器 */\n request?: RequestInterceptor;\n /** 请求错误拦截器 */\n requestError?: ErrorInterceptor;\n /** 响应拦截器 */\n response?: ResponseInterceptor;\n /** 响应错误拦截器 */\n responseError?: ErrorInterceptor;\n}\n\n/**\n * Code 提示映射表\n */\nexport type CodeMessageMap = Record<number | string, string>;\n\n/**\n * HTTP 状态码提示映射表\n */\nexport type HttpStatusMessageMap = Record<number, string>;\n\n/**\n * 全局配置选项\n */\nexport interface GlobalConfig<T = unknown> {\n /** 基础响应数据类型(用于类型推断) */\n baseResponseType?: T;\n /** 成功状态码 */\n successCode?: number | number[];\n /** Code 提示映射表 */\n codeMessageMap?: CodeMessageMap;\n /** HTTP 状态码提示映射表 */\n httpStatusMessageMap?: HttpStatusMessageMap;\n /** 默认超时时间(毫秒) */\n timeout?: number;\n /** 请求拦截器配置 */\n interceptors?: InterceptorConfig;\n /** 错误处理钩子(预留 event-bus 接入点) */\n onError?: (error: unknown) => void;\n}\n\n/**\n * 请求错误类\n */\nexport class RequestError extends Error {\n /** 错误码(业务码或 HTTP 状态码) */\n code: number | string;\n /** 原始错误对象 */\n originalError: unknown;\n /** 是否为业务错误 */\n isBusinessError: boolean;\n /** 是否为 HTTP 错误 */\n isHttpError: boolean;\n /** 请求配置 */\n config?: AxiosRequestConfig;\n\n constructor(options: {\n message: string;\n code: number | string;\n originalError: unknown;\n isBusinessError?: boolean;\n isHttpError?: boolean;\n config?: AxiosRequestConfig;\n }) {\n super(options.message);\n this.name = 'RequestError';\n this.code = options.code;\n this.originalError = options.originalError;\n this.isBusinessError = options.isBusinessError ?? false;\n this.isHttpError = options.isHttpError ?? false;\n this.config = options.config;\n }\n}\n\n/**\n * 取消请求控制器\n */\nexport interface CancelTokenController {\n /** 取消函数 */\n cancel: Canceler;\n /** 取消令牌 */\n token: AbortSignal;\n}\n\n/**\n * 请求方法类型定义\n */\nexport type RequestMethod = 'get' | 'post' | 'put' | 'delete' | 'patch';\n\n/**\n * 请求参数类型(对象格式)\n * 使用宽泛的类型约束以支持任意对象\n */\nexport type RequestParams = object;\n","import type { AxiosError, AxiosResponse } from 'axios';\nimport { RequestError } from './types.js';\nimport { configManager } from './config.js';\n\n/**\n * 判断是否为 Axios 错误\n */\nfunction isAxiosError(error: unknown): error is AxiosError {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'isAxiosError' in error &&\n (error as AxiosError).isAxiosError === true\n );\n}\n\n/**\n * 判断是否为业务响应错误\n */\nfunction isBusinessResponse(response: unknown): response is { code: number; msg?: string; message?: string } {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'code' in response &&\n typeof (response as { code: unknown }).code === 'number'\n );\n}\n\n/**\n * 处理 HTTP 错误\n */\nfunction handleHttpError(error: AxiosError): RequestError {\n const status = error.response?.status ?? 0;\n const defaultMessage = '网络请求错误';\n const message = configManager.getMessageByHttpStatus(status) ?? defaultMessage;\n\n return new RequestError({\n message,\n code: status,\n originalError: error,\n isHttpError: true,\n config: error.config,\n });\n}\n\n/**\n * 处理业务错误\n */\nfunction handleBusinessError(response: AxiosResponse): RequestError {\n const data = response.data;\n const code = isBusinessResponse(data) ? data.code : -1;\n const msg = isBusinessResponse(data) ? (data.msg ?? data.message ?? '业务处理失败') : '业务处理失败';\n const message = configManager.getMessageByCode(code) ?? msg;\n\n return new RequestError({\n message,\n code,\n originalError: data,\n isBusinessError: true,\n });\n}\n\n// 导出业务错误处理函数供外部使用\nexport { handleBusinessError };\n\n/**\n * 处理请求错误(网络错误、超时等)\n */\nfunction handleRequestError(error: AxiosError): RequestError {\n let message = '请求失败';\n let code: number | string = -1;\n\n if (error.code === 'ECONNABORTED') {\n message = '请求超时,请稍后重试';\n code = 408;\n } else if (error.code === 'ERR_NETWORK') {\n message = '网络连接失败,请检查网络';\n code = 'NETWORK_ERROR';\n } else if (error.code === 'ERR_CANCELED') {\n message = '请求已取消';\n code = 'CANCELED';\n }\n\n return new RequestError({\n message,\n code,\n originalError: error,\n config: error.config,\n });\n}\n\n/**\n * 统一错误处理入口\n */\nexport function handleError(error: unknown): RequestError {\n let requestError: RequestError;\n\n if (isAxiosError(error)) {\n // HTTP 错误(有响应但状态码非 2xx)\n if (error.response) {\n requestError = handleHttpError(error);\n } else {\n // 请求错误(无响应,网络问题、超时等)\n requestError = handleRequestError(error);\n }\n } else if (error instanceof RequestError) {\n requestError = error;\n } else if (error instanceof Error) {\n requestError = new RequestError({\n message: error.message,\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n } else {\n requestError = new RequestError({\n message: '未知错误',\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n }\n\n // 触发错误处理钩子(预留 event-bus 接入点)\n const errorHandler = configManager.getErrorHandler();\n if (errorHandler) {\n try {\n errorHandler(requestError);\n } catch (e) {\n console.error('[Request] 错误处理钩子执行失败:', e);\n }\n }\n\n return requestError;\n}\n\n/**\n * 检查响应是否为成功响应\n */\nexport function isSuccessResponse(response: AxiosResponse): boolean {\n const data = response.data;\n\n if (!isBusinessResponse(data)) {\n // 如果不是标准业务响应格式,默认认为成功(HTTP 2xx)\n return true;\n }\n\n return configManager.isSuccessCode(data.code);\n}\n\nexport { isAxiosError, isBusinessResponse };\n","import axios, { type AxiosInstance, type AxiosResponse, type InternalAxiosRequestConfig } from 'axios';\nimport type { BaseResponse, RequestConfig, RequestParams, GlobalConfig } from './types.js';\nimport { configManager } from './config.js';\nimport { handleError, isSuccessResponse } from './error-handler.js';\n\n/**\n * 获取基础 URL\n * 优先从环境变量读取,未定义时返回空字符串\n */\nfunction getBaseURL(): string {\n // 使用类型断言访问 Vite 环境变量\n const env = (import.meta as unknown as { env: Record<string, string | undefined> }).env;\n const prefix = env?.VITE_BASE_API_PREFIX;\n\n if (prefix === undefined) {\n console.warn('[Request] VITE_BASE_API_PREFIX 未定义,使用空字符串作为基础路径');\n return '';\n }\n\n return prefix;\n}\n\n/**\n * 将对象转换为 URL 查询字符串\n */\nfunction objectToQueryString(obj: RequestParams): string {\n const params = new URLSearchParams();\n\n Object.entries(obj).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => params.append(key, String(item)));\n } else {\n params.append(key, String(value));\n }\n });\n\n return params.toString();\n}\n\n/**\n * 构建完整 URL(带查询参数)\n */\nfunction buildURL(url: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return url;\n }\n\n const queryString = objectToQueryString(params);\n const separator = url.includes('?') ? '&' : '?';\n\n return `${url}${separator}${queryString}`;\n}\n\n/**\n * 请求类\n */\nclass RequestClass {\n private instance: AxiosInstance;\n\n constructor() {\n this.instance = axios.create({\n baseURL: getBaseURL(),\n timeout: configManager.getTimeout(),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n /**\n * 配置对象\n * 用于全局配置访问\n */\n get config(): {\n set: (config: GlobalConfig) => void;\n get: () => ReturnType<typeof configManager.getConfig>;\n reset: () => void;\n } {\n return {\n set: (config: GlobalConfig) => configManager.setConfig(config),\n get: () => configManager.getConfig(),\n reset: () => configManager.reset(),\n };\n }\n\n /**\n * 设置拦截器\n */\n private setupInterceptors(): void {\n const interceptors = configManager.getInterceptors();\n\n // 请求拦截器\n this.instance.interceptors.request.use(\n (config: InternalAxiosRequestConfig) => {\n // 应用用户自定义请求拦截器\n if (interceptors.request) {\n return interceptors.request(config);\n }\n return config;\n },\n (error: unknown) => {\n if (interceptors.requestError) {\n return Promise.reject(interceptors.requestError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n\n // 响应拦截器\n this.instance.interceptors.response.use(\n (response: AxiosResponse) => {\n // 检查业务状态码\n if (!isSuccessResponse(response)) {\n return Promise.reject(handleError(response));\n }\n\n // 应用用户自定义响应拦截器\n if (interceptors.response) {\n return interceptors.response(response);\n }\n\n return response;\n },\n (error: unknown) => {\n if (interceptors.responseError) {\n return Promise.reject(interceptors.responseError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n }\n\n /**\n * 创建取消令牌\n */\n createCancelToken(): { token: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n return {\n token: controller.signal,\n cancel: () => controller.abort(),\n };\n }\n\n /**\n * GET 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async get<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.get<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * DELETE 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async delete<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.delete<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * POST 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async post<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.post<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PUT 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async put<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.put<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PATCH 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async patch<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.patch<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * POST 表单请求(multipart/form-data)\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async postForm<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const formData = new FormData();\n\n if (data) {\n Object.entries(data).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, String(value));\n }\n }\n });\n }\n\n const response = await this.instance.post<BaseResponse<R>>(url, formData, {\n ...config,\n headers: {\n ...config?.headers,\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n return response.data;\n }\n\n /**\n * 通用请求方法\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async request<P extends RequestParams = RequestParams, R = unknown>(\n method: 'get' | 'post' | 'put' | 'delete' | 'patch',\n url: string,\n paramsOrData?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n switch (method) {\n case 'get':\n return this.get<P, R>(url, paramsOrData, config);\n case 'delete':\n return this.delete<P, R>(url, paramsOrData, config);\n case 'post':\n return this.post<P, R>(url, paramsOrData, config);\n case 'put':\n return this.put<P, R>(url, paramsOrData, config);\n case 'patch':\n return this.patch<P, R>(url, paramsOrData, config);\n default:\n throw new Error(`[Request] 不支持的请求方法: ${method}`);\n }\n }\n}\n\n/**\n * Request 实例\n */\nexport const Request = new RequestClass();\n\n/**\n * 重新初始化 Request(配置变更后调用)\n * @internal\n */\nexport function reinitializeRequest(): void {\n // 通过创建新实例来应用新配置\n Object.setPrototypeOf(Request, new RequestClass());\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/token.ts","../src/config.ts","../src/types.ts","../src/error-handler.ts","../src/request.ts"],"sourcesContent":["/**\n * @boo-dreamer/request - Token 管理\n * 支持从 storage 自动获取 token 并注入请求头\n */\nimport type { TokenConfig } from './types.js';\n\n/**\n * 默认 Token 配置\n */\nconst DEFAULT_TOKEN_CONFIG: Required<Omit<TokenConfig, 'getToken' | 'whiteList'>> & { whiteList: string[] } = {\n enable: false,\n storageKey: 'token',\n storageType: 'localStorage',\n headerName: 'Authorization',\n tokenPrefix: 'Bearer',\n whiteList: [],\n};\n\n/**\n * Token 管理类\n */\nclass TokenManager {\n private config: TokenConfig | undefined;\n\n /**\n * 设置配置\n */\n setConfig(config: TokenConfig | undefined): void {\n this.config = config;\n }\n\n /**\n * 获取配置\n */\n getConfig(): TokenConfig | undefined {\n return this.config;\n }\n\n /**\n * 是否启用\n */\n isEnabled(): boolean {\n return this.config?.enable ?? false;\n }\n\n /**\n * 获取 token\n */\n async getToken(): Promise<string | null> {\n if (!this.config?.enable) return null;\n\n // 优先使用自定义获取函数\n if (this.config.getToken) {\n try {\n return await this.config.getToken();\n } catch {\n return null;\n }\n }\n\n // 从 storage 读取\n const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;\n\n try {\n const storage = storageType === 'sessionStorage' ? sessionStorage : localStorage;\n return storage.getItem(storageKey);\n } catch {\n // storage 不可用(如 SSR 环境)\n return null;\n }\n }\n\n /**\n * 设置 token\n */\n setToken(token: string): void {\n if (!this.config?.enable) return;\n\n const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;\n\n try {\n const storage = storageType === 'sessionStorage' ? sessionStorage : localStorage;\n storage.setItem(storageKey, token);\n } catch {\n // storage 不可用\n }\n }\n\n /**\n * 清除 token\n */\n removeToken(): void {\n if (!this.config?.enable) return;\n\n const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;\n\n try {\n const storage = storageType === 'sessionStorage' ? sessionStorage : localStorage;\n storage.removeItem(storageKey);\n } catch {\n // storage 不可用\n }\n }\n\n /**\n * 检查 URL 是否在白名单中\n */\n isInWhiteList(url: string): boolean {\n if (!this.config?.whiteList?.length) return false;\n return this.config.whiteList.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return false;\n });\n }\n\n /**\n * 构建 Authorization 头\n */\n async buildAuthHeader(): Promise<{ key: string; value: string } | null> {\n const token = await this.getToken();\n if (!token) return null;\n\n const headerName = this.config?.headerName ?? DEFAULT_TOKEN_CONFIG.headerName;\n const tokenPrefix = this.config?.tokenPrefix ?? DEFAULT_TOKEN_CONFIG.tokenPrefix;\n const value = tokenPrefix ? `${tokenPrefix} ${token}` : token;\n\n return { key: headerName, value };\n }\n}\n\n/**\n * Token 管理器实例\n */\nexport const tokenManager = new TokenManager();\n","import type { GlobalConfig, CodeMessageMap, HttpStatusMessageMap, InterceptorConfig, TokenConfig } from './types.js';\nimport { tokenManager } from './token.js';\n\n/**\n * 默认 Code 提示映射表\n */\nexport const DEFAULT_CODE_MESSAGE_MAP: CodeMessageMap = {\n 200: '操作成功',\n 201: '创建成功',\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 500: '服务器内部错误',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认 HTTP 状态码提示映射表\n */\nexport const DEFAULT_HTTP_STATUS_MESSAGE_MAP: HttpStatusMessageMap = {\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 405: '请求方法不允许',\n 408: '请求超时',\n 500: '服务器内部错误',\n 501: '服务未实现',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认成功状态码\n */\nexport const DEFAULT_SUCCESS_CODE: number[] = [200, 0];\n\n/**\n * 默认超时时间(10秒)\n */\nexport const DEFAULT_TIMEOUT = 10000;\n\n/**\n * 配置管理类\n */\nclass ConfigManager {\n private config: GlobalConfig = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n tokenConfig: undefined,\n };\n\n /**\n * 获取当前配置\n */\n getConfig(): GlobalConfig {\n return { ...this.config };\n }\n\n /**\n * 设置全局配置\n */\n setConfig(config: GlobalConfig): void {\n this.config = {\n ...this.config,\n ...config,\n // 深度合并映射表\n codeMessageMap: {\n ...this.config.codeMessageMap,\n ...config.codeMessageMap,\n },\n httpStatusMessageMap: {\n ...this.config.httpStatusMessageMap,\n ...config.httpStatusMessageMap,\n },\n // 合并拦截器配置\n interceptors: {\n ...this.config.interceptors,\n ...config.interceptors,\n },\n };\n\n // 更新 token 配置\n if (config.tokenConfig !== undefined) {\n tokenManager.setConfig(config.tokenConfig);\n }\n }\n\n /**\n * 获取成功状态码\n */\n getSuccessCodes(): number[] {\n const codes = this.config.successCode ?? DEFAULT_SUCCESS_CODE;\n return Array.isArray(codes) ? codes : [codes];\n }\n\n /**\n * 检查是否为成功状态码\n */\n isSuccessCode(code: number): boolean {\n return this.getSuccessCodes().includes(code);\n }\n\n /**\n * 根据 Code 获取提示消息\n */\n getMessageByCode(code: number | string): string | undefined {\n return this.config.codeMessageMap?.[code];\n }\n\n /**\n * 根据 HTTP 状态码获取提示消息\n */\n getMessageByHttpStatus(status: number): string | undefined {\n return this.config.httpStatusMessageMap?.[status];\n }\n\n /**\n * 获取超时时间\n */\n getTimeout(): number {\n return this.config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * 获取拦截器配置\n */\n getInterceptors(): InterceptorConfig {\n return this.config.interceptors ?? {};\n }\n\n /**\n * 获取错误处理钩子\n */\n getErrorHandler(): ((error: unknown) => void) | undefined {\n return this.config.onError ?? undefined;\n }\n\n /**\n * 重置为默认配置\n */\n reset(): void {\n this.config = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n tokenConfig: undefined,\n };\n tokenManager.setConfig(undefined);\n }\n\n /**\n * 获取 Token 配置\n */\n getTokenConfig(): TokenConfig | undefined {\n return this.config.tokenConfig;\n }\n}\n\n/**\n * 全局配置管理器实例\n */\nexport const configManager = new ConfigManager();\n","import type { AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, Canceler } from 'axios';\n\n/**\n * 默认响应数据格式\n * @template T - data 字段的数据类型\n */\nexport interface BaseResponse<T = unknown> {\n /** 业务状态码 */\n code: number;\n /** 响应数据 */\n data: T;\n /** 提示消息 */\n msg: string;\n /** 是否成功 */\n success: boolean;\n}\n\n/**\n * 自定义响应数据格式接口\n * 用户可通过继承此接口实现自定义响应格式\n */\nexport interface CustomResponse<T = unknown> {\n [key: string]: unknown;\n data?: T;\n}\n\n/**\n * 请求配置选项\n */\nexport interface RequestConfig extends AxiosRequestConfig {\n /** 是否显示错误提示 */\n showError?: boolean;\n /** 自定义错误提示消息 */\n errorMessage?: string;\n /** 是否携带 token */\n withToken?: boolean;\n}\n\n/**\n * 请求拦截器函数类型\n */\nexport type RequestInterceptor = (\n config: InternalAxiosRequestConfig\n) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;\n\n/**\n * 响应拦截器函数类型\n */\nexport type ResponseInterceptor<T = unknown> = (\n response: AxiosResponse<T>\n) => AxiosResponse<T> | Promise<AxiosResponse<T>>;\n\n/**\n * 错误拦截器函数类型\n */\nexport type ErrorInterceptor = (error: unknown) => unknown;\n\n/**\n * 拦截器配置\n */\nexport interface InterceptorConfig {\n /** 请求拦截器 */\n request?: RequestInterceptor;\n /** 请求错误拦截器 */\n requestError?: ErrorInterceptor;\n /** 响应拦截器 */\n response?: ResponseInterceptor;\n /** 响应错误拦截器 */\n responseError?: ErrorInterceptor;\n}\n\n/**\n * Code 提示映射表\n */\nexport type CodeMessageMap = Record<number | string, string>;\n\n/**\n * HTTP 状态码提示映射表\n */\nexport type HttpStatusMessageMap = Record<number, string>;\n\n/**\n * Token 配置选项\n */\nexport interface TokenConfig {\n /** 是否启用自动 token 注入 */\n enable: boolean;\n /** token 存储 key(localStorage/sessionStorage) */\n storageKey?: string;\n /** 存储类型 */\n storageType?: 'localStorage' | 'sessionStorage';\n /** 自定义 token 获取函数(优先级高于 storage) */\n getToken?: () => string | null | Promise<string | null>;\n /** 请求头名称,默认 Authorization */\n headerName?: string;\n /** token 前缀,默认 Bearer */\n tokenPrefix?: string;\n /** 不需要 token 的 URL 白名单 */\n whiteList?: string[];\n}\n\n/**\n * 全局配置选项\n */\nexport interface GlobalConfig<T = unknown> {\n /** 基础响应数据类型(用于类型推断) */\n baseResponseType?: T;\n /** 成功状态码 */\n successCode?: number | number[];\n /** Code 提示映射表 */\n codeMessageMap?: CodeMessageMap;\n /** HTTP 状态码提示映射表 */\n httpStatusMessageMap?: HttpStatusMessageMap;\n /** 默认超时时间(毫秒) */\n timeout?: number;\n /** 请求拦截器配置 */\n interceptors?: InterceptorConfig;\n /** 错误处理钩子(预留 event-bus 接入点) */\n onError?: (error: unknown) => void;\n /** Token 配置 */\n tokenConfig?: TokenConfig;\n}\n\n/**\n * 请求错误类\n */\nexport class RequestError extends Error {\n /** 错误码(业务码或 HTTP 状态码) */\n code: number | string;\n /** 原始错误对象 */\n originalError: unknown;\n /** 是否为业务错误 */\n isBusinessError: boolean;\n /** 是否为 HTTP 错误 */\n isHttpError: boolean;\n /** 请求配置 */\n config?: AxiosRequestConfig;\n\n constructor(options: {\n message: string;\n code: number | string;\n originalError: unknown;\n isBusinessError?: boolean;\n isHttpError?: boolean;\n config?: AxiosRequestConfig;\n }) {\n super(options.message);\n this.name = 'RequestError';\n this.code = options.code;\n this.originalError = options.originalError;\n this.isBusinessError = options.isBusinessError ?? false;\n this.isHttpError = options.isHttpError ?? false;\n this.config = options.config;\n }\n}\n\n/**\n * 取消请求控制器\n */\nexport interface CancelTokenController {\n /** 取消函数 */\n cancel: Canceler;\n /** 取消令牌 */\n token: AbortSignal;\n}\n\n/**\n * 请求方法类型定义\n */\nexport type RequestMethod = 'get' | 'post' | 'put' | 'delete' | 'patch';\n\n/**\n * 请求参数类型(对象格式)\n * 使用宽泛的类型约束以支持任意对象\n */\nexport type RequestParams = object;\n","import type { AxiosError, AxiosResponse } from 'axios';\nimport { RequestError } from './types.js';\nimport { configManager } from './config.js';\n\n/**\n * 判断是否为 Axios 错误\n */\nfunction isAxiosError(error: unknown): error is AxiosError {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'isAxiosError' in error &&\n (error as AxiosError).isAxiosError === true\n );\n}\n\n/**\n * 判断是否为业务响应错误\n */\nfunction isBusinessResponse(response: unknown): response is { code: number; msg?: string; message?: string } {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'code' in response &&\n typeof (response as { code: unknown }).code === 'number'\n );\n}\n\n/**\n * 处理 HTTP 错误\n */\nfunction handleHttpError(error: AxiosError): RequestError {\n const status = error.response?.status ?? 0;\n const defaultMessage = '网络请求错误';\n const message = configManager.getMessageByHttpStatus(status) ?? defaultMessage;\n\n return new RequestError({\n message,\n code: status,\n originalError: error,\n isHttpError: true,\n config: error.config,\n });\n}\n\n/**\n * 处理业务错误\n */\nfunction handleBusinessError(response: AxiosResponse): RequestError {\n const data = response.data;\n const code = isBusinessResponse(data) ? data.code : -1;\n const msg = isBusinessResponse(data) ? (data.msg ?? data.message ?? '业务处理失败') : '业务处理失败';\n const message = configManager.getMessageByCode(code) ?? msg;\n\n return new RequestError({\n message,\n code,\n originalError: data,\n isBusinessError: true,\n });\n}\n\n// 导出业务错误处理函数供外部使用\nexport { handleBusinessError };\n\n/**\n * 处理请求错误(网络错误、超时等)\n */\nfunction handleRequestError(error: AxiosError): RequestError {\n let message = '请求失败';\n let code: number | string = -1;\n\n if (error.code === 'ECONNABORTED') {\n message = '请求超时,请稍后重试';\n code = 408;\n } else if (error.code === 'ERR_NETWORK') {\n message = '网络连接失败,请检查网络';\n code = 'NETWORK_ERROR';\n } else if (error.code === 'ERR_CANCELED') {\n message = '请求已取消';\n code = 'CANCELED';\n }\n\n return new RequestError({\n message,\n code,\n originalError: error,\n config: error.config,\n });\n}\n\n/**\n * 统一错误处理入口\n */\nexport function handleError(error: unknown): RequestError {\n let requestError: RequestError;\n\n if (isAxiosError(error)) {\n // HTTP 错误(有响应但状态码非 2xx)\n if (error.response) {\n requestError = handleHttpError(error);\n } else {\n // 请求错误(无响应,网络问题、超时等)\n requestError = handleRequestError(error);\n }\n } else if (error instanceof RequestError) {\n requestError = error;\n } else if (error instanceof Error) {\n requestError = new RequestError({\n message: error.message,\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n } else {\n requestError = new RequestError({\n message: '未知错误',\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n }\n\n // 触发错误处理钩子(预留 event-bus 接入点)\n const errorHandler = configManager.getErrorHandler();\n if (errorHandler) {\n try {\n errorHandler(requestError);\n } catch (e) {\n console.error('[Request] 错误处理钩子执行失败:', e);\n }\n }\n\n return requestError;\n}\n\n/**\n * 检查响应是否为成功响应\n */\nexport function isSuccessResponse(response: AxiosResponse): boolean {\n const data = response.data;\n\n if (!isBusinessResponse(data)) {\n // 如果不是标准业务响应格式,默认认为成功(HTTP 2xx)\n return true;\n }\n\n return configManager.isSuccessCode(data.code);\n}\n\nexport { isAxiosError, isBusinessResponse };\n","import axios, { type AxiosInstance, type AxiosResponse, type InternalAxiosRequestConfig } from 'axios';\nimport type { BaseResponse, RequestConfig, RequestParams, GlobalConfig } from './types.js';\nimport { configManager } from './config.js';\nimport { handleError, isSuccessResponse } from './error-handler.js';\nimport { tokenManager } from './token.js';\n\n/**\n * 获取基础 URL\n * 优先从环境变量读取,未定义时返回空字符串\n */\nfunction getBaseURL(): string {\n // 使用类型断言访问 Vite 环境变量\n const env = (import.meta as unknown as { env: Record<string, string | undefined> }).env;\n const prefix = env?.VITE_BASE_API_PREFIX;\n\n if (prefix === undefined) {\n console.warn('[Request] VITE_BASE_API_PREFIX 未定义,使用空字符串作为基础路径');\n return '';\n }\n\n return prefix;\n}\n\n/**\n * 将对象转换为 URL 查询字符串\n */\nfunction objectToQueryString(obj: RequestParams): string {\n const params = new URLSearchParams();\n\n Object.entries(obj).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => params.append(key, String(item)));\n } else {\n params.append(key, String(value));\n }\n });\n\n return params.toString();\n}\n\n/**\n * 构建完整 URL(带查询参数)\n */\nfunction buildURL(url: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return url;\n }\n\n const queryString = objectToQueryString(params);\n const separator = url.includes('?') ? '&' : '?';\n\n return `${url}${separator}${queryString}`;\n}\n\n/**\n * 请求类\n */\nclass RequestClass {\n private instance: AxiosInstance;\n\n constructor() {\n this.instance = axios.create({\n baseURL: getBaseURL(),\n timeout: configManager.getTimeout(),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n /**\n * 配置对象\n * 用于全局配置访问\n */\n get config(): {\n set: (config: GlobalConfig) => void;\n get: () => ReturnType<typeof configManager.getConfig>;\n reset: () => void;\n } {\n return {\n set: (config: GlobalConfig) => configManager.setConfig(config),\n get: () => configManager.getConfig(),\n reset: () => configManager.reset(),\n };\n }\n\n /**\n * 设置拦截器\n */\n private setupInterceptors(): void {\n const interceptors = configManager.getInterceptors();\n\n // 请求拦截器\n this.instance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig) => {\n // 注入 token\n if (tokenManager.isEnabled() && !tokenManager.isInWhiteList(config.url || '')) {\n const authHeader = await tokenManager.buildAuthHeader();\n if (authHeader) {\n config.headers[authHeader.key] = authHeader.value;\n }\n }\n\n // 应用用户自定义请求拦截器\n if (interceptors.request) {\n return interceptors.request(config);\n }\n return config;\n },\n (error: unknown) => {\n if (interceptors.requestError) {\n return Promise.reject(interceptors.requestError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n\n // 响应拦截器\n this.instance.interceptors.response.use(\n (response: AxiosResponse) => {\n // 检查业务状态码\n if (!isSuccessResponse(response)) {\n return Promise.reject(handleError(response));\n }\n\n // 应用用户自定义响应拦截器\n if (interceptors.response) {\n return interceptors.response(response);\n }\n\n return response;\n },\n (error: unknown) => {\n if (interceptors.responseError) {\n return Promise.reject(interceptors.responseError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n }\n\n /**\n * 创建取消令牌\n */\n createCancelToken(): { token: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n return {\n token: controller.signal,\n cancel: () => controller.abort(),\n };\n }\n\n /**\n * GET 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async get<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.get<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * DELETE 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async delete<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.delete<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * POST 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async post<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.post<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PUT 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async put<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.put<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PATCH 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async patch<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.patch<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * POST 表单请求(multipart/form-data)\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async postForm<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const formData = new FormData();\n\n if (data) {\n Object.entries(data).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, String(value));\n }\n }\n });\n }\n\n const response = await this.instance.post<BaseResponse<R>>(url, formData, {\n ...config,\n headers: {\n ...config?.headers,\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n return response.data;\n }\n\n /**\n * 通用请求方法\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async request<P extends RequestParams = RequestParams, R = unknown>(\n method: 'get' | 'post' | 'put' | 'delete' | 'patch',\n url: string,\n paramsOrData?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n switch (method) {\n case 'get':\n return this.get<P, R>(url, paramsOrData, config);\n case 'delete':\n return this.delete<P, R>(url, paramsOrData, config);\n case 'post':\n return this.post<P, R>(url, paramsOrData, config);\n case 'put':\n return this.put<P, R>(url, paramsOrData, config);\n case 'patch':\n return this.patch<P, R>(url, paramsOrData, config);\n default:\n throw new Error(`[Request] 不支持的请求方法: ${method}`);\n }\n }\n}\n\n/**\n * Request 实例\n */\nexport const Request = new RequestClass();\n\n/**\n * 重新初始化 Request(配置变更后调用)\n * @internal\n */\nexport function reinitializeRequest(): void {\n // 通过创建新实例来应用新配置\n Object.setPrototypeOf(Request, new RequestClass());\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -78,6 +78,10 @@ declare class ConfigManager {
|
|
|
78
78
|
* 重置为默认配置
|
|
79
79
|
*/
|
|
80
80
|
reset(): void;
|
|
81
|
+
/**
|
|
82
|
+
* 获取 Token 配置
|
|
83
|
+
*/
|
|
84
|
+
getTokenConfig(): TokenConfig | undefined;
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
/**
|
|
@@ -137,6 +141,8 @@ export declare interface GlobalConfig<T = unknown> {
|
|
|
137
141
|
interceptors?: InterceptorConfig;
|
|
138
142
|
/** 错误处理钩子(预留 event-bus 接入点) */
|
|
139
143
|
onError?: (error: unknown) => void;
|
|
144
|
+
/** Token 配置 */
|
|
145
|
+
tokenConfig?: TokenConfig;
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
/**
|
|
@@ -301,4 +307,71 @@ export declare type RequestParams = object;
|
|
|
301
307
|
*/
|
|
302
308
|
export declare type ResponseInterceptor<T = unknown> = (response: AxiosResponse<T>) => AxiosResponse<T> | Promise<AxiosResponse<T>>;
|
|
303
309
|
|
|
310
|
+
/**
|
|
311
|
+
* Token 配置选项
|
|
312
|
+
*/
|
|
313
|
+
export declare interface TokenConfig {
|
|
314
|
+
/** 是否启用自动 token 注入 */
|
|
315
|
+
enable: boolean;
|
|
316
|
+
/** token 存储 key(localStorage/sessionStorage) */
|
|
317
|
+
storageKey?: string;
|
|
318
|
+
/** 存储类型 */
|
|
319
|
+
storageType?: 'localStorage' | 'sessionStorage';
|
|
320
|
+
/** 自定义 token 获取函数(优先级高于 storage) */
|
|
321
|
+
getToken?: () => string | null | Promise<string | null>;
|
|
322
|
+
/** 请求头名称,默认 Authorization */
|
|
323
|
+
headerName?: string;
|
|
324
|
+
/** token 前缀,默认 Bearer */
|
|
325
|
+
tokenPrefix?: string;
|
|
326
|
+
/** 不需要 token 的 URL 白名单 */
|
|
327
|
+
whiteList?: string[];
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Token 管理类
|
|
332
|
+
*/
|
|
333
|
+
declare class TokenManager {
|
|
334
|
+
private config;
|
|
335
|
+
/**
|
|
336
|
+
* 设置配置
|
|
337
|
+
*/
|
|
338
|
+
setConfig(config: TokenConfig | undefined): void;
|
|
339
|
+
/**
|
|
340
|
+
* 获取配置
|
|
341
|
+
*/
|
|
342
|
+
getConfig(): TokenConfig | undefined;
|
|
343
|
+
/**
|
|
344
|
+
* 是否启用
|
|
345
|
+
*/
|
|
346
|
+
isEnabled(): boolean;
|
|
347
|
+
/**
|
|
348
|
+
* 获取 token
|
|
349
|
+
*/
|
|
350
|
+
getToken(): Promise<string | null>;
|
|
351
|
+
/**
|
|
352
|
+
* 设置 token
|
|
353
|
+
*/
|
|
354
|
+
setToken(token: string): void;
|
|
355
|
+
/**
|
|
356
|
+
* 清除 token
|
|
357
|
+
*/
|
|
358
|
+
removeToken(): void;
|
|
359
|
+
/**
|
|
360
|
+
* 检查 URL 是否在白名单中
|
|
361
|
+
*/
|
|
362
|
+
isInWhiteList(url: string): boolean;
|
|
363
|
+
/**
|
|
364
|
+
* 构建 Authorization 头
|
|
365
|
+
*/
|
|
366
|
+
buildAuthHeader(): Promise<{
|
|
367
|
+
key: string;
|
|
368
|
+
value: string;
|
|
369
|
+
} | null>;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Token 管理器实例
|
|
374
|
+
*/
|
|
375
|
+
export declare const tokenManager: TokenManager;
|
|
376
|
+
|
|
304
377
|
export { }
|
package/dist/index.mjs
CHANGED
|
@@ -2,6 +2,109 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import axios from "axios";
|
|
5
|
+
const DEFAULT_TOKEN_CONFIG = {
|
|
6
|
+
storageKey: "token",
|
|
7
|
+
storageType: "localStorage",
|
|
8
|
+
headerName: "Authorization",
|
|
9
|
+
tokenPrefix: "Bearer"
|
|
10
|
+
};
|
|
11
|
+
class TokenManager {
|
|
12
|
+
constructor() {
|
|
13
|
+
__publicField(this, "config");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 设置配置
|
|
17
|
+
*/
|
|
18
|
+
setConfig(config) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 获取配置
|
|
23
|
+
*/
|
|
24
|
+
getConfig() {
|
|
25
|
+
return this.config;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 是否启用
|
|
29
|
+
*/
|
|
30
|
+
isEnabled() {
|
|
31
|
+
var _a;
|
|
32
|
+
return ((_a = this.config) == null ? void 0 : _a.enable) ?? false;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 获取 token
|
|
36
|
+
*/
|
|
37
|
+
async getToken() {
|
|
38
|
+
var _a;
|
|
39
|
+
if (!((_a = this.config) == null ? void 0 : _a.enable)) return null;
|
|
40
|
+
if (this.config.getToken) {
|
|
41
|
+
try {
|
|
42
|
+
return await this.config.getToken();
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;
|
|
48
|
+
try {
|
|
49
|
+
const storage = storageType === "sessionStorage" ? sessionStorage : localStorage;
|
|
50
|
+
return storage.getItem(storageKey);
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 设置 token
|
|
57
|
+
*/
|
|
58
|
+
setToken(token) {
|
|
59
|
+
var _a;
|
|
60
|
+
if (!((_a = this.config) == null ? void 0 : _a.enable)) return;
|
|
61
|
+
const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;
|
|
62
|
+
try {
|
|
63
|
+
const storage = storageType === "sessionStorage" ? sessionStorage : localStorage;
|
|
64
|
+
storage.setItem(storageKey, token);
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 清除 token
|
|
70
|
+
*/
|
|
71
|
+
removeToken() {
|
|
72
|
+
var _a;
|
|
73
|
+
if (!((_a = this.config) == null ? void 0 : _a.enable)) return;
|
|
74
|
+
const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;
|
|
75
|
+
try {
|
|
76
|
+
const storage = storageType === "sessionStorage" ? sessionStorage : localStorage;
|
|
77
|
+
storage.removeItem(storageKey);
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 检查 URL 是否在白名单中
|
|
83
|
+
*/
|
|
84
|
+
isInWhiteList(url) {
|
|
85
|
+
var _a, _b;
|
|
86
|
+
if (!((_b = (_a = this.config) == null ? void 0 : _a.whiteList) == null ? void 0 : _b.length)) return false;
|
|
87
|
+
return this.config.whiteList.some((pattern) => {
|
|
88
|
+
if (typeof pattern === "string") {
|
|
89
|
+
return url.includes(pattern);
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 构建 Authorization 头
|
|
96
|
+
*/
|
|
97
|
+
async buildAuthHeader() {
|
|
98
|
+
var _a, _b;
|
|
99
|
+
const token = await this.getToken();
|
|
100
|
+
if (!token) return null;
|
|
101
|
+
const headerName = ((_a = this.config) == null ? void 0 : _a.headerName) ?? DEFAULT_TOKEN_CONFIG.headerName;
|
|
102
|
+
const tokenPrefix = ((_b = this.config) == null ? void 0 : _b.tokenPrefix) ?? DEFAULT_TOKEN_CONFIG.tokenPrefix;
|
|
103
|
+
const value = tokenPrefix ? `${tokenPrefix} ${token}` : token;
|
|
104
|
+
return { key: headerName, value };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const tokenManager = new TokenManager();
|
|
5
108
|
const DEFAULT_CODE_MESSAGE_MAP = {
|
|
6
109
|
200: "操作成功",
|
|
7
110
|
201: "创建成功",
|
|
@@ -38,7 +141,8 @@ class ConfigManager {
|
|
|
38
141
|
httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },
|
|
39
142
|
timeout: DEFAULT_TIMEOUT,
|
|
40
143
|
interceptors: {},
|
|
41
|
-
onError: void 0
|
|
144
|
+
onError: void 0,
|
|
145
|
+
tokenConfig: void 0
|
|
42
146
|
});
|
|
43
147
|
}
|
|
44
148
|
/**
|
|
@@ -69,6 +173,9 @@ class ConfigManager {
|
|
|
69
173
|
...config.interceptors
|
|
70
174
|
}
|
|
71
175
|
};
|
|
176
|
+
if (config.tokenConfig !== void 0) {
|
|
177
|
+
tokenManager.setConfig(config.tokenConfig);
|
|
178
|
+
}
|
|
72
179
|
}
|
|
73
180
|
/**
|
|
74
181
|
* 获取成功状态码
|
|
@@ -126,8 +233,16 @@ class ConfigManager {
|
|
|
126
233
|
httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },
|
|
127
234
|
timeout: DEFAULT_TIMEOUT,
|
|
128
235
|
interceptors: {},
|
|
129
|
-
onError: void 0
|
|
236
|
+
onError: void 0,
|
|
237
|
+
tokenConfig: void 0
|
|
130
238
|
};
|
|
239
|
+
tokenManager.setConfig(void 0);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* 获取 Token 配置
|
|
243
|
+
*/
|
|
244
|
+
getTokenConfig() {
|
|
245
|
+
return this.config.tokenConfig;
|
|
131
246
|
}
|
|
132
247
|
}
|
|
133
248
|
const configManager = new ConfigManager();
|
|
@@ -292,7 +407,13 @@ class RequestClass {
|
|
|
292
407
|
setupInterceptors() {
|
|
293
408
|
const interceptors = configManager.getInterceptors();
|
|
294
409
|
this.instance.interceptors.request.use(
|
|
295
|
-
(config) => {
|
|
410
|
+
async (config) => {
|
|
411
|
+
if (tokenManager.isEnabled() && !tokenManager.isInWhiteList(config.url || "")) {
|
|
412
|
+
const authHeader = await tokenManager.buildAuthHeader();
|
|
413
|
+
if (authHeader) {
|
|
414
|
+
config.headers[authHeader.key] = authHeader.value;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
296
417
|
if (interceptors.request) {
|
|
297
418
|
return interceptors.request(config);
|
|
298
419
|
}
|
|
@@ -439,6 +560,7 @@ export {
|
|
|
439
560
|
RequestError,
|
|
440
561
|
configManager,
|
|
441
562
|
handleError,
|
|
442
|
-
isSuccessResponse
|
|
563
|
+
isSuccessResponse,
|
|
564
|
+
tokenManager
|
|
443
565
|
};
|
|
444
566
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/config.ts","../src/types.ts","../src/error-handler.ts","../src/request.ts"],"sourcesContent":["import type { GlobalConfig, CodeMessageMap, HttpStatusMessageMap, InterceptorConfig } from './types.js';\n\n/**\n * 默认 Code 提示映射表\n */\nexport const DEFAULT_CODE_MESSAGE_MAP: CodeMessageMap = {\n 200: '操作成功',\n 201: '创建成功',\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 500: '服务器内部错误',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认 HTTP 状态码提示映射表\n */\nexport const DEFAULT_HTTP_STATUS_MESSAGE_MAP: HttpStatusMessageMap = {\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 405: '请求方法不允许',\n 408: '请求超时',\n 500: '服务器内部错误',\n 501: '服务未实现',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认成功状态码\n */\nexport const DEFAULT_SUCCESS_CODE: number[] = [200, 0];\n\n/**\n * 默认超时时间(10秒)\n */\nexport const DEFAULT_TIMEOUT = 10000;\n\n/**\n * 配置管理类\n */\nclass ConfigManager {\n private config: GlobalConfig = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n };\n\n /**\n * 获取当前配置\n */\n getConfig(): GlobalConfig {\n return { ...this.config };\n }\n\n /**\n * 设置全局配置\n */\n setConfig(config: GlobalConfig): void {\n this.config = {\n ...this.config,\n ...config,\n // 深度合并映射表\n codeMessageMap: {\n ...this.config.codeMessageMap,\n ...config.codeMessageMap,\n },\n httpStatusMessageMap: {\n ...this.config.httpStatusMessageMap,\n ...config.httpStatusMessageMap,\n },\n // 合并拦截器配置\n interceptors: {\n ...this.config.interceptors,\n ...config.interceptors,\n },\n };\n }\n\n /**\n * 获取成功状态码\n */\n getSuccessCodes(): number[] {\n const codes = this.config.successCode ?? DEFAULT_SUCCESS_CODE;\n return Array.isArray(codes) ? codes : [codes];\n }\n\n /**\n * 检查是否为成功状态码\n */\n isSuccessCode(code: number): boolean {\n return this.getSuccessCodes().includes(code);\n }\n\n /**\n * 根据 Code 获取提示消息\n */\n getMessageByCode(code: number | string): string | undefined {\n return this.config.codeMessageMap?.[code];\n }\n\n /**\n * 根据 HTTP 状态码获取提示消息\n */\n getMessageByHttpStatus(status: number): string | undefined {\n return this.config.httpStatusMessageMap?.[status];\n }\n\n /**\n * 获取超时时间\n */\n getTimeout(): number {\n return this.config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * 获取拦截器配置\n */\n getInterceptors(): InterceptorConfig {\n return this.config.interceptors ?? {};\n }\n\n /**\n * 获取错误处理钩子\n */\n getErrorHandler(): ((error: unknown) => void) | undefined {\n return this.config.onError ?? undefined;\n }\n\n /**\n * 重置为默认配置\n */\n reset(): void {\n this.config = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n };\n }\n}\n\n/**\n * 全局配置管理器实例\n */\nexport const configManager = new ConfigManager();\n","import type { AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, Canceler } from 'axios';\n\n/**\n * 默认响应数据格式\n * @template T - data 字段的数据类型\n */\nexport interface BaseResponse<T = unknown> {\n /** 业务状态码 */\n code: number;\n /** 响应数据 */\n data: T;\n /** 提示消息 */\n msg: string;\n /** 是否成功 */\n success: boolean;\n}\n\n/**\n * 自定义响应数据格式接口\n * 用户可通过继承此接口实现自定义响应格式\n */\nexport interface CustomResponse<T = unknown> {\n [key: string]: unknown;\n data?: T;\n}\n\n/**\n * 请求配置选项\n */\nexport interface RequestConfig extends AxiosRequestConfig {\n /** 是否显示错误提示 */\n showError?: boolean;\n /** 自定义错误提示消息 */\n errorMessage?: string;\n /** 是否携带 token */\n withToken?: boolean;\n}\n\n/**\n * 请求拦截器函数类型\n */\nexport type RequestInterceptor = (\n config: InternalAxiosRequestConfig\n) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;\n\n/**\n * 响应拦截器函数类型\n */\nexport type ResponseInterceptor<T = unknown> = (\n response: AxiosResponse<T>\n) => AxiosResponse<T> | Promise<AxiosResponse<T>>;\n\n/**\n * 错误拦截器函数类型\n */\nexport type ErrorInterceptor = (error: unknown) => unknown;\n\n/**\n * 拦截器配置\n */\nexport interface InterceptorConfig {\n /** 请求拦截器 */\n request?: RequestInterceptor;\n /** 请求错误拦截器 */\n requestError?: ErrorInterceptor;\n /** 响应拦截器 */\n response?: ResponseInterceptor;\n /** 响应错误拦截器 */\n responseError?: ErrorInterceptor;\n}\n\n/**\n * Code 提示映射表\n */\nexport type CodeMessageMap = Record<number | string, string>;\n\n/**\n * HTTP 状态码提示映射表\n */\nexport type HttpStatusMessageMap = Record<number, string>;\n\n/**\n * 全局配置选项\n */\nexport interface GlobalConfig<T = unknown> {\n /** 基础响应数据类型(用于类型推断) */\n baseResponseType?: T;\n /** 成功状态码 */\n successCode?: number | number[];\n /** Code 提示映射表 */\n codeMessageMap?: CodeMessageMap;\n /** HTTP 状态码提示映射表 */\n httpStatusMessageMap?: HttpStatusMessageMap;\n /** 默认超时时间(毫秒) */\n timeout?: number;\n /** 请求拦截器配置 */\n interceptors?: InterceptorConfig;\n /** 错误处理钩子(预留 event-bus 接入点) */\n onError?: (error: unknown) => void;\n}\n\n/**\n * 请求错误类\n */\nexport class RequestError extends Error {\n /** 错误码(业务码或 HTTP 状态码) */\n code: number | string;\n /** 原始错误对象 */\n originalError: unknown;\n /** 是否为业务错误 */\n isBusinessError: boolean;\n /** 是否为 HTTP 错误 */\n isHttpError: boolean;\n /** 请求配置 */\n config?: AxiosRequestConfig;\n\n constructor(options: {\n message: string;\n code: number | string;\n originalError: unknown;\n isBusinessError?: boolean;\n isHttpError?: boolean;\n config?: AxiosRequestConfig;\n }) {\n super(options.message);\n this.name = 'RequestError';\n this.code = options.code;\n this.originalError = options.originalError;\n this.isBusinessError = options.isBusinessError ?? false;\n this.isHttpError = options.isHttpError ?? false;\n this.config = options.config;\n }\n}\n\n/**\n * 取消请求控制器\n */\nexport interface CancelTokenController {\n /** 取消函数 */\n cancel: Canceler;\n /** 取消令牌 */\n token: AbortSignal;\n}\n\n/**\n * 请求方法类型定义\n */\nexport type RequestMethod = 'get' | 'post' | 'put' | 'delete' | 'patch';\n\n/**\n * 请求参数类型(对象格式)\n * 使用宽泛的类型约束以支持任意对象\n */\nexport type RequestParams = object;\n","import type { AxiosError, AxiosResponse } from 'axios';\nimport { RequestError } from './types.js';\nimport { configManager } from './config.js';\n\n/**\n * 判断是否为 Axios 错误\n */\nfunction isAxiosError(error: unknown): error is AxiosError {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'isAxiosError' in error &&\n (error as AxiosError).isAxiosError === true\n );\n}\n\n/**\n * 判断是否为业务响应错误\n */\nfunction isBusinessResponse(response: unknown): response is { code: number; msg?: string; message?: string } {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'code' in response &&\n typeof (response as { code: unknown }).code === 'number'\n );\n}\n\n/**\n * 处理 HTTP 错误\n */\nfunction handleHttpError(error: AxiosError): RequestError {\n const status = error.response?.status ?? 0;\n const defaultMessage = '网络请求错误';\n const message = configManager.getMessageByHttpStatus(status) ?? defaultMessage;\n\n return new RequestError({\n message,\n code: status,\n originalError: error,\n isHttpError: true,\n config: error.config,\n });\n}\n\n/**\n * 处理业务错误\n */\nfunction handleBusinessError(response: AxiosResponse): RequestError {\n const data = response.data;\n const code = isBusinessResponse(data) ? data.code : -1;\n const msg = isBusinessResponse(data) ? (data.msg ?? data.message ?? '业务处理失败') : '业务处理失败';\n const message = configManager.getMessageByCode(code) ?? msg;\n\n return new RequestError({\n message,\n code,\n originalError: data,\n isBusinessError: true,\n });\n}\n\n// 导出业务错误处理函数供外部使用\nexport { handleBusinessError };\n\n/**\n * 处理请求错误(网络错误、超时等)\n */\nfunction handleRequestError(error: AxiosError): RequestError {\n let message = '请求失败';\n let code: number | string = -1;\n\n if (error.code === 'ECONNABORTED') {\n message = '请求超时,请稍后重试';\n code = 408;\n } else if (error.code === 'ERR_NETWORK') {\n message = '网络连接失败,请检查网络';\n code = 'NETWORK_ERROR';\n } else if (error.code === 'ERR_CANCELED') {\n message = '请求已取消';\n code = 'CANCELED';\n }\n\n return new RequestError({\n message,\n code,\n originalError: error,\n config: error.config,\n });\n}\n\n/**\n * 统一错误处理入口\n */\nexport function handleError(error: unknown): RequestError {\n let requestError: RequestError;\n\n if (isAxiosError(error)) {\n // HTTP 错误(有响应但状态码非 2xx)\n if (error.response) {\n requestError = handleHttpError(error);\n } else {\n // 请求错误(无响应,网络问题、超时等)\n requestError = handleRequestError(error);\n }\n } else if (error instanceof RequestError) {\n requestError = error;\n } else if (error instanceof Error) {\n requestError = new RequestError({\n message: error.message,\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n } else {\n requestError = new RequestError({\n message: '未知错误',\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n }\n\n // 触发错误处理钩子(预留 event-bus 接入点)\n const errorHandler = configManager.getErrorHandler();\n if (errorHandler) {\n try {\n errorHandler(requestError);\n } catch (e) {\n console.error('[Request] 错误处理钩子执行失败:', e);\n }\n }\n\n return requestError;\n}\n\n/**\n * 检查响应是否为成功响应\n */\nexport function isSuccessResponse(response: AxiosResponse): boolean {\n const data = response.data;\n\n if (!isBusinessResponse(data)) {\n // 如果不是标准业务响应格式,默认认为成功(HTTP 2xx)\n return true;\n }\n\n return configManager.isSuccessCode(data.code);\n}\n\nexport { isAxiosError, isBusinessResponse };\n","import axios, { type AxiosInstance, type AxiosResponse, type InternalAxiosRequestConfig } from 'axios';\nimport type { BaseResponse, RequestConfig, RequestParams, GlobalConfig } from './types.js';\nimport { configManager } from './config.js';\nimport { handleError, isSuccessResponse } from './error-handler.js';\n\n/**\n * 获取基础 URL\n * 优先从环境变量读取,未定义时返回空字符串\n */\nfunction getBaseURL(): string {\n // 使用类型断言访问 Vite 环境变量\n const env = (import.meta as unknown as { env: Record<string, string | undefined> }).env;\n const prefix = env?.VITE_BASE_API_PREFIX;\n\n if (prefix === undefined) {\n console.warn('[Request] VITE_BASE_API_PREFIX 未定义,使用空字符串作为基础路径');\n return '';\n }\n\n return prefix;\n}\n\n/**\n * 将对象转换为 URL 查询字符串\n */\nfunction objectToQueryString(obj: RequestParams): string {\n const params = new URLSearchParams();\n\n Object.entries(obj).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => params.append(key, String(item)));\n } else {\n params.append(key, String(value));\n }\n });\n\n return params.toString();\n}\n\n/**\n * 构建完整 URL(带查询参数)\n */\nfunction buildURL(url: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return url;\n }\n\n const queryString = objectToQueryString(params);\n const separator = url.includes('?') ? '&' : '?';\n\n return `${url}${separator}${queryString}`;\n}\n\n/**\n * 请求类\n */\nclass RequestClass {\n private instance: AxiosInstance;\n\n constructor() {\n this.instance = axios.create({\n baseURL: getBaseURL(),\n timeout: configManager.getTimeout(),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n /**\n * 配置对象\n * 用于全局配置访问\n */\n get config(): {\n set: (config: GlobalConfig) => void;\n get: () => ReturnType<typeof configManager.getConfig>;\n reset: () => void;\n } {\n return {\n set: (config: GlobalConfig) => configManager.setConfig(config),\n get: () => configManager.getConfig(),\n reset: () => configManager.reset(),\n };\n }\n\n /**\n * 设置拦截器\n */\n private setupInterceptors(): void {\n const interceptors = configManager.getInterceptors();\n\n // 请求拦截器\n this.instance.interceptors.request.use(\n (config: InternalAxiosRequestConfig) => {\n // 应用用户自定义请求拦截器\n if (interceptors.request) {\n return interceptors.request(config);\n }\n return config;\n },\n (error: unknown) => {\n if (interceptors.requestError) {\n return Promise.reject(interceptors.requestError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n\n // 响应拦截器\n this.instance.interceptors.response.use(\n (response: AxiosResponse) => {\n // 检查业务状态码\n if (!isSuccessResponse(response)) {\n return Promise.reject(handleError(response));\n }\n\n // 应用用户自定义响应拦截器\n if (interceptors.response) {\n return interceptors.response(response);\n }\n\n return response;\n },\n (error: unknown) => {\n if (interceptors.responseError) {\n return Promise.reject(interceptors.responseError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n }\n\n /**\n * 创建取消令牌\n */\n createCancelToken(): { token: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n return {\n token: controller.signal,\n cancel: () => controller.abort(),\n };\n }\n\n /**\n * GET 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async get<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.get<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * DELETE 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async delete<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.delete<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * POST 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async post<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.post<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PUT 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async put<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.put<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PATCH 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async patch<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.patch<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * POST 表单请求(multipart/form-data)\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async postForm<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const formData = new FormData();\n\n if (data) {\n Object.entries(data).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, String(value));\n }\n }\n });\n }\n\n const response = await this.instance.post<BaseResponse<R>>(url, formData, {\n ...config,\n headers: {\n ...config?.headers,\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n return response.data;\n }\n\n /**\n * 通用请求方法\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async request<P extends RequestParams = RequestParams, R = unknown>(\n method: 'get' | 'post' | 'put' | 'delete' | 'patch',\n url: string,\n paramsOrData?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n switch (method) {\n case 'get':\n return this.get<P, R>(url, paramsOrData, config);\n case 'delete':\n return this.delete<P, R>(url, paramsOrData, config);\n case 'post':\n return this.post<P, R>(url, paramsOrData, config);\n case 'put':\n return this.put<P, R>(url, paramsOrData, config);\n case 'patch':\n return this.patch<P, R>(url, paramsOrData, config);\n default:\n throw new Error(`[Request] 不支持的请求方法: ${method}`);\n }\n }\n}\n\n/**\n * Request 实例\n */\nexport const Request = new RequestClass();\n\n/**\n * 重新初始化 Request(配置变更后调用)\n * @internal\n */\nexport function reinitializeRequest(): void {\n // 通过创建新实例来应用新配置\n Object.setPrototypeOf(Request, new RequestClass());\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/token.ts","../src/config.ts","../src/types.ts","../src/error-handler.ts","../src/request.ts"],"sourcesContent":["/**\n * @boo-dreamer/request - Token 管理\n * 支持从 storage 自动获取 token 并注入请求头\n */\nimport type { TokenConfig } from './types.js';\n\n/**\n * 默认 Token 配置\n */\nconst DEFAULT_TOKEN_CONFIG: Required<Omit<TokenConfig, 'getToken' | 'whiteList'>> & { whiteList: string[] } = {\n enable: false,\n storageKey: 'token',\n storageType: 'localStorage',\n headerName: 'Authorization',\n tokenPrefix: 'Bearer',\n whiteList: [],\n};\n\n/**\n * Token 管理类\n */\nclass TokenManager {\n private config: TokenConfig | undefined;\n\n /**\n * 设置配置\n */\n setConfig(config: TokenConfig | undefined): void {\n this.config = config;\n }\n\n /**\n * 获取配置\n */\n getConfig(): TokenConfig | undefined {\n return this.config;\n }\n\n /**\n * 是否启用\n */\n isEnabled(): boolean {\n return this.config?.enable ?? false;\n }\n\n /**\n * 获取 token\n */\n async getToken(): Promise<string | null> {\n if (!this.config?.enable) return null;\n\n // 优先使用自定义获取函数\n if (this.config.getToken) {\n try {\n return await this.config.getToken();\n } catch {\n return null;\n }\n }\n\n // 从 storage 读取\n const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;\n\n try {\n const storage = storageType === 'sessionStorage' ? sessionStorage : localStorage;\n return storage.getItem(storageKey);\n } catch {\n // storage 不可用(如 SSR 环境)\n return null;\n }\n }\n\n /**\n * 设置 token\n */\n setToken(token: string): void {\n if (!this.config?.enable) return;\n\n const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;\n\n try {\n const storage = storageType === 'sessionStorage' ? sessionStorage : localStorage;\n storage.setItem(storageKey, token);\n } catch {\n // storage 不可用\n }\n }\n\n /**\n * 清除 token\n */\n removeToken(): void {\n if (!this.config?.enable) return;\n\n const { storageKey = DEFAULT_TOKEN_CONFIG.storageKey, storageType = DEFAULT_TOKEN_CONFIG.storageType } = this.config;\n\n try {\n const storage = storageType === 'sessionStorage' ? sessionStorage : localStorage;\n storage.removeItem(storageKey);\n } catch {\n // storage 不可用\n }\n }\n\n /**\n * 检查 URL 是否在白名单中\n */\n isInWhiteList(url: string): boolean {\n if (!this.config?.whiteList?.length) return false;\n return this.config.whiteList.some((pattern) => {\n if (typeof pattern === 'string') {\n return url.includes(pattern);\n }\n return false;\n });\n }\n\n /**\n * 构建 Authorization 头\n */\n async buildAuthHeader(): Promise<{ key: string; value: string } | null> {\n const token = await this.getToken();\n if (!token) return null;\n\n const headerName = this.config?.headerName ?? DEFAULT_TOKEN_CONFIG.headerName;\n const tokenPrefix = this.config?.tokenPrefix ?? DEFAULT_TOKEN_CONFIG.tokenPrefix;\n const value = tokenPrefix ? `${tokenPrefix} ${token}` : token;\n\n return { key: headerName, value };\n }\n}\n\n/**\n * Token 管理器实例\n */\nexport const tokenManager = new TokenManager();\n","import type { GlobalConfig, CodeMessageMap, HttpStatusMessageMap, InterceptorConfig, TokenConfig } from './types.js';\nimport { tokenManager } from './token.js';\n\n/**\n * 默认 Code 提示映射表\n */\nexport const DEFAULT_CODE_MESSAGE_MAP: CodeMessageMap = {\n 200: '操作成功',\n 201: '创建成功',\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 500: '服务器内部错误',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认 HTTP 状态码提示映射表\n */\nexport const DEFAULT_HTTP_STATUS_MESSAGE_MAP: HttpStatusMessageMap = {\n 400: '请求参数错误',\n 401: '未授权,请重新登录',\n 403: '拒绝访问',\n 404: '请求资源不存在',\n 405: '请求方法不允许',\n 408: '请求超时',\n 500: '服务器内部错误',\n 501: '服务未实现',\n 502: '网关错误',\n 503: '服务不可用',\n 504: '网关超时',\n};\n\n/**\n * 默认成功状态码\n */\nexport const DEFAULT_SUCCESS_CODE: number[] = [200, 0];\n\n/**\n * 默认超时时间(10秒)\n */\nexport const DEFAULT_TIMEOUT = 10000;\n\n/**\n * 配置管理类\n */\nclass ConfigManager {\n private config: GlobalConfig = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n tokenConfig: undefined,\n };\n\n /**\n * 获取当前配置\n */\n getConfig(): GlobalConfig {\n return { ...this.config };\n }\n\n /**\n * 设置全局配置\n */\n setConfig(config: GlobalConfig): void {\n this.config = {\n ...this.config,\n ...config,\n // 深度合并映射表\n codeMessageMap: {\n ...this.config.codeMessageMap,\n ...config.codeMessageMap,\n },\n httpStatusMessageMap: {\n ...this.config.httpStatusMessageMap,\n ...config.httpStatusMessageMap,\n },\n // 合并拦截器配置\n interceptors: {\n ...this.config.interceptors,\n ...config.interceptors,\n },\n };\n\n // 更新 token 配置\n if (config.tokenConfig !== undefined) {\n tokenManager.setConfig(config.tokenConfig);\n }\n }\n\n /**\n * 获取成功状态码\n */\n getSuccessCodes(): number[] {\n const codes = this.config.successCode ?? DEFAULT_SUCCESS_CODE;\n return Array.isArray(codes) ? codes : [codes];\n }\n\n /**\n * 检查是否为成功状态码\n */\n isSuccessCode(code: number): boolean {\n return this.getSuccessCodes().includes(code);\n }\n\n /**\n * 根据 Code 获取提示消息\n */\n getMessageByCode(code: number | string): string | undefined {\n return this.config.codeMessageMap?.[code];\n }\n\n /**\n * 根据 HTTP 状态码获取提示消息\n */\n getMessageByHttpStatus(status: number): string | undefined {\n return this.config.httpStatusMessageMap?.[status];\n }\n\n /**\n * 获取超时时间\n */\n getTimeout(): number {\n return this.config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * 获取拦截器配置\n */\n getInterceptors(): InterceptorConfig {\n return this.config.interceptors ?? {};\n }\n\n /**\n * 获取错误处理钩子\n */\n getErrorHandler(): ((error: unknown) => void) | undefined {\n return this.config.onError ?? undefined;\n }\n\n /**\n * 重置为默认配置\n */\n reset(): void {\n this.config = {\n baseResponseType: undefined,\n successCode: DEFAULT_SUCCESS_CODE,\n codeMessageMap: { ...DEFAULT_CODE_MESSAGE_MAP },\n httpStatusMessageMap: { ...DEFAULT_HTTP_STATUS_MESSAGE_MAP },\n timeout: DEFAULT_TIMEOUT,\n interceptors: {},\n onError: undefined,\n tokenConfig: undefined,\n };\n tokenManager.setConfig(undefined);\n }\n\n /**\n * 获取 Token 配置\n */\n getTokenConfig(): TokenConfig | undefined {\n return this.config.tokenConfig;\n }\n}\n\n/**\n * 全局配置管理器实例\n */\nexport const configManager = new ConfigManager();\n","import type { AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, Canceler } from 'axios';\n\n/**\n * 默认响应数据格式\n * @template T - data 字段的数据类型\n */\nexport interface BaseResponse<T = unknown> {\n /** 业务状态码 */\n code: number;\n /** 响应数据 */\n data: T;\n /** 提示消息 */\n msg: string;\n /** 是否成功 */\n success: boolean;\n}\n\n/**\n * 自定义响应数据格式接口\n * 用户可通过继承此接口实现自定义响应格式\n */\nexport interface CustomResponse<T = unknown> {\n [key: string]: unknown;\n data?: T;\n}\n\n/**\n * 请求配置选项\n */\nexport interface RequestConfig extends AxiosRequestConfig {\n /** 是否显示错误提示 */\n showError?: boolean;\n /** 自定义错误提示消息 */\n errorMessage?: string;\n /** 是否携带 token */\n withToken?: boolean;\n}\n\n/**\n * 请求拦截器函数类型\n */\nexport type RequestInterceptor = (\n config: InternalAxiosRequestConfig\n) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;\n\n/**\n * 响应拦截器函数类型\n */\nexport type ResponseInterceptor<T = unknown> = (\n response: AxiosResponse<T>\n) => AxiosResponse<T> | Promise<AxiosResponse<T>>;\n\n/**\n * 错误拦截器函数类型\n */\nexport type ErrorInterceptor = (error: unknown) => unknown;\n\n/**\n * 拦截器配置\n */\nexport interface InterceptorConfig {\n /** 请求拦截器 */\n request?: RequestInterceptor;\n /** 请求错误拦截器 */\n requestError?: ErrorInterceptor;\n /** 响应拦截器 */\n response?: ResponseInterceptor;\n /** 响应错误拦截器 */\n responseError?: ErrorInterceptor;\n}\n\n/**\n * Code 提示映射表\n */\nexport type CodeMessageMap = Record<number | string, string>;\n\n/**\n * HTTP 状态码提示映射表\n */\nexport type HttpStatusMessageMap = Record<number, string>;\n\n/**\n * Token 配置选项\n */\nexport interface TokenConfig {\n /** 是否启用自动 token 注入 */\n enable: boolean;\n /** token 存储 key(localStorage/sessionStorage) */\n storageKey?: string;\n /** 存储类型 */\n storageType?: 'localStorage' | 'sessionStorage';\n /** 自定义 token 获取函数(优先级高于 storage) */\n getToken?: () => string | null | Promise<string | null>;\n /** 请求头名称,默认 Authorization */\n headerName?: string;\n /** token 前缀,默认 Bearer */\n tokenPrefix?: string;\n /** 不需要 token 的 URL 白名单 */\n whiteList?: string[];\n}\n\n/**\n * 全局配置选项\n */\nexport interface GlobalConfig<T = unknown> {\n /** 基础响应数据类型(用于类型推断) */\n baseResponseType?: T;\n /** 成功状态码 */\n successCode?: number | number[];\n /** Code 提示映射表 */\n codeMessageMap?: CodeMessageMap;\n /** HTTP 状态码提示映射表 */\n httpStatusMessageMap?: HttpStatusMessageMap;\n /** 默认超时时间(毫秒) */\n timeout?: number;\n /** 请求拦截器配置 */\n interceptors?: InterceptorConfig;\n /** 错误处理钩子(预留 event-bus 接入点) */\n onError?: (error: unknown) => void;\n /** Token 配置 */\n tokenConfig?: TokenConfig;\n}\n\n/**\n * 请求错误类\n */\nexport class RequestError extends Error {\n /** 错误码(业务码或 HTTP 状态码) */\n code: number | string;\n /** 原始错误对象 */\n originalError: unknown;\n /** 是否为业务错误 */\n isBusinessError: boolean;\n /** 是否为 HTTP 错误 */\n isHttpError: boolean;\n /** 请求配置 */\n config?: AxiosRequestConfig;\n\n constructor(options: {\n message: string;\n code: number | string;\n originalError: unknown;\n isBusinessError?: boolean;\n isHttpError?: boolean;\n config?: AxiosRequestConfig;\n }) {\n super(options.message);\n this.name = 'RequestError';\n this.code = options.code;\n this.originalError = options.originalError;\n this.isBusinessError = options.isBusinessError ?? false;\n this.isHttpError = options.isHttpError ?? false;\n this.config = options.config;\n }\n}\n\n/**\n * 取消请求控制器\n */\nexport interface CancelTokenController {\n /** 取消函数 */\n cancel: Canceler;\n /** 取消令牌 */\n token: AbortSignal;\n}\n\n/**\n * 请求方法类型定义\n */\nexport type RequestMethod = 'get' | 'post' | 'put' | 'delete' | 'patch';\n\n/**\n * 请求参数类型(对象格式)\n * 使用宽泛的类型约束以支持任意对象\n */\nexport type RequestParams = object;\n","import type { AxiosError, AxiosResponse } from 'axios';\nimport { RequestError } from './types.js';\nimport { configManager } from './config.js';\n\n/**\n * 判断是否为 Axios 错误\n */\nfunction isAxiosError(error: unknown): error is AxiosError {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'isAxiosError' in error &&\n (error as AxiosError).isAxiosError === true\n );\n}\n\n/**\n * 判断是否为业务响应错误\n */\nfunction isBusinessResponse(response: unknown): response is { code: number; msg?: string; message?: string } {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'code' in response &&\n typeof (response as { code: unknown }).code === 'number'\n );\n}\n\n/**\n * 处理 HTTP 错误\n */\nfunction handleHttpError(error: AxiosError): RequestError {\n const status = error.response?.status ?? 0;\n const defaultMessage = '网络请求错误';\n const message = configManager.getMessageByHttpStatus(status) ?? defaultMessage;\n\n return new RequestError({\n message,\n code: status,\n originalError: error,\n isHttpError: true,\n config: error.config,\n });\n}\n\n/**\n * 处理业务错误\n */\nfunction handleBusinessError(response: AxiosResponse): RequestError {\n const data = response.data;\n const code = isBusinessResponse(data) ? data.code : -1;\n const msg = isBusinessResponse(data) ? (data.msg ?? data.message ?? '业务处理失败') : '业务处理失败';\n const message = configManager.getMessageByCode(code) ?? msg;\n\n return new RequestError({\n message,\n code,\n originalError: data,\n isBusinessError: true,\n });\n}\n\n// 导出业务错误处理函数供外部使用\nexport { handleBusinessError };\n\n/**\n * 处理请求错误(网络错误、超时等)\n */\nfunction handleRequestError(error: AxiosError): RequestError {\n let message = '请求失败';\n let code: number | string = -1;\n\n if (error.code === 'ECONNABORTED') {\n message = '请求超时,请稍后重试';\n code = 408;\n } else if (error.code === 'ERR_NETWORK') {\n message = '网络连接失败,请检查网络';\n code = 'NETWORK_ERROR';\n } else if (error.code === 'ERR_CANCELED') {\n message = '请求已取消';\n code = 'CANCELED';\n }\n\n return new RequestError({\n message,\n code,\n originalError: error,\n config: error.config,\n });\n}\n\n/**\n * 统一错误处理入口\n */\nexport function handleError(error: unknown): RequestError {\n let requestError: RequestError;\n\n if (isAxiosError(error)) {\n // HTTP 错误(有响应但状态码非 2xx)\n if (error.response) {\n requestError = handleHttpError(error);\n } else {\n // 请求错误(无响应,网络问题、超时等)\n requestError = handleRequestError(error);\n }\n } else if (error instanceof RequestError) {\n requestError = error;\n } else if (error instanceof Error) {\n requestError = new RequestError({\n message: error.message,\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n } else {\n requestError = new RequestError({\n message: '未知错误',\n code: 'UNKNOWN_ERROR',\n originalError: error,\n });\n }\n\n // 触发错误处理钩子(预留 event-bus 接入点)\n const errorHandler = configManager.getErrorHandler();\n if (errorHandler) {\n try {\n errorHandler(requestError);\n } catch (e) {\n console.error('[Request] 错误处理钩子执行失败:', e);\n }\n }\n\n return requestError;\n}\n\n/**\n * 检查响应是否为成功响应\n */\nexport function isSuccessResponse(response: AxiosResponse): boolean {\n const data = response.data;\n\n if (!isBusinessResponse(data)) {\n // 如果不是标准业务响应格式,默认认为成功(HTTP 2xx)\n return true;\n }\n\n return configManager.isSuccessCode(data.code);\n}\n\nexport { isAxiosError, isBusinessResponse };\n","import axios, { type AxiosInstance, type AxiosResponse, type InternalAxiosRequestConfig } from 'axios';\nimport type { BaseResponse, RequestConfig, RequestParams, GlobalConfig } from './types.js';\nimport { configManager } from './config.js';\nimport { handleError, isSuccessResponse } from './error-handler.js';\nimport { tokenManager } from './token.js';\n\n/**\n * 获取基础 URL\n * 优先从环境变量读取,未定义时返回空字符串\n */\nfunction getBaseURL(): string {\n // 使用类型断言访问 Vite 环境变量\n const env = (import.meta as unknown as { env: Record<string, string | undefined> }).env;\n const prefix = env?.VITE_BASE_API_PREFIX;\n\n if (prefix === undefined) {\n console.warn('[Request] VITE_BASE_API_PREFIX 未定义,使用空字符串作为基础路径');\n return '';\n }\n\n return prefix;\n}\n\n/**\n * 将对象转换为 URL 查询字符串\n */\nfunction objectToQueryString(obj: RequestParams): string {\n const params = new URLSearchParams();\n\n Object.entries(obj).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => params.append(key, String(item)));\n } else {\n params.append(key, String(value));\n }\n });\n\n return params.toString();\n}\n\n/**\n * 构建完整 URL(带查询参数)\n */\nfunction buildURL(url: string, params?: RequestParams): string {\n if (!params || Object.keys(params).length === 0) {\n return url;\n }\n\n const queryString = objectToQueryString(params);\n const separator = url.includes('?') ? '&' : '?';\n\n return `${url}${separator}${queryString}`;\n}\n\n/**\n * 请求类\n */\nclass RequestClass {\n private instance: AxiosInstance;\n\n constructor() {\n this.instance = axios.create({\n baseURL: getBaseURL(),\n timeout: configManager.getTimeout(),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n /**\n * 配置对象\n * 用于全局配置访问\n */\n get config(): {\n set: (config: GlobalConfig) => void;\n get: () => ReturnType<typeof configManager.getConfig>;\n reset: () => void;\n } {\n return {\n set: (config: GlobalConfig) => configManager.setConfig(config),\n get: () => configManager.getConfig(),\n reset: () => configManager.reset(),\n };\n }\n\n /**\n * 设置拦截器\n */\n private setupInterceptors(): void {\n const interceptors = configManager.getInterceptors();\n\n // 请求拦截器\n this.instance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig) => {\n // 注入 token\n if (tokenManager.isEnabled() && !tokenManager.isInWhiteList(config.url || '')) {\n const authHeader = await tokenManager.buildAuthHeader();\n if (authHeader) {\n config.headers[authHeader.key] = authHeader.value;\n }\n }\n\n // 应用用户自定义请求拦截器\n if (interceptors.request) {\n return interceptors.request(config);\n }\n return config;\n },\n (error: unknown) => {\n if (interceptors.requestError) {\n return Promise.reject(interceptors.requestError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n\n // 响应拦截器\n this.instance.interceptors.response.use(\n (response: AxiosResponse) => {\n // 检查业务状态码\n if (!isSuccessResponse(response)) {\n return Promise.reject(handleError(response));\n }\n\n // 应用用户自定义响应拦截器\n if (interceptors.response) {\n return interceptors.response(response);\n }\n\n return response;\n },\n (error: unknown) => {\n if (interceptors.responseError) {\n return Promise.reject(interceptors.responseError(error));\n }\n return Promise.reject(handleError(error));\n }\n );\n }\n\n /**\n * 创建取消令牌\n */\n createCancelToken(): { token: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n return {\n token: controller.signal,\n cancel: () => controller.abort(),\n };\n }\n\n /**\n * GET 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async get<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.get<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * DELETE 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async delete<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n params?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const fullURL = buildURL(url, params);\n\n const response = await this.instance.delete<BaseResponse<R>>(fullURL, config);\n return response.data;\n }\n\n /**\n * POST 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async post<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.post<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PUT 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async put<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.put<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * PATCH 请求\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async patch<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const response = await this.instance.patch<BaseResponse<R>>(url, data, config);\n return response.data;\n }\n\n /**\n * POST 表单请求(multipart/form-data)\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async postForm<P extends RequestParams = RequestParams, R = unknown>(\n url: string,\n data?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n const formData = new FormData();\n\n if (data) {\n Object.entries(data).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n } else {\n formData.append(key, String(value));\n }\n }\n });\n }\n\n const response = await this.instance.post<BaseResponse<R>>(url, formData, {\n ...config,\n headers: {\n ...config?.headers,\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n return response.data;\n }\n\n /**\n * 通用请求方法\n * @template P - 请求参数类型\n * @template R - 响应 data 字段类型\n */\n async request<P extends RequestParams = RequestParams, R = unknown>(\n method: 'get' | 'post' | 'put' | 'delete' | 'patch',\n url: string,\n paramsOrData?: P,\n config?: RequestConfig\n ): Promise<BaseResponse<R>> {\n switch (method) {\n case 'get':\n return this.get<P, R>(url, paramsOrData, config);\n case 'delete':\n return this.delete<P, R>(url, paramsOrData, config);\n case 'post':\n return this.post<P, R>(url, paramsOrData, config);\n case 'put':\n return this.put<P, R>(url, paramsOrData, config);\n case 'patch':\n return this.patch<P, R>(url, paramsOrData, config);\n default:\n throw new Error(`[Request] 不支持的请求方法: ${method}`);\n }\n }\n}\n\n/**\n * Request 实例\n */\nexport const Request = new RequestClass();\n\n/**\n * 重新初始化 Request(配置变更后调用)\n * @internal\n */\nexport function reinitializeRequest(): void {\n // 通过创建新实例来应用新配置\n Object.setPrototypeOf(Request, new RequestClass());\n}\n"],"names":[],"mappings":";;;;AASA,MAAM,uBAAwG;AAAA,EAE5G,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,aAAa;AAEf;AAKA,MAAM,aAAa;AAAA,EAAnB;AACU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKR,UAAU,QAAuC;AAC/C,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;;AACnB,aAAO,UAAK,WAAL,mBAAa,WAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAmC;;AACvC,QAAI,GAAC,UAAK,WAAL,mBAAa,QAAQ,QAAO;AAGjC,QAAI,KAAK,OAAO,UAAU;AACxB,UAAI;AACF,eAAO,MAAM,KAAK,OAAO,SAAA;AAAA,MAC3B,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAGA,UAAM,EAAE,aAAa,qBAAqB,YAAY,cAAc,qBAAqB,gBAAgB,KAAK;AAE9G,QAAI;AACF,YAAM,UAAU,gBAAgB,mBAAmB,iBAAiB;AACpE,aAAO,QAAQ,QAAQ,UAAU;AAAA,IACnC,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,OAAqB;;AAC5B,QAAI,GAAC,UAAK,WAAL,mBAAa,QAAQ;AAE1B,UAAM,EAAE,aAAa,qBAAqB,YAAY,cAAc,qBAAqB,gBAAgB,KAAK;AAE9G,QAAI;AACF,YAAM,UAAU,gBAAgB,mBAAmB,iBAAiB;AACpE,cAAQ,QAAQ,YAAY,KAAK;AAAA,IACnC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;;AAClB,QAAI,GAAC,UAAK,WAAL,mBAAa,QAAQ;AAE1B,UAAM,EAAE,aAAa,qBAAqB,YAAY,cAAc,qBAAqB,gBAAgB,KAAK;AAE9G,QAAI;AACF,YAAM,UAAU,gBAAgB,mBAAmB,iBAAiB;AACpE,cAAQ,WAAW,UAAU;AAAA,IAC/B,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,KAAsB;;AAClC,QAAI,GAAC,gBAAK,WAAL,mBAAa,cAAb,mBAAwB,QAAQ,QAAO;AAC5C,WAAO,KAAK,OAAO,UAAU,KAAK,CAAC,YAAY;AAC7C,UAAI,OAAO,YAAY,UAAU;AAC/B,eAAO,IAAI,SAAS,OAAO;AAAA,MAC7B;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkE;;AACtE,UAAM,QAAQ,MAAM,KAAK,SAAA;AACzB,QAAI,CAAC,MAAO,QAAO;AAEnB,UAAM,eAAa,UAAK,WAAL,mBAAa,eAAc,qBAAqB;AACnE,UAAM,gBAAc,UAAK,WAAL,mBAAa,gBAAe,qBAAqB;AACrE,UAAM,QAAQ,cAAc,GAAG,WAAW,IAAI,KAAK,KAAK;AAExD,WAAO,EAAE,KAAK,YAAY,MAAA;AAAA,EAC5B;AACF;AAKO,MAAM,eAAe,IAAI,aAAA;ACjIzB,MAAM,2BAA2C;AAAA,EACtD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAKO,MAAM,kCAAwD;AAAA,EACnE,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAKO,MAAM,uBAAiC,CAAC,KAAK,CAAC;AAK9C,MAAM,kBAAkB;AAK/B,MAAM,cAAc;AAAA,EAApB;AACU,kCAAuB;AAAA,MAC7B,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,gBAAgB,EAAE,GAAG,yBAAA;AAAA,MACrB,sBAAsB,EAAE,GAAG,gCAAA;AAAA,MAC3B,SAAS;AAAA,MACT,cAAc,CAAA;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMf,YAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,OAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,QAA4B;AACpC,SAAK,SAAS;AAAA,MACZ,GAAG,KAAK;AAAA,MACR,GAAG;AAAA;AAAA,MAEH,gBAAgB;AAAA,QACd,GAAG,KAAK,OAAO;AAAA,QACf,GAAG,OAAO;AAAA,MAAA;AAAA,MAEZ,sBAAsB;AAAA,QACpB,GAAG,KAAK,OAAO;AAAA,QACf,GAAG,OAAO;AAAA,MAAA;AAAA;AAAA,MAGZ,cAAc;AAAA,QACZ,GAAG,KAAK,OAAO;AAAA,QACf,GAAG,OAAO;AAAA,MAAA;AAAA,IACZ;AAIF,QAAI,OAAO,gBAAgB,QAAW;AACpC,mBAAa,UAAU,OAAO,WAAW;AAAA,IAC3C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA4B;AAC1B,UAAM,QAAQ,KAAK,OAAO,eAAe;AACzC,WAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,MAAuB;AACnC,WAAO,KAAK,kBAAkB,SAAS,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,MAA2C;;AAC1D,YAAO,UAAK,OAAO,mBAAZ,mBAA6B;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,QAAoC;;AACzD,YAAO,UAAK,OAAO,yBAAZ,mBAAmC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAqB;AACnB,WAAO,KAAK,OAAO,WAAW;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAqC;AACnC,WAAO,KAAK,OAAO,gBAAgB,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA0D;AACxD,WAAO,KAAK,OAAO,WAAW;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS;AAAA,MACZ,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,gBAAgB,EAAE,GAAG,yBAAA;AAAA,MACrB,sBAAsB,EAAE,GAAG,gCAAA;AAAA,MAC3B,SAAS;AAAA,MACT,cAAc,CAAA;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,IAAA;AAEf,iBAAa,UAAU,MAAS;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAA0C;AACxC,WAAO,KAAK,OAAO;AAAA,EACrB;AACF;AAKO,MAAM,gBAAgB,IAAI,cAAA;ACjD1B,MAAM,qBAAqB,MAAM;AAAA,EAYtC,YAAY,SAOT;AACD,UAAM,QAAQ,OAAO;AAlBvB;AAAA;AAEA;AAAA;AAEA;AAAA;AAEA;AAAA;AAEA;AAAA;AAWE,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,SAAS,QAAQ;AAAA,EACxB;AACF;ACnJA,SAAS,aAAa,OAAqC;AACzD,SACE,OAAO,UAAU,YACjB,UAAU,QACV,kBAAkB,SACjB,MAAqB,iBAAiB;AAE3C;AAKA,SAAS,mBAAmB,UAAiF;AAC3G,SACE,OAAO,aAAa,YACpB,aAAa,QACb,UAAU,YACV,OAAQ,SAA+B,SAAS;AAEpD;AAKA,SAAS,gBAAgB,OAAiC;;AACxD,QAAM,WAAS,WAAM,aAAN,mBAAgB,WAAU;AACzC,QAAM,iBAAiB;AACvB,QAAM,UAAU,cAAc,uBAAuB,MAAM,KAAK;AAEhE,SAAO,IAAI,aAAa;AAAA,IACtB;AAAA,IACA,MAAM;AAAA,IACN,eAAe;AAAA,IACf,aAAa;AAAA,IACb,QAAQ,MAAM;AAAA,EAAA,CACf;AACH;AAyBA,SAAS,mBAAmB,OAAiC;AAC3D,MAAI,UAAU;AACd,MAAI,OAAwB;AAE5B,MAAI,MAAM,SAAS,gBAAgB;AACjC,cAAU;AACV,WAAO;AAAA,EACT,WAAW,MAAM,SAAS,eAAe;AACvC,cAAU;AACV,WAAO;AAAA,EACT,WAAW,MAAM,SAAS,gBAAgB;AACxC,cAAU;AACV,WAAO;AAAA,EACT;AAEA,SAAO,IAAI,aAAa;AAAA,IACtB;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,QAAQ,MAAM;AAAA,EAAA,CACf;AACH;AAKO,SAAS,YAAY,OAA8B;AACxD,MAAI;AAEJ,MAAI,aAAa,KAAK,GAAG;AAEvB,QAAI,MAAM,UAAU;AAClB,qBAAe,gBAAgB,KAAK;AAAA,IACtC,OAAO;AAEL,qBAAe,mBAAmB,KAAK;AAAA,IACzC;AAAA,EACF,WAAW,iBAAiB,cAAc;AACxC,mBAAe;AAAA,EACjB,WAAW,iBAAiB,OAAO;AACjC,mBAAe,IAAI,aAAa;AAAA,MAC9B,SAAS,MAAM;AAAA,MACf,MAAM;AAAA,MACN,eAAe;AAAA,IAAA,CAChB;AAAA,EACH,OAAO;AACL,mBAAe,IAAI,aAAa;AAAA,MAC9B,SAAS;AAAA,MACT,MAAM;AAAA,MACN,eAAe;AAAA,IAAA,CAChB;AAAA,EACH;AAGA,QAAM,eAAe,cAAc,gBAAA;AACnC,MAAI,cAAc;AAChB,QAAI;AACF,mBAAa,YAAY;AAAA,IAC3B,SAAS,GAAG;AACV,cAAQ,MAAM,yBAAyB,CAAC;AAAA,IAC1C;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,kBAAkB,UAAkC;AAClE,QAAM,OAAO,SAAS;AAEtB,MAAI,CAAC,mBAAmB,IAAI,GAAG;AAE7B,WAAO;AAAA,EACT;AAEA,SAAO,cAAc,cAAc,KAAK,IAAI;AAC9C;;ACxIA,SAAS,aAAqB;AAE5B,QAAM,MAAO;AACb,QAAM,SAAS,2BAAK;AAEpB,MAAI,WAAW,QAAW;AACxB,YAAQ,KAAK,iDAAiD;AAC9D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKA,SAAS,oBAAoB,KAA4B;AACvD,QAAM,SAAS,IAAI,gBAAA;AAEnB,SAAO,QAAQ,GAAG,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC5C,QAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,CAAC,SAAS,OAAO,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC;AAAA,IAC1D,OAAO;AACL,aAAO,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,IAClC;AAAA,EACF,CAAC;AAED,SAAO,OAAO,SAAA;AAChB;AAKA,SAAS,SAAS,KAAa,QAAgC;AAC7D,MAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,oBAAoB,MAAM;AAC9C,QAAM,YAAY,IAAI,SAAS,GAAG,IAAI,MAAM;AAE5C,SAAO,GAAG,GAAG,GAAG,SAAS,GAAG,WAAW;AACzC;AAKA,MAAM,aAAa;AAAA,EAGjB,cAAc;AAFN;AAGN,SAAK,WAAW,MAAM,OAAO;AAAA,MAC3B,SAAS,WAAA;AAAA,MACT,SAAS,cAAc,WAAA;AAAA,MACvB,SAAS;AAAA,QACP,gBAAgB;AAAA,MAAA;AAAA,IAClB,CACD;AAED,SAAK,kBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,SAIF;AACA,WAAO;AAAA,MACL,KAAK,CAAC,WAAyB,cAAc,UAAU,MAAM;AAAA,MAC7D,KAAK,MAAM,cAAc,UAAA;AAAA,MACzB,OAAO,MAAM,cAAc,MAAA;AAAA,IAAM;AAAA,EAErC;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAA0B;AAChC,UAAM,eAAe,cAAc,gBAAA;AAGnC,SAAK,SAAS,aAAa,QAAQ;AAAA,MACjC,OAAO,WAAuC;AAE5C,YAAI,aAAa,eAAe,CAAC,aAAa,cAAc,OAAO,OAAO,EAAE,GAAG;AAC7E,gBAAM,aAAa,MAAM,aAAa,gBAAA;AACtC,cAAI,YAAY;AACd,mBAAO,QAAQ,WAAW,GAAG,IAAI,WAAW;AAAA,UAC9C;AAAA,QACF;AAGA,YAAI,aAAa,SAAS;AACxB,iBAAO,aAAa,QAAQ,MAAM;AAAA,QACpC;AACA,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAmB;AAClB,YAAI,aAAa,cAAc;AAC7B,iBAAO,QAAQ,OAAO,aAAa,aAAa,KAAK,CAAC;AAAA,QACxD;AACA,eAAO,QAAQ,OAAO,YAAY,KAAK,CAAC;AAAA,MAC1C;AAAA,IAAA;AAIF,SAAK,SAAS,aAAa,SAAS;AAAA,MAClC,CAAC,aAA4B;AAE3B,YAAI,CAAC,kBAAkB,QAAQ,GAAG;AAChC,iBAAO,QAAQ,OAAO,YAAY,QAAQ,CAAC;AAAA,QAC7C;AAGA,YAAI,aAAa,UAAU;AACzB,iBAAO,aAAa,SAAS,QAAQ;AAAA,QACvC;AAEA,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAmB;AAClB,YAAI,aAAa,eAAe;AAC9B,iBAAO,QAAQ,OAAO,aAAa,cAAc,KAAK,CAAC;AAAA,QACzD;AACA,eAAO,QAAQ,OAAO,YAAY,KAAK,CAAC;AAAA,MAC1C;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAgE;AAC9D,UAAM,aAAa,IAAI,gBAAA;AACvB,WAAO;AAAA,MACL,OAAO,WAAW;AAAA,MAClB,QAAQ,MAAM,WAAW,MAAA;AAAA,IAAM;AAAA,EAEnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IACJ,KACA,QACA,QAC0B;AAC1B,UAAM,UAAU,SAAS,KAAK,MAAM;AAEpC,UAAM,WAAW,MAAM,KAAK,SAAS,IAAqB,SAAS,MAAM;AACzE,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OACJ,KACA,QACA,QAC0B;AAC1B,UAAM,UAAU,SAAS,KAAK,MAAM;AAEpC,UAAM,WAAW,MAAM,KAAK,SAAS,OAAwB,SAAS,MAAM;AAC5E,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KACJ,KACA,MACA,QAC0B;AAC1B,UAAM,WAAW,MAAM,KAAK,SAAS,KAAsB,KAAK,MAAM,MAAM;AAC5E,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IACJ,KACA,MACA,QAC0B;AAC1B,UAAM,WAAW,MAAM,KAAK,SAAS,IAAqB,KAAK,MAAM,MAAM;AAC3E,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MACJ,KACA,MACA,QAC0B;AAC1B,UAAM,WAAW,MAAM,KAAK,SAAS,MAAuB,KAAK,MAAM,MAAM;AAC7E,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SACJ,KACA,MACA,QAC0B;AAC1B,UAAM,WAAW,IAAI,SAAA;AAErB,QAAI,MAAM;AACR,aAAO,QAAQ,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC7C,YAAI,UAAU,UAAa,UAAU,MAAM;AACzC,cAAI,iBAAiB,QAAQ,iBAAiB,MAAM;AAClD,qBAAS,OAAO,KAAK,KAAK;AAAA,UAC5B,OAAO;AACL,qBAAS,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,UACpC;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM,KAAK,SAAS,KAAsB,KAAK,UAAU;AAAA,MACxE,GAAG;AAAA,MACH,SAAS;AAAA,QACP,GAAG,iCAAQ;AAAA,QACX,gBAAgB;AAAA,MAAA;AAAA,IAClB,CACD;AAED,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QACJ,QACA,KACA,cACA,QAC0B;AAC1B,YAAQ,QAAA;AAAA,MACN,KAAK;AACH,eAAO,KAAK,IAAU,KAAK,cAAc,MAAM;AAAA,MACjD,KAAK;AACH,eAAO,KAAK,OAAa,KAAK,cAAc,MAAM;AAAA,MACpD,KAAK;AACH,eAAO,KAAK,KAAW,KAAK,cAAc,MAAM;AAAA,MAClD,KAAK;AACH,eAAO,KAAK,IAAU,KAAK,cAAc,MAAM;AAAA,MACjD,KAAK;AACH,eAAO,KAAK,MAAY,KAAK,cAAc,MAAM;AAAA,MACnD;AACE,cAAM,IAAI,MAAM,uBAAuB,MAAM,EAAE;AAAA,IAAA;AAAA,EAErD;AACF;AAKO,MAAM,UAAU,IAAI,aAAA;"}
|