@lytjs/common-http 6.5.0 → 6.6.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/README.md ADDED
@@ -0,0 +1,257 @@
1
+ # @lytjs/common-http
2
+
3
+ 基于原生 `fetch` API 的轻量级 HTTP 客户端,支持拦截器、超时、数组查询参数等功能。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pnpm add @lytjs/common-http
9
+ ```
10
+
11
+ ## 快速开始
12
+
13
+ ### 基础使用
14
+
15
+ ```typescript
16
+ import { http, getJson, postJson } from '@lytjs/common-http';
17
+
18
+ // 使用默认 http 实例发送请求
19
+ const response = await http.get('/api/users');
20
+ console.log(response.data);
21
+
22
+ // 或使用便捷的 JSON 方法
23
+ const data = await getJson('/api/users');
24
+ ```
25
+
26
+ ### 创建自定义客户端
27
+
28
+ ```typescript
29
+ import { createHttpClient } from '@lytjs/common-http';
30
+
31
+ const apiClient = createHttpClient({
32
+ baseURL: 'https://api.example.com',
33
+ headers: {
34
+ Authorization: 'Bearer YOUR_TOKEN',
35
+ 'Content-Type': 'application/json',
36
+ },
37
+ timeout: 5000,
38
+ });
39
+
40
+ const users = await apiClient.get('/users');
41
+ ```
42
+
43
+ ## API
44
+
45
+ ### 便捷方法
46
+
47
+ | 方法 | 说明 |
48
+ | ------------------------------------ | ------------------------------------ |
49
+ | `get<T>(url, options?)` | 发送 GET 请求 |
50
+ | `post<T>(url, data?, options?)` | 发送 POST 请求 |
51
+ | `put<T>(url, data?, options?)` | 发送 PUT 请求 |
52
+ | `patch<T>(url, data?, options?)` | 发送 PATCH 请求 |
53
+ | `del<T>(url, options?)` | 发送 DELETE 请求 |
54
+ | `getJson<T>(url, options?)` | 发送 GET 请求并直接返回 JSON 数据 |
55
+ | `postJson<T>(url, data?, options?)` | 发送 POST 请求并直接返回 JSON 数据 |
56
+ | `putJson<T>(url, data?, options?)` | 发送 PUT 请求并直接返回 JSON 数据 |
57
+ | `patchJson<T>(url, data?, options?)` | 发送 PATCH 请求并直接返回 JSON 数据 |
58
+ | `deleteJson<T>(url, options?)` | 发送 DELETE 请求并直接返回 JSON 数据 |
59
+
60
+ ### HttpClient 类
61
+
62
+ ```typescript
63
+ import { HttpClient, createHttpClient } from '@lytjs/common-http';
64
+
65
+ const client = new HttpClient({
66
+ baseURL: 'https://api.example.com',
67
+ headers: { 'X-API-Key': 'your-key' },
68
+ timeout: 10000,
69
+ });
70
+
71
+ // 或者使用工厂函数
72
+ const client = createHttpClient({
73
+ baseURL: 'https://api.example.com',
74
+ });
75
+ ```
76
+
77
+ ### 请求选项
78
+
79
+ ```typescript
80
+ interface RequestOptions {
81
+ headers?: Record<string, string>;
82
+ params?: Record<string, string | number | boolean | Array<string | number | boolean>>;
83
+ timeout?: number;
84
+ signal?: AbortSignal;
85
+ responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';
86
+ }
87
+ ```
88
+
89
+ ### 响应格式
90
+
91
+ ```typescript
92
+ interface HttpResponse<T> {
93
+ data: T;
94
+ status: number;
95
+ statusText: string;
96
+ headers: Record<string, string>;
97
+ ok: boolean;
98
+ }
99
+ ```
100
+
101
+ ## 特性
102
+
103
+ ### 1. 数组查询参数支持
104
+
105
+ ```typescript
106
+ import { get } from '@lytjs/common-http';
107
+
108
+ // 数组参数会被正确地处理为多个相同键名的查询参数
109
+ await get('/api/users', {
110
+ params: {
111
+ ids: [1, 2, 3],
112
+ tags: ['admin', 'user'],
113
+ },
114
+ });
115
+ // 结果: /api/users?ids=1&ids=2&ids=3&tags=admin&tags=user
116
+ ```
117
+
118
+ ### 2. 拦截器
119
+
120
+ ```typescript
121
+ import { http } from '@lytjs/common-http';
122
+
123
+ // 添加请求拦截器
124
+ http.use({
125
+ request(config) {
126
+ config.headers['X-Request-ID'] = Math.random().toString(36);
127
+ return config;
128
+ },
129
+ });
130
+
131
+ // 添加响应拦截器
132
+ http.use({
133
+ response(response) {
134
+ console.log('请求成功:', response.status);
135
+ return response;
136
+ },
137
+ error(error) {
138
+ console.error('请求失败:', error);
139
+ throw error;
140
+ },
141
+ });
142
+ ```
143
+
144
+ ### 3. 请求取消
145
+
146
+ ```typescript
147
+ import { http } from '@lytjs/common-http';
148
+
149
+ const controller = new AbortController();
150
+
151
+ // 5 秒后取消请求
152
+ setTimeout(() => controller.abort(), 5000);
153
+
154
+ try {
155
+ await http.get('/api/slow-endpoint', {
156
+ signal: controller.signal,
157
+ });
158
+ } catch (err) {
159
+ if (err.name === 'AbortError') {
160
+ console.log('请求已取消');
161
+ }
162
+ }
163
+ ```
164
+
165
+ ### 4. 超时控制
166
+
167
+ ```typescript
168
+ import { http, createHttpClient } from '@lytjs/common-http';
169
+
170
+ // 单次请求超时
171
+ await http.get('/api/slow', { timeout: 3000 });
172
+
173
+ // 全局超时配置
174
+ const client = createHttpClient({ timeout: 5000 });
175
+ ```
176
+
177
+ ## 错误处理
178
+
179
+ ```typescript
180
+ import { http, HttpError } from '@lytjs/common-http';
181
+
182
+ try {
183
+ const response = await http.get('/api/users');
184
+ } catch (err) {
185
+ if (err instanceof HttpError) {
186
+ console.error('HTTP 错误:', err.status, err.message);
187
+ if (err.response) {
188
+ console.error('响应数据:', err.response.data);
189
+ }
190
+ } else {
191
+ console.error('其他错误:', err);
192
+ }
193
+ }
194
+ ```
195
+
196
+ ## 完整示例
197
+
198
+ ```typescript
199
+ import { createHttpClient, getJson, postJson, HttpError } from '@lytjs/common-http';
200
+
201
+ // 创建 API 客户端
202
+ const api = createHttpClient({
203
+ baseURL: 'https://api.example.com',
204
+ headers: {
205
+ 'Content-Type': 'application/json',
206
+ },
207
+ });
208
+
209
+ // 添加身份验证拦截器
210
+ api.use({
211
+ request(config) {
212
+ const token = localStorage.getItem('token');
213
+ if (token) {
214
+ config.headers['Authorization'] = `Bearer ${token}`;
215
+ }
216
+ return config;
217
+ },
218
+ error(err) {
219
+ if (err instanceof HttpError && err.status === 401) {
220
+ // 处理未授权
221
+ window.location.href = '/login';
222
+ }
223
+ throw err;
224
+ },
225
+ });
226
+
227
+ // 使用 API 客户端
228
+ async function fetchUsers() {
229
+ try {
230
+ const users = await api.get('/users', {
231
+ params: {
232
+ status: 'active',
233
+ page: 1,
234
+ },
235
+ });
236
+ return users.data;
237
+ } catch (err) {
238
+ console.error('获取用户失败', err);
239
+ }
240
+ }
241
+
242
+ // 使用便捷方法
243
+ async function createUser(data: any) {
244
+ try {
245
+ const user = await postJson('/users', data, {
246
+ baseURL: 'https://api.example.com',
247
+ });
248
+ return user;
249
+ } catch (err) {
250
+ console.error('创建用户失败', err);
251
+ }
252
+ }
253
+ ```
254
+
255
+ ## License
256
+
257
+ MIT
package/dist/index.cjs CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var commonQuery = require('@lytjs/common-query');
4
+
3
5
  // src/index.ts
4
6
  var HttpError = class extends Error {
5
7
  constructor(message, response) {
@@ -70,14 +72,18 @@ var HttpClient = class {
70
72
  let httpResponse = await this._parseResponse(response, config.responseType);
71
73
  for (const interceptor of this._interceptors) {
72
74
  if (interceptor.response) {
73
- httpResponse = await interceptor.response(httpResponse);
75
+ httpResponse = await interceptor.response(
76
+ httpResponse
77
+ );
74
78
  }
75
79
  }
76
80
  return httpResponse;
77
81
  } catch (err) {
78
82
  for (const interceptor of this._interceptors) {
79
83
  if (interceptor.error) {
80
- const result = interceptor.error(err instanceof HttpError ? err : new HttpError(String(err)));
84
+ const result = interceptor.error(
85
+ err instanceof HttpError ? err : new HttpError(String(err))
86
+ );
81
87
  if (result !== void 0) return result;
82
88
  }
83
89
  }
@@ -124,8 +130,7 @@ var HttpClient = class {
124
130
  _resolveURL(base, url, params) {
125
131
  let resolved = base ? base.replace(/\/+$/, "") + "/" + url.replace(/^\/+/, "") : url;
126
132
  if (params) {
127
- const searchParams = new URLSearchParams(params);
128
- const qs = searchParams.toString();
133
+ const qs = commonQuery.stringifyQueryString(params);
129
134
  if (qs) {
130
135
  resolved += (resolved.includes("?") ? "&" : "?") + qs;
131
136
  }
@@ -144,10 +149,14 @@ var HttpClient = class {
144
149
  clearTimeout(timeoutId);
145
150
  throw new HttpError("Request was aborted", void 0);
146
151
  }
147
- signal.addEventListener("abort", () => {
148
- clearTimeout(timeoutId);
149
- timeoutController.abort();
150
- }, { once: true });
152
+ signal.addEventListener(
153
+ "abort",
154
+ () => {
155
+ clearTimeout(timeoutId);
156
+ timeoutController.abort();
157
+ },
158
+ { once: true }
159
+ );
151
160
  }
152
161
  }
153
162
  const fetchOptions = {
@@ -167,10 +176,7 @@ var HttpClient = class {
167
176
  headers: this._parseHeaders(response.headers),
168
177
  ok: false
169
178
  };
170
- throw new HttpError(
171
- `HTTP ${response.status}: ${response.statusText}`,
172
- errorResponse
173
- );
179
+ throw new HttpError(`HTTP ${response.status}: ${response.statusText}`, errorResponse);
174
180
  }
175
181
  return response;
176
182
  } finally {
@@ -218,11 +224,61 @@ function createHttpClient(options) {
218
224
  return new HttpClient(options);
219
225
  }
220
226
  var http = new HttpClient();
227
+ function get(url, options) {
228
+ return http.get(url, options);
229
+ }
230
+ function post(url, data, options) {
231
+ return http.post(url, data, options);
232
+ }
233
+ function put(url, data, options) {
234
+ return http.put(url, data, options);
235
+ }
236
+ function del(url, options) {
237
+ return http.delete(url, options);
238
+ }
239
+ function patch(url, data, options) {
240
+ return http.patch(url, data, options);
241
+ }
242
+ async function requestJson(method, url, options) {
243
+ const { data, ...config } = options || {};
244
+ if (method === "GET" || method === "DELETE") {
245
+ const response2 = await http.request(method, url, config);
246
+ return response2.data;
247
+ }
248
+ const response = await http.request(method, url, { ...config, body: data });
249
+ return response.data;
250
+ }
251
+ async function getJson(url, options) {
252
+ return requestJson("GET", url, options);
253
+ }
254
+ async function postJson(url, data, options) {
255
+ return requestJson("POST", url, { ...options, data });
256
+ }
257
+ async function putJson(url, data, options) {
258
+ return requestJson("PUT", url, { ...options, data });
259
+ }
260
+ async function patchJson(url, data, options) {
261
+ return requestJson("PATCH", url, { ...options, data });
262
+ }
263
+ async function deleteJson(url, options) {
264
+ return requestJson("DELETE", url, options);
265
+ }
221
266
 
222
267
  exports.CancellationToken = CancellationToken;
223
268
  exports.HttpClient = HttpClient;
224
269
  exports.HttpError = HttpError;
225
270
  exports.createHttpClient = createHttpClient;
271
+ exports.del = del;
272
+ exports.deleteJson = deleteJson;
273
+ exports.get = get;
274
+ exports.getJson = getJson;
226
275
  exports.http = http;
276
+ exports.patch = patch;
277
+ exports.patchJson = patchJson;
278
+ exports.post = post;
279
+ exports.postJson = postJson;
280
+ exports.put = put;
281
+ exports.putJson = putJson;
282
+ exports.requestJson = requestJson;
227
283
  //# sourceMappingURL=index.cjs.map
228
284
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAiDO,IAAM,SAAA,GAAN,cAAwB,KAAA,CAAM;AAAA,EAInC,WAAA,CAAY,SAAiB,QAAA,EAAkC;AAC7D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AACZ,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,IAAA,CAAK,SAAS,QAAA,EAAU,MAAA;AAAA,EAC1B;AACF;AAIO,IAAM,iBAAA,GAAN,MAAM,kBAAA,CAAkB;AAAA,EAI7B,WAAA,GAAc;AACZ,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,eAAA,EAAgB;AACvC,IAAA,IAAA,CAAK,gBAAgB,EAAC;AAAA,EACxB;AAAA,EAEA,IAAI,MAAA,GAAsB;AACxB,IAAA,OAAO,KAAK,WAAA,CAAY,MAAA;AAAA,EAC1B;AAAA,EAEA,MAAA,GAAe;AACb,IAAA,IAAA,CAAK,YAAY,KAAA,EAAM;AACvB,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,aAAA,EAAe;AACtC,MAAA,KAAA,CAAM,MAAA,EAAO;AAAA,IACf;AAAA,EACF;AAAA,EAEA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,IAAA,CAAK,YAAY,MAAA,CAAO,OAAA;AAAA,EACjC;AAAA,EAEA,OAAO,qBAAqB,MAAA,EAAgD;AAC1E,IAAA,MAAM,MAAA,GAAS,IAAI,kBAAA,EAAkB;AACrC,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,KAAA,CAAM,aAAA,CAAc,KAAK,MAAM,CAAA;AAC/B,MAAA,IAAI,MAAM,WAAA,EAAa;AACrB,QAAA,MAAA,CAAO,MAAA,EAAO;AACd,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAIO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAAY,OAAA,EAA6B;AACvC,IAAA,IAAA,CAAK,QAAA,GAAW,EAAE,GAAG,OAAA,EAAQ;AAC7B,IAAA,IAAA,CAAK,gBAAgB,EAAC;AAAA,EACxB;AAAA,EAEA,GAAA,CAAiB,KAAa,OAAA,EAAoD;AAChF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAW,KAAA,EAAO,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5C;AAAA,EAEA,IAAA,CAAkB,GAAA,EAAa,IAAA,EAAgB,OAAA,EAAoD;AACjG,IAAA,OAAO,IAAA,CAAK,QAAW,MAAA,EAAQ,GAAA,EAAK,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,IAAA,EAA6C,CAAA;AAAA,EACvG;AAAA,EAEA,GAAA,CAAiB,GAAA,EAAa,IAAA,EAAgB,OAAA,EAAoD;AAChG,IAAA,OAAO,IAAA,CAAK,QAAW,KAAA,EAAO,GAAA,EAAK,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,IAAA,EAA6C,CAAA;AAAA,EACtG;AAAA,EAEA,MAAA,CAAoB,KAAa,OAAA,EAAoD;AACnF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAW,QAAA,EAAU,GAAA,EAAK,OAAO,CAAA;AAAA,EAC/C;AAAA,EAEA,KAAA,CAAmB,GAAA,EAAa,IAAA,EAAgB,OAAA,EAAoD;AAClG,IAAA,OAAO,IAAA,CAAK,QAAW,OAAA,EAAS,GAAA,EAAK,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,IAAA,EAA6C,CAAA;AAAA,EACxG;AAAA,EAEA,MAAM,OAAA,CACJ,MAAA,EACA,GAAA,EACA,OAAA,EAC0B;AAC1B,IAAA,IAAI,MAAA,GAAS,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ,KAAK,OAAO,CAAA;AAGnD,IAAA,KAAA,MAAW,WAAA,IAAe,KAAK,aAAA,EAAe;AAC5C,MAAA,IAAI,YAAY,OAAA,EAAS;AACvB,QAAA,MAAA,GAAS,MAAM,WAAA,CAAY,OAAA,CAAQ,MAAM,CAAA;AAAA,MAC3C;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AACzC,MAAA,IAAI,eAAe,MAAM,IAAA,CAAK,cAAA,CAAkB,QAAA,EAAU,OAAO,YAAY,CAAA;AAG7E,MAAA,KAAA,MAAW,WAAA,IAAe,KAAK,aAAA,EAAe;AAC5C,QAAA,IAAI,YAAY,QAAA,EAAU;AACxB,UAAA,YAAA,GAAgB,MAAM,WAAA,CAAY,QAAA,CAAS,YAAqC,CAAA;AAAA,QAClF;AAAA,MACF;AAEA,MAAA,OAAO,YAAA;AAAA,IACT,SAAS,GAAA,EAAK;AAEZ,MAAA,KAAA,MAAW,WAAA,IAAe,KAAK,aAAA,EAAe;AAC5C,QAAA,IAAI,YAAY,KAAA,EAAO;AACrB,UAAA,MAAM,MAAA,GAAS,WAAA,CAAY,KAAA,CAAM,GAAA,YAAe,SAAA,GAAY,GAAA,GAAM,IAAI,SAAA,CAAU,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA;AAC5F,UAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AAAA,QACnC;AAAA,MACF;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,IAAI,WAAA,EAAsC;AACxC,IAAA,IAAA,CAAK,aAAA,CAAc,KAAK,WAAW,CAAA;AACnC,IAAA,OAAO,MAAM,IAAA,CAAK,KAAA,CAAM,WAAW,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,WAAA,EAAgC;AACpC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAAc,OAAA,CAAQ,WAAW,CAAA;AACpD,IAAA,IAAI,UAAU,EAAA,EAAI;AAChB,MAAA,IAAA,CAAK,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,CAAC,CAAA;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,YAAA,CACN,MAAA,EACA,GAAA,EACA,OAAA,EACuB;AACvB,IAAA,MAAM,EAAE,UAAU,EAAA,EAAI,OAAA,EAAS,iBAAiB,EAAC,KAAM,IAAA,CAAK,QAAA;AAC5D,IAAA,MAAM,cAAc,IAAA,CAAK,WAAA,CAAY,OAAA,EAAS,GAAA,EAAK,SAAS,MAAM,CAAA;AAElE,IAAA,MAAM,UAAkC,EAAE,GAAG,cAAA,EAAgB,GAAG,SAAS,OAAA,EAAQ;AAEjF,IAAA,IAAI,IAAA,GAAwB,IAAA;AAC5B,IAAA,IAAI,OAAA,IAAW,MAAA,IAAU,OAAA,IAAW,OAAA,CAAQ,SAAS,MAAA,EAAW;AAC9D,MAAA,IAAI,OAAO,OAAA,CAAQ,IAAA,KAAS,QAAA,IAAY,OAAA,CAAQ,SAAS,IAAA,EAAM;AAC7D,QAAA,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAClC,QAAA,IAAI,CAAC,OAAA,CAAQ,cAAc,CAAA,EAAG;AAC5B,UAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAAA,QAC5B;AAAA,MACF,CAAA,MAAO;AACL,QAAA,IAAA,GAAO,MAAA,CAAO,QAAQ,IAAI,CAAA;AAAA,MAC5B;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,OAAA,EAAS,OAAA,IAAW,IAAA,CAAK,QAAA,CAAS,OAAA;AAElD,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,OAAO,WAAA,EAAY;AAAA,MAC3B,GAAA,EAAK,WAAA;AAAA,MACL,OAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAQ,OAAA,EAAS,MAAA;AAAA,MACjB,cAAc,OAAA,EAAS,YAAA;AAAA,MACvB,eAAA,EAAiB,KAAK,QAAA,CAAS,eAAA;AAAA,MAC/B;AAAA,KACF;AAAA,EACF;AAAA,EAEQ,WAAA,CAAY,IAAA,EAAc,GAAA,EAAa,MAAA,EAAyC;AACtF,IAAA,IAAI,QAAA,GAAW,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,GAAI,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,GAAI,GAAA;AACjF,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,YAAA,GAAe,IAAI,eAAA,CAAgB,MAAM,CAAA;AAC/C,MAAA,MAAM,EAAA,GAAK,aAAa,QAAA,EAAS;AACjC,MAAA,IAAI,EAAA,EAAI;AACN,QAAA,QAAA,IAAA,CAAa,QAAA,CAAS,QAAA,CAAS,GAAG,CAAA,GAAI,MAAM,GAAA,IAAO,EAAA;AAAA,MACrD;AAAA,IACF;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,MAAc,OAAO,MAAA,EAAkD;AACrE,IAAA,MAAM,EAAE,QAAQ,GAAA,EAAK,OAAA,EAAS,MAAM,MAAA,EAAQ,eAAA,EAAiB,SAAQ,GAAI,MAAA;AAGzE,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI,iBAAA;AAEJ,IAAA,IAAI,OAAA,IAAW,UAAU,CAAA,EAAG;AAC1B,MAAA,iBAAA,GAAoB,IAAI,eAAA,EAAgB;AACxC,MAAA,SAAA,GAAY,UAAA,CAAW,MAAM,iBAAA,CAAmB,KAAA,IAAS,OAAO,CAAA;AAGhE,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,IAAI,OAAO,OAAA,EAAS;AAClB,UAAA,YAAA,CAAa,SAAS,CAAA;AACtB,UAAA,MAAM,IAAI,SAAA,CAAU,qBAAA,EAAuB,MAAS,CAAA;AAAA,QACtD;AACA,QAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,MAAM;AACrC,UAAA,YAAA,CAAa,SAAS,CAAA;AACtB,UAAA,iBAAA,CAAmB,KAAA,EAAM;AAAA,QAC3B,CAAA,EAAG,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,MACnB;AAAA,IACF;AAEA,IAAA,MAAM,YAAA,GAA4B;AAAA,MAChC,MAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA;AAAA,MACA,WAAA,EAAa,kBAAkB,SAAA,GAAY,MAAA;AAAA,MAC3C,MAAA,EAAQ,iBAAA,GAAoB,iBAAA,CAAkB,MAAA,GAAS;AAAA,KACzD;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,YAAY,CAAA;AAE9C,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,aAAA,GAAuC;AAAA,UAC3C,IAAA,EAAM,IAAA;AAAA,UACN,QAAQ,QAAA,CAAS,MAAA;AAAA,UACjB,YAAY,QAAA,CAAS,UAAA;AAAA,UACrB,OAAA,EAAS,IAAA,CAAK,aAAA,CAAc,QAAA,CAAS,OAAO,CAAA;AAAA,UAC5C,EAAA,EAAI;AAAA,SACN;AACA,QAAA,MAAM,IAAI,SAAA;AAAA,UACR,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAAA,UAC/C;AAAA,SACF;AAAA,MACF;AAEA,MAAA,OAAO,QAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,QAAA,YAAA,CAAa,SAAS,CAAA;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,cAAA,CACZ,QAAA,EACA,YAAA,EAC0B;AAC1B,IAAA,IAAI,IAAA;AACJ,IAAA,QAAQ,YAAA;AAAc,MACpB,KAAK,MAAA;AACH,QAAA,IAAA,GAAQ,MAAM,SAAS,IAAA,EAAK;AAC5B,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,IAAA,GAAQ,MAAM,SAAS,IAAA,EAAK;AAC5B,QAAA;AAAA,MACF,KAAK,aAAA;AACH,QAAA,IAAA,GAAQ,MAAM,SAAS,WAAA,EAAY;AACnC,QAAA;AAAA,MACF,KAAK,MAAA;AAAA,MACL,SAAS;AACP,QAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,QAAA,IAAA,GAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,GAAK,IAAA;AAClC,QAAA;AAAA,MACF;AAAA;AAGF,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,OAAA,EAAS,IAAA,CAAK,aAAA,CAAc,QAAA,CAAS,OAAO,CAAA;AAAA,MAC5C,IAAI,QAAA,CAAS;AAAA,KACf;AAAA,EACF;AAAA,EAEQ,cAAc,OAAA,EAA0C;AAC9D,IAAA,MAAM,SAAiC,EAAC;AACxC,IAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AAC9B,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB,CAAC,CAAA;AACD,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAIO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,OAAO,IAAI,WAAW,OAAO,CAAA;AAC/B;AAEO,IAAM,IAAA,GAAmB,IAAI,UAAA","file":"index.cjs","sourcesContent":["/**\r\n * @lytjs/common-http\r\n * Lightweight HTTP client based on native fetch API\r\n */\r\n\r\n// --- Types ---\r\n\r\nexport interface HttpClientOptions {\r\n baseURL?: string;\r\n headers?: Record<string, string>;\r\n timeout?: number;\r\n withCredentials?: boolean;\r\n}\r\n\r\nexport interface RequestOptions {\r\n headers?: Record<string, string>;\r\n params?: Record<string, string>;\r\n timeout?: number;\r\n signal?: AbortSignal;\r\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\r\n}\r\n\r\nexport interface HttpResponse<T> {\r\n data: T;\r\n status: number;\r\n statusText: string;\r\n headers: Record<string, string>;\r\n ok: boolean;\r\n}\r\n\r\nexport interface InternalRequestConfig {\r\n method: string;\r\n url: string;\r\n headers: Record<string, string>;\r\n body?: BodyInit | null;\r\n signal?: AbortSignal;\r\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\r\n withCredentials?: boolean;\r\n timeout?: number;\r\n}\r\n\r\nexport interface Interceptor {\r\n request?(config: InternalRequestConfig): InternalRequestConfig | Promise<InternalRequestConfig>;\r\n response?(response: HttpResponse<unknown>): HttpResponse<unknown> | Promise<HttpResponse<unknown>>;\r\n error?(error: HttpError): unknown;\r\n}\r\n\r\n// --- HttpError ---\r\n\r\nexport class HttpError extends Error {\r\n readonly response?: HttpResponse<unknown>;\r\n readonly status?: number;\r\n\r\n constructor(message: string, response?: HttpResponse<unknown>) {\r\n super(message);\r\n this.name = 'HttpError';\r\n this.response = response;\r\n this.status = response?.status;\r\n }\r\n}\r\n\r\n// --- CancellationToken ---\r\n\r\nexport class CancellationToken {\r\n private readonly _controller: AbortController;\r\n private readonly _linkedTokens: CancellationToken[];\r\n\r\n constructor() {\r\n this._controller = new AbortController();\r\n this._linkedTokens = [];\r\n }\r\n\r\n get signal(): AbortSignal {\r\n return this._controller.signal;\r\n }\r\n\r\n cancel(): void {\r\n this._controller.abort();\r\n for (const token of this._linkedTokens) {\r\n token.cancel();\r\n }\r\n }\r\n\r\n get isCancelled(): boolean {\r\n return this._controller.signal.aborted;\r\n }\r\n\r\n static createLinkedToken(...tokens: CancellationToken[]): CancellationToken {\r\n const linked = new CancellationToken();\r\n for (const token of tokens) {\r\n token._linkedTokens.push(linked);\r\n if (token.isCancelled) {\r\n linked.cancel();\r\n return linked;\r\n }\r\n }\r\n return linked;\r\n }\r\n}\r\n\r\n// --- HttpClient ---\r\n\r\nexport class HttpClient {\r\n private readonly _options: HttpClientOptions;\r\n private readonly _interceptors: Interceptor[];\r\n\r\n constructor(options?: HttpClientOptions) {\r\n this._options = { ...options };\r\n this._interceptors = [];\r\n }\r\n\r\n get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('GET', url, options);\r\n }\r\n\r\n post<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('POST', url, { ...options, body: data } as RequestOptions & { body?: unknown });\r\n }\r\n\r\n put<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('PUT', url, { ...options, body: data } as RequestOptions & { body?: unknown });\r\n }\r\n\r\n delete<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('DELETE', url, options);\r\n }\r\n\r\n patch<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('PATCH', url, { ...options, body: data } as RequestOptions & { body?: unknown });\r\n }\r\n\r\n async request<T = unknown>(\r\n method: string,\r\n url: string,\r\n options?: RequestOptions & { body?: unknown },\r\n ): Promise<HttpResponse<T>> {\r\n let config = this._buildConfig(method, url, options);\r\n\r\n // Apply request interceptors\r\n for (const interceptor of this._interceptors) {\r\n if (interceptor.request) {\r\n config = await interceptor.request(config);\r\n }\r\n }\r\n\r\n try {\r\n const response = await this._fetch(config);\r\n let httpResponse = await this._parseResponse<T>(response, config.responseType);\r\n\r\n // Apply response interceptors\r\n for (const interceptor of this._interceptors) {\r\n if (interceptor.response) {\r\n httpResponse = (await interceptor.response(httpResponse as HttpResponse<unknown>)) as HttpResponse<T>;\r\n }\r\n }\r\n\r\n return httpResponse;\r\n } catch (err) {\r\n // Apply error interceptors\r\n for (const interceptor of this._interceptors) {\r\n if (interceptor.error) {\r\n const result = interceptor.error(err instanceof HttpError ? err : new HttpError(String(err)));\r\n if (result !== undefined) return result as HttpResponse<T>;\r\n }\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n use(interceptor: Interceptor): () => void {\r\n this._interceptors.push(interceptor);\r\n return () => this.eject(interceptor);\r\n }\r\n\r\n eject(interceptor: Interceptor): void {\r\n const index = this._interceptors.indexOf(interceptor);\r\n if (index !== -1) {\r\n this._interceptors.splice(index, 1);\r\n }\r\n }\r\n\r\n private _buildConfig(\r\n method: string,\r\n url: string,\r\n options?: RequestOptions & { body?: unknown },\r\n ): InternalRequestConfig {\r\n const { baseURL = '', headers: defaultHeaders = {} } = this._options;\r\n const resolvedURL = this._resolveURL(baseURL, url, options?.params);\r\n\r\n const headers: Record<string, string> = { ...defaultHeaders, ...options?.headers };\r\n\r\n let body: BodyInit | null = null;\r\n if (options && 'body' in options && options.body !== undefined) {\r\n if (typeof options.body === 'object' && options.body !== null) {\r\n body = JSON.stringify(options.body);\r\n if (!headers['Content-Type']) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n } else {\r\n body = String(options.body);\r\n }\r\n }\r\n\r\n const timeout = options?.timeout ?? this._options.timeout;\r\n\r\n return {\r\n method: method.toUpperCase(),\r\n url: resolvedURL,\r\n headers,\r\n body,\r\n signal: options?.signal,\r\n responseType: options?.responseType,\r\n withCredentials: this._options.withCredentials,\r\n timeout,\r\n };\r\n }\r\n\r\n private _resolveURL(base: string, url: string, params?: Record<string, string>): string {\r\n let resolved = base ? base.replace(/\\/+$/, '') + '/' + url.replace(/^\\/+/, '') : url;\r\n if (params) {\r\n const searchParams = new URLSearchParams(params);\r\n const qs = searchParams.toString();\r\n if (qs) {\r\n resolved += (resolved.includes('?') ? '&' : '?') + qs;\r\n }\r\n }\r\n return resolved;\r\n }\r\n\r\n private async _fetch(config: InternalRequestConfig): Promise<Response> {\r\n const { method, url, headers, body, signal, withCredentials, timeout } = config;\r\n\r\n // Handle timeout via AbortController\r\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\r\n let timeoutController: AbortController | undefined;\r\n\r\n if (timeout && timeout > 0) {\r\n timeoutController = new AbortController();\r\n timeoutId = setTimeout(() => timeoutController!.abort(), timeout);\r\n\r\n // Link with existing signal\r\n if (signal) {\r\n if (signal.aborted) {\r\n clearTimeout(timeoutId);\r\n throw new HttpError('Request was aborted', undefined);\r\n }\r\n signal.addEventListener('abort', () => {\r\n clearTimeout(timeoutId);\r\n timeoutController!.abort();\r\n }, { once: true });\r\n }\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method,\r\n headers,\r\n body,\r\n credentials: withCredentials ? 'include' : undefined,\r\n signal: timeoutController ? timeoutController.signal : signal,\r\n };\r\n\r\n try {\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorResponse: HttpResponse<unknown> = {\r\n data: null,\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: this._parseHeaders(response.headers),\r\n ok: false,\r\n };\r\n throw new HttpError(\r\n `HTTP ${response.status}: ${response.statusText}`,\r\n errorResponse,\r\n );\r\n }\r\n\r\n return response;\r\n } finally {\r\n if (timeoutId !== undefined) {\r\n clearTimeout(timeoutId);\r\n }\r\n }\r\n }\r\n\r\n private async _parseResponse<T>(\r\n response: Response,\r\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer',\r\n ): Promise<HttpResponse<T>> {\r\n let data: T;\r\n switch (responseType) {\r\n case 'text':\r\n data = (await response.text()) as unknown as T;\r\n break;\r\n case 'blob':\r\n data = (await response.blob()) as unknown as T;\r\n break;\r\n case 'arraybuffer':\r\n data = (await response.arrayBuffer()) as unknown as T;\r\n break;\r\n case 'json':\r\n default: {\r\n const text = await response.text();\r\n data = text ? JSON.parse(text) : (null as unknown as T);\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n data,\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: this._parseHeaders(response.headers),\r\n ok: response.ok,\r\n };\r\n }\r\n\r\n private _parseHeaders(headers: Headers): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n headers.forEach((value, key) => {\r\n result[key] = value;\r\n });\r\n return result;\r\n }\r\n}\r\n\r\n// --- Convenience exports ---\r\n\r\nexport function createHttpClient(options?: HttpClientOptions): HttpClient {\r\n return new HttpClient(options);\r\n}\r\n\r\nexport const http: HttpClient = new HttpClient();\r\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["stringifyQueryString","response"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @lytjs/common-http\n * Lightweight HTTP client based on native fetch API\n */\n\n// --- Imports ---\nimport { stringifyQueryString } from '@lytjs/common-query';\n\n// --- Types ---\n\nexport interface HttpClientOptions {\n baseURL?: string;\n headers?: Record<string, string>;\n timeout?: number;\n withCredentials?: boolean;\n}\n\nexport interface RequestOptions {\n headers?: Record<string, string>;\n params?: Record<string, string | number | boolean | Array<string | number | boolean>>;\n timeout?: number;\n signal?: AbortSignal;\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\n}\n\nexport interface HttpResponse<T> {\n data: T;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n ok: boolean;\n}\n\nexport interface InternalRequestConfig {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: BodyInit | null;\n signal?: AbortSignal;\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\n withCredentials?: boolean;\n timeout?: number;\n}\n\nexport interface Interceptor {\n request?(config: InternalRequestConfig): InternalRequestConfig | Promise<InternalRequestConfig>;\n response?(\n response: HttpResponse<unknown>,\n ): HttpResponse<unknown> | Promise<HttpResponse<unknown>>;\n error?(error: HttpError): unknown;\n}\n\n// --- HttpError ---\n\nexport class HttpError extends Error {\n readonly response?: HttpResponse<unknown>;\n readonly status?: number;\n\n constructor(message: string, response?: HttpResponse<unknown>) {\n super(message);\n this.name = 'HttpError';\n this.response = response;\n this.status = response?.status;\n }\n}\n\n// --- CancellationToken ---\n\nexport class CancellationToken {\n private readonly _controller: AbortController;\n private readonly _linkedTokens: CancellationToken[];\n\n constructor() {\n this._controller = new AbortController();\n this._linkedTokens = [];\n }\n\n get signal(): AbortSignal {\n return this._controller.signal;\n }\n\n cancel(): void {\n this._controller.abort();\n for (const token of this._linkedTokens) {\n token.cancel();\n }\n }\n\n get isCancelled(): boolean {\n return this._controller.signal.aborted;\n }\n\n static createLinkedToken(...tokens: CancellationToken[]): CancellationToken {\n const linked = new CancellationToken();\n for (const token of tokens) {\n token._linkedTokens.push(linked);\n if (token.isCancelled) {\n linked.cancel();\n return linked;\n }\n }\n return linked;\n }\n}\n\n// --- HttpClient ---\n\nexport class HttpClient {\n private readonly _options: HttpClientOptions;\n private readonly _interceptors: Interceptor[];\n\n constructor(options?: HttpClientOptions) {\n this._options = { ...options };\n this._interceptors = [];\n }\n\n get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return this.request<T>('GET', url, options);\n }\n\n post<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n return this.request<T>('POST', url, { ...options, body: data } as RequestOptions & {\n body?: unknown;\n });\n }\n\n put<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n return this.request<T>('PUT', url, { ...options, body: data } as RequestOptions & {\n body?: unknown;\n });\n }\n\n delete<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return this.request<T>('DELETE', url, options);\n }\n\n patch<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n return this.request<T>('PATCH', url, { ...options, body: data } as RequestOptions & {\n body?: unknown;\n });\n }\n\n async request<T = unknown>(\n method: string,\n url: string,\n options?: RequestOptions & { body?: unknown },\n ): Promise<HttpResponse<T>> {\n let config = this._buildConfig(method, url, options);\n\n // Apply request interceptors\n for (const interceptor of this._interceptors) {\n if (interceptor.request) {\n config = await interceptor.request(config);\n }\n }\n\n try {\n const response = await this._fetch(config);\n let httpResponse = await this._parseResponse<T>(response, config.responseType);\n\n // Apply response interceptors\n for (const interceptor of this._interceptors) {\n if (interceptor.response) {\n httpResponse = (await interceptor.response(\n httpResponse as HttpResponse<unknown>,\n )) as HttpResponse<T>;\n }\n }\n\n return httpResponse;\n } catch (err) {\n // Apply error interceptors\n for (const interceptor of this._interceptors) {\n if (interceptor.error) {\n const result = interceptor.error(\n err instanceof HttpError ? err : new HttpError(String(err)),\n );\n if (result !== undefined) return result as HttpResponse<T>;\n }\n }\n throw err;\n }\n }\n\n use(interceptor: Interceptor): () => void {\n this._interceptors.push(interceptor);\n return () => this.eject(interceptor);\n }\n\n eject(interceptor: Interceptor): void {\n const index = this._interceptors.indexOf(interceptor);\n if (index !== -1) {\n this._interceptors.splice(index, 1);\n }\n }\n\n private _buildConfig(\n method: string,\n url: string,\n options?: RequestOptions & { body?: unknown },\n ): InternalRequestConfig {\n const { baseURL = '', headers: defaultHeaders = {} } = this._options;\n const resolvedURL = this._resolveURL(baseURL, url, options?.params);\n\n const headers: Record<string, string> = { ...defaultHeaders, ...options?.headers };\n\n let body: BodyInit | null = null;\n if (options && 'body' in options && options.body !== undefined) {\n if (typeof options.body === 'object' && options.body !== null) {\n body = JSON.stringify(options.body);\n if (!headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n } else {\n body = String(options.body);\n }\n }\n\n const timeout = options?.timeout ?? this._options.timeout;\n\n return {\n method: method.toUpperCase(),\n url: resolvedURL,\n headers,\n body,\n signal: options?.signal,\n responseType: options?.responseType,\n withCredentials: this._options.withCredentials,\n timeout,\n };\n }\n\n private _resolveURL(\n base: string,\n url: string,\n params?: Record<string, string | number | boolean | Array<string | number | boolean>>,\n ): string {\n let resolved = base ? base.replace(/\\/+$/, '') + '/' + url.replace(/^\\/+/, '') : url;\n if (params) {\n const qs = stringifyQueryString(params);\n if (qs) {\n resolved += (resolved.includes('?') ? '&' : '?') + qs;\n }\n }\n return resolved;\n }\n\n private async _fetch(config: InternalRequestConfig): Promise<Response> {\n const { method, url, headers, body, signal, withCredentials, timeout } = config;\n\n // Handle timeout via AbortController\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timeoutController: AbortController | undefined;\n\n if (timeout && timeout > 0) {\n timeoutController = new AbortController();\n timeoutId = setTimeout(() => timeoutController!.abort(), timeout);\n\n // Link with existing signal\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timeoutId);\n throw new HttpError('Request was aborted', undefined);\n }\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeoutId);\n timeoutController!.abort();\n },\n { once: true },\n );\n }\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n body,\n credentials: withCredentials ? 'include' : undefined,\n signal: timeoutController ? timeoutController.signal : signal,\n };\n\n try {\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorResponse: HttpResponse<unknown> = {\n data: null,\n status: response.status,\n statusText: response.statusText,\n headers: this._parseHeaders(response.headers),\n ok: false,\n };\n throw new HttpError(`HTTP ${response.status}: ${response.statusText}`, errorResponse);\n }\n\n return response;\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async _parseResponse<T>(\n response: Response,\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer',\n ): Promise<HttpResponse<T>> {\n let data: T;\n switch (responseType) {\n case 'text':\n data = (await response.text()) as unknown as T;\n break;\n case 'blob':\n data = (await response.blob()) as unknown as T;\n break;\n case 'arraybuffer':\n data = (await response.arrayBuffer()) as unknown as T;\n break;\n case 'json':\n default: {\n const text = await response.text();\n data = text ? JSON.parse(text) : (null as unknown as T);\n break;\n }\n }\n\n return {\n data,\n status: response.status,\n statusText: response.statusText,\n headers: this._parseHeaders(response.headers),\n ok: response.ok,\n };\n }\n\n private _parseHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n }\n}\n\n// --- Convenience exports ---\n\nexport function createHttpClient(options?: HttpClientOptions): HttpClient {\n return new HttpClient(options);\n}\n\nexport const http: HttpClient = new HttpClient();\n\n// --- Convenience methods for the default http client ---\n\n/**\n * 便捷 GET 请求\n */\nexport function get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return http.get<T>(url, options);\n}\n\n/**\n * 便捷 POST 请求\n */\nexport function post<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<HttpResponse<T>> {\n return http.post<T>(url, data, options);\n}\n\n/**\n * 便捷 PUT 请求\n */\nexport function put<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<HttpResponse<T>> {\n return http.put<T>(url, data, options);\n}\n\n/**\n * 便捷 DELETE 请求\n */\nexport function del<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return http.delete<T>(url, options);\n}\n\n/**\n * 便捷 PATCH 请求\n */\nexport function patch<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<HttpResponse<T>> {\n return http.patch<T>(url, data, options);\n}\n\n/**\n * 发送 JSON 请求并直接获取数据\n * 自动处理响应解析和错误\n */\nexport async function requestJson<T = unknown>(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n url: string,\n options?: RequestOptions & { data?: unknown },\n): Promise<T> {\n const { data, ...config } = options || {};\n\n if (method === 'GET' || method === 'DELETE') {\n const response = await http.request<T>(method, url, config);\n return response.data;\n }\n\n const response = await http.request<T>(method, url, { ...config, body: data });\n return response.data;\n}\n\n/**\n * 发送 GET JSON 请求\n */\nexport async function getJson<T = unknown>(url: string, options?: RequestOptions): Promise<T> {\n return requestJson<T>('GET', url, options);\n}\n\n/**\n * 发送 POST JSON 请求\n */\nexport async function postJson<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<T> {\n return requestJson<T>('POST', url, { ...options, data });\n}\n\n/**\n * 发送 PUT JSON 请求\n */\nexport async function putJson<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<T> {\n return requestJson<T>('PUT', url, { ...options, data });\n}\n\n/**\n * 发送 PATCH JSON 请求\n */\nexport async function patchJson<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<T> {\n return requestJson<T>('PATCH', url, { ...options, data });\n}\n\n/**\n * 发送 DELETE JSON 请求\n */\nexport async function deleteJson<T = unknown>(url: string, options?: RequestOptions): Promise<T> {\n return requestJson<T>('DELETE', url, options);\n}\n"]}
package/dist/index.d.mts CHANGED
@@ -10,7 +10,7 @@ interface HttpClientOptions {
10
10
  }
11
11
  interface RequestOptions {
12
12
  headers?: Record<string, string>;
13
- params?: Record<string, string>;
13
+ params?: Record<string, string | number | boolean | Array<string | number | boolean>>;
14
14
  timeout?: number;
15
15
  signal?: AbortSignal;
16
16
  responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';
@@ -73,5 +73,52 @@ declare class HttpClient {
73
73
  }
74
74
  declare function createHttpClient(options?: HttpClientOptions): HttpClient;
75
75
  declare const http: HttpClient;
76
+ /**
77
+ * 便捷 GET 请求
78
+ */
79
+ declare function get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>;
80
+ /**
81
+ * 便捷 POST 请求
82
+ */
83
+ declare function post<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>>;
84
+ /**
85
+ * 便捷 PUT 请求
86
+ */
87
+ declare function put<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>>;
88
+ /**
89
+ * 便捷 DELETE 请求
90
+ */
91
+ declare function del<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>;
92
+ /**
93
+ * 便捷 PATCH 请求
94
+ */
95
+ declare function patch<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>>;
96
+ /**
97
+ * 发送 JSON 请求并直接获取数据
98
+ * 自动处理响应解析和错误
99
+ */
100
+ declare function requestJson<T = unknown>(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', url: string, options?: RequestOptions & {
101
+ data?: unknown;
102
+ }): Promise<T>;
103
+ /**
104
+ * 发送 GET JSON 请求
105
+ */
106
+ declare function getJson<T = unknown>(url: string, options?: RequestOptions): Promise<T>;
107
+ /**
108
+ * 发送 POST JSON 请求
109
+ */
110
+ declare function postJson<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<T>;
111
+ /**
112
+ * 发送 PUT JSON 请求
113
+ */
114
+ declare function putJson<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<T>;
115
+ /**
116
+ * 发送 PATCH JSON 请求
117
+ */
118
+ declare function patchJson<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<T>;
119
+ /**
120
+ * 发送 DELETE JSON 请求
121
+ */
122
+ declare function deleteJson<T = unknown>(url: string, options?: RequestOptions): Promise<T>;
76
123
 
77
- export { CancellationToken, HttpClient, type HttpClientOptions, HttpError, type HttpResponse, type Interceptor, type InternalRequestConfig, type RequestOptions, createHttpClient, http };
124
+ export { CancellationToken, HttpClient, type HttpClientOptions, HttpError, type HttpResponse, type Interceptor, type InternalRequestConfig, type RequestOptions, createHttpClient, del, deleteJson, get, getJson, http, patch, patchJson, post, postJson, put, putJson, requestJson };
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ interface HttpClientOptions {
10
10
  }
11
11
  interface RequestOptions {
12
12
  headers?: Record<string, string>;
13
- params?: Record<string, string>;
13
+ params?: Record<string, string | number | boolean | Array<string | number | boolean>>;
14
14
  timeout?: number;
15
15
  signal?: AbortSignal;
16
16
  responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';
@@ -73,5 +73,52 @@ declare class HttpClient {
73
73
  }
74
74
  declare function createHttpClient(options?: HttpClientOptions): HttpClient;
75
75
  declare const http: HttpClient;
76
+ /**
77
+ * 便捷 GET 请求
78
+ */
79
+ declare function get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>;
80
+ /**
81
+ * 便捷 POST 请求
82
+ */
83
+ declare function post<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>>;
84
+ /**
85
+ * 便捷 PUT 请求
86
+ */
87
+ declare function put<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>>;
88
+ /**
89
+ * 便捷 DELETE 请求
90
+ */
91
+ declare function del<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>>;
92
+ /**
93
+ * 便捷 PATCH 请求
94
+ */
95
+ declare function patch<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>>;
96
+ /**
97
+ * 发送 JSON 请求并直接获取数据
98
+ * 自动处理响应解析和错误
99
+ */
100
+ declare function requestJson<T = unknown>(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', url: string, options?: RequestOptions & {
101
+ data?: unknown;
102
+ }): Promise<T>;
103
+ /**
104
+ * 发送 GET JSON 请求
105
+ */
106
+ declare function getJson<T = unknown>(url: string, options?: RequestOptions): Promise<T>;
107
+ /**
108
+ * 发送 POST JSON 请求
109
+ */
110
+ declare function postJson<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<T>;
111
+ /**
112
+ * 发送 PUT JSON 请求
113
+ */
114
+ declare function putJson<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<T>;
115
+ /**
116
+ * 发送 PATCH JSON 请求
117
+ */
118
+ declare function patchJson<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<T>;
119
+ /**
120
+ * 发送 DELETE JSON 请求
121
+ */
122
+ declare function deleteJson<T = unknown>(url: string, options?: RequestOptions): Promise<T>;
76
123
 
77
- export { CancellationToken, HttpClient, type HttpClientOptions, HttpError, type HttpResponse, type Interceptor, type InternalRequestConfig, type RequestOptions, createHttpClient, http };
124
+ export { CancellationToken, HttpClient, type HttpClientOptions, HttpError, type HttpResponse, type Interceptor, type InternalRequestConfig, type RequestOptions, createHttpClient, del, deleteJson, get, getJson, http, patch, patchJson, post, postJson, put, putJson, requestJson };