@ticatec/restful_service_api 0.2.0 → 0.3.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-CN.md +201 -54
- package/README.md +194 -48
- package/dist/ApiError.d.ts +17 -0
- package/dist/ApiError.js +17 -0
- package/dist/FileService.d.ts +92 -0
- package/dist/FileService.js +1 -0
- package/dist/RestService.d.ts +128 -54
- package/dist/RestService.js +12 -0
- package/dist/UploadCallback.d.ts +16 -16
- package/dist/index.d.ts +5 -0
- package/package.json +1 -1
package/README-CN.md
CHANGED
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
- 🛡️ **错误处理**: 内置错误处理机制,包含自定义 ApiError 类
|
|
15
15
|
- ⚡ **拦截器**: 支持请求前后拦截器,用于身份验证和数据处理
|
|
16
16
|
- 🎯 **灵活性**: 支持自定义请求头、超时设置和数据处理器
|
|
17
|
+
- 📁 **文件操作**: 专用的文件上传/下载接口
|
|
17
18
|
- 🌐 **浏览器优先**: 专为前端应用程序设计
|
|
19
|
+
- ✨ **PATCH 支持**: 完整支持 HTTP PATCH 方法进行部分更新
|
|
18
20
|
|
|
19
21
|
## 安装
|
|
20
22
|
|
|
@@ -25,7 +27,7 @@ npm install @ticatec/restful_service_api
|
|
|
25
27
|
## 快速开始
|
|
26
28
|
|
|
27
29
|
```typescript
|
|
28
|
-
import RestService from '@ticatec/restful_service_api';
|
|
30
|
+
import RestService, { FileService } from '@ticatec/restful_service_api';
|
|
29
31
|
|
|
30
32
|
// 实现 RestService 接口
|
|
31
33
|
class MyApiClient implements RestService {
|
|
@@ -37,42 +39,78 @@ class MyApiClient implements RestService {
|
|
|
37
39
|
// 在这里实现
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
async patch(url: string, data?: any, options?: RestfulOptions) {
|
|
43
|
+
// 在这里实现
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
// ... 其他方法
|
|
41
47
|
}
|
|
42
48
|
|
|
49
|
+
// 实现 FileService 接口
|
|
50
|
+
class MyFileClient implements FileService {
|
|
51
|
+
async upload(url: string, params: any, file: File, fileKey?: string, dataProcessor?: DataProcessor) {
|
|
52
|
+
// 在这里实现
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string) {
|
|
56
|
+
// 在这里实现
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async download(url: string, filename: string, params: any, method?: string, formData?: any) {
|
|
60
|
+
// 在这里实现
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
43
64
|
const api = new MyApiClient();
|
|
65
|
+
const fileApi = new MyFileClient();
|
|
44
66
|
|
|
45
|
-
//
|
|
67
|
+
// 发起 REST 请求
|
|
46
68
|
const users = await api.get('/users');
|
|
47
69
|
const newUser = await api.post('/users', { name: '张三' });
|
|
70
|
+
const partialUpdate = await api.patch('/users/1', { status: 'active' });
|
|
71
|
+
|
|
72
|
+
// 文件操作
|
|
73
|
+
const result = await fileApi.upload('/upload', { userId: 123 }, file);
|
|
48
74
|
```
|
|
49
75
|
|
|
50
76
|
## API 参考
|
|
51
77
|
|
|
52
78
|
### RestService 接口
|
|
53
79
|
|
|
54
|
-
|
|
80
|
+
用于标准 HTTP REST 操作的主要接口:
|
|
55
81
|
|
|
56
82
|
```typescript
|
|
57
83
|
interface RestService {
|
|
58
84
|
get(url: string, params?: any, dataProcessor?: DataProcessor): Promise<any>;
|
|
59
85
|
post(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
60
86
|
put(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
87
|
+
patch(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
61
88
|
del(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### FileService 接口
|
|
93
|
+
|
|
94
|
+
专用于文件上传和下载操作的接口:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
interface FileService {
|
|
62
98
|
upload(url: string, params: any, file: File, fileKey?: string, dataProcessor?: DataProcessor): Promise<any>;
|
|
63
99
|
asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string): Promise<UploadProgress>;
|
|
64
100
|
download(url: string, filename: string, params: any, method?: string, formData?: any): Promise<any>;
|
|
65
101
|
}
|
|
66
102
|
```
|
|
67
103
|
|
|
68
|
-
###
|
|
104
|
+
### RestService 方法
|
|
69
105
|
|
|
70
106
|
#### `get(url, params?, dataProcessor?)`
|
|
107
|
+
执行 HTTP GET 请求获取资源。
|
|
71
108
|
- **url**: 接口端点 URL
|
|
72
109
|
- **params**: 查询参数(可选)
|
|
73
110
|
- **dataProcessor**: 处理响应数据的函数(可选)
|
|
74
111
|
|
|
75
112
|
#### `post(url, data?, options?)`
|
|
113
|
+
执行 HTTP POST 请求创建新资源。
|
|
76
114
|
- **url**: 接口端点 URL
|
|
77
115
|
- **data**: 请求载荷(可选)
|
|
78
116
|
- **options**: 可选的配置对象,包含:
|
|
@@ -81,20 +119,36 @@ interface RestService {
|
|
|
81
119
|
- **dataProcessor**: 处理响应数据的函数(可选)
|
|
82
120
|
|
|
83
121
|
#### `put(url, data?, options?)`
|
|
84
|
-
|
|
122
|
+
执行 HTTP PUT 请求更新整个资源。
|
|
123
|
+
- **url**: 接口端点 URL
|
|
124
|
+
- **data**: 请求载荷(可选)
|
|
125
|
+
- **options**: 可选的配置对象,包含:
|
|
126
|
+
- **params**: 查询参数(可选)
|
|
127
|
+
- **contentType**: Content-Type 请求头(可选,默认为 application/json)
|
|
128
|
+
- **dataProcessor**: 处理响应数据的函数(可选)
|
|
129
|
+
|
|
130
|
+
#### `patch(url, data?, options?)`
|
|
131
|
+
执行 HTTP PATCH 请求部分更新资源。
|
|
132
|
+
- **url**: 接口端点 URL
|
|
133
|
+
- **data**: 包含要更新字段的请求载荷(可选)
|
|
85
134
|
- **options**: 可选的配置对象,包含:
|
|
86
135
|
- **params**: 查询参数(可选)
|
|
87
136
|
- **contentType**: Content-Type 请求头(可选,默认为 application/json)
|
|
88
137
|
- **dataProcessor**: 处理响应数据的函数(可选)
|
|
89
138
|
|
|
90
139
|
#### `del(url, data?, options?)`
|
|
91
|
-
|
|
140
|
+
执行 HTTP DELETE 请求删除资源。
|
|
141
|
+
- **url**: 接口端点 URL
|
|
142
|
+
- **data**: 请求体数据(可选)
|
|
92
143
|
- **options**: 可选的配置对象,包含:
|
|
93
144
|
- **params**: 查询参数(可选)
|
|
94
145
|
- **contentType**: Content-Type 请求头(可选,默认为 application/json)
|
|
95
146
|
- **dataProcessor**: 处理响应数据的函数(可选)
|
|
96
147
|
|
|
148
|
+
### FileService 方法
|
|
149
|
+
|
|
97
150
|
#### `upload(url, params, file, fileKey?, dataProcessor?)`
|
|
151
|
+
执行同步文件上传操作。
|
|
98
152
|
- **url**: 上传端点 URL
|
|
99
153
|
- **params**: 上传请求的附加参数
|
|
100
154
|
- **file**: 要上传的文件对象
|
|
@@ -102,6 +156,7 @@ interface RestService {
|
|
|
102
156
|
- **dataProcessor**: 处理响应数据的函数(可选)
|
|
103
157
|
|
|
104
158
|
#### `asyncUpload(url, params, file, callback, fileKey?)`
|
|
159
|
+
执行异步文件上传,支持进度监控和取消功能。
|
|
105
160
|
- **url**: 上传端点 URL
|
|
106
161
|
- **params**: 上传请求的附加参数
|
|
107
162
|
- **file**: 要上传的文件对象
|
|
@@ -110,6 +165,7 @@ interface RestService {
|
|
|
110
165
|
- **返回值**: 返回 Promise,解析为 UploadProgress 对象,可用于取消上传
|
|
111
166
|
|
|
112
167
|
#### `download(url, filename, params, method?, formData?)`
|
|
168
|
+
执行文件下载操作。
|
|
113
169
|
- **url**: 下载端点 URL
|
|
114
170
|
- **filename**: 保存下载文件的名称
|
|
115
171
|
- **params**: 下载请求参数
|
|
@@ -202,13 +258,16 @@ await api.post('/upload', data, {}, { contentType: TYPE_JSON });
|
|
|
202
258
|
|
|
203
259
|
以下是使用原生 fetch API 的完整实现示例:
|
|
204
260
|
|
|
261
|
+
### RestService 实现
|
|
262
|
+
|
|
205
263
|
```typescript
|
|
206
264
|
import RestService, {
|
|
207
265
|
ApiError,
|
|
208
266
|
PreInterceptor,
|
|
209
267
|
PostInterceptor,
|
|
210
268
|
RestfulOptions,
|
|
211
|
-
TYPE_JSON
|
|
269
|
+
TYPE_JSON,
|
|
270
|
+
DataProcessor
|
|
212
271
|
} from '@ticatec/restful_service_api';
|
|
213
272
|
|
|
214
273
|
class FetchRestService implements RestService {
|
|
@@ -241,6 +300,13 @@ class FetchRestService implements RestService {
|
|
|
241
300
|
return this.request('PUT', url + queryString, data, contentType, options?.dataProcessor);
|
|
242
301
|
}
|
|
243
302
|
|
|
303
|
+
async patch(url: string, data?: any, options?: RestfulOptions): Promise<any> {
|
|
304
|
+
const contentType = options?.contentType || TYPE_JSON;
|
|
305
|
+
const params = options?.params;
|
|
306
|
+
const queryString = params ? '?' + new URLSearchParams(params).toString() : '';
|
|
307
|
+
return this.request('PATCH', url + queryString, data, contentType, options?.dataProcessor);
|
|
308
|
+
}
|
|
309
|
+
|
|
244
310
|
async del(url: string, data?: any, options?: RestfulOptions): Promise<any> {
|
|
245
311
|
const contentType = options?.contentType || TYPE_JSON;
|
|
246
312
|
const params = options?.params;
|
|
@@ -298,60 +364,140 @@ class FetchRestService implements RestService {
|
|
|
298
364
|
const api = new FetchRestService('https://api.example.com');
|
|
299
365
|
const users = await api.get('/users');
|
|
300
366
|
const newUser = await api.post('/users', { name: '张三' });
|
|
301
|
-
const
|
|
367
|
+
const partialUpdate = await api.patch('/users/1', { status: 'active' });
|
|
368
|
+
const fullUpdate = await api.put('/users/1', { name: '李四', age: 30 });
|
|
302
369
|
```
|
|
303
370
|
|
|
304
|
-
###
|
|
371
|
+
### FileService 实现
|
|
305
372
|
|
|
306
373
|
```typescript
|
|
307
|
-
import
|
|
308
|
-
UploadCallback,
|
|
309
|
-
UploadProgress
|
|
310
|
-
} from '@ticatec/restful_service_api';
|
|
374
|
+
import FileService, { UploadCallback, UploadProgress, DataProcessor } from '@ticatec/restful_service_api';
|
|
311
375
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const file = fileInput.files[0];
|
|
376
|
+
class FetchFileService implements FileService {
|
|
377
|
+
private baseURL: string;
|
|
315
378
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
} catch (error) {
|
|
320
|
-
console.error('上传失败:', error);
|
|
321
|
-
}
|
|
379
|
+
constructor(baseURL: string) {
|
|
380
|
+
this.baseURL = baseURL;
|
|
381
|
+
}
|
|
322
382
|
|
|
323
|
-
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
383
|
+
async upload(url: string, params: any, file: File, fileKey?: string, dataProcessor?: DataProcessor): Promise<any> {
|
|
384
|
+
const formData = new FormData();
|
|
385
|
+
formData.append(fileKey || 'file', file);
|
|
386
|
+
|
|
387
|
+
// 添加附加参数
|
|
388
|
+
Object.keys(params).forEach(key => {
|
|
389
|
+
formData.append(key, params[key]);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const response = await fetch(this.baseURL + url, {
|
|
393
|
+
method: 'POST',
|
|
394
|
+
body: formData
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
if (!response.ok) {
|
|
398
|
+
throw new Error(`上传失败: ${response.statusText}`);
|
|
334
399
|
}
|
|
335
|
-
};
|
|
336
400
|
|
|
337
|
-
const
|
|
401
|
+
const data = await response.json();
|
|
402
|
+
return dataProcessor ? dataProcessor(data) : data;
|
|
403
|
+
}
|
|
338
404
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}, 5000);
|
|
405
|
+
async asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string): Promise<UploadProgress> {
|
|
406
|
+
const formData = new FormData();
|
|
407
|
+
formData.append(fileKey || 'file', file);
|
|
343
408
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
409
|
+
Object.keys(params).forEach(key => {
|
|
410
|
+
formData.append(key, params[key]);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
const xhr = new XMLHttpRequest();
|
|
414
|
+
|
|
415
|
+
return new Promise((resolve) => {
|
|
416
|
+
xhr.upload.addEventListener('progress', (e) => {
|
|
417
|
+
if (e.lengthComputable && callback.progressUpdate) {
|
|
418
|
+
callback.progressUpdate(e.loaded);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
xhr.addEventListener('load', () => {
|
|
423
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
424
|
+
const data = JSON.parse(xhr.responseText);
|
|
425
|
+
callback.onCompleted(data);
|
|
426
|
+
} else if (callback.handleError) {
|
|
427
|
+
callback.handleError(new Error(`上传失败: ${xhr.statusText}`));
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
xhr.addEventListener('error', () => {
|
|
432
|
+
if (callback.handleError) {
|
|
433
|
+
callback.handleError(new Error('网络错误'));
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
xhr.open(callback.method || 'POST', this.baseURL + url);
|
|
438
|
+
xhr.send(formData);
|
|
439
|
+
|
|
440
|
+
resolve({
|
|
441
|
+
cancel: () => xhr.abort()
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async download(url: string, filename: string, params: any, method?: string, formData?: any): Promise<any> {
|
|
447
|
+
let fullUrl = this.baseURL + url;
|
|
448
|
+
|
|
449
|
+
if (method === 'POST' && formData) {
|
|
450
|
+
const form = new FormData();
|
|
451
|
+
Object.keys(formData).forEach(key => {
|
|
452
|
+
form.append(key, formData[key]);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
const response = await fetch(fullUrl, {
|
|
456
|
+
method: 'POST',
|
|
457
|
+
body: form
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const blob = await response.blob();
|
|
461
|
+
const downloadUrl = window.URL.createObjectURL(blob);
|
|
462
|
+
const a = document.createElement('a');
|
|
463
|
+
a.href = downloadUrl;
|
|
464
|
+
a.download = filename;
|
|
465
|
+
a.click();
|
|
466
|
+
window.URL.revokeObjectURL(downloadUrl);
|
|
467
|
+
} else {
|
|
468
|
+
const queryString = params ? '?' + new URLSearchParams(params).toString() : '';
|
|
469
|
+
fullUrl += queryString;
|
|
470
|
+
|
|
471
|
+
const response = await fetch(fullUrl);
|
|
472
|
+
const blob = await response.blob();
|
|
473
|
+
const downloadUrl = window.URL.createObjectURL(blob);
|
|
474
|
+
const a = document.createElement('a');
|
|
475
|
+
a.href = downloadUrl;
|
|
476
|
+
a.download = filename;
|
|
477
|
+
a.click();
|
|
478
|
+
window.URL.revokeObjectURL(downloadUrl);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
350
481
|
}
|
|
351
482
|
|
|
352
|
-
//
|
|
353
|
-
const
|
|
354
|
-
|
|
483
|
+
// 使用示例
|
|
484
|
+
const fileApi = new FetchFileService('https://api.example.com');
|
|
485
|
+
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
|
|
486
|
+
const file = fileInput.files[0];
|
|
487
|
+
|
|
488
|
+
// 简单上传
|
|
489
|
+
const result = await fileApi.upload('/upload', { userId: 123 }, file);
|
|
490
|
+
|
|
491
|
+
// 带进度跟踪的异步上传
|
|
492
|
+
const progress = await fileApi.asyncUpload('/upload', { userId: 123 }, file, {
|
|
493
|
+
method: 'POST',
|
|
494
|
+
progressUpdate: (loaded) => console.log(`已上传: ${loaded} 字节`),
|
|
495
|
+
onCompleted: (data) => console.log('完成!', data),
|
|
496
|
+
handleError: (err) => console.error('错误!', err)
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
// 下载文件
|
|
500
|
+
await fileApi.download('/files/document.pdf', 'my-document.pdf', { userId: 123 });
|
|
355
501
|
```
|
|
356
502
|
|
|
357
503
|
## 工具函数
|
|
@@ -362,20 +508,20 @@ await api.download('/reports/generate', 'monthly-report.pdf', {}, 'POST', formDa
|
|
|
362
508
|
import utils from '@ticatec/restful_service_api/utils';
|
|
363
509
|
|
|
364
510
|
// 将对象转换为查询字符串
|
|
365
|
-
const queryString = utils.toQueryString({ name: '
|
|
366
|
-
// 返回: "name
|
|
511
|
+
const queryString = utils.toQueryString({ name: '张三', age: 30 });
|
|
512
|
+
// 返回: "name=张三&age=30"
|
|
367
513
|
|
|
368
514
|
// 将 URL 与参数组合
|
|
369
515
|
const fullUrl = utils.combineUrl('/api/users', { page: 1, limit: 10 });
|
|
370
516
|
// 返回: "/api/users?page=1&limit=10"
|
|
371
517
|
|
|
372
518
|
// 生成 HTTP 请求选项
|
|
373
|
-
const options = utils.generateRequestOptions('POST', { id: 1 }, { name: '
|
|
374
|
-
// 返回: { method: 'POST', headers: {}, params: { id: 1 }, data: { name: '
|
|
519
|
+
const options = utils.generateRequestOptions('POST', { id: 1 }, { name: '张三' });
|
|
520
|
+
// 返回: { method: 'POST', headers: {}, params: { id: 1 }, data: { name: '张三' } }
|
|
375
521
|
|
|
376
522
|
// 清理参数(移除 null、undefined、空字符串,修剪字符串值)
|
|
377
|
-
const cleanedParams = utils.cleanParams({ name: '
|
|
378
|
-
// 返回: { name: '
|
|
523
|
+
const cleanedParams = utils.cleanParams({ name: ' 张三 ', age: null, email: '' });
|
|
524
|
+
// 返回: { name: '张三' }
|
|
379
525
|
|
|
380
526
|
// 函数工具
|
|
381
527
|
utils.invokeFunction(callback, arg1, arg2); // 安全地调用函数(如果存在)
|
|
@@ -423,6 +569,7 @@ const api = new FetchRestService(
|
|
|
423
569
|
// 现在所有请求都会自动包含认证头
|
|
424
570
|
const profile = await api.get('/user/profile');
|
|
425
571
|
const updated = await api.put('/user/profile', { name: '新名称' });
|
|
572
|
+
const partial = await api.patch('/user/profile', { status: 'active' });
|
|
426
573
|
```
|
|
427
574
|
|
|
428
575
|
## 贡献
|
package/README.md
CHANGED
|
@@ -14,7 +14,9 @@ A lightweight TypeScript RESTful API client for browsers with comprehensive erro
|
|
|
14
14
|
- 🛡️ **Error Handling**: Built-in error handling with custom ApiError class
|
|
15
15
|
- ⚡ **Interceptors**: Pre and post request interceptors for authentication and data processing
|
|
16
16
|
- 🎯 **Flexible**: Support for custom headers, timeouts, and data processors
|
|
17
|
+
- 📁 **File Operations**: Dedicated interface for file upload/download operations
|
|
17
18
|
- 🌐 **Browser-First**: Designed specifically for frontend applications
|
|
19
|
+
- ✨ **PATCH Support**: Full support for HTTP PATCH method for partial updates
|
|
18
20
|
|
|
19
21
|
## Installation
|
|
20
22
|
|
|
@@ -25,7 +27,7 @@ npm install @ticatec/restful_service_api
|
|
|
25
27
|
## Quick Start
|
|
26
28
|
|
|
27
29
|
```typescript
|
|
28
|
-
import RestService from '@ticatec/restful_service_api';
|
|
30
|
+
import RestService, { FileService } from '@ticatec/restful_service_api';
|
|
29
31
|
|
|
30
32
|
// Your implementation of RestService interface
|
|
31
33
|
class MyApiClient implements RestService {
|
|
@@ -37,42 +39,78 @@ class MyApiClient implements RestService {
|
|
|
37
39
|
// Implementation here
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
async patch(url: string, data?: any, options?: RestfulOptions) {
|
|
43
|
+
// Implementation here
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
// ... other methods
|
|
41
47
|
}
|
|
42
48
|
|
|
49
|
+
// Your implementation of FileService interface
|
|
50
|
+
class MyFileClient implements FileService {
|
|
51
|
+
async upload(url: string, params: any, file: File, fileKey?: string, dataProcessor?: DataProcessor) {
|
|
52
|
+
// Implementation here
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string) {
|
|
56
|
+
// Implementation here
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async download(url: string, filename: string, params: any, method?: string, formData?: any) {
|
|
60
|
+
// Implementation here
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
43
64
|
const api = new MyApiClient();
|
|
65
|
+
const fileApi = new MyFileClient();
|
|
44
66
|
|
|
45
|
-
// Make requests
|
|
67
|
+
// Make REST requests
|
|
46
68
|
const users = await api.get('/users');
|
|
47
69
|
const newUser = await api.post('/users', { name: 'John Doe' });
|
|
70
|
+
const partialUpdate = await api.patch('/users/1', { status: 'active' });
|
|
71
|
+
|
|
72
|
+
// File operations
|
|
73
|
+
const result = await fileApi.upload('/upload', { userId: 123 }, file);
|
|
48
74
|
```
|
|
49
75
|
|
|
50
76
|
## API Reference
|
|
51
77
|
|
|
52
78
|
### RestService Interface
|
|
53
79
|
|
|
54
|
-
The main interface
|
|
80
|
+
The main interface for standard HTTP REST operations:
|
|
55
81
|
|
|
56
82
|
```typescript
|
|
57
83
|
interface RestService {
|
|
58
84
|
get(url: string, params?: any, dataProcessor?: DataProcessor): Promise<any>;
|
|
59
85
|
post(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
60
86
|
put(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
87
|
+
patch(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
61
88
|
del(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### FileService Interface
|
|
93
|
+
|
|
94
|
+
Dedicated interface for file upload and download operations:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
interface FileService {
|
|
62
98
|
upload(url: string, params: any, file: File, fileKey?: string, dataProcessor?: DataProcessor): Promise<any>;
|
|
63
99
|
asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string): Promise<UploadProgress>;
|
|
64
100
|
download(url: string, filename: string, params: any, method?: string, formData?: any): Promise<any>;
|
|
65
101
|
}
|
|
66
102
|
```
|
|
67
103
|
|
|
68
|
-
### Methods
|
|
104
|
+
### RestService Methods
|
|
69
105
|
|
|
70
106
|
#### `get(url, params?, dataProcessor?)`
|
|
107
|
+
Performs HTTP GET request to retrieve a resource.
|
|
71
108
|
- **url**: The endpoint URL
|
|
72
109
|
- **params**: Query parameters (optional)
|
|
73
110
|
- **dataProcessor**: Function to process response data (optional)
|
|
74
111
|
|
|
75
112
|
#### `post(url, data?, options?)`
|
|
113
|
+
Performs HTTP POST request to create a new resource.
|
|
76
114
|
- **url**: The endpoint URL
|
|
77
115
|
- **data**: Request payload (optional)
|
|
78
116
|
- **options**: Optional configuration object containing:
|
|
@@ -81,20 +119,36 @@ interface RestService {
|
|
|
81
119
|
- **dataProcessor**: Function to process response data (optional)
|
|
82
120
|
|
|
83
121
|
#### `put(url, data?, options?)`
|
|
84
|
-
|
|
122
|
+
Performs HTTP PUT request to update an entire resource.
|
|
123
|
+
- **url**: The endpoint URL
|
|
124
|
+
- **data**: Request payload (optional)
|
|
125
|
+
- **options**: Optional configuration object containing:
|
|
126
|
+
- **params**: Query parameters (optional)
|
|
127
|
+
- **contentType**: Content-Type header (optional, defaults to application/json)
|
|
128
|
+
- **dataProcessor**: Function to process response data (optional)
|
|
129
|
+
|
|
130
|
+
#### `patch(url, data?, options?)`
|
|
131
|
+
Performs HTTP PATCH request to partially update a resource.
|
|
132
|
+
- **url**: The endpoint URL
|
|
133
|
+
- **data**: Request payload with fields to update (optional)
|
|
85
134
|
- **options**: Optional configuration object containing:
|
|
86
135
|
- **params**: Query parameters (optional)
|
|
87
136
|
- **contentType**: Content-Type header (optional, defaults to application/json)
|
|
88
137
|
- **dataProcessor**: Function to process response data (optional)
|
|
89
138
|
|
|
90
139
|
#### `del(url, data?, options?)`
|
|
91
|
-
|
|
140
|
+
Performs HTTP DELETE request to delete a resource.
|
|
141
|
+
- **url**: The endpoint URL
|
|
142
|
+
- **data**: Request body data (optional)
|
|
92
143
|
- **options**: Optional configuration object containing:
|
|
93
144
|
- **params**: Query parameters (optional)
|
|
94
145
|
- **contentType**: Content-Type header (optional, defaults to application/json)
|
|
95
146
|
- **dataProcessor**: Function to process response data (optional)
|
|
96
147
|
|
|
148
|
+
### FileService Methods
|
|
149
|
+
|
|
97
150
|
#### `upload(url, params, file, fileKey?, dataProcessor?)`
|
|
151
|
+
Performs synchronous file upload operation.
|
|
98
152
|
- **url**: The upload endpoint URL
|
|
99
153
|
- **params**: Additional parameters for the upload request
|
|
100
154
|
- **file**: The File object to upload
|
|
@@ -102,6 +156,7 @@ For delete operations with optional request body.
|
|
|
102
156
|
- **dataProcessor**: Function to process response data (optional)
|
|
103
157
|
|
|
104
158
|
#### `asyncUpload(url, params, file, callback, fileKey?)`
|
|
159
|
+
Performs asynchronous file upload with progress monitoring and cancellation support.
|
|
105
160
|
- **url**: The upload endpoint URL
|
|
106
161
|
- **params**: Additional parameters for the upload request
|
|
107
162
|
- **file**: The File object to upload
|
|
@@ -110,6 +165,7 @@ For delete operations with optional request body.
|
|
|
110
165
|
- **Returns**: Promise that resolves to UploadProgress object for cancellation
|
|
111
166
|
|
|
112
167
|
#### `download(url, filename, params, method?, formData?)`
|
|
168
|
+
Performs file download operation.
|
|
113
169
|
- **url**: The download endpoint URL
|
|
114
170
|
- **filename**: The name to save the downloaded file
|
|
115
171
|
- **params**: Download request parameters
|
|
@@ -202,13 +258,16 @@ await api.post('/upload', data, {}, { contentType: TYPE_JSON });
|
|
|
202
258
|
|
|
203
259
|
Here's a complete example implementation using the native fetch API:
|
|
204
260
|
|
|
261
|
+
### RestService Implementation
|
|
262
|
+
|
|
205
263
|
```typescript
|
|
206
264
|
import RestService, {
|
|
207
265
|
ApiError,
|
|
208
266
|
PreInterceptor,
|
|
209
267
|
PostInterceptor,
|
|
210
268
|
RestfulOptions,
|
|
211
|
-
TYPE_JSON
|
|
269
|
+
TYPE_JSON,
|
|
270
|
+
DataProcessor
|
|
212
271
|
} from '@ticatec/restful_service_api';
|
|
213
272
|
|
|
214
273
|
class FetchRestService implements RestService {
|
|
@@ -241,6 +300,13 @@ class FetchRestService implements RestService {
|
|
|
241
300
|
return this.request('PUT', url + queryString, data, contentType, options?.dataProcessor);
|
|
242
301
|
}
|
|
243
302
|
|
|
303
|
+
async patch(url: string, data?: any, options?: RestfulOptions): Promise<any> {
|
|
304
|
+
const contentType = options?.contentType || TYPE_JSON;
|
|
305
|
+
const params = options?.params;
|
|
306
|
+
const queryString = params ? '?' + new URLSearchParams(params).toString() : '';
|
|
307
|
+
return this.request('PATCH', url + queryString, data, contentType, options?.dataProcessor);
|
|
308
|
+
}
|
|
309
|
+
|
|
244
310
|
async del(url: string, data?: any, options?: RestfulOptions): Promise<any> {
|
|
245
311
|
const contentType = options?.contentType || TYPE_JSON;
|
|
246
312
|
const params = options?.params;
|
|
@@ -298,60 +364,140 @@ class FetchRestService implements RestService {
|
|
|
298
364
|
const api = new FetchRestService('https://api.example.com');
|
|
299
365
|
const users = await api.get('/users');
|
|
300
366
|
const newUser = await api.post('/users', { name: 'John Doe' });
|
|
301
|
-
const
|
|
367
|
+
const partialUpdate = await api.patch('/users/1', { status: 'active' });
|
|
368
|
+
const fullUpdate = await api.put('/users/1', { name: 'Jane Doe', age: 30 });
|
|
302
369
|
```
|
|
303
370
|
|
|
304
|
-
###
|
|
371
|
+
### FileService Implementation
|
|
305
372
|
|
|
306
373
|
```typescript
|
|
307
|
-
import
|
|
308
|
-
UploadCallback,
|
|
309
|
-
UploadProgress
|
|
310
|
-
} from '@ticatec/restful_service_api';
|
|
374
|
+
import FileService, { UploadCallback, UploadProgress, DataProcessor } from '@ticatec/restful_service_api';
|
|
311
375
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const file = fileInput.files[0];
|
|
376
|
+
class FetchFileService implements FileService {
|
|
377
|
+
private baseURL: string;
|
|
315
378
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
} catch (error) {
|
|
320
|
-
console.error('Upload failed:', error);
|
|
321
|
-
}
|
|
379
|
+
constructor(baseURL: string) {
|
|
380
|
+
this.baseURL = baseURL;
|
|
381
|
+
}
|
|
322
382
|
|
|
323
|
-
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
383
|
+
async upload(url: string, params: any, file: File, fileKey?: string, dataProcessor?: DataProcessor): Promise<any> {
|
|
384
|
+
const formData = new FormData();
|
|
385
|
+
formData.append(fileKey || 'file', file);
|
|
386
|
+
|
|
387
|
+
// Add additional parameters
|
|
388
|
+
Object.keys(params).forEach(key => {
|
|
389
|
+
formData.append(key, params[key]);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const response = await fetch(this.baseURL + url, {
|
|
393
|
+
method: 'POST',
|
|
394
|
+
body: formData
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
if (!response.ok) {
|
|
398
|
+
throw new Error(`Upload failed: ${response.statusText}`);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const data = await response.json();
|
|
402
|
+
return dataProcessor ? dataProcessor(data) : data;
|
|
334
403
|
}
|
|
335
|
-
};
|
|
336
404
|
|
|
337
|
-
|
|
405
|
+
async asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string): Promise<UploadProgress> {
|
|
406
|
+
const formData = new FormData();
|
|
407
|
+
formData.append(fileKey || 'file', file);
|
|
338
408
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}, 5000);
|
|
409
|
+
Object.keys(params).forEach(key => {
|
|
410
|
+
formData.append(key, params[key]);
|
|
411
|
+
});
|
|
343
412
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
413
|
+
const xhr = new XMLHttpRequest();
|
|
414
|
+
|
|
415
|
+
return new Promise((resolve) => {
|
|
416
|
+
xhr.upload.addEventListener('progress', (e) => {
|
|
417
|
+
if (e.lengthComputable && callback.progressUpdate) {
|
|
418
|
+
callback.progressUpdate(e.loaded);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
xhr.addEventListener('load', () => {
|
|
423
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
424
|
+
const data = JSON.parse(xhr.responseText);
|
|
425
|
+
callback.onCompleted(data);
|
|
426
|
+
} else if (callback.handleError) {
|
|
427
|
+
callback.handleError(new Error(`Upload failed: ${xhr.statusText}`));
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
xhr.addEventListener('error', () => {
|
|
432
|
+
if (callback.handleError) {
|
|
433
|
+
callback.handleError(new Error('Network error'));
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
xhr.open(callback.method || 'POST', this.baseURL + url);
|
|
438
|
+
xhr.send(formData);
|
|
439
|
+
|
|
440
|
+
resolve({
|
|
441
|
+
cancel: () => xhr.abort()
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async download(url: string, filename: string, params: any, method?: string, formData?: any): Promise<any> {
|
|
447
|
+
let fullUrl = this.baseURL + url;
|
|
448
|
+
|
|
449
|
+
if (method === 'POST' && formData) {
|
|
450
|
+
const form = new FormData();
|
|
451
|
+
Object.keys(formData).forEach(key => {
|
|
452
|
+
form.append(key, formData[key]);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
const response = await fetch(fullUrl, {
|
|
456
|
+
method: 'POST',
|
|
457
|
+
body: form
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const blob = await response.blob();
|
|
461
|
+
const downloadUrl = window.URL.createObjectURL(blob);
|
|
462
|
+
const a = document.createElement('a');
|
|
463
|
+
a.href = downloadUrl;
|
|
464
|
+
a.download = filename;
|
|
465
|
+
a.click();
|
|
466
|
+
window.URL.revokeObjectURL(downloadUrl);
|
|
467
|
+
} else {
|
|
468
|
+
const queryString = params ? '?' + new URLSearchParams(params).toString() : '';
|
|
469
|
+
fullUrl += queryString;
|
|
470
|
+
|
|
471
|
+
const response = await fetch(fullUrl);
|
|
472
|
+
const blob = await response.blob();
|
|
473
|
+
const downloadUrl = window.URL.createObjectURL(blob);
|
|
474
|
+
const a = document.createElement('a');
|
|
475
|
+
a.href = downloadUrl;
|
|
476
|
+
a.download = filename;
|
|
477
|
+
a.click();
|
|
478
|
+
window.URL.revokeObjectURL(downloadUrl);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
350
481
|
}
|
|
351
482
|
|
|
352
|
-
//
|
|
353
|
-
const
|
|
354
|
-
|
|
483
|
+
// Usage
|
|
484
|
+
const fileApi = new FetchFileService('https://api.example.com');
|
|
485
|
+
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
|
|
486
|
+
const file = fileInput.files[0];
|
|
487
|
+
|
|
488
|
+
// Simple upload
|
|
489
|
+
const result = await fileApi.upload('/upload', { userId: 123 }, file);
|
|
490
|
+
|
|
491
|
+
// Async upload with progress
|
|
492
|
+
const progress = await fileApi.asyncUpload('/upload', { userId: 123 }, file, {
|
|
493
|
+
method: 'POST',
|
|
494
|
+
progressUpdate: (loaded) => console.log(`Uploaded: ${loaded} bytes`),
|
|
495
|
+
onCompleted: (data) => console.log('Done!', data),
|
|
496
|
+
handleError: (err) => console.error('Error!', err)
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
// Download file
|
|
500
|
+
await fileApi.download('/files/document.pdf', 'my-document.pdf', { userId: 123 });
|
|
355
501
|
```
|
|
356
502
|
|
|
357
503
|
## Utility Functions
|
package/dist/ApiError.d.ts
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API error class for handling HTTP request errors
|
|
3
|
+
*/
|
|
1
4
|
export default class ApiError extends Error {
|
|
2
5
|
private _code;
|
|
3
6
|
private _details;
|
|
4
7
|
private _status;
|
|
8
|
+
/**
|
|
9
|
+
* Error code from the API response
|
|
10
|
+
*/
|
|
5
11
|
get code(): any;
|
|
12
|
+
/**
|
|
13
|
+
* Detailed error information from the API response
|
|
14
|
+
*/
|
|
6
15
|
get details(): any;
|
|
16
|
+
/**
|
|
17
|
+
* HTTP status code of the error response
|
|
18
|
+
*/
|
|
7
19
|
get status(): any;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new API error instance
|
|
22
|
+
* @param status HTTP status code
|
|
23
|
+
* @param err Error object containing code and details
|
|
24
|
+
*/
|
|
8
25
|
constructor(status: any, err: any);
|
|
9
26
|
}
|
package/dist/ApiError.js
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API error class for handling HTTP request errors
|
|
3
|
+
*/
|
|
1
4
|
export default class ApiError extends Error {
|
|
5
|
+
/**
|
|
6
|
+
* Error code from the API response
|
|
7
|
+
*/
|
|
2
8
|
get code() {
|
|
3
9
|
return this._code;
|
|
4
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Detailed error information from the API response
|
|
13
|
+
*/
|
|
5
14
|
get details() {
|
|
6
15
|
return this._details;
|
|
7
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* HTTP status code of the error response
|
|
19
|
+
*/
|
|
8
20
|
get status() {
|
|
9
21
|
return this._status;
|
|
10
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new API error instance
|
|
25
|
+
* @param status HTTP status code
|
|
26
|
+
* @param err Error object containing code and details
|
|
27
|
+
*/
|
|
11
28
|
constructor(status, err) {
|
|
12
29
|
super(err.code);
|
|
13
30
|
this.name = this.constructor.name;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import UploadCallback from "./UploadCallback";
|
|
2
|
+
import { DataProcessor } from "./RestService";
|
|
3
|
+
/**
|
|
4
|
+
* File service interface for file upload and download operations
|
|
5
|
+
*/
|
|
6
|
+
export default interface FileService {
|
|
7
|
+
/**
|
|
8
|
+
* Performs synchronous file upload operation
|
|
9
|
+
* @param url The target URL path for upload
|
|
10
|
+
* @param params Parameters object for the upload request
|
|
11
|
+
* @param file The file object to upload
|
|
12
|
+
* @param fileKey Optional file field name, defaults to 'file'
|
|
13
|
+
* @param dataProcessor Optional data processing function to transform response data before returning
|
|
14
|
+
* @returns Promise that resolves to the server response data
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // Simple file upload
|
|
19
|
+
* const file = document.querySelector('input[type="file"]').files[0];
|
|
20
|
+
* const result = await fileService.upload('/api/upload', { userId: 123 }, file);
|
|
21
|
+
*
|
|
22
|
+
* // Upload with custom file key
|
|
23
|
+
* const result = await fileService.upload('/api/upload', {}, file, 'avatar');
|
|
24
|
+
*
|
|
25
|
+
* // Upload with data processor
|
|
26
|
+
* const result = await fileService.upload('/api/upload', {}, file, 'file', (data) => data.url);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
upload(url: string, params: any, file: File, fileKey?: string, dataProcessor?: DataProcessor): Promise<any>;
|
|
30
|
+
/**
|
|
31
|
+
* Performs asynchronous file upload operation with progress monitoring and cancellation support
|
|
32
|
+
* @param url The target URL path for upload
|
|
33
|
+
* @param params Parameters object for the upload request
|
|
34
|
+
* @param file The file object to upload
|
|
35
|
+
* @param callback Callback function during upload process, including progress updates, error handling, etc.
|
|
36
|
+
* @param fileKey Optional file field name, defaults to 'file'
|
|
37
|
+
* @returns Promise that resolves to UploadProgress object, which can be used to cancel the upload
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* // Async upload with progress monitoring
|
|
42
|
+
* const progress = await fileService.asyncUpload(
|
|
43
|
+
* '/api/upload',
|
|
44
|
+
* { userId: 123 },
|
|
45
|
+
* file,
|
|
46
|
+
* {
|
|
47
|
+
* onProgress: (loaded, total, percent) => {
|
|
48
|
+
* console.log(`Upload: ${percent}%`);
|
|
49
|
+
* },
|
|
50
|
+
* onCompleted: (data) => {
|
|
51
|
+
* console.log('Upload complete:', data);
|
|
52
|
+
* },
|
|
53
|
+
* onError: (error) => {
|
|
54
|
+
* console.error('Upload failed:', error);
|
|
55
|
+
* }
|
|
56
|
+
* }
|
|
57
|
+
* );
|
|
58
|
+
*
|
|
59
|
+
* // Cancel the upload
|
|
60
|
+
* progress.abort();
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string): Promise<import("./UploadCallback").UploadProgress>;
|
|
64
|
+
/**
|
|
65
|
+
* Performs file download operation
|
|
66
|
+
* @param url The URL path to download the file
|
|
67
|
+
* @param filename The filename to save as
|
|
68
|
+
* @param params Parameters object for the download request
|
|
69
|
+
* @param method Optional HTTP method, defaults to GET
|
|
70
|
+
* @param formData Optional form data for POST download
|
|
71
|
+
* @returns Promise that resolves to the download result
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* // Simple file download
|
|
76
|
+
* await fileService.download('/api/files/123', 'document.pdf', {});
|
|
77
|
+
*
|
|
78
|
+
* // Download with parameters
|
|
79
|
+
* await fileService.download('/api/files/export', 'report.xlsx', {
|
|
80
|
+
* format: 'xlsx',
|
|
81
|
+
* date: '2024-01-01'
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* // Download via POST
|
|
85
|
+
* await fileService.download('/api/files/generate', 'custom.pdf', {}, 'POST', {
|
|
86
|
+
* template: 'invoice',
|
|
87
|
+
* data: invoiceData
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
download(url: string, filename: string, params: any, method?: string, formData?: any): Promise<any>;
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/RestService.d.ts
CHANGED
|
@@ -1,97 +1,171 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Result object returned by pre-interceptor
|
|
3
|
+
*/
|
|
2
4
|
export interface PreInterceptorResult {
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
6
|
+
* Additional headers to add to the request
|
|
5
7
|
*/
|
|
6
8
|
headers: any;
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
10
|
+
* Request timeout in milliseconds
|
|
9
11
|
*/
|
|
10
12
|
timeout?: number;
|
|
11
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Data processor function type for transforming response data
|
|
16
|
+
*/
|
|
12
17
|
export type DataProcessor = (data: any) => any;
|
|
18
|
+
/**
|
|
19
|
+
* Pre-interceptor function type for modifying requests before sending
|
|
20
|
+
* @param method HTTP method (GET, POST, etc.)
|
|
21
|
+
* @param url Request URL
|
|
22
|
+
* @returns PreInterceptorResult object with optional headers and timeout
|
|
23
|
+
*/
|
|
13
24
|
export type PreInterceptor = (method: string, url: string) => PreInterceptorResult;
|
|
25
|
+
/**
|
|
26
|
+
* Post-interceptor function type for processing responses after receiving
|
|
27
|
+
* @param data Response data from the server
|
|
28
|
+
* @returns Promise that resolves to processed data
|
|
29
|
+
*/
|
|
14
30
|
export type PostInterceptor = (data: any) => Promise<any>;
|
|
31
|
+
/**
|
|
32
|
+
* Error handler function type for handling request errors
|
|
33
|
+
* @param ex The error object
|
|
34
|
+
* @returns Boolean indicating if the error was handled (true) or should be thrown (false)
|
|
35
|
+
*/
|
|
15
36
|
export type ErrorHandler = (ex: Error) => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* RESTful API request options
|
|
39
|
+
*/
|
|
16
40
|
export type RestfulOptions = {
|
|
17
41
|
/**
|
|
18
|
-
*
|
|
42
|
+
* Optional Content-Type header, defaults to 'application/json'
|
|
19
43
|
*/
|
|
20
44
|
contentType?: string;
|
|
21
45
|
/**
|
|
22
|
-
*
|
|
46
|
+
* Optional data processing function to transform response data before returning
|
|
23
47
|
*/
|
|
24
48
|
dataProcessor?: DataProcessor;
|
|
25
49
|
/**
|
|
26
|
-
*
|
|
50
|
+
* Optional query parameters object that will be converted to URL query string
|
|
27
51
|
*/
|
|
28
52
|
params?: any;
|
|
29
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* HTTP header name for Content-Type
|
|
56
|
+
*/
|
|
30
57
|
export declare const CONTENT_TYPE_NAME = "Content-Type";
|
|
58
|
+
/**
|
|
59
|
+
* MIME type for JSON content
|
|
60
|
+
*/
|
|
31
61
|
export declare const TYPE_JSON = "application/json";
|
|
62
|
+
/**
|
|
63
|
+
* MIME type for HTML content
|
|
64
|
+
*/
|
|
32
65
|
export declare const TYPE_HTML = "text/html";
|
|
66
|
+
/**
|
|
67
|
+
* MIME type for plain text content
|
|
68
|
+
*/
|
|
33
69
|
export declare const TYPE_TEXT = "text/plain";
|
|
70
|
+
/**
|
|
71
|
+
* RESTful API service interface for standard HTTP operations
|
|
72
|
+
*/
|
|
34
73
|
export default interface RestService {
|
|
35
74
|
/**
|
|
36
|
-
*
|
|
37
|
-
* @param url
|
|
38
|
-
* @param params
|
|
39
|
-
* @param dataProcessor
|
|
40
|
-
* @returns
|
|
75
|
+
* Performs an HTTP GET request to retrieve a resource
|
|
76
|
+
* @param url The target URL path for the request
|
|
77
|
+
* @param params Query parameters object that will be converted to URL query string
|
|
78
|
+
* @param dataProcessor Optional data processing function to transform response data before returning
|
|
79
|
+
* @returns Promise that resolves to the server response data
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Simple GET request
|
|
84
|
+
* const users = await restService.get('/api/users');
|
|
85
|
+
*
|
|
86
|
+
* // GET with query parameters
|
|
87
|
+
* const filteredUsers = await restService.get('/api/users', { page: 1, limit: 10 });
|
|
88
|
+
*
|
|
89
|
+
* // GET with data processor
|
|
90
|
+
* const users = await restService.get('/api/users', null, (data) => data.items);
|
|
91
|
+
* ```
|
|
41
92
|
*/
|
|
42
93
|
get(url: string, params?: any, dataProcessor?: DataProcessor): Promise<any>;
|
|
43
94
|
/**
|
|
44
|
-
*
|
|
45
|
-
* @param url
|
|
46
|
-
* @param data
|
|
47
|
-
* @param options
|
|
48
|
-
* @returns
|
|
95
|
+
* Performs an HTTP POST request to create a new resource
|
|
96
|
+
* @param url The target URL path for the request
|
|
97
|
+
* @param data Request body data to be sent, typically an object or string
|
|
98
|
+
* @param options Optional request configuration options, including contentType and dataProcessor
|
|
99
|
+
* @returns Promise that resolves to the server response data
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* // Simple POST request
|
|
104
|
+
* const newUser = await restService.post('/api/users', { name: 'John', age: 30 });
|
|
105
|
+
*
|
|
106
|
+
* // POST with custom content type
|
|
107
|
+
* const result = await restService.post('/api/data', formData, {
|
|
108
|
+
* contentType: 'multipart/form-data'
|
|
109
|
+
* });
|
|
110
|
+
*
|
|
111
|
+
* // POST with data processor
|
|
112
|
+
* const user = await restService.post('/api/users', userData, {
|
|
113
|
+
* dataProcessor: (data) => data.result
|
|
114
|
+
* });
|
|
115
|
+
* ```
|
|
49
116
|
*/
|
|
50
117
|
post(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
51
118
|
/**
|
|
52
|
-
*
|
|
53
|
-
* @param url
|
|
54
|
-
* @param data
|
|
55
|
-
* @param options
|
|
56
|
-
* @returns
|
|
119
|
+
* Performs an HTTP PUT request to update an existing resource
|
|
120
|
+
* @param url The target URL path for the request
|
|
121
|
+
* @param data Optional request body data to be sent for updating the resource
|
|
122
|
+
* @param options Optional request configuration options, including contentType and dataProcessor
|
|
123
|
+
* @returns Promise that resolves to the server response data
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* // Update a user
|
|
128
|
+
* const updatedUser = await restService.put('/api/users/123', { name: 'John Doe' });
|
|
129
|
+
*
|
|
130
|
+
* // PUT without data (some APIs may support this)
|
|
131
|
+
* const result = await restService.put('/api/users/123/toggle-status');
|
|
132
|
+
* ```
|
|
57
133
|
*/
|
|
58
134
|
put(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
59
135
|
/**
|
|
60
|
-
*
|
|
61
|
-
* @param url
|
|
62
|
-
* @param data
|
|
63
|
-
* @param options
|
|
64
|
-
* @returns
|
|
136
|
+
* Performs an HTTP DELETE request to delete a resource
|
|
137
|
+
* @param url The target URL path for the request
|
|
138
|
+
* @param data Optional request body data, some DELETE operations may require sending data
|
|
139
|
+
* @param options Optional request configuration options, including contentType and dataProcessor
|
|
140
|
+
* @returns Promise that resolves to the server response data
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* // Delete a user
|
|
145
|
+
* await restService.del('/api/users/123');
|
|
146
|
+
*
|
|
147
|
+
* // DELETE with request body
|
|
148
|
+
* await restService.del('/api/users/batch', { ids: [1, 2, 3] });
|
|
149
|
+
* ```
|
|
65
150
|
*/
|
|
66
151
|
del(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
67
152
|
/**
|
|
68
|
-
*
|
|
69
|
-
* @param url
|
|
70
|
-
* @param
|
|
71
|
-
* @param
|
|
72
|
-
* @
|
|
73
|
-
*
|
|
74
|
-
* @
|
|
153
|
+
* Performs an HTTP PATCH request to partially update a resource
|
|
154
|
+
* @param url The target URL path for the request
|
|
155
|
+
* @param data Optional request body data to be sent for partially updating the resource
|
|
156
|
+
* @param options Optional request configuration options, including contentType and dataProcessor
|
|
157
|
+
* @returns Promise that resolves to the server response data
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```typescript
|
|
161
|
+
* // Partially update a user
|
|
162
|
+
* const updatedUser = await restService.patch('/api/users/123', { status: 'active' });
|
|
163
|
+
*
|
|
164
|
+
* // PATCH with options
|
|
165
|
+
* const result = await restService.patch('/api/users/123', { age: 31 }, {
|
|
166
|
+
* dataProcessor: (data) => data.user
|
|
167
|
+
* });
|
|
168
|
+
* ```
|
|
75
169
|
*/
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* 执行异步文件上传操作,支持进度监控和取消功能
|
|
79
|
-
* @param url 上传的目标URL路径
|
|
80
|
-
* @param params 上传请求的参数对象
|
|
81
|
-
* @param file 要上传的文件对象
|
|
82
|
-
* @param callback 上传过程中的回调函数,包含进度更新、错误处理等
|
|
83
|
-
* @param fileKey 可选的文件字段名,默认为'file'
|
|
84
|
-
* @returns 返回Promise,解析为UploadProgress对象,可用于取消上传
|
|
85
|
-
*/
|
|
86
|
-
asyncUpload(url: string, params: any, file: File, callback: UploadCallback, fileKey?: string): Promise<UploadProgress>;
|
|
87
|
-
/**
|
|
88
|
-
* 执行文件下载操作
|
|
89
|
-
* @param url 下载文件的URL路径
|
|
90
|
-
* @param filename 保存的文件名
|
|
91
|
-
* @param params 下载请求的参数对象
|
|
92
|
-
* @param method 可选的HTTP方法,默认为GET
|
|
93
|
-
* @param formData 可选的表单数据,用于POST下载
|
|
94
|
-
* @returns 返回Promise,解析为下载结果
|
|
95
|
-
*/
|
|
96
|
-
download(url: string, filename: string, params: any, method?: string, formData?: any): Promise<any>;
|
|
170
|
+
patch(url: string, data?: any, options?: RestfulOptions): Promise<any>;
|
|
97
171
|
}
|
package/dist/RestService.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP header name for Content-Type
|
|
3
|
+
*/
|
|
1
4
|
export const CONTENT_TYPE_NAME = 'Content-Type';
|
|
5
|
+
/**
|
|
6
|
+
* MIME type for JSON content
|
|
7
|
+
*/
|
|
2
8
|
export const TYPE_JSON = "application/json";
|
|
9
|
+
/**
|
|
10
|
+
* MIME type for HTML content
|
|
11
|
+
*/
|
|
3
12
|
export const TYPE_HTML = "text/html";
|
|
13
|
+
/**
|
|
14
|
+
* MIME type for plain text content
|
|
15
|
+
*/
|
|
4
16
|
export const TYPE_TEXT = "text/plain";
|
package/dist/UploadCallback.d.ts
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @param uploadBytes
|
|
2
|
+
* Upload progress update callback function type
|
|
3
|
+
* @param uploadBytes Number of bytes uploaded
|
|
4
4
|
*/
|
|
5
5
|
export type ProgressUpdate = (uploadBytes: number) => void;
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* @param e
|
|
7
|
+
* Upload error handling callback function type
|
|
8
|
+
* @param e Error object that occurred during upload
|
|
9
9
|
*/
|
|
10
10
|
export type ErrorHandler = (e: Error) => void;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
* @param data
|
|
12
|
+
* Upload completion callback function type
|
|
13
|
+
* @param data Response data returned from the server
|
|
14
14
|
*/
|
|
15
15
|
export type OnCompleted = (data: any) => void;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Upload progress control interface, providing control functions during upload process
|
|
18
18
|
*/
|
|
19
19
|
export interface UploadProgress {
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Cancel the ongoing upload operation
|
|
22
22
|
*/
|
|
23
23
|
cancel: () => void;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
* @param url
|
|
28
|
-
* @param thumbnail
|
|
26
|
+
* Callback function type after file upload completion
|
|
27
|
+
* @param url File access URL after upload
|
|
28
|
+
* @param thumbnail Optional thumbnail URL
|
|
29
29
|
*/
|
|
30
30
|
export type OnUploaded = (url: string, thumbnail?: string) => void;
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* File upload callback interface, defining various callback functions during upload process
|
|
33
33
|
*/
|
|
34
34
|
export default interface UploadCallback {
|
|
35
35
|
/**
|
|
36
|
-
* HTTP
|
|
36
|
+
* HTTP request method, defaults to POST, but allows PUT or other methods in special cases
|
|
37
37
|
*/
|
|
38
38
|
method: string;
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* Optional upload progress update callback function
|
|
41
41
|
*/
|
|
42
42
|
progressUpdate?: ProgressUpdate;
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* Optional error handling callback function
|
|
45
45
|
*/
|
|
46
46
|
handleError?: ErrorHandler;
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Required upload completion callback function
|
|
49
49
|
*/
|
|
50
50
|
onCompleted: OnCompleted;
|
|
51
51
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import ApiError from "./ApiError";
|
|
2
2
|
import RestService from "./RestService";
|
|
3
|
+
import FileService from "./FileService";
|
|
3
4
|
import { ErrorHandler, PostInterceptor, PreInterceptor, DataProcessor } from "./RestService";
|
|
4
5
|
import { PreInterceptorResult } from "./RestService";
|
|
5
6
|
import { CONTENT_TYPE_NAME, TYPE_JSON, TYPE_HTML, TYPE_TEXT } from "./RestService";
|
|
6
7
|
import UploadCallback, { UploadProgress, ProgressUpdate, OnCompleted, OnUploaded } from "./UploadCallback";
|
|
8
|
+
import { RestfulOptions } from "./RestService";
|
|
7
9
|
export default RestService;
|
|
8
10
|
export { ApiError };
|
|
11
|
+
export { RestService };
|
|
12
|
+
export { FileService };
|
|
9
13
|
export type { ErrorHandler, PostInterceptor, PreInterceptor, DataProcessor };
|
|
10
14
|
export type { PreInterceptorResult };
|
|
11
15
|
export { CONTENT_TYPE_NAME, TYPE_JSON, TYPE_HTML, TYPE_TEXT };
|
|
12
16
|
export { UploadCallback };
|
|
13
17
|
export type { UploadProgress, ProgressUpdate, OnCompleted, OnUploaded };
|
|
18
|
+
export type { RestfulOptions };
|
package/package.json
CHANGED