@ahoo-wang/fetcher 0.2.0 → 0.2.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@ahoo-wang/fetcher.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher)
4
4
  [![Build Status](https://github.com/Ahoo-Wang/fetcher/actions/workflows/ci.yml/badge.svg)](https://github.com/Ahoo-Wang/fetcher/actions)
5
- [![codecov](https://codecov.io/gh/Ahoo-Wang/Fetcher/graph/badge.svg?token=CUPgk8DmH5)](https://codecov.io/gh/Ahoo-Wang/Fetcher)
5
+ [![codecov](https://codecov.io/gh/Ahoo-Wang/fetcher/graph/badge.svg?token=JGiWZ52CvJ)](https://codecov.io/gh/Ahoo-Wang/fetcher)
6
6
  [![License](https://img.shields.io/npm/l/@ahoo-wang/fetcher.svg)](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
7
7
  [![npm downloads](https://img.shields.io/npm/dm/@ahoo-wang/fetcher.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher)
8
8
 
@@ -87,13 +87,16 @@ const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });
87
87
 
88
88
  // Add request interceptor
89
89
  const requestInterceptorId = fetcher.interceptors.request.use({
90
- intercept(request) {
90
+ intercept(exchange) {
91
91
  // Modify request configuration, e.g., add auth header
92
92
  return {
93
- ...request,
94
- headers: {
95
- ...request.headers,
96
- Authorization: 'Bearer token',
93
+ ...exchange,
94
+ request: {
95
+ ...exchange.request,
96
+ headers: {
97
+ ...exchange.request.headers,
98
+ Authorization: 'Bearer token',
99
+ },
97
100
  },
98
101
  };
99
102
  },
@@ -101,18 +104,18 @@ const requestInterceptorId = fetcher.interceptors.request.use({
101
104
 
102
105
  // Add response interceptor
103
106
  const responseInterceptorId = fetcher.interceptors.response.use({
104
- intercept(response) {
107
+ intercept(exchange) {
105
108
  // Process response data, e.g., parse JSON
106
- return response;
109
+ return exchange;
107
110
  },
108
111
  });
109
112
 
110
113
  // Add error interceptor
111
114
  const errorInterceptorId = fetcher.interceptors.error.use({
112
- intercept(error) {
115
+ intercept(exchange) {
113
116
  // Handle errors, e.g., log them
114
- console.error('Request failed:', error);
115
- return error;
117
+ console.error('Request failed:', exchange.error);
118
+ return exchange;
116
119
  },
117
120
  });
118
121
  ```
@@ -160,10 +163,10 @@ Interceptor manager for managing multiple interceptors of the same type.
160
163
 
161
164
  #### Methods
162
165
 
163
- - `use(interceptor: T): number` - Add interceptor, returns interceptor ID
166
+ - `use(interceptor: Interceptor): number` - Add interceptor, returns interceptor ID
164
167
  - `eject(index: number): void` - Remove interceptor by ID
165
168
  - `clear(): void` - Clear all interceptors
166
- - `intercept(data: R): Promise<R>` - Execute all interceptors sequentially
169
+ - `intercept(exchange: FetchExchange): Promise<FetchExchange>` - Execute all interceptors sequentially
167
170
 
168
171
  ### FetcherInterceptors Class
169
172
 
@@ -171,9 +174,9 @@ Fetcher interceptor collection, including request, response, and error intercept
171
174
 
172
175
  #### Properties
173
176
 
174
- - `request: RequestInterceptorManager` - Request interceptor manager
175
- - `response: ResponseInterceptorManager` - Response interceptor manager
176
- - `error: ErrorInterceptorManager` - Error interceptor manager
177
+ - `request: InterceptorManager` - Request interceptor manager
178
+ - `response: InterceptorManager` - Response interceptor manager
179
+ - `error: InterceptorManager` - Error interceptor manager
177
180
 
178
181
  ## Complete Example
179
182
 
@@ -191,38 +194,37 @@ const fetcher = new Fetcher({
191
194
 
192
195
  // Add request interceptor - Add auth header
193
196
  fetcher.interceptors.request.use({
194
- intercept(request) {
197
+ intercept(exchange) {
195
198
  return {
196
- ...request,
197
- headers: {
198
- ...request.headers,
199
- Authorization: 'Bearer ' + getAuthToken(),
199
+ ...exchange,
200
+ request: {
201
+ ...exchange.request,
202
+ headers: {
203
+ ...exchange.request.headers,
204
+ Authorization: 'Bearer ' + getAuthToken(),
205
+ },
200
206
  },
201
207
  };
202
208
  },
203
209
  });
204
210
 
205
- // Add response interceptor - Auto-parse JSON
211
+ // Add response interceptor - Process response
206
212
  fetcher.interceptors.response.use({
207
- intercept(response) {
208
- if (response.headers.get('content-type')?.includes('application/json')) {
209
- return response.json().then(data => {
210
- return new Response(JSON.stringify(data), response);
211
- });
212
- }
213
- return response;
213
+ intercept(exchange) {
214
+ // Note: Response processing would typically happen after the response is received
215
+ return exchange;
214
216
  },
215
217
  });
216
218
 
217
219
  // Add error interceptor - Unified error handling
218
220
  fetcher.interceptors.error.use({
219
- intercept(error) {
220
- if (error.name === 'FetchTimeoutError') {
221
- console.error('Request timeout:', error.message);
221
+ intercept(exchange) {
222
+ if (exchange.error?.name === 'FetchTimeoutError') {
223
+ console.error('Request timeout:', exchange.error.message);
222
224
  } else {
223
- console.error('Network error:', error.message);
225
+ console.error('Network error:', exchange.error?.message);
224
226
  }
225
- return error;
227
+ return exchange;
226
228
  },
227
229
  });
228
230
 
package/README.zh-CN.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@ahoo-wang/fetcher.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher)
4
4
  [![Build Status](https://github.com/Ahoo-Wang/fetcher/actions/workflows/ci.yml/badge.svg)](https://github.com/Ahoo-Wang/fetcher/actions)
5
- [![codecov](https://codecov.io/gh/Ahoo-Wang/Fetcher/graph/badge.svg?token=CUPgk8DmH5)](https://codecov.io/gh/Ahoo-Wang/Fetcher)
5
+ [![codecov](https://codecov.io/gh/Ahoo-Wang/fetcher/graph/badge.svg?token=JGiWZ52CvJ)](https://codecov.io/gh/Ahoo-Wang/fetcher)
6
6
  [![License](https://img.shields.io/npm/l/@ahoo-wang/fetcher.svg)](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
7
7
  [![npm downloads](https://img.shields.io/npm/dm/@ahoo-wang/fetcher.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher)
8
8
 
@@ -87,13 +87,16 @@ const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });
87
87
 
88
88
  // 添加请求拦截器
89
89
  const requestInterceptorId = fetcher.interceptors.request.use({
90
- intercept(request) {
90
+ intercept(exchange) {
91
91
  // 修改请求配置,例如添加认证头部
92
92
  return {
93
- ...request,
94
- headers: {
95
- ...request.headers,
96
- Authorization: 'Bearer token',
93
+ ...exchange,
94
+ request: {
95
+ ...exchange.request,
96
+ headers: {
97
+ ...exchange.request.headers,
98
+ Authorization: 'Bearer token',
99
+ },
97
100
  },
98
101
  };
99
102
  },
@@ -101,18 +104,18 @@ const requestInterceptorId = fetcher.interceptors.request.use({
101
104
 
102
105
  // 添加响应拦截器
103
106
  const responseInterceptorId = fetcher.interceptors.response.use({
104
- intercept(response) {
107
+ intercept(exchange) {
105
108
  // 处理响应数据,例如解析 JSON
106
- return response;
109
+ return exchange;
107
110
  },
108
111
  });
109
112
 
110
113
  // 添加错误拦截器
111
114
  const errorInterceptorId = fetcher.interceptors.error.use({
112
- intercept(error) {
115
+ intercept(exchange) {
113
116
  // 处理错误,例如记录日志
114
- console.error('请求失败:', error);
115
- return error;
117
+ console.error('请求失败:', exchange.error);
118
+ return exchange;
116
119
  },
117
120
  });
118
121
  ```
@@ -160,10 +163,10 @@ new Fetcher(options?: FetcherOptions)
160
163
 
161
164
  #### 方法
162
165
 
163
- - `use(interceptor: T): number` - 添加拦截器,返回拦截器 ID
166
+ - `use(interceptor: Interceptor): number` - 添加拦截器,返回拦截器 ID
164
167
  - `eject(index: number): void` - 按 ID 移除拦截器
165
168
  - `clear(): void` - 清除所有拦截器
166
- - `intercept(data: R): Promise<R>` - 顺序执行所有拦截器
169
+ - `intercept(exchange: FetchExchange): Promise<FetchExchange>` - 顺序执行所有拦截器
167
170
 
168
171
  ### FetcherInterceptors 类
169
172
 
@@ -171,9 +174,9 @@ Fetcher 拦截器集合,包括请求、响应和错误拦截器管理器。
171
174
 
172
175
  #### 属性
173
176
 
174
- - `request: RequestInterceptorManager` - 请求拦截器管理器
175
- - `response: ResponseInterceptorManager` - 响应拦截器管理器
176
- - `error: ErrorInterceptorManager` - 错误拦截器管理器
177
+ - `request: InterceptorManager` - 请求拦截器管理器
178
+ - `response: InterceptorManager` - 响应拦截器管理器
179
+ - `error: InterceptorManager` - 错误拦截器管理器
177
180
 
178
181
  ## 完整示例
179
182
 
@@ -191,38 +194,37 @@ const fetcher = new Fetcher({
191
194
 
192
195
  // 添加请求拦截器 - 添加认证头部
193
196
  fetcher.interceptors.request.use({
194
- intercept(request) {
197
+ intercept(exchange) {
195
198
  return {
196
- ...request,
197
- headers: {
198
- ...request.headers,
199
- Authorization: 'Bearer ' + getAuthToken(),
199
+ ...exchange,
200
+ request: {
201
+ ...exchange.request,
202
+ headers: {
203
+ ...exchange.request.headers,
204
+ Authorization: 'Bearer ' + getAuthToken(),
205
+ },
200
206
  },
201
207
  };
202
208
  },
203
209
  });
204
210
 
205
- // 添加响应拦截器 - 自动解析 JSON
211
+ // 添加响应拦截器 - 处理响应
206
212
  fetcher.interceptors.response.use({
207
- intercept(response) {
208
- if (response.headers.get('content-type')?.includes('application/json')) {
209
- return response.json().then(data => {
210
- return new Response(JSON.stringify(data), response);
211
- });
212
- }
213
- return response;
213
+ intercept(exchange) {
214
+ // 注意:响应处理通常在收到响应后进行
215
+ return exchange;
214
216
  },
215
217
  });
216
218
 
217
219
  // 添加错误拦截器 - 统一错误处理
218
220
  fetcher.interceptors.error.use({
219
- intercept(error) {
220
- if (error.name === 'FetchTimeoutError') {
221
- console.error('请求超时:', error.message);
221
+ intercept(exchange) {
222
+ if (exchange.error?.name === 'FetchTimeoutError') {
223
+ console.error('请求超时:', exchange.error.message);
222
224
  } else {
223
- console.error('网络错误:', error.message);
225
+ console.error('网络错误:', exchange.error?.message);
224
226
  }
225
- return error;
227
+ return exchange;
226
228
  },
227
229
  });
228
230
 
package/dist/fetcher.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { TimeoutCapable } from './timeout';
2
2
  import { BaseURLCapable, HeadersCapable, RequestField } from './types';
3
- import { FetcherInterceptors } from './interceptor';
3
+ import { FetcherInterceptors, FetchExchange } from './interceptor';
4
4
  /**
5
- * Fetcher配置选项接口
5
+ * Fetcher configuration options interface
6
6
  */
7
7
  export interface FetcherOptions extends BaseURLCapable, HeadersCapable, TimeoutCapable {
8
8
  }
9
9
  /**
10
- * Fetcher请求选项接口
10
+ * Fetcher request options interface
11
11
  */
12
12
  export interface FetcherRequest extends TimeoutCapable, Omit<RequestInit, 'body'> {
13
13
  pathParams?: Record<string, any>;
@@ -15,7 +15,7 @@ export interface FetcherRequest extends TimeoutCapable, Omit<RequestInit, 'body'
15
15
  body?: BodyInit | Record<string, any> | null;
16
16
  }
17
17
  /**
18
- * HTTP请求客户端类,支持URL构建、超时控制等功能
18
+ * HTTP client class that supports URL building, timeout control, and more
19
19
  *
20
20
  * @example
21
21
  * const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });
@@ -31,85 +31,104 @@ export declare class Fetcher implements HeadersCapable, TimeoutCapable {
31
31
  private urlBuilder;
32
32
  interceptors: FetcherInterceptors;
33
33
  /**
34
- * 创建Fetcher实例
34
+ * Create a Fetcher instance
35
35
  *
36
- * @param options - Fetcher配置选项
36
+ * @param options - Fetcher configuration options
37
37
  */
38
38
  constructor(options?: FetcherOptions);
39
39
  /**
40
- * 发起HTTP请求
40
+ * Make an HTTP request
41
41
  *
42
- * @param url - 请求URL路径
43
- * @param request - 请求选项,包括路径参数、查询参数等
44
- * @returns Promise<Response> HTTP响应
42
+ * @param url - Request URL path
43
+ * @param request - Request options, including path parameters, query parameters, etc.
44
+ * @returns Promise<Response> HTTP response
45
45
  */
46
46
  fetch(url: string, request?: FetcherRequest): Promise<Response>;
47
47
  /**
48
- * 带超时控制的HTTP请求方法
48
+ * Send an HTTP request
49
49
  *
50
- * 该方法使用Promise.race来实现超时控制,同时发起fetch请求和超时Promise,
51
- * 当任一Promise完成时,会返回其结果或抛出异常。
50
+ * @param url - Request URL address, supports path parameter placeholders
51
+ * @param request - Request configuration object, including method, headers, body, etc.
52
+ * @returns Promise that resolves to a FetchExchange object containing request and response information
52
53
  *
53
- * @param url - 请求的URL地址
54
- * @param request - 请求选项,包括method、headers、body等fetch API支持的选项
55
- * @returns Promise<Response> HTTP响应Promise
56
- * @throws FetchTimeoutError 当请求超时时抛出
54
+ * @throws Throws an exception when an error occurs during the request and is not handled by error interceptors
55
+ */
56
+ request(url: string, request?: FetcherRequest): Promise<FetchExchange>;
57
+ /**
58
+ * HTTP request method with timeout control
59
+ *
60
+ * This method uses Promise.race to implement timeout control, initiating both
61
+ * fetch request and timeout Promise simultaneously. When either Promise completes,
62
+ * it returns the result or throws an exception.
63
+ *
64
+ * @param exchange - The exchange containing request information
65
+ * @returns Promise<Response> HTTP response Promise
66
+ * @throws FetchTimeoutError Thrown when the request times out
57
67
  */
58
68
  private timeoutFetch;
59
69
  /**
60
- * 发起GET请求
70
+ * Make an HTTP request with the specified method
71
+ *
72
+ * @param method - HTTP method to use
73
+ * @param url - Request URL path
74
+ * @param request - Request options
75
+ * @returns Promise<Response> HTTP response
76
+ */
77
+ private methodFetch;
78
+ /**
79
+ * Make a GET request
61
80
  *
62
- * @param url - 请求URL路径
63
- * @param request - 请求选项,包括路径参数、查询参数等
64
- * @returns Promise<Response> HTTP响应
81
+ * @param url - Request URL path
82
+ * @param request - Request options, including path parameters, query parameters, etc.
83
+ * @returns Promise<Response> HTTP response
65
84
  */
66
85
  get(url: string, request?: Omit<FetcherRequest, RequestField.METHOD | RequestField.BODY>): Promise<Response>;
67
86
  /**
68
- * 发起POST请求
87
+ * Make a POST request
69
88
  *
70
- * @param url - 请求URL路径
71
- * @param request - 请求选项,包括路径参数、查询参数、请求体等
72
- * @returns Promise<Response> HTTP响应
89
+ * @param url - Request URL path
90
+ * @param request - Request options, including path parameters, query parameters, request body, etc.
91
+ * @returns Promise<Response> HTTP response
73
92
  */
74
93
  post(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
75
94
  /**
76
- * 发起PUT请求
95
+ * Make a PUT request
77
96
  *
78
- * @param url - 请求URL路径
79
- * @param request - 请求选项,包括路径参数、查询参数、请求体等
80
- * @returns Promise<Response> HTTP响应
97
+ * @param url - Request URL path
98
+ * @param request - Request options, including path parameters, query parameters, request body, etc.
99
+ * @returns Promise<Response> HTTP response
81
100
  */
82
101
  put(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
83
102
  /**
84
- * 发起DELETE请求
103
+ * Make a DELETE request
85
104
  *
86
- * @param url - 请求URL路径
87
- * @param request - 请求选项,包括路径参数、查询参数等
88
- * @returns Promise<Response> HTTP响应
105
+ * @param url - Request URL path
106
+ * @param request - Request options, including path parameters, query parameters, etc.
107
+ * @returns Promise<Response> HTTP response
89
108
  */
90
109
  delete(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
91
110
  /**
92
- * 发起PATCH请求
111
+ * Make a PATCH request
93
112
  *
94
- * @param url - 请求URL路径
95
- * @param request - 请求选项,包括路径参数、查询参数、请求体等
96
- * @returns Promise<Response> HTTP响应
113
+ * @param url - Request URL path
114
+ * @param request - Request options, including path parameters, query parameters, request body, etc.
115
+ * @returns Promise<Response> HTTP response
97
116
  */
98
117
  patch(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
99
118
  /**
100
- * 发起HEAD请求
119
+ * Make a HEAD request
101
120
  *
102
- * @param url - 请求URL路径
103
- * @param request - 请求选项,包括路径参数、查询参数等
104
- * @returns Promise<Response> HTTP响应
121
+ * @param url - Request URL path
122
+ * @param request - Request options, including path parameters, query parameters, etc.
123
+ * @returns Promise<Response> HTTP response
105
124
  */
106
125
  head(url: string, request?: Omit<FetcherRequest, RequestField.METHOD | RequestField.BODY>): Promise<Response>;
107
126
  /**
108
- * 发起OPTIONS请求
127
+ * Make an OPTIONS request
109
128
  *
110
- * @param url - 请求URL路径
111
- * @param request - 请求选项,包括路径参数、查询参数等
112
- * @returns Promise<Response> HTTP响应
129
+ * @param url - Request URL path
130
+ * @param request - Request options, including path parameters, query parameters, etc.
131
+ * @returns Promise<Response> HTTP response
113
132
  */
114
133
  options(url: string, request?: Omit<FetcherRequest, RequestField.METHOD | RequestField.BODY>): Promise<Response>;
115
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EACL,cAAc,EAGd,cAAc,EAEd,YAAY,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD;;GAEG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,EACpB,cAAc,EACd,cAAc;CAAG;AAWrB;;GAEG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,EACpB,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;CAC9C;AAED;;;;;;;;;;GAUG;AACH,qBAAa,OAAQ,YAAW,cAAc,EAAE,cAAc;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAkB;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,UAAU,CAAa;IAC/B,YAAY,EAAE,mBAAmB,CAA6B;IAE9D;;;;OAIG;gBACS,OAAO,GAAE,cAA+B;IASpD;;;;;;OAMG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAyCzE;;;;;;;;;;OAUG;YACW,YAAY;IA4C1B;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;IAOpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAOpB;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAOpB;;;;;;OAMG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAOpB;;;;;;OAMG;IACG,KAAK,CACT,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAOpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;IAOpB;;;;;;OAMG;IACG,OAAO,CACX,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;CAMrB"}
1
+ {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EACL,cAAc,EAGd,cAAc,EAEd,YAAY,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnE;;GAEG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,EACpB,cAAc,EACd,cAAc;CACjB;AAWD;;GAEG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,EACpB,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;CAC9C;AAED;;;;;;;;;;GAUG;AACH,qBAAa,OAAQ,YAAW,cAAc,EAAE,cAAc;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAkB;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,UAAU,CAAa;IAC/B,YAAY,EAAE,mBAAmB,CAA6B;IAE9D;;;;OAIG;gBACS,OAAO,GAAE,cAA+B;IASpD;;;;;;OAMG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQzE;;;;;;;;OAQG;IACG,OAAO,CACX,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC;IAgDzB;;;;;;;;;;OAUG;YACW,YAAY;IA2C1B;;;;;;;OAOG;YACW,WAAW;IAWzB;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,KAAK,CACT,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,OAAO,CACX,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;CAGrB"}
package/dist/index.es.js CHANGED
@@ -1,10 +1,10 @@
1
- function T(r) {
1
+ function b(r) {
2
2
  return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(r);
3
3
  }
4
- function b(r, e) {
5
- return T(e) ? e : e ? r.replace(/\/?\/$/, "") + "/" + e.replace(/^\/+/, "") : r;
4
+ function E(r, e) {
5
+ return b(e) ? e : e ? r.replace(/\/?\/$/, "") + "/" + e.replace(/^\/+/, "") : r;
6
6
  }
7
- class E {
7
+ class w {
8
8
  /**
9
9
  * 创建UrlBuilder实例
10
10
  *
@@ -22,13 +22,13 @@ class E {
22
22
  * @returns 完整的URL字符串
23
23
  * @throws 当路径参数中缺少必需的占位符时抛出错误
24
24
  */
25
- build(e, t, n) {
26
- let s = b(this.baseURL, e), o = this.interpolateUrl(s, t);
27
- if (n) {
28
- const a = new URLSearchParams(n).toString();
29
- a && (o += "?" + a);
25
+ build(e, t, s) {
26
+ let o = E(this.baseURL, e), i = this.interpolateUrl(o, t);
27
+ if (s) {
28
+ const n = new URLSearchParams(s).toString();
29
+ n && (i += "?" + n);
30
30
  }
31
- return o;
31
+ return i;
32
32
  }
33
33
  /**
34
34
  * 替换url中的占位符参数
@@ -39,26 +39,26 @@ class E {
39
39
  * @throws 当路径参数中缺少必需的占位符时抛出错误
40
40
  */
41
41
  interpolateUrl(e, t) {
42
- return t ? e.replace(/{([^}]+)}/g, (n, s) => {
43
- const o = t[s];
44
- if (o === void 0)
45
- throw new Error(`Missing required path parameter: ${s}`);
46
- return String(o);
42
+ return t ? e.replace(/{([^}]+)}/g, (s, o) => {
43
+ const i = t[o];
44
+ if (i === void 0)
45
+ throw new Error(`Missing required path parameter: ${o}`);
46
+ return String(i);
47
47
  }) : e;
48
48
  }
49
49
  }
50
50
  function P(r, e) {
51
51
  return typeof r < "u" ? r : e;
52
52
  }
53
- class f extends Error {
54
- constructor(e, t, n) {
55
- const s = `Request timeout of ${n}ms exceeded for ${t?.method || "GET"} ${e}`;
56
- super(s), this.name = "FetchTimeoutError", this.url = e, this.request = t, Object.setPrototypeOf(this, f.prototype);
53
+ class l extends Error {
54
+ constructor(e, t) {
55
+ const s = e.request?.method || "GET", o = `Request timeout of ${t}ms exceeded for ${s} ${e.url}`;
56
+ super(o), this.name = "FetchTimeoutError", this.exchange = e, Object.setPrototypeOf(this, l.prototype);
57
57
  }
58
58
  }
59
59
  var c = /* @__PURE__ */ ((r) => (r.GET = "GET", r.POST = "POST", r.PUT = "PUT", r.DELETE = "DELETE", r.PATCH = "PATCH", r.HEAD = "HEAD", r.OPTIONS = "OPTIONS", r))(c || {}), O = /* @__PURE__ */ ((r) => (r.METHOD = "method", r.BODY = "body", r))(O || {});
60
60
  const d = "Content-Type";
61
- var u = /* @__PURE__ */ ((r) => (r.APPLICATION_JSON = "application/json", r.TEXT_EVENT_STREAM = "text/event-stream", r))(u || {});
61
+ var f = /* @__PURE__ */ ((r) => (r.APPLICATION_JSON = "application/json", r.TEXT_EVENT_STREAM = "text/event-stream", r))(f || {});
62
62
  class h {
63
63
  constructor() {
64
64
  this.interceptors = [];
@@ -87,17 +87,17 @@ class h {
87
87
  }
88
88
  /**
89
89
  * 依次执行所有拦截器对数据的处理
90
- * @param data - 需要处理的数据
90
+ * @param exchange - 需要处理的数据
91
91
  * @returns 经过所有拦截器处理后的数据
92
92
  */
93
93
  async intercept(e) {
94
94
  let t = e;
95
- for (let n of this.interceptors)
96
- n && (t = await n.intercept(t));
95
+ for (let s of this.interceptors)
96
+ s && (t = await s.intercept(t));
97
97
  return t;
98
98
  }
99
99
  }
100
- class w {
100
+ class q {
101
101
  constructor() {
102
102
  this.request = new h(), this.response = new h(), this.error = new h();
103
103
  }
@@ -122,206 +122,223 @@ class A {
122
122
  *
123
123
  * 对于不支持的 object 类型(如普通对象),将自动转换为 JSON 字符串
124
124
  *
125
- * @param request 请求参数
125
+ * @param exchange
126
126
  * @returns 转换后的请求
127
127
  */
128
128
  intercept(e) {
129
- if (e.body === void 0 || e.body === null || typeof e.body != "object" || e.body instanceof ArrayBuffer || ArrayBuffer.isView(e.body) || // 包括 TypedArray 和 DataView
130
- e.body instanceof Blob || e.body instanceof File || e.body instanceof URLSearchParams || e.body instanceof FormData || e.body instanceof ReadableStream)
129
+ const t = e.request;
130
+ if (t.body === void 0 || t.body === null || typeof t.body != "object" || t.body instanceof ArrayBuffer || ArrayBuffer.isView(t.body) || // 包括 TypedArray 和 DataView
131
+ t.body instanceof Blob || t.body instanceof File || t.body instanceof URLSearchParams || t.body instanceof FormData || t.body instanceof ReadableStream)
131
132
  return e;
132
- const t = { ...e };
133
- t.body = JSON.stringify(e.body), t.headers || (t.headers = {});
134
- const n = t.headers;
135
- return n[d] || (n[d] = u.APPLICATION_JSON), t;
133
+ const s = { ...t };
134
+ s.body = JSON.stringify(t.body), s.headers || (s.headers = {});
135
+ const o = s.headers;
136
+ return o[d] || (o[d] = f.APPLICATION_JSON), { ...e, request: s };
136
137
  }
137
138
  }
138
- const p = {
139
- [d]: u.APPLICATION_JSON
139
+ const m = {
140
+ [d]: f.APPLICATION_JSON
140
141
  }, S = {
141
142
  baseURL: "",
142
- headers: p
143
+ headers: m
143
144
  };
144
145
  class I {
145
146
  /**
146
- * 创建Fetcher实例
147
+ * Create a Fetcher instance
147
148
  *
148
- * @param options - Fetcher配置选项
149
+ * @param options - Fetcher configuration options
149
150
  */
150
151
  constructor(e = S) {
151
- this.headers = p, this.interceptors = new w(), this.urlBuilder = new E(e.baseURL), e.headers !== void 0 && (this.headers = e.headers), this.timeout = e.timeout, this.interceptors.request.use(new A());
152
+ this.headers = m, this.interceptors = new q(), this.urlBuilder = new w(e.baseURL), e.headers !== void 0 && (this.headers = e.headers), this.timeout = e.timeout, this.interceptors.request.use(new A());
152
153
  }
153
154
  /**
154
- * 发起HTTP请求
155
+ * Make an HTTP request
155
156
  *
156
- * @param url - 请求URL路径
157
- * @param request - 请求选项,包括路径参数、查询参数等
158
- * @returns Promise<Response> HTTP响应
157
+ * @param url - Request URL path
158
+ * @param request - Request options, including path parameters, query parameters, etc.
159
+ * @returns Promise<Response> HTTP response
159
160
  */
160
161
  async fetch(e, t = {}) {
161
- const n = {
162
+ const s = await this.request(e, t);
163
+ if (!s.response)
164
+ throw new Error(`Request to ${s.url} failed with no response`);
165
+ return s.response;
166
+ }
167
+ /**
168
+ * Send an HTTP request
169
+ *
170
+ * @param url - Request URL address, supports path parameter placeholders
171
+ * @param request - Request configuration object, including method, headers, body, etc.
172
+ * @returns Promise that resolves to a FetchExchange object containing request and response information
173
+ *
174
+ * @throws Throws an exception when an error occurs during the request and is not handled by error interceptors
175
+ */
176
+ async request(e, t = {}) {
177
+ const s = {
162
178
  ...this.headers || {},
163
179
  ...t.headers || {}
164
- };
165
- let s = {
180
+ }, o = {
166
181
  ...t,
167
- headers: Object.keys(n).length > 0 ? n : void 0
182
+ headers: Object.keys(s).length > 0 ? s : void 0
183
+ }, i = this.urlBuilder.build(
184
+ e,
185
+ t.pathParams,
186
+ t.queryParams
187
+ );
188
+ let n = {
189
+ fetcher: this,
190
+ url: i,
191
+ request: o,
192
+ response: void 0,
193
+ error: void 0
168
194
  };
169
195
  try {
170
- s = await this.interceptors.request.intercept(s);
171
- const o = this.urlBuilder.build(
172
- e,
173
- t.pathParams,
174
- t.queryParams
175
- ), a = {
176
- ...s,
177
- body: s.body
196
+ const u = {
197
+ ...n
178
198
  };
179
- let i = await this.timeoutFetch(o, a);
180
- return i = await this.interceptors.response.intercept(i), i;
181
- } catch (o) {
182
- throw await this.interceptors.error.intercept(o);
199
+ n = await this.interceptors.request.intercept(u), n.response = await this.timeoutFetch(n);
200
+ const a = {
201
+ ...n
202
+ };
203
+ return n = await this.interceptors.response.intercept(a), n;
204
+ } catch (u) {
205
+ if (n.error = u, n = await this.interceptors.error.intercept(n), n.response)
206
+ return n;
207
+ throw n.error;
183
208
  }
184
209
  }
185
210
  /**
186
- * 带超时控制的HTTP请求方法
211
+ * HTTP request method with timeout control
187
212
  *
188
- * 该方法使用Promise.race来实现超时控制,同时发起fetch请求和超时Promise,
189
- * 当任一Promise完成时,会返回其结果或抛出异常。
213
+ * This method uses Promise.race to implement timeout control, initiating both
214
+ * fetch request and timeout Promise simultaneously. When either Promise completes,
215
+ * it returns the result or throws an exception.
190
216
  *
191
- * @param url - 请求的URL地址
192
- * @param request - 请求选项,包括method、headers、body等fetch API支持的选项
193
- * @returns Promise<Response> HTTP响应Promise
194
- * @throws FetchTimeoutError 当请求超时时抛出
217
+ * @param exchange - The exchange containing request information
218
+ * @returns Promise<Response> HTTP response Promise
219
+ * @throws FetchTimeoutError Thrown when the request times out
195
220
  */
196
- async timeoutFetch(e, t) {
197
- const n = t.timeout, s = P(n, this.timeout);
198
- if (!s)
199
- return fetch(e, t);
200
- const o = new AbortController(), a = {
201
- ...t,
202
- signal: o.signal
221
+ async timeoutFetch(e) {
222
+ const t = e.url, s = e.request, o = s.timeout, i = P(o, this.timeout);
223
+ if (!i)
224
+ return fetch(t, s);
225
+ const n = new AbortController(), u = {
226
+ ...s,
227
+ signal: n.signal
203
228
  };
204
- let i = null;
205
- const m = new Promise((g, y) => {
206
- i = setTimeout(() => {
207
- i && clearTimeout(i);
208
- const l = new f(
209
- e,
210
- t,
211
- s
212
- );
213
- o.abort(l), y(l);
214
- }, s);
229
+ let a = null;
230
+ const y = new Promise((F, T) => {
231
+ a = setTimeout(() => {
232
+ a && clearTimeout(a);
233
+ const p = new l(e, i);
234
+ n.abort(p), T(p);
235
+ }, i);
215
236
  });
216
237
  try {
217
- return await Promise.race([fetch(e, a), m]);
238
+ return await Promise.race([
239
+ fetch(t, u),
240
+ y
241
+ ]);
218
242
  } finally {
219
- i && clearTimeout(i);
243
+ a && clearTimeout(a);
220
244
  }
221
245
  }
222
246
  /**
223
- * 发起GET请求
247
+ * Make an HTTP request with the specified method
224
248
  *
225
- * @param url - 请求URL路径
226
- * @param request - 请求选项,包括路径参数、查询参数等
227
- * @returns Promise<Response> HTTP响应
249
+ * @param method - HTTP method to use
250
+ * @param url - Request URL path
251
+ * @param request - Request options
252
+ * @returns Promise<Response> HTTP response
228
253
  */
229
- async get(e, t = {}) {
230
- return this.fetch(e, {
231
- ...t,
232
- method: c.GET
254
+ async methodFetch(e, t, s = {}) {
255
+ return this.fetch(t, {
256
+ ...s,
257
+ method: e
233
258
  });
234
259
  }
235
260
  /**
236
- * 发起POST请求
261
+ * Make a GET request
237
262
  *
238
- * @param url - 请求URL路径
239
- * @param request - 请求选项,包括路径参数、查询参数、请求体等
240
- * @returns Promise<Response> HTTP响应
263
+ * @param url - Request URL path
264
+ * @param request - Request options, including path parameters, query parameters, etc.
265
+ * @returns Promise<Response> HTTP response
266
+ */
267
+ async get(e, t = {}) {
268
+ return this.methodFetch(c.GET, e, t);
269
+ }
270
+ /**
271
+ * Make a POST request
272
+ *
273
+ * @param url - Request URL path
274
+ * @param request - Request options, including path parameters, query parameters, request body, etc.
275
+ * @returns Promise<Response> HTTP response
241
276
  */
242
277
  async post(e, t = {}) {
243
- return this.fetch(e, {
244
- ...t,
245
- method: c.POST
246
- });
278
+ return this.methodFetch(c.POST, e, t);
247
279
  }
248
280
  /**
249
- * 发起PUT请求
281
+ * Make a PUT request
250
282
  *
251
- * @param url - 请求URL路径
252
- * @param request - 请求选项,包括路径参数、查询参数、请求体等
253
- * @returns Promise<Response> HTTP响应
283
+ * @param url - Request URL path
284
+ * @param request - Request options, including path parameters, query parameters, request body, etc.
285
+ * @returns Promise<Response> HTTP response
254
286
  */
255
287
  async put(e, t = {}) {
256
- return this.fetch(e, {
257
- ...t,
258
- method: c.PUT
259
- });
288
+ return this.methodFetch(c.PUT, e, t);
260
289
  }
261
290
  /**
262
- * 发起DELETE请求
291
+ * Make a DELETE request
263
292
  *
264
- * @param url - 请求URL路径
265
- * @param request - 请求选项,包括路径参数、查询参数等
266
- * @returns Promise<Response> HTTP响应
293
+ * @param url - Request URL path
294
+ * @param request - Request options, including path parameters, query parameters, etc.
295
+ * @returns Promise<Response> HTTP response
267
296
  */
268
297
  async delete(e, t = {}) {
269
- return this.fetch(e, {
270
- ...t,
271
- method: c.DELETE
272
- });
298
+ return this.methodFetch(c.DELETE, e, t);
273
299
  }
274
300
  /**
275
- * 发起PATCH请求
301
+ * Make a PATCH request
276
302
  *
277
- * @param url - 请求URL路径
278
- * @param request - 请求选项,包括路径参数、查询参数、请求体等
279
- * @returns Promise<Response> HTTP响应
303
+ * @param url - Request URL path
304
+ * @param request - Request options, including path parameters, query parameters, request body, etc.
305
+ * @returns Promise<Response> HTTP response
280
306
  */
281
307
  async patch(e, t = {}) {
282
- return this.fetch(e, {
283
- ...t,
284
- method: c.PATCH
285
- });
308
+ return this.methodFetch(c.PATCH, e, t);
286
309
  }
287
310
  /**
288
- * 发起HEAD请求
311
+ * Make a HEAD request
289
312
  *
290
- * @param url - 请求URL路径
291
- * @param request - 请求选项,包括路径参数、查询参数等
292
- * @returns Promise<Response> HTTP响应
313
+ * @param url - Request URL path
314
+ * @param request - Request options, including path parameters, query parameters, etc.
315
+ * @returns Promise<Response> HTTP response
293
316
  */
294
317
  async head(e, t = {}) {
295
- return this.fetch(e, {
296
- ...t,
297
- method: c.HEAD
298
- });
318
+ return this.methodFetch(c.HEAD, e, t);
299
319
  }
300
320
  /**
301
- * 发起OPTIONS请求
321
+ * Make an OPTIONS request
302
322
  *
303
- * @param url - 请求URL路径
304
- * @param request - 请求选项,包括路径参数、查询参数等
305
- * @returns Promise<Response> HTTP响应
323
+ * @param url - Request URL path
324
+ * @param request - Request options, including path parameters, query parameters, etc.
325
+ * @returns Promise<Response> HTTP response
306
326
  */
307
327
  async options(e, t = {}) {
308
- return this.fetch(e, {
309
- ...t,
310
- method: c.OPTIONS
311
- });
328
+ return this.methodFetch(c.OPTIONS, e, t);
312
329
  }
313
330
  }
314
331
  export {
315
332
  d as ContentTypeHeader,
316
- u as ContentTypeValues,
317
- f as FetchTimeoutError,
333
+ f as ContentTypeValues,
334
+ l as FetchTimeoutError,
318
335
  I as Fetcher,
319
- w as FetcherInterceptors,
336
+ q as FetcherInterceptors,
320
337
  c as HttpMethod,
321
338
  h as InterceptorManager,
322
339
  O as RequestField,
323
- E as UrlBuilder,
324
- b as combineURLs,
325
- T as isAbsoluteURL,
340
+ w as UrlBuilder,
341
+ E as combineURLs,
342
+ b as isAbsoluteURL,
326
343
  P as resolveTimeout
327
344
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(n,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(n=typeof globalThis<"u"?globalThis:n||self,d(n.Fetcher={}))})(this,(function(n){"use strict";function d(r){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(r)}function y(r,e){return d(e)?e:e?r.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):r}class p{constructor(e){this.baseURL=e}build(e,t,i){let o=y(this.baseURL,e),s=this.interpolateUrl(o,t);if(i){const h=new URLSearchParams(i).toString();h&&(s+="?"+h)}return s}interpolateUrl(e,t){return t?e.replace(/{([^}]+)}/g,(i,o)=>{const s=t[o];if(s===void 0)throw new Error(`Missing required path parameter: ${o}`);return String(s)}):e}}function T(r,e){return typeof r<"u"?r:e}class u extends Error{constructor(e,t,i){const o=`Request timeout of ${i}ms exceeded for ${t?.method||"GET"} ${e}`;super(o),this.name="FetchTimeoutError",this.url=e,this.request=t,Object.setPrototypeOf(this,u.prototype)}}var c=(r=>(r.GET="GET",r.POST="POST",r.PUT="PUT",r.DELETE="DELETE",r.PATCH="PATCH",r.HEAD="HEAD",r.OPTIONS="OPTIONS",r))(c||{}),b=(r=>(r.METHOD="method",r.BODY="body",r))(b||{});const f="Content-Type";var l=(r=>(r.APPLICATION_JSON="application/json",r.TEXT_EVENT_STREAM="text/event-stream",r))(l||{});class m{constructor(){this.interceptors=[]}use(e){const t=this.interceptors.length;return this.interceptors.push(e),t}eject(e){this.interceptors[e]&&(this.interceptors[e]=null)}clear(){this.interceptors=[]}async intercept(e){let t=e;for(let i of this.interceptors)i&&(t=await i.intercept(t));return t}}class E{constructor(){this.request=new m,this.response=new m,this.error=new m}}class w{intercept(e){if(e.body===void 0||e.body===null||typeof e.body!="object"||e.body instanceof ArrayBuffer||ArrayBuffer.isView(e.body)||e.body instanceof Blob||e.body instanceof File||e.body instanceof URLSearchParams||e.body instanceof FormData||e.body instanceof ReadableStream)return e;const t={...e};t.body=JSON.stringify(e.body),t.headers||(t.headers={});const i=t.headers;return i[f]||(i[f]=l.APPLICATION_JSON),t}}const P={[f]:l.APPLICATION_JSON},S={baseURL:"",headers:P};class A{constructor(e=S){this.headers=P,this.interceptors=new E,this.urlBuilder=new p(e.baseURL),e.headers!==void 0&&(this.headers=e.headers),this.timeout=e.timeout,this.interceptors.request.use(new w)}async fetch(e,t={}){const i={...this.headers||{},...t.headers||{}};let o={...t,headers:Object.keys(i).length>0?i:void 0};try{o=await this.interceptors.request.intercept(o);const s=this.urlBuilder.build(e,t.pathParams,t.queryParams),h={...o,body:o.body};let a=await this.timeoutFetch(s,h);return a=await this.interceptors.response.intercept(a),a}catch(s){throw await this.interceptors.error.intercept(s)}}async timeoutFetch(e,t){const i=t.timeout,o=T(i,this.timeout);if(!o)return fetch(e,t);const s=new AbortController,h={...t,signal:s.signal};let a=null;const g=new Promise((I,U)=>{a=setTimeout(()=>{a&&clearTimeout(a);const O=new u(e,t,o);s.abort(O),U(O)},o)});try{return await Promise.race([fetch(e,h),g])}finally{a&&clearTimeout(a)}}async get(e,t={}){return this.fetch(e,{...t,method:c.GET})}async post(e,t={}){return this.fetch(e,{...t,method:c.POST})}async put(e,t={}){return this.fetch(e,{...t,method:c.PUT})}async delete(e,t={}){return this.fetch(e,{...t,method:c.DELETE})}async patch(e,t={}){return this.fetch(e,{...t,method:c.PATCH})}async head(e,t={}){return this.fetch(e,{...t,method:c.HEAD})}async options(e,t={}){return this.fetch(e,{...t,method:c.OPTIONS})}}n.ContentTypeHeader=f,n.ContentTypeValues=l,n.FetchTimeoutError=u,n.Fetcher=A,n.FetcherInterceptors=E,n.HttpMethod=c,n.InterceptorManager=m,n.RequestField=b,n.UrlBuilder=p,n.combineURLs=y,n.isAbsoluteURL=d,n.resolveTimeout=T,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(o,h){typeof exports=="object"&&typeof module<"u"?h(exports):typeof define=="function"&&define.amd?define(["exports"],h):(o=typeof globalThis<"u"?globalThis:o||self,h(o.Fetcher={}))})(this,(function(o){"use strict";function h(r){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(r)}function y(r,e){return h(e)?e:e?r.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):r}class T{constructor(e){this.baseURL=e}build(e,t,s){let i=y(this.baseURL,e),c=this.interpolateUrl(i,t);if(s){const n=new URLSearchParams(s).toString();n&&(c+="?"+n)}return c}interpolateUrl(e,t){return t?e.replace(/{([^}]+)}/g,(s,i)=>{const c=t[i];if(c===void 0)throw new Error(`Missing required path parameter: ${i}`);return String(c)}):e}}function b(r,e){return typeof r<"u"?r:e}class l extends Error{constructor(e,t){const s=e.request?.method||"GET",i=`Request timeout of ${t}ms exceeded for ${s} ${e.url}`;super(i),this.name="FetchTimeoutError",this.exchange=e,Object.setPrototypeOf(this,l.prototype)}}var u=(r=>(r.GET="GET",r.POST="POST",r.PUT="PUT",r.DELETE="DELETE",r.PATCH="PATCH",r.HEAD="HEAD",r.OPTIONS="OPTIONS",r))(u||{}),E=(r=>(r.METHOD="method",r.BODY="body",r))(E||{});const f="Content-Type";var m=(r=>(r.APPLICATION_JSON="application/json",r.TEXT_EVENT_STREAM="text/event-stream",r))(m||{});class p{constructor(){this.interceptors=[]}use(e){const t=this.interceptors.length;return this.interceptors.push(e),t}eject(e){this.interceptors[e]&&(this.interceptors[e]=null)}clear(){this.interceptors=[]}async intercept(e){let t=e;for(let s of this.interceptors)s&&(t=await s.intercept(t));return t}}class P{constructor(){this.request=new p,this.response=new p,this.error=new p}}class F{intercept(e){const t=e.request;if(t.body===void 0||t.body===null||typeof t.body!="object"||t.body instanceof ArrayBuffer||ArrayBuffer.isView(t.body)||t.body instanceof Blob||t.body instanceof File||t.body instanceof URLSearchParams||t.body instanceof FormData||t.body instanceof ReadableStream)return e;const s={...t};s.body=JSON.stringify(t.body),s.headers||(s.headers={});const i=s.headers;return i[f]||(i[f]=m.APPLICATION_JSON),{...e,request:s}}}const w={[f]:m.APPLICATION_JSON},S={baseURL:"",headers:w};class q{constructor(e=S){this.headers=w,this.interceptors=new P,this.urlBuilder=new T(e.baseURL),e.headers!==void 0&&(this.headers=e.headers),this.timeout=e.timeout,this.interceptors.request.use(new F)}async fetch(e,t={}){const s=await this.request(e,t);if(!s.response)throw new Error(`Request to ${s.url} failed with no response`);return s.response}async request(e,t={}){const s={...this.headers||{},...t.headers||{}},i={...t,headers:Object.keys(s).length>0?s:void 0},c=this.urlBuilder.build(e,t.pathParams,t.queryParams);let n={fetcher:this,url:c,request:i,response:void 0,error:void 0};try{const d={...n};n=await this.interceptors.request.intercept(d),n.response=await this.timeoutFetch(n);const a={...n};return n=await this.interceptors.response.intercept(a),n}catch(d){if(n.error=d,n=await this.interceptors.error.intercept(n),n.response)return n;throw n.error}}async timeoutFetch(e){const t=e.url,s=e.request,i=s.timeout,c=b(i,this.timeout);if(!c)return fetch(t,s);const n=new AbortController,d={...s,signal:n.signal};let a=null;const A=new Promise((g,U)=>{a=setTimeout(()=>{a&&clearTimeout(a);const O=new l(e,c);n.abort(O),U(O)},c)});try{return await Promise.race([fetch(t,d),A])}finally{a&&clearTimeout(a)}}async methodFetch(e,t,s={}){return this.fetch(t,{...s,method:e})}async get(e,t={}){return this.methodFetch(u.GET,e,t)}async post(e,t={}){return this.methodFetch(u.POST,e,t)}async put(e,t={}){return this.methodFetch(u.PUT,e,t)}async delete(e,t={}){return this.methodFetch(u.DELETE,e,t)}async patch(e,t={}){return this.methodFetch(u.PATCH,e,t)}async head(e,t={}){return this.methodFetch(u.HEAD,e,t)}async options(e,t={}){return this.methodFetch(u.OPTIONS,e,t)}}o.ContentTypeHeader=f,o.ContentTypeValues=m,o.FetchTimeoutError=l,o.Fetcher=q,o.FetcherInterceptors=P,o.HttpMethod=u,o.InterceptorManager=p,o.RequestField=E,o.UrlBuilder=T,o.combineURLs=y,o.isAbsoluteURL=h,o.resolveTimeout=b,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})}));
@@ -1,44 +1,34 @@
1
- import { FetcherRequest } from './fetcher';
1
+ import { Fetcher, FetcherRequest } from './fetcher';
2
+ export interface FetchExchange {
3
+ fetcher: Fetcher;
4
+ url: string;
5
+ request: FetcherRequest;
6
+ response: Response | undefined;
7
+ error: Error | any | undefined;
8
+ }
2
9
  /**
3
10
  * 拦截器接口,定义了拦截器的基本结构
4
11
  * @template T - 拦截器处理的数据类型
5
12
  */
6
- export interface Interceptor<T> {
13
+ export interface Interceptor {
7
14
  /**
8
15
  * 拦截并处理数据
9
- * @param data - 需要处理的数据
16
+ * @param exchange - 需要处理的数据
10
17
  * @returns 处理后的数据,可以是同步或异步返回
11
18
  */
12
- intercept(data: T): T | Promise<T>;
13
- }
14
- /**
15
- * 请求拦截器接口,专门用于处理请求数据
16
- */
17
- export interface RequestInterceptor extends Interceptor<FetcherRequest> {
18
- }
19
- /**
20
- * 响应拦截器接口,专门用于处理响应数据
21
- */
22
- export interface ResponseInterceptor extends Interceptor<Response> {
23
- }
24
- /**
25
- * 错误拦截器接口,专门用于处理错误数据
26
- */
27
- export interface ErrorInterceptor extends Interceptor<any> {
19
+ intercept(exchange: FetchExchange): FetchExchange | Promise<FetchExchange>;
28
20
  }
29
21
  /**
30
22
  * 拦截器管理器类,用于管理同一类型的多个拦截器
31
- * @template R - 拦截器处理的数据类型
32
- * @template T - 拦截器类型
33
23
  */
34
- export declare class InterceptorManager<R, T extends Interceptor<R>> implements Interceptor<R> {
24
+ export declare class InterceptorManager implements Interceptor {
35
25
  private interceptors;
36
26
  /**
37
27
  * 添加拦截器到管理器中
38
28
  * @param interceptor - 要添加的拦截器
39
29
  * @returns 拦截器在管理器中的索引位置
40
30
  */
41
- use(interceptor: T): number;
31
+ use(interceptor: Interceptor): number;
42
32
  /**
43
33
  * 根据索引移除拦截器
44
34
  * @param index - 要移除的拦截器索引
@@ -50,23 +40,11 @@ export declare class InterceptorManager<R, T extends Interceptor<R>> implements
50
40
  clear(): void;
51
41
  /**
52
42
  * 依次执行所有拦截器对数据的处理
53
- * @param data - 需要处理的数据
43
+ * @param exchange - 需要处理的数据
54
44
  * @returns 经过所有拦截器处理后的数据
55
45
  */
56
- intercept(data: R): Promise<R>;
46
+ intercept(exchange: FetchExchange): Promise<FetchExchange>;
57
47
  }
58
- /**
59
- * 请求拦截器管理器类型定义
60
- */
61
- export type RequestInterceptorManager = InterceptorManager<FetcherRequest, RequestInterceptor>;
62
- /**
63
- * 响应拦截器管理器类型定义
64
- */
65
- export type ResponseInterceptorManager = InterceptorManager<Response, ResponseInterceptor>;
66
- /**
67
- * 错误拦截器管理器类型定义
68
- */
69
- export type ErrorInterceptorManager = InterceptorManager<any, ErrorInterceptor>;
70
48
  /**
71
49
  * Fetcher拦截器集合类,包含请求、响应和错误拦截器管理器
72
50
  */
@@ -74,14 +52,14 @@ export declare class FetcherInterceptors {
74
52
  /**
75
53
  * 请求拦截器管理器
76
54
  */
77
- request: RequestInterceptorManager;
55
+ request: InterceptorManager;
78
56
  /**
79
57
  * 响应拦截器管理器
80
58
  */
81
- response: ResponseInterceptorManager;
59
+ response: InterceptorManager;
82
60
  /**
83
61
  * 错误拦截器管理器
84
62
  */
85
- error: ErrorInterceptorManager;
63
+ error: InterceptorManager;
86
64
  }
87
65
  //# sourceMappingURL=interceptor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../src/interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C;;;GAGG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,WAAW,CAAC,cAAc,CAAC;CAAG;AAE1E;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,WAAW,CAAC,QAAQ,CAAC;CAAG;AAErE;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,WAAW,CAAC,GAAG,CAAC;CAAG;AAE7D;;;;GAIG;AACH,qBAAa,kBAAkB,CAAC,CAAC,EAAE,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,CACzD,YAAW,WAAW,CAAC,CAAC,CAAC;IAEzB,OAAO,CAAC,YAAY,CAAuB;IAE3C;;;;OAIG;IACH,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,MAAM;IAM3B;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;OAIG;IACG,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAUrC;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,kBAAkB,CACxD,cAAc,EACd,kBAAkB,CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,kBAAkB,CACzD,QAAQ,EACR,mBAAmB,CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAEhF;;GAEG;AACH,qBAAa,mBAAmB;IAC9B;;OAEG;IACH,OAAO,EAAE,yBAAyB,CAG9B;IAEJ;;OAEG;IACH,QAAQ,EAAE,0BAA0B,CAGhC;IAEJ;;OAEG;IACH,KAAK,EAAE,uBAAuB,CAG1B;CACL"}
1
+ {"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../src/interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/B,KAAK,EAAE,KAAK,GAAG,GAAG,GAAG,SAAS,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC5E;AAED;;GAEG;AACH,qBAAa,kBAAmB,YAAW,WAAW;IACpD,OAAO,CAAC,YAAY,CAAiC;IAErD;;;;OAIG;IACH,GAAG,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM;IAMrC;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;OAIG;IACG,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;CAUjE;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC9B;;OAEG;IACH,OAAO,EAAE,kBAAkB,CAA4B;IAEvD;;OAEG;IACH,QAAQ,EAAE,kBAAkB,CAA4B;IAExD;;OAEG;IACH,KAAK,EAAE,kBAAkB,CAA4B;CACtD"}
@@ -1,9 +1,8 @@
1
- import { RequestInterceptor } from './interceptor';
2
- import { FetcherRequest } from './fetcher';
1
+ import { FetchExchange, Interceptor } from './interceptor';
3
2
  /**
4
3
  * 请求体拦截器,负责将普通对象转换为JSON字符串
5
4
  */
6
- export declare class RequestBodyInterceptor implements RequestInterceptor {
5
+ export declare class RequestBodyInterceptor implements Interceptor {
7
6
  /**
8
7
  * 尝试转换请求体为合法的 fetch API body 类型
9
8
  *
@@ -23,9 +22,9 @@ export declare class RequestBodyInterceptor implements RequestInterceptor {
23
22
  *
24
23
  * 对于不支持的 object 类型(如普通对象),将自动转换为 JSON 字符串
25
24
  *
26
- * @param request 请求参数
25
+ * @param exchange
27
26
  * @returns 转换后的请求
28
27
  */
29
- intercept(request: FetcherRequest): FetcherRequest;
28
+ intercept(exchange: FetchExchange): FetchExchange;
30
29
  }
31
30
  //# sourceMappingURL=requestBodyInterceptor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"requestBodyInterceptor.d.ts","sourceRoot":"","sources":["../src/requestBodyInterceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C;;GAEG;AACH,qBAAa,sBAAuB,YAAW,kBAAkB;IAC/D;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc;CA0CnD"}
1
+ {"version":3,"file":"requestBodyInterceptor.d.ts","sourceRoot":"","sources":["../src/requestBodyInterceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG3D;;GAEG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IACxD;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa;CA2ClD"}
package/dist/timeout.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { FetcherRequest } from './fetcher';
1
+ import { FetchExchange } from './interceptor';
2
2
  /**
3
3
  * 定义具有超时能力的接口
4
4
  */
@@ -22,8 +22,7 @@ export declare function resolveTimeout(requestTimeout?: number, optionsTimeout?:
22
22
  * 当HTTP请求超时时抛出此异常
23
23
  */
24
24
  export declare class FetchTimeoutError extends Error {
25
- url: string;
26
- request: FetcherRequest;
27
- constructor(url: string, request: FetcherRequest, timeout: number);
25
+ exchange: FetchExchange;
26
+ constructor(exchange: FetchExchange, timeout: number);
28
27
  }
29
28
  //# sourceMappingURL=timeout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../src/timeout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,GAAG,SAAS,CAKpB;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,cAAc,CAAC;gBAEZ,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM;CAUlE"}
1
+ {"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../src/timeout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,GAAG,SAAS,CAKpB;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,EAAE,aAAa,CAAC;gBAEZ,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM;CAUrD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahoo-wang/fetcher",
3
- "version": "0.2.0",
3
+ "version": "0.2.3",
4
4
  "description": "Core library providing basic HTTP client functionality for Fetcher",
5
5
  "keywords": [
6
6
  "fetch",