@blueking/chat-helper 0.0.2 → 0.0.3
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/http/fetch/fetch.d.ts +3 -0
- package/dist/http/fetch/fetch.ts.js +6 -47
- package/dist/http/fetch/index.ts.js +118 -4
- package/dist/type.d.ts +2 -0
- package/package.json +1 -1
|
@@ -3,11 +3,14 @@ export interface ApiResponse<T = unknown> {
|
|
|
3
3
|
data: T;
|
|
4
4
|
message: string;
|
|
5
5
|
}
|
|
6
|
+
/** 单次请求配置,优先级高于 `requestData` 全局默认值 */
|
|
6
7
|
export interface IRequestConfig {
|
|
7
8
|
baseURL?: string;
|
|
8
9
|
controller?: AbortController;
|
|
9
10
|
credentials?: 'include' | 'omit' | 'same-origin';
|
|
11
|
+
/** 请求体;可传函数以便延迟求值(在 `prepareRequest` 中通过 `getValue` 解析) */
|
|
10
12
|
data?: (() => unknown) | unknown;
|
|
13
|
+
/** 请求头;可传函数以便延迟求值,便于动态注入(如 token) */
|
|
11
14
|
headers?: (() => Record<string, string>) | Record<string, string>;
|
|
12
15
|
method?: string;
|
|
13
16
|
mode?: 'cors' | 'no-cors' | 'same-origin';
|
|
@@ -132,7 +132,6 @@ class InterceptorManager {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
export class FetchClient {
|
|
135
|
-
// 应用响应拦截器的错误处理
|
|
136
135
|
applyResponseErrorInterceptors(error) {
|
|
137
136
|
let rejectedError = error;
|
|
138
137
|
this.interceptors.response.forEach((interceptor)=>{
|
|
@@ -142,7 +141,6 @@ export class FetchClient {
|
|
|
142
141
|
});
|
|
143
142
|
return rejectedError;
|
|
144
143
|
}
|
|
145
|
-
// 创建新实例
|
|
146
144
|
create(config) {
|
|
147
145
|
return new FetchClient(mergeConfig(this.defaults, config || {}));
|
|
148
146
|
}
|
|
@@ -188,13 +186,9 @@ export class FetchClient {
|
|
|
188
186
|
data
|
|
189
187
|
}));
|
|
190
188
|
}
|
|
191
|
-
// 准备请求:合并配置、应用拦截器、构建 URL 和请求体
|
|
192
189
|
prepareRequest(config, isStream = false) {
|
|
193
|
-
// 合并配置
|
|
194
190
|
const mergedConfig = mergeConfig(this.defaults, config);
|
|
195
|
-
// 总的请求配置
|
|
196
191
|
let requestConfig = mergedConfig;
|
|
197
|
-
// 应用请求拦截器
|
|
198
192
|
this.interceptors.request.forEach((interceptor)=>{
|
|
199
193
|
if (interceptor.fulfilled) {
|
|
200
194
|
try {
|
|
@@ -207,20 +201,16 @@ export class FetchClient {
|
|
|
207
201
|
}
|
|
208
202
|
}
|
|
209
203
|
});
|
|
210
|
-
// 构建完整 URL
|
|
211
204
|
let url = requestConfig.url || '';
|
|
212
205
|
if (requestConfig.baseURL && !url.startsWith('http')) {
|
|
213
206
|
url = requestConfig.baseURL + url;
|
|
214
207
|
}
|
|
215
208
|
url = buildURL(url, requestConfig.params);
|
|
216
|
-
// 处理请求体
|
|
217
209
|
let body = getValue(requestConfig.data);
|
|
218
210
|
const headers = new Headers(getValue(requestConfig.headers));
|
|
219
|
-
// 流式请求设置 Accept 头
|
|
220
211
|
if (isStream && !headers.has('Accept')) {
|
|
221
212
|
headers.set('Accept', 'text/event-stream');
|
|
222
213
|
}
|
|
223
|
-
// 处理请求体
|
|
224
214
|
if (body !== undefined && body !== null) {
|
|
225
215
|
var _headers_get;
|
|
226
216
|
if (requestConfig.transformRequest) {
|
|
@@ -229,9 +219,8 @@ export class FetchClient {
|
|
|
229
219
|
body = JSON.stringify(body);
|
|
230
220
|
}
|
|
231
221
|
}
|
|
232
|
-
|
|
233
|
-
const controller = requestConfig.controller ?
|
|
234
|
-
// 请求配置
|
|
222
|
+
var _requestConfig_controller;
|
|
223
|
+
const controller = (_requestConfig_controller = requestConfig.controller) !== null && _requestConfig_controller !== void 0 ? _requestConfig_controller : new AbortController();
|
|
235
224
|
const fetchConfig = {
|
|
236
225
|
method: requestConfig.method,
|
|
237
226
|
credentials: requestConfig.credentials,
|
|
@@ -257,18 +246,13 @@ export class FetchClient {
|
|
|
257
246
|
request(config) {
|
|
258
247
|
var _this = this;
|
|
259
248
|
return _async_to_generator(function*() {
|
|
260
|
-
// 准备请求
|
|
261
249
|
const { url, fetchConfig, requestConfig, controller } = _this.prepareRequest(config);
|
|
262
|
-
// 创建超时控制
|
|
263
250
|
const timeoutId = requestConfig.timeout && requestConfig.timeout > 0 ? setTimeout(()=>controller.abort(), requestConfig.timeout) : undefined;
|
|
264
251
|
try {
|
|
265
|
-
// 发送请求
|
|
266
252
|
const fetchResponse = yield fetch(url, fetchConfig);
|
|
267
|
-
// 清除超时定时器
|
|
268
253
|
if (timeoutId) {
|
|
269
254
|
clearTimeout(timeoutId);
|
|
270
255
|
}
|
|
271
|
-
// 解析响应数据
|
|
272
256
|
let data;
|
|
273
257
|
const responseType = requestConfig.responseType || 'json';
|
|
274
258
|
try {
|
|
@@ -294,11 +278,9 @@ export class FetchClient {
|
|
|
294
278
|
} catch (_error) {
|
|
295
279
|
data = null;
|
|
296
280
|
}
|
|
297
|
-
// 应用响应转换
|
|
298
281
|
if (requestConfig.transformResponse) {
|
|
299
282
|
data = requestConfig.transformResponse(data);
|
|
300
283
|
}
|
|
301
|
-
// 构建响应对象
|
|
302
284
|
const response = {
|
|
303
285
|
data: data,
|
|
304
286
|
status: fetchResponse.status,
|
|
@@ -306,14 +288,12 @@ export class FetchClient {
|
|
|
306
288
|
headers: fetchResponse.headers,
|
|
307
289
|
config: requestConfig
|
|
308
290
|
};
|
|
309
|
-
// 验证状态码
|
|
310
291
|
const validateStatus = requestConfig.validateStatus || _this.defaults.validateStatus;
|
|
311
292
|
if (!validateStatus(fetchResponse.status)) {
|
|
312
293
|
var _response_data_error, _response_data;
|
|
313
294
|
const message = ((_response_data = response.data) === null || _response_data === void 0 ? void 0 : (_response_data_error = _response_data.error) === null || _response_data_error === void 0 ? void 0 : _response_data_error.message) || `Request failed with status code ${fetchResponse.status}`;
|
|
314
295
|
throw createError(message, requestConfig, `ERR_BAD_RESPONSE`, response);
|
|
315
296
|
}
|
|
316
|
-
// 应用响应拦截器
|
|
317
297
|
let finalResponse = response;
|
|
318
298
|
_this.interceptors.response.forEach((interceptor)=>{
|
|
319
299
|
if (interceptor.fulfilled) {
|
|
@@ -327,11 +307,10 @@ export class FetchClient {
|
|
|
327
307
|
}
|
|
328
308
|
}
|
|
329
309
|
});
|
|
330
|
-
// 等待所有异步拦截器完成
|
|
331
310
|
if (finalResponse instanceof Promise) {
|
|
332
311
|
finalResponse = yield finalResponse;
|
|
333
312
|
}
|
|
334
|
-
//
|
|
313
|
+
// 检查业务状态码(区别于 HTTP 状态码)
|
|
335
314
|
const apiResponse = finalResponse.data;
|
|
336
315
|
if (![
|
|
337
316
|
0,
|
|
@@ -341,39 +320,30 @@ export class FetchClient {
|
|
|
341
320
|
}
|
|
342
321
|
return apiResponse.data;
|
|
343
322
|
} catch (error) {
|
|
344
|
-
// 清除超时定时器
|
|
345
323
|
if (timeoutId) {
|
|
346
324
|
clearTimeout(timeoutId);
|
|
347
325
|
}
|
|
348
|
-
// 处理中断错误
|
|
349
326
|
if (error instanceof Error && error.name === 'AbortError') {
|
|
350
327
|
const requestError = createError('Request timeout', requestConfig, 'ECONNABORTED', undefined);
|
|
351
328
|
throw _this.applyResponseErrorInterceptors(requestError);
|
|
352
329
|
}
|
|
353
|
-
// 处理其他错误
|
|
354
330
|
const requestError = error.isAxiosError === true ? error : createError(error.message, requestConfig, error.code, undefined);
|
|
355
331
|
throw _this.applyResponseErrorInterceptors(requestError);
|
|
356
332
|
}
|
|
357
333
|
})();
|
|
358
334
|
}
|
|
359
|
-
// SSE 流式请求便捷方法
|
|
360
335
|
stream(url, config) {
|
|
361
336
|
return this.streamRequest(_object_spread_props(_object_spread({}, config), {
|
|
362
337
|
url
|
|
363
338
|
}));
|
|
364
339
|
}
|
|
365
|
-
// SSE 流式请求
|
|
366
340
|
streamRequest(config) {
|
|
367
341
|
var _this = this;
|
|
368
342
|
return _async_to_generator(function*() {
|
|
369
|
-
// 准备请求(标记为流式请求)
|
|
370
343
|
const { url, fetchConfig, requestConfig } = _this.prepareRequest(config, true);
|
|
371
344
|
try {
|
|
372
|
-
var
|
|
373
|
-
_config_onStart, _fetchResponse_body;
|
|
374
|
-
// 发送请求
|
|
345
|
+
var _config_onStart, _fetchResponse_body;
|
|
375
346
|
const fetchResponse = yield fetch(url, fetchConfig);
|
|
376
|
-
// 验证状态码
|
|
377
347
|
const validateStatus = requestConfig.validateStatus || _this.defaults.validateStatus;
|
|
378
348
|
if (!validateStatus(fetchResponse.status)) {
|
|
379
349
|
var _config_onError;
|
|
@@ -392,7 +362,6 @@ export class FetchClient {
|
|
|
392
362
|
return;
|
|
393
363
|
}
|
|
394
364
|
(_config_onStart = config.onStart) === null || _config_onStart === void 0 ? void 0 : _config_onStart.call(config);
|
|
395
|
-
// 获取 reader
|
|
396
365
|
const reader = (_fetchResponse_body = fetchResponse.body) === null || _fetchResponse_body === void 0 ? void 0 : _fetchResponse_body.pipeThrough(new window.TextDecoderStream()).getReader();
|
|
397
366
|
if (!reader) {
|
|
398
367
|
var _config_onError1;
|
|
@@ -400,9 +369,8 @@ export class FetchClient {
|
|
|
400
369
|
(_config_onError1 = config.onError) === null || _config_onError1 === void 0 ? void 0 : _config_onError1.call(config, error);
|
|
401
370
|
return;
|
|
402
371
|
}
|
|
403
|
-
//
|
|
372
|
+
// 缓存跨行分片数据
|
|
404
373
|
let temp = '';
|
|
405
|
-
// 判断是否为 JSON 字符串
|
|
406
374
|
const isJson = (str)=>{
|
|
407
375
|
try {
|
|
408
376
|
JSON.parse(str);
|
|
@@ -414,7 +382,6 @@ export class FetchClient {
|
|
|
414
382
|
// eslint-disable-next-line no-constant-condition
|
|
415
383
|
while(true){
|
|
416
384
|
const { value, done } = yield reader.read();
|
|
417
|
-
// 接口完成
|
|
418
385
|
if (done) {
|
|
419
386
|
var _config_onDone;
|
|
420
387
|
(_config_onDone = config.onDone) === null || _config_onDone === void 0 ? void 0 : _config_onDone.call(config);
|
|
@@ -467,7 +434,6 @@ export class FetchClient {
|
|
|
467
434
|
};
|
|
468
435
|
}
|
|
469
436
|
}
|
|
470
|
-
// 构建完整 URL
|
|
471
437
|
function buildURL(url, params) {
|
|
472
438
|
if (!params) return url;
|
|
473
439
|
const searchParams = new URLSearchParams();
|
|
@@ -488,7 +454,6 @@ function buildURL(url, params) {
|
|
|
488
454
|
}
|
|
489
455
|
return url;
|
|
490
456
|
}
|
|
491
|
-
// 创建错误对象
|
|
492
457
|
function createError(message, config, code, response) {
|
|
493
458
|
const error = new Error(message);
|
|
494
459
|
error.config = config;
|
|
@@ -497,22 +462,18 @@ function createError(message, config, code, response) {
|
|
|
497
462
|
error.isAxiosError = true;
|
|
498
463
|
return error;
|
|
499
464
|
}
|
|
500
|
-
// 获取值
|
|
501
465
|
function getValue(value) {
|
|
502
466
|
return typeof value === 'function' ? value() : value;
|
|
503
467
|
}
|
|
504
|
-
|
|
505
|
-
function isPlainObject(value) {
|
|
468
|
+
/** 排除 AbortController、Headers 等类实例,只对普通对象深度合并 */ function isPlainObject(value) {
|
|
506
469
|
if (!value || typeof value !== 'object') return false;
|
|
507
470
|
const proto = Object.getPrototypeOf(value);
|
|
508
471
|
return proto === Object.prototype || proto === null;
|
|
509
472
|
}
|
|
510
|
-
// 合并配置
|
|
511
473
|
function mergeConfig(config1, config2) {
|
|
512
474
|
const output = _object_spread({}, config1);
|
|
513
475
|
for(const key in config2){
|
|
514
476
|
const value2 = config2[key];
|
|
515
|
-
// 只对普通对象进行深度合并,类实例(如 AbortController)直接赋值
|
|
516
477
|
if (isPlainObject(value2)) {
|
|
517
478
|
const value1 = config1[key];
|
|
518
479
|
output[key] = mergeConfig(value1 || {}, value2);
|
|
@@ -522,7 +483,5 @@ function mergeConfig(config1, config2) {
|
|
|
522
483
|
}
|
|
523
484
|
return output;
|
|
524
485
|
}
|
|
525
|
-
// 创建默认实例
|
|
526
486
|
const fetchClient = new FetchClient();
|
|
527
|
-
// 导出默认实例
|
|
528
487
|
export default fetchClient;
|
|
@@ -22,13 +22,127 @@
|
|
|
22
22
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
23
23
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
24
24
|
* IN THE SOFTWARE.
|
|
25
|
-
*/
|
|
25
|
+
*/ function _define_property(obj, key, value) {
|
|
26
|
+
if (key in obj) {
|
|
27
|
+
Object.defineProperty(obj, key, {
|
|
28
|
+
value: value,
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
obj[key] = value;
|
|
35
|
+
}
|
|
36
|
+
return obj;
|
|
37
|
+
}
|
|
38
|
+
function _object_spread(target) {
|
|
39
|
+
for(var i = 1; i < arguments.length; i++){
|
|
40
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
41
|
+
var ownKeys = Object.keys(source);
|
|
42
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
43
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
44
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
ownKeys.forEach(function(key) {
|
|
48
|
+
_define_property(target, key, source[key]);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return target;
|
|
52
|
+
}
|
|
53
|
+
function ownKeys(object, enumerableOnly) {
|
|
54
|
+
var keys = Object.keys(object);
|
|
55
|
+
if (Object.getOwnPropertySymbols) {
|
|
56
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
57
|
+
if (enumerableOnly) {
|
|
58
|
+
symbols = symbols.filter(function(sym) {
|
|
59
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
keys.push.apply(keys, symbols);
|
|
63
|
+
}
|
|
64
|
+
return keys;
|
|
65
|
+
}
|
|
66
|
+
function _object_spread_props(target, source) {
|
|
67
|
+
source = source != null ? source : {};
|
|
68
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
69
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
70
|
+
} else {
|
|
71
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
72
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return target;
|
|
76
|
+
}
|
|
77
|
+
import { FetchClient } from './fetch.ts.js';
|
|
78
|
+
/** 仅支持 body 的 HTTP 方法 */ const BODY_METHODS = new Set([
|
|
79
|
+
'POST',
|
|
80
|
+
'PUT',
|
|
81
|
+
'PATCH',
|
|
82
|
+
'DELETE'
|
|
83
|
+
]);
|
|
84
|
+
/** 排除 FormData / Blob / ArrayBuffer 等,只对普通对象展开合并 */ function isPlainObject(value) {
|
|
85
|
+
if (!value || typeof value !== 'object') return false;
|
|
86
|
+
const proto = Object.getPrototypeOf(value);
|
|
87
|
+
return proto === Object.prototype || proto === null;
|
|
88
|
+
}
|
|
89
|
+
/** 解析「函数 | 值」两种形式,支持延迟求值(如响应式 token) */ function resolveValue(value) {
|
|
90
|
+
return typeof value === 'function' ? value() : value;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 注册全局默认请求配置拦截器,将 `requestData.headers/data` 自动合并到每次请求。
|
|
94
|
+
* - `headers` 注入所有请求;`data` 仅注入 POST/PUT/PATCH/DELETE,避免 GET/HEAD body 报错。
|
|
95
|
+
* - 优先级最低(单次 IRequestConfig > 用户拦截器 > 本拦截器)。
|
|
96
|
+
*/ function registerRequestDataInterceptor(client, opts) {
|
|
97
|
+
const { headers: extraHeadersFn, data: extraDataFn } = opts.requestData;
|
|
98
|
+
if (!extraHeadersFn && !extraDataFn) return;
|
|
99
|
+
client.interceptors.request.use((config)=>{
|
|
100
|
+
let result = config;
|
|
101
|
+
if (extraHeadersFn) {
|
|
102
|
+
const extra = resolveValue(extraHeadersFn);
|
|
103
|
+
if (extra && Object.keys(extra).length > 0) {
|
|
104
|
+
var _resolveValue;
|
|
105
|
+
const existing = (_resolveValue = resolveValue(config.headers)) !== null && _resolveValue !== void 0 ? _resolveValue : {};
|
|
106
|
+
result = _object_spread_props(_object_spread({}, result), {
|
|
107
|
+
headers: _object_spread({}, existing, extra)
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
var _config_method;
|
|
112
|
+
const method = ((_config_method = config.method) !== null && _config_method !== void 0 ? _config_method : 'GET').toUpperCase();
|
|
113
|
+
if (extraDataFn && BODY_METHODS.has(method)) {
|
|
114
|
+
const extra = resolveValue(extraDataFn);
|
|
115
|
+
if (extra && Object.keys(extra).length > 0) {
|
|
116
|
+
const existing = resolveValue(config.data);
|
|
117
|
+
if (existing == null) {
|
|
118
|
+
// body 为空(如 clearSession POST undefined):直接用 extra 作为 body
|
|
119
|
+
result = _object_spread_props(_object_spread({}, result), {
|
|
120
|
+
data: extra
|
|
121
|
+
});
|
|
122
|
+
} else if (isPlainObject(existing)) {
|
|
123
|
+
// body 是普通对象:浅合并,extra 字段优先级更低(existing 已有同名字段时保留)
|
|
124
|
+
result = _object_spread_props(_object_spread({}, result), {
|
|
125
|
+
data: _object_spread({}, extra, existing)
|
|
126
|
+
});
|
|
127
|
+
} else {
|
|
128
|
+
// body 是 FormData / Blob / string 等:跳过注入,避免破坏原始 body
|
|
129
|
+
console.warn('[chat-helper] requestData.data 无法注入:当前请求体不是普通对象(FormData/Blob/string 等),已跳过合并。', {
|
|
130
|
+
method,
|
|
131
|
+
existingType: typeof existing
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return result;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
26
139
|
export const useFetch = (options)=>{
|
|
27
140
|
var _options_interceptors, _options_interceptors1;
|
|
28
141
|
const fetchClient = new FetchClient({
|
|
29
142
|
baseURL: options.requestData.urlPrefix
|
|
30
143
|
});
|
|
31
|
-
//
|
|
144
|
+
// 先注册默认拦截器(优先级低),再注册用户拦截器(优先级高)
|
|
145
|
+
registerRequestDataInterceptor(fetchClient, options);
|
|
32
146
|
if ((_options_interceptors = options.interceptors) === null || _options_interceptors === void 0 ? void 0 : _options_interceptors.request) {
|
|
33
147
|
fetchClient.interceptors.request.use(options.interceptors.request);
|
|
34
148
|
}
|
|
@@ -38,11 +152,11 @@ export const useFetch = (options)=>{
|
|
|
38
152
|
// 重置 fetchClient 配置
|
|
39
153
|
const reset = (newOptions)=>{
|
|
40
154
|
var _newOptions_interceptors, _newOptions_interceptors1;
|
|
41
|
-
// 更新 baseURL
|
|
42
155
|
fetchClient.defaults.baseURL = newOptions.requestData.urlPrefix;
|
|
43
|
-
//
|
|
156
|
+
// 清空并重新注册所有拦截器
|
|
44
157
|
fetchClient.interceptors.request.clear();
|
|
45
158
|
fetchClient.interceptors.response.clear();
|
|
159
|
+
registerRequestDataInterceptor(fetchClient, newOptions);
|
|
46
160
|
if ((_newOptions_interceptors = newOptions.interceptors) === null || _newOptions_interceptors === void 0 ? void 0 : _newOptions_interceptors.request) {
|
|
47
161
|
fetchClient.interceptors.request.use(newOptions.interceptors.request);
|
|
48
162
|
}
|
package/dist/type.d.ts
CHANGED
|
@@ -2,10 +2,12 @@ import type { IRequestConfig, ISSEProtocol } from './http/fetch';
|
|
|
2
2
|
import type { IResponse } from './http/fetch';
|
|
3
3
|
export interface IUseChatHelperOptions {
|
|
4
4
|
protocol?: ISSEProtocol;
|
|
5
|
+
/** 自定义拦截器,优先级高于内置 requestData 拦截器 */
|
|
5
6
|
interceptors?: {
|
|
6
7
|
request?: (config: IRequestConfig) => IRequestConfig;
|
|
7
8
|
response?: (response: IResponse) => IResponse;
|
|
8
9
|
};
|
|
10
|
+
/** 全局默认请求配置,通过内置拦截器自动合并到每次请求(函数形式可延迟求值) */
|
|
9
11
|
requestData: {
|
|
10
12
|
data?: (() => Record<string, unknown>) | Record<string, unknown>;
|
|
11
13
|
headers?: (() => Record<string, string>) | Record<string, string>;
|