wangji-request 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/build.js +16 -0
- package/dist/http-client.d.ts +47 -0
- package/dist/http-client.d.ts.map +1 -0
- package/dist/http-client.js +139 -0
- package/dist/http-client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +6 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +12 -0
- package/package.json +56 -0
- package/src/__tests__/http-client.test.ts +72 -0
- package/src/http-client.ts +237 -0
- package/src/index.ts +21 -0
- package/src/types.ts +30 -0
- package/tsconfig.json +21 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Your Name
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# HTTP Client
|
|
2
|
+
|
|
3
|
+
一个轻量级的 HTTP 客户端库,基于 axios 封装,提供简洁的 API 和 TypeScript 类型支持。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install git@github.com:HanWuJiJack/request.git
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
或者使用 yarn:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
yarn add git@github.com:HanWuJiJack/request.git
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 快速开始
|
|
22
|
+
|
|
23
|
+
### 基础用法
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## 许可证
|
|
28
|
+
|
|
29
|
+
MIT
|
|
30
|
+
|
|
31
|
+
## 贡献
|
|
32
|
+
|
|
33
|
+
欢迎提交 issue 和 pull request!
|
|
34
|
+
|
|
35
|
+
## 支持
|
|
36
|
+
|
|
37
|
+
如有问题或建议,请提交 issue。
|
package/build.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
// Create ES module version
|
|
5
|
+
const indexPath = path.join(__dirname, 'dist', 'index.js');
|
|
6
|
+
const indexContent = fs.readFileSync(indexPath, 'utf8');
|
|
7
|
+
|
|
8
|
+
// Transform CommonJS to ESM
|
|
9
|
+
const esmContent = indexContent
|
|
10
|
+
.replace(/^"use strict";?\n?/, '')
|
|
11
|
+
.replace(/Object\.defineProperty\(exports,.*?\{.*?\}\);?\n?/gs, '');
|
|
12
|
+
|
|
13
|
+
const mesmPath = path.join(__dirname, 'dist', 'index.mjs');
|
|
14
|
+
fs.writeFileSync(mesmPath, esmContent);
|
|
15
|
+
|
|
16
|
+
console.log('Build complete: ESM module created at dist/index.mjs');
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AxiosRequestConfig } from 'axios';
|
|
2
|
+
type ErrorCodeMap = Record<string | number, string>;
|
|
3
|
+
interface HttpClientOptions {
|
|
4
|
+
Notification: any;
|
|
5
|
+
Message: any;
|
|
6
|
+
store: any;
|
|
7
|
+
getToken: () => string | null;
|
|
8
|
+
errorCode: ErrorCodeMap;
|
|
9
|
+
MessageDebounce: (msg: string) => void;
|
|
10
|
+
baseURL: string;
|
|
11
|
+
timeout?: number;
|
|
12
|
+
loadingObj?: {
|
|
13
|
+
open: () => void;
|
|
14
|
+
close: () => void;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
interface RequestOptions extends AxiosRequestConfig {
|
|
18
|
+
load?: boolean;
|
|
19
|
+
delayTime?: number;
|
|
20
|
+
time?: number;
|
|
21
|
+
autoCancel?: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface CancelMap {
|
|
24
|
+
[key: string]: (msg?: string) => void;
|
|
25
|
+
}
|
|
26
|
+
declare global {
|
|
27
|
+
interface Window {
|
|
28
|
+
cancelApiMap?: CancelMap;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export default class HttpClient {
|
|
32
|
+
private opts;
|
|
33
|
+
private requestFn;
|
|
34
|
+
private service;
|
|
35
|
+
constructor(opts: HttpClientOptions);
|
|
36
|
+
getRequest(): (options: {
|
|
37
|
+
method?: string;
|
|
38
|
+
url: string;
|
|
39
|
+
data?: any;
|
|
40
|
+
params?: any;
|
|
41
|
+
headers?: any;
|
|
42
|
+
config?: RequestOptions;
|
|
43
|
+
autoCancel?: boolean;
|
|
44
|
+
}) => Promise<any>;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"AAAA,OAAc,EAEZ,kBAAkB,EAGnB,MAAM,OAAO,CAAA;AAEd,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,CAAA;AAEnD,UAAU,iBAAiB;IACzB,YAAY,EAAE,GAAG,CAAA;IACjB,OAAO,EAAE,GAAG,CAAA;IACZ,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAE,YAAY,CAAA;IACvB,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,IAAI,CAAA;QAChB,KAAK,EAAE,MAAM,IAAI,CAAA;KAClB,CAAA;CACF;AAED,UAAU,cAAe,SAAQ,kBAAkB;IACjD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,UAAU,SAAS;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CACtC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,YAAY,CAAC,EAAE,SAAS,CAAA;KACzB;CACF;AAED,MAAM,CAAC,OAAO,OAAO,UAAU;IAajB,OAAO,CAAC,IAAI;IAZxB,OAAO,CAAC,SAAS,CAQC;IAElB,OAAO,CAAC,OAAO,CAAe;gBAEV,IAAI,EAAE,iBAAiB;IAmLpC,UAAU,cA/LY;QAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,GAAG,EAAE,MAAM,CAAA;QACX,IAAI,CAAC,EAAE,GAAG,CAAA;QACV,MAAM,CAAC,EAAE,GAAG,CAAA;QACZ,OAAO,CAAC,EAAE,GAAG,CAAA;QACb,MAAM,CAAC,EAAE,cAAc,CAAA;QACvB,UAAU,CAAC,EAAE,OAAO,CAAA;KACrB,KAAK,OAAO,CAAC,GAAG,CAAC;CA0LnB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import axios from 'axios';
|
|
11
|
+
export default class HttpClient {
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
this.opts = opts;
|
|
14
|
+
const { Notification, Message, store, getToken, errorCode, MessageDebounce, baseURL, timeout = 5000, loadingObj } = opts;
|
|
15
|
+
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
|
|
16
|
+
this.service = axios.create({
|
|
17
|
+
baseURL,
|
|
18
|
+
timeout
|
|
19
|
+
});
|
|
20
|
+
// ================= 请求拦截 =================
|
|
21
|
+
this.service.interceptors.request.use((config) => {
|
|
22
|
+
var _a;
|
|
23
|
+
const isToken = ((_a = config.headers) === null || _a === void 0 ? void 0 : _a.isToken) === false;
|
|
24
|
+
const token = getToken();
|
|
25
|
+
if (token && !isToken) {
|
|
26
|
+
config.headers = Object.assign(Object.assign({}, config.headers), { Authorization: `Bearer ${token}` });
|
|
27
|
+
}
|
|
28
|
+
// GET 参数拼接(保持你原逻辑)
|
|
29
|
+
if (config.method === 'get' && config.params) {
|
|
30
|
+
let url = config.url + '?';
|
|
31
|
+
for (const key of Object.keys(config.params)) {
|
|
32
|
+
const value = config.params[key];
|
|
33
|
+
const part = encodeURIComponent(key) + '=';
|
|
34
|
+
if (value !== null && value !== undefined) {
|
|
35
|
+
if (typeof value === 'object') {
|
|
36
|
+
for (const subKey of Object.keys(value)) {
|
|
37
|
+
const subVal = value[subKey];
|
|
38
|
+
if (subVal !== null && subVal !== undefined) {
|
|
39
|
+
const paramsKey = `${key}[${subKey}]`;
|
|
40
|
+
url +=
|
|
41
|
+
encodeURIComponent(paramsKey) +
|
|
42
|
+
'=' +
|
|
43
|
+
encodeURIComponent(subVal) +
|
|
44
|
+
'&';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
url += part + encodeURIComponent(value) + '&';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
url = url.slice(0, -1);
|
|
54
|
+
config.params = undefined;
|
|
55
|
+
config.url = url;
|
|
56
|
+
}
|
|
57
|
+
return config;
|
|
58
|
+
}, (error) => Promise.reject(error));
|
|
59
|
+
// ================= 响应拦截 =================
|
|
60
|
+
this.service.interceptors.response.use((res) => {
|
|
61
|
+
var _a, _b, _c;
|
|
62
|
+
const code = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.code) !== null && _b !== void 0 ? _b : 200;
|
|
63
|
+
const message = errorCode[code] || ((_c = res.data) === null || _c === void 0 ? void 0 : _c.msg) || errorCode['default'];
|
|
64
|
+
if (code === 401) {
|
|
65
|
+
store.dispatch('LogOut').then(() => {
|
|
66
|
+
window.location.href = '/PI/index';
|
|
67
|
+
});
|
|
68
|
+
return Promise.reject('令牌验证失败');
|
|
69
|
+
}
|
|
70
|
+
if (code === 500) {
|
|
71
|
+
Message({
|
|
72
|
+
message,
|
|
73
|
+
type: 'error'
|
|
74
|
+
});
|
|
75
|
+
return Promise.reject({ message, code });
|
|
76
|
+
}
|
|
77
|
+
if (code !== 200) {
|
|
78
|
+
Notification.error({ title: message });
|
|
79
|
+
return Promise.reject({ message, code });
|
|
80
|
+
}
|
|
81
|
+
return res.data;
|
|
82
|
+
}, (error) => {
|
|
83
|
+
let message = error.message;
|
|
84
|
+
if (message === 'Network Error') {
|
|
85
|
+
message = '后端接口连接异常';
|
|
86
|
+
}
|
|
87
|
+
else if (message.includes('timeout')) {
|
|
88
|
+
message = '系统接口请求超时';
|
|
89
|
+
}
|
|
90
|
+
else if (message.includes('Request failed with status code')) {
|
|
91
|
+
message = `系统接口${message.slice(-3)}异常`;
|
|
92
|
+
}
|
|
93
|
+
MessageDebounce(message);
|
|
94
|
+
return Promise.reject(error);
|
|
95
|
+
});
|
|
96
|
+
// ================= request 包装 =================
|
|
97
|
+
this.requestFn = (_a) => __awaiter(this, [_a], void 0, function* ({ method = 'get', url, data, params, headers, config = {}, autoCancel = false }) {
|
|
98
|
+
const requestMethod = method.toLowerCase();
|
|
99
|
+
if (method === 'post' || config.load) {
|
|
100
|
+
loadingObj === null || loadingObj === void 0 ? void 0 : loadingObj.open();
|
|
101
|
+
}
|
|
102
|
+
// ================= 取消请求 =================
|
|
103
|
+
if (autoCancel) {
|
|
104
|
+
if (!window.cancelApiMap) {
|
|
105
|
+
window.cancelApiMap = {};
|
|
106
|
+
}
|
|
107
|
+
const key = url + method;
|
|
108
|
+
if (window.cancelApiMap[key]) {
|
|
109
|
+
return Promise.reject('阻止进程');
|
|
110
|
+
}
|
|
111
|
+
config.cancelToken = new axios.CancelToken((cancel) => {
|
|
112
|
+
window.cancelApiMap[key] = cancel;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const res = yield this.service(Object.assign({ method: requestMethod, url,
|
|
117
|
+
data,
|
|
118
|
+
params,
|
|
119
|
+
headers }, config));
|
|
120
|
+
const delay = config.time || 1800;
|
|
121
|
+
const result = yield new Promise((resolve) => {
|
|
122
|
+
setTimeout(() => resolve(res), delay);
|
|
123
|
+
});
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
if (method === 'post' || config.load) {
|
|
128
|
+
setTimeout(() => {
|
|
129
|
+
loadingObj === null || loadingObj === void 0 ? void 0 : loadingObj.close();
|
|
130
|
+
}, config.delayTime || 1000);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
getRequest() {
|
|
136
|
+
return this.requestFn;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import HttpClient from './http-client';
|
|
2
|
+
import type { RequestConfig, HttpClientConfig, RequestInterceptor, ResponseInterceptor, ErrorInterceptor } from './types';
|
|
3
|
+
export default HttpClient;
|
|
4
|
+
export { HttpClient, RequestConfig, HttpClientConfig, RequestInterceptor, ResponseInterceptor, ErrorInterceptor, };
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,eAAe,CAAC;AACvC,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAGjB,eAAe,UAAU,CAAC;AAG1B,OAAO,EACL,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GACjB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,eAAe,CAAC;AASvC,iBAAiB;AACjB,eAAe,UAAU,CAAC;AAE1B,gBAAgB;AAChB,OAAO,EACL,UAAU,GAMX,CAAC"}
|
package/dist/index.mjs
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
+
export interface RequestConfig extends AxiosRequestConfig {
|
|
3
|
+
showLoading?: boolean;
|
|
4
|
+
showError?: boolean;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface HttpClientConfig {
|
|
8
|
+
baseURL?: string;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
interceptors?: {
|
|
12
|
+
request?: (config: AxiosRequestConfig) => AxiosRequestConfig;
|
|
13
|
+
response?: (response: AxiosResponse) => AxiosResponse;
|
|
14
|
+
error?: (error: any) => Promise<any>;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface RequestInterceptor {
|
|
18
|
+
(config: AxiosRequestConfig): AxiosRequestConfig;
|
|
19
|
+
}
|
|
20
|
+
export interface ResponseInterceptor {
|
|
21
|
+
(response: AxiosResponse): AxiosResponse;
|
|
22
|
+
}
|
|
23
|
+
export interface ErrorInterceptor {
|
|
24
|
+
(error: any): Promise<any>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE1D,MAAM,WAAW,aAAc,SAAQ,kBAAkB;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE;QACb,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,kBAAkB,CAAC;QAC7D,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,aAAa,CAAC;QACtD,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;KACtC,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CAAC;CAClD;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAAC;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CAC5B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
preset: 'ts-jest',
|
|
3
|
+
testEnvironment: 'node',
|
|
4
|
+
roots: ['<rootDir>/src'],
|
|
5
|
+
testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
|
|
6
|
+
collectCoverageFrom: [
|
|
7
|
+
'src/**/*.ts',
|
|
8
|
+
'!src/**/*.d.ts',
|
|
9
|
+
'!src/**/index.ts',
|
|
10
|
+
],
|
|
11
|
+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
|
12
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wangji-request",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight HTTP client wrapper based on axios",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc && node build.js",
|
|
16
|
+
"prebuild": "npm run clean",
|
|
17
|
+
"clean": "rm -rf dist",
|
|
18
|
+
"test": "jest",
|
|
19
|
+
"prepare": "npm run build",
|
|
20
|
+
"prepublishOnly": "npm run build",
|
|
21
|
+
"version": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"http",
|
|
25
|
+
"axios",
|
|
26
|
+
"request",
|
|
27
|
+
"client",
|
|
28
|
+
"api"
|
|
29
|
+
],
|
|
30
|
+
"author": "Your Name",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/your-username/http-client"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/your-username/http-client/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/your-username/http-client#readme",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"axios": "^0.21.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/jest": "^29.5.0",
|
|
45
|
+
"@types/node": "^20.0.0",
|
|
46
|
+
"jest": "^29.5.0",
|
|
47
|
+
"ts-jest": "^29.1.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=14.0.0"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import HttpClient from '../http-client';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
|
|
4
|
+
jest.mock('axios');
|
|
5
|
+
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
|
6
|
+
|
|
7
|
+
describe('HttpClient', () => {
|
|
8
|
+
let client: HttpClient;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
jest.clearAllMocks();
|
|
12
|
+
mockedAxios.create.mockReturnValue({
|
|
13
|
+
get: jest.fn(),
|
|
14
|
+
post: jest.fn(),
|
|
15
|
+
put: jest.fn(),
|
|
16
|
+
patch: jest.fn(),
|
|
17
|
+
delete: jest.fn(),
|
|
18
|
+
head: jest.fn(),
|
|
19
|
+
options: jest.fn(),
|
|
20
|
+
defaults: {
|
|
21
|
+
headers: { common: {} },
|
|
22
|
+
},
|
|
23
|
+
interceptors: {
|
|
24
|
+
request: { use: jest.fn() },
|
|
25
|
+
response: { use: jest.fn() },
|
|
26
|
+
},
|
|
27
|
+
} as any);
|
|
28
|
+
client = new HttpClient();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should create an instance', () => {
|
|
32
|
+
expect(client).toBeTruthy();
|
|
33
|
+
expect(mockedAxios.create).toHaveBeenCalled();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should initialize with custom config', () => {
|
|
37
|
+
const customConfig = {
|
|
38
|
+
baseURL: 'https://api.example.com',
|
|
39
|
+
timeout: 5000,
|
|
40
|
+
};
|
|
41
|
+
new HttpClient(customConfig);
|
|
42
|
+
expect(mockedAxios.create).toHaveBeenCalledWith(
|
|
43
|
+
expect.objectContaining({
|
|
44
|
+
baseURL: customConfig.baseURL,
|
|
45
|
+
timeout: customConfig.timeout,
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should have all HTTP methods', () => {
|
|
51
|
+
expect(typeof client.get).toBe('function');
|
|
52
|
+
expect(typeof client.post).toBe('function');
|
|
53
|
+
expect(typeof client.put).toBe('function');
|
|
54
|
+
expect(typeof client.patch).toBe('function');
|
|
55
|
+
expect(typeof client.delete).toBe('function');
|
|
56
|
+
expect(typeof client.head).toBe('function');
|
|
57
|
+
expect(typeof client.options).toBe('function');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should provide setToken method', () => {
|
|
61
|
+
expect(typeof client.setToken).toBe('function');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should provide clearToken method', () => {
|
|
65
|
+
expect(typeof client.clearToken).toBe('function');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should expose axios instance', () => {
|
|
69
|
+
const instance = client.getAxiosInstance();
|
|
70
|
+
expect(instance).toBeDefined();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import axios, {
|
|
2
|
+
AxiosInstance,
|
|
3
|
+
AxiosRequestConfig,
|
|
4
|
+
AxiosResponse,
|
|
5
|
+
CancelTokenSource
|
|
6
|
+
} from 'axios'
|
|
7
|
+
|
|
8
|
+
type ErrorCodeMap = Record<string | number, string>
|
|
9
|
+
|
|
10
|
+
interface HttpClientOptions {
|
|
11
|
+
Notification: any
|
|
12
|
+
Message: any
|
|
13
|
+
store: any
|
|
14
|
+
getToken: () => string | null
|
|
15
|
+
errorCode: ErrorCodeMap
|
|
16
|
+
MessageDebounce: (msg: string) => void
|
|
17
|
+
baseURL: string
|
|
18
|
+
timeout?: number
|
|
19
|
+
loadingObj?: {
|
|
20
|
+
open: () => void
|
|
21
|
+
close: () => void
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface RequestOptions extends AxiosRequestConfig {
|
|
26
|
+
load?: boolean
|
|
27
|
+
delayTime?: number
|
|
28
|
+
time?: number
|
|
29
|
+
autoCancel?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface CancelMap {
|
|
33
|
+
[key: string]: (msg?: string) => void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare global {
|
|
37
|
+
interface Window {
|
|
38
|
+
cancelApiMap?: CancelMap
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default class HttpClient {
|
|
43
|
+
private requestFn: (options: {
|
|
44
|
+
method?: string
|
|
45
|
+
url: string
|
|
46
|
+
data?: any
|
|
47
|
+
params?: any
|
|
48
|
+
headers?: any
|
|
49
|
+
config?: RequestOptions
|
|
50
|
+
autoCancel?: boolean
|
|
51
|
+
}) => Promise<any>
|
|
52
|
+
|
|
53
|
+
private service: AxiosInstance
|
|
54
|
+
|
|
55
|
+
constructor(private opts: HttpClientOptions) {
|
|
56
|
+
const {
|
|
57
|
+
Notification,
|
|
58
|
+
Message,
|
|
59
|
+
store,
|
|
60
|
+
getToken,
|
|
61
|
+
errorCode,
|
|
62
|
+
MessageDebounce,
|
|
63
|
+
baseURL,
|
|
64
|
+
timeout = 5000,
|
|
65
|
+
loadingObj
|
|
66
|
+
} = opts
|
|
67
|
+
|
|
68
|
+
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
|
|
69
|
+
|
|
70
|
+
this.service = axios.create({
|
|
71
|
+
baseURL,
|
|
72
|
+
timeout
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// ================= 请求拦截 =================
|
|
76
|
+
this.service.interceptors.request.use(
|
|
77
|
+
(config: AxiosRequestConfig & any) => {
|
|
78
|
+
const isToken = config.headers?.isToken === false
|
|
79
|
+
|
|
80
|
+
const token = getToken()
|
|
81
|
+
if (token && !isToken) {
|
|
82
|
+
config.headers = {
|
|
83
|
+
...config.headers,
|
|
84
|
+
Authorization: `Bearer ${token}`
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// GET 参数拼接(保持你原逻辑)
|
|
89
|
+
if (config.method === 'get' && config.params) {
|
|
90
|
+
let url = config.url + '?'
|
|
91
|
+
|
|
92
|
+
for (const key of Object.keys(config.params)) {
|
|
93
|
+
const value = config.params[key]
|
|
94
|
+
|
|
95
|
+
const part = encodeURIComponent(key) + '='
|
|
96
|
+
|
|
97
|
+
if (value !== null && value !== undefined) {
|
|
98
|
+
if (typeof value === 'object') {
|
|
99
|
+
for (const subKey of Object.keys(value)) {
|
|
100
|
+
const subVal = value[subKey]
|
|
101
|
+
if (subVal !== null && subVal !== undefined) {
|
|
102
|
+
const paramsKey = `${key}[${subKey}]`
|
|
103
|
+
url +=
|
|
104
|
+
encodeURIComponent(paramsKey) +
|
|
105
|
+
'=' +
|
|
106
|
+
encodeURIComponent(subVal) +
|
|
107
|
+
'&'
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
url += part + encodeURIComponent(value) + '&'
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
url = url.slice(0, -1)
|
|
117
|
+
config.params = undefined
|
|
118
|
+
config.url = url
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return config
|
|
122
|
+
},
|
|
123
|
+
(error) => Promise.reject(error)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
// ================= 响应拦截 =================
|
|
127
|
+
this.service.interceptors.response.use(
|
|
128
|
+
(res: AxiosResponse<any>) => {
|
|
129
|
+
const code = res.data?.code ?? 200
|
|
130
|
+
const message =
|
|
131
|
+
errorCode[code] || res.data?.msg || errorCode['default']
|
|
132
|
+
|
|
133
|
+
if (code === 401) {
|
|
134
|
+
store.dispatch('LogOut').then(() => {
|
|
135
|
+
window.location.href = '/PI/index'
|
|
136
|
+
})
|
|
137
|
+
return Promise.reject('令牌验证失败')
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (code === 500) {
|
|
141
|
+
Message({
|
|
142
|
+
message,
|
|
143
|
+
type: 'error'
|
|
144
|
+
})
|
|
145
|
+
return Promise.reject({ message, code })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (code !== 200) {
|
|
149
|
+
Notification.error({ title: message })
|
|
150
|
+
return Promise.reject({ message, code })
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return res.data
|
|
154
|
+
},
|
|
155
|
+
(error) => {
|
|
156
|
+
let message: string = error.message
|
|
157
|
+
|
|
158
|
+
if (message === 'Network Error') {
|
|
159
|
+
message = '后端接口连接异常'
|
|
160
|
+
} else if (message.includes('timeout')) {
|
|
161
|
+
message = '系统接口请求超时'
|
|
162
|
+
} else if (message.includes('Request failed with status code')) {
|
|
163
|
+
message = `系统接口${message.slice(-3)}异常`
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
MessageDebounce(message)
|
|
167
|
+
return Promise.reject(error)
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
// ================= request 包装 =================
|
|
172
|
+
this.requestFn = async ({
|
|
173
|
+
method = 'get',
|
|
174
|
+
url,
|
|
175
|
+
data,
|
|
176
|
+
params,
|
|
177
|
+
headers,
|
|
178
|
+
config = {},
|
|
179
|
+
autoCancel = false
|
|
180
|
+
}) => {
|
|
181
|
+
const requestMethod =
|
|
182
|
+
method.toLowerCase() as AxiosRequestConfig['method']
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if (method === 'post' || config.load) {
|
|
187
|
+
loadingObj?.open()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ================= 取消请求 =================
|
|
191
|
+
if (autoCancel) {
|
|
192
|
+
if (!window.cancelApiMap) {
|
|
193
|
+
window.cancelApiMap = {}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const key = url + method
|
|
197
|
+
|
|
198
|
+
if (window.cancelApiMap[key]) {
|
|
199
|
+
return Promise.reject('阻止进程')
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
config.cancelToken = new axios.CancelToken((cancel) => {
|
|
203
|
+
window.cancelApiMap![key] = cancel
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
const res = await this.service({
|
|
209
|
+
method: requestMethod,
|
|
210
|
+
url,
|
|
211
|
+
data,
|
|
212
|
+
params,
|
|
213
|
+
headers,
|
|
214
|
+
...config
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
const delay = config.time || 1800
|
|
218
|
+
|
|
219
|
+
const result = await new Promise((resolve) => {
|
|
220
|
+
setTimeout(() => resolve(res), delay)
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
return result
|
|
224
|
+
} finally {
|
|
225
|
+
if (method === 'post' || config.load) {
|
|
226
|
+
setTimeout(() => {
|
|
227
|
+
loadingObj?.close()
|
|
228
|
+
}, config.delayTime || 1000)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
public getRequest() {
|
|
235
|
+
return this.requestFn
|
|
236
|
+
}
|
|
237
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import HttpClient from './http-client';
|
|
2
|
+
import type {
|
|
3
|
+
RequestConfig,
|
|
4
|
+
HttpClientConfig,
|
|
5
|
+
RequestInterceptor,
|
|
6
|
+
ResponseInterceptor,
|
|
7
|
+
ErrorInterceptor,
|
|
8
|
+
} from './types';
|
|
9
|
+
|
|
10
|
+
// Default export
|
|
11
|
+
export default HttpClient;
|
|
12
|
+
|
|
13
|
+
// Named exports
|
|
14
|
+
export {
|
|
15
|
+
HttpClient,
|
|
16
|
+
RequestConfig,
|
|
17
|
+
HttpClientConfig,
|
|
18
|
+
RequestInterceptor,
|
|
19
|
+
ResponseInterceptor,
|
|
20
|
+
ErrorInterceptor,
|
|
21
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
+
|
|
3
|
+
export interface RequestConfig extends AxiosRequestConfig {
|
|
4
|
+
showLoading?: boolean;
|
|
5
|
+
showError?: boolean;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface HttpClientConfig {
|
|
10
|
+
baseURL?: string;
|
|
11
|
+
timeout?: number;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
interceptors?: {
|
|
14
|
+
request?: (config: AxiosRequestConfig) => AxiosRequestConfig;
|
|
15
|
+
response?: (response: AxiosResponse) => AxiosResponse;
|
|
16
|
+
error?: (error: any) => Promise<any>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RequestInterceptor {
|
|
21
|
+
(config: AxiosRequestConfig): AxiosRequestConfig;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ResponseInterceptor {
|
|
25
|
+
(response: AxiosResponse): AxiosResponse;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ErrorInterceptor {
|
|
29
|
+
(error: any): Promise<any>;
|
|
30
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2015",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ESNext", "DOM"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"moduleResolution": "Node",
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"allowSyntheticDefaultImports": true
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"],
|
|
20
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
21
|
+
}
|