@snail-js/api 0.1.4 → 0.1.6
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 +102 -5
- package/dist/core/snail.d.ts +2 -4
- package/dist/decorators/progress.d.ts +3 -1
- package/dist/snail-api.js +19 -11
- package/dist/snail-api.umd.cjs +19 -11
- package/dist/typings/apiProxy.d.ts +4 -4
- package/dist/typings/response.data.d.ts +1 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -335,7 +335,11 @@ class Test {
|
|
|
335
335
|
|
|
336
336
|
### 上传进度装饰器`@UploadProgress`
|
|
337
337
|
|
|
338
|
-
- `@UploadProgress((
|
|
338
|
+
- `@UploadProgress((progressEvent: AxiosProgressEvent) => void)`
|
|
339
|
+
|
|
340
|
+
### 下载进度装饰器`@DownloadProgress`
|
|
341
|
+
|
|
342
|
+
- `@DownloadProgress((progressEvent: AxiosProgressEvent) => void)`
|
|
339
343
|
|
|
340
344
|
## Server Send Event 服务端推送
|
|
341
345
|
|
|
@@ -374,33 +378,126 @@ export const Sse = Service.createSse(ServerSend);
|
|
|
374
378
|
```
|
|
375
379
|
|
|
376
380
|
### 服务端推送装饰器`@Sse`
|
|
381
|
+
|
|
377
382
|
- `@Sse(path:string,options:{withCredentials: boolean})`
|
|
378
383
|
- 创建一个服务端推送连接,当被装饰的方法调用时打开连接
|
|
379
384
|
- 被装饰的方法调用后会返回`{eventSource:EventSource,close:function}`
|
|
380
|
-
|
|
381
|
-
|
|
385
|
+
- eventSource: sse 连接实例
|
|
386
|
+
- close: 关闭此 sse 连接的方法
|
|
382
387
|
|
|
383
388
|
### 注册`onopen`装饰器`@OnSseOpen`
|
|
389
|
+
|
|
384
390
|
- 当`@Sse`装饰的方法被调用时,将`@OnSseOpen`装饰的方法注册为`@Sse`装饰的方法返回的`EventSource`实例`onopen`处理函数
|
|
385
391
|
|
|
386
392
|
### 注册`onerror`装饰器`@OnSseError`
|
|
393
|
+
|
|
387
394
|
- 当`@Sse`装饰的方法被调用时,将`@OnSseError`装饰的方法注册为`@Sse`装饰的方法返回的`EventSource`实例`onerror`处理函数
|
|
388
395
|
|
|
389
396
|
### 事件处理装饰器`@SseEvent`
|
|
397
|
+
|
|
390
398
|
- `@SseEvent(eventName?:string)`
|
|
391
399
|
- 未传入`eventName`,默认注册为`message`事件处理器
|
|
392
400
|
- 传入`eventName`,注册为对应名称的事件处理器
|
|
393
401
|
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## TypeScript 支持
|
|
405
|
+
|
|
406
|
+
### 默认返回类型
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
export interface ResponseData<T = any> {
|
|
410
|
+
code: 0;
|
|
411
|
+
message: string;
|
|
412
|
+
data: T;
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### 定义返回类型
|
|
417
|
+
|
|
418
|
+
1. 定义后端标准数据格式
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
export class CustomResponse {
|
|
422
|
+
status_code: number;
|
|
423
|
+
msg: string;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
2. 创建时应用格式
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
// service.ts
|
|
431
|
+
import { Snail, Server } from "@snail-js/api";
|
|
432
|
+
|
|
433
|
+
@Server({
|
|
434
|
+
baseURL: "/api",
|
|
435
|
+
timeout: 5000,
|
|
436
|
+
})
|
|
437
|
+
class BackEnd extends Snail<CustomResponse> {}
|
|
438
|
+
|
|
439
|
+
export const Service = new BackEnd();
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
3. 调用 API 时携带数据格式
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import { userApi } from "./user";
|
|
446
|
+
|
|
447
|
+
class User {
|
|
448
|
+
id: number;
|
|
449
|
+
name: string;
|
|
450
|
+
tel: string;
|
|
451
|
+
age: number;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const res = await userApi.get<User>("1");
|
|
455
|
+
// 默认情况,以data为key存储数据
|
|
456
|
+
// res.data => CustomResponse & { data : User}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
> API 被调用的返回格式
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
const res = await userApi.get<User>("1");
|
|
463
|
+
|
|
464
|
+
// res type
|
|
465
|
+
{
|
|
466
|
+
data: T;
|
|
467
|
+
error: null | Error
|
|
468
|
+
hitCache?: boolean
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
> `data: T`,后端响应数据;默认为`ResponseData<T = any>`类型;可由用户自定义修改
|
|
473
|
+
|
|
474
|
+
> `error: null | Error` ; 请求过程中的错误包含在此,可先判断 error 是否为 null 再进行数据处理
|
|
475
|
+
|
|
476
|
+
> `hitCache?: boolean`; 标识请求是否击中缓存;若从缓存获得数据,则不会发送请求。
|
|
477
|
+
|
|
478
|
+
4. 若后端返回数据不是以 data 为 key 包含数据
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
@Server({
|
|
482
|
+
baseURL: "/api",
|
|
483
|
+
timeout: 5000,
|
|
484
|
+
})
|
|
485
|
+
class BackEnd extends Snail<CustomResponse, "record"> {}
|
|
486
|
+
|
|
487
|
+
const res = await userApi.get<User>("1");
|
|
488
|
+
// 自定义数据key
|
|
489
|
+
// res.data => CustomResponse & { record : User}
|
|
490
|
+
```
|
|
394
491
|
|
|
395
492
|
### 代码仓库
|
|
396
493
|
|
|
397
494
|
<p>
|
|
398
|
-
<a
|
|
495
|
+
<a href="https://gitee.com/limich/snail">
|
|
399
496
|
<img src="https://img.shields.io/badge/snail-js?style=flat&label=gitee&labelColor=F56C6C&link=https%3A%2F%2Fgitee.com%2Flimich%2Fsnail"></img>
|
|
400
497
|
</a>
|
|
401
498
|
</p>
|
|
402
499
|
<p>
|
|
403
|
-
<a
|
|
500
|
+
<a href="https://github.com/limingchang/snail">
|
|
404
501
|
<img src="https://img.shields.io/badge/snail-js?style=flat&label=github&labelColor=F56C6C&link=https%3A%2F%2Fgihub.com%2Flimingchang%2Fsnail"></img>
|
|
405
502
|
</a>
|
|
406
503
|
</p>
|
package/dist/core/snail.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
2
|
import { Strategy, ApiProxy, SseProxy, ResponseData } from "../typings";
|
|
3
|
-
export declare class Snail<R extends {
|
|
4
|
-
data: any;
|
|
5
|
-
} = ResponseData> {
|
|
3
|
+
export declare class Snail<R extends {} = ResponseData, DK extends string = "data"> {
|
|
6
4
|
private axiosInstance;
|
|
7
5
|
private strategies;
|
|
8
6
|
private cacheStorage?;
|
|
@@ -10,7 +8,7 @@ export declare class Snail<R extends {
|
|
|
10
8
|
private sourceMap;
|
|
11
9
|
private eventSource;
|
|
12
10
|
registerStrategy(strategy: Strategy): void;
|
|
13
|
-
createApi<T extends object>(constructor: new () => T): ApiProxy<T, R>;
|
|
11
|
+
createApi<T extends object>(constructor: new () => T): ApiProxy<T, R, DK>;
|
|
14
12
|
private buildRequestArgs;
|
|
15
13
|
private getStrategies;
|
|
16
14
|
private applyStrategies;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
2
|
import { AxiosProgressEvent } from "axios";
|
|
3
3
|
export declare const UPLOAD_PROGRESS_KEY: unique symbol;
|
|
4
|
-
export declare const UploadProgress: (handler: (
|
|
4
|
+
export declare const UploadProgress: (handler: (progressEvent: AxiosProgressEvent) => void) => (target: any, propertyKey: string) => void;
|
|
5
|
+
export declare const DOWNLOAD_PROGRESS_KEY: unique symbol;
|
|
6
|
+
export declare const DownloadProgress: (handler: (progressEvent: AxiosProgressEvent) => void) => (target: any, propertyKey: string) => void;
|
package/dist/snail-api.js
CHANGED
|
@@ -3816,6 +3816,7 @@ const Cache = (hitSource) => {
|
|
|
3816
3816
|
};
|
|
3817
3817
|
};
|
|
3818
3818
|
const UPLOAD_PROGRESS_KEY = Symbol("SNAIL_UPLOAD_PROGRESS_KEY");
|
|
3819
|
+
const DOWNLOAD_PROGRESS_KEY = Symbol("SNAIL_DOWNLOAD_PROGRESS_KEY");
|
|
3819
3820
|
const EVENT_SOURCE_OPTION_KEY = Symbol("SNAIL_EVENT_SOURCE_OPTION_KEY");
|
|
3820
3821
|
const Sse = (path, options) => {
|
|
3821
3822
|
return (target, propertyKey) => {
|
|
@@ -3931,15 +3932,29 @@ class Snail {
|
|
|
3931
3932
|
target,
|
|
3932
3933
|
propertyKey
|
|
3933
3934
|
);
|
|
3935
|
+
const onDownloadProgress = Reflect.getMetadata(
|
|
3936
|
+
DOWNLOAD_PROGRESS_KEY,
|
|
3937
|
+
target,
|
|
3938
|
+
propertyKey
|
|
3939
|
+
);
|
|
3934
3940
|
try {
|
|
3935
3941
|
enableLog && console.log("send request:", request);
|
|
3936
3942
|
const response = await this.axiosInstance({
|
|
3937
3943
|
...request,
|
|
3938
|
-
onUploadProgress
|
|
3944
|
+
onUploadProgress,
|
|
3945
|
+
onDownloadProgress
|
|
3939
3946
|
});
|
|
3947
|
+
const responseStrategies = strategies.filter(
|
|
3948
|
+
(strategy) => strategy.applyResponse
|
|
3949
|
+
);
|
|
3950
|
+
const strategyResponse = await this.applyStrategies(
|
|
3951
|
+
response,
|
|
3952
|
+
responseStrategies,
|
|
3953
|
+
"response"
|
|
3954
|
+
);
|
|
3940
3955
|
hitSource !== null && this.setCache(request, response);
|
|
3941
3956
|
this.expireCache(propertyKey);
|
|
3942
|
-
return this.handleResponse(
|
|
3957
|
+
return this.handleResponse(strategyResponse, false);
|
|
3943
3958
|
} catch (error) {
|
|
3944
3959
|
return this.handleError(error);
|
|
3945
3960
|
}
|
|
@@ -4017,16 +4032,9 @@ class Snail {
|
|
|
4017
4032
|
statusText: "get response data from cache",
|
|
4018
4033
|
config: { headers: new AxiosHeaders2() }
|
|
4019
4034
|
};
|
|
4020
|
-
|
|
4021
|
-
(strategy) => strategy.applyResponse
|
|
4022
|
-
);
|
|
4023
|
-
const strategyResponse = await this.applyStrategies(
|
|
4024
|
-
cacheResponse,
|
|
4025
|
-
responseStrategies,
|
|
4026
|
-
"response"
|
|
4027
|
-
);
|
|
4028
|
-
return strategyResponse;
|
|
4035
|
+
return cacheResponse;
|
|
4029
4036
|
}
|
|
4037
|
+
return void 0;
|
|
4030
4038
|
}
|
|
4031
4039
|
initCacheManage(options) {
|
|
4032
4040
|
if (!this.cacheStorage && options !== void 0) {
|
package/dist/snail-api.umd.cjs
CHANGED
|
@@ -3820,6 +3820,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3820
3820
|
};
|
|
3821
3821
|
};
|
|
3822
3822
|
const UPLOAD_PROGRESS_KEY = Symbol("SNAIL_UPLOAD_PROGRESS_KEY");
|
|
3823
|
+
const DOWNLOAD_PROGRESS_KEY = Symbol("SNAIL_DOWNLOAD_PROGRESS_KEY");
|
|
3823
3824
|
const EVENT_SOURCE_OPTION_KEY = Symbol("SNAIL_EVENT_SOURCE_OPTION_KEY");
|
|
3824
3825
|
const Sse = (path, options) => {
|
|
3825
3826
|
return (target, propertyKey) => {
|
|
@@ -3935,15 +3936,29 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
3935
3936
|
target,
|
|
3936
3937
|
propertyKey
|
|
3937
3938
|
);
|
|
3939
|
+
const onDownloadProgress = Reflect.getMetadata(
|
|
3940
|
+
DOWNLOAD_PROGRESS_KEY,
|
|
3941
|
+
target,
|
|
3942
|
+
propertyKey
|
|
3943
|
+
);
|
|
3938
3944
|
try {
|
|
3939
3945
|
enableLog && console.log("send request:", request);
|
|
3940
3946
|
const response = await this.axiosInstance({
|
|
3941
3947
|
...request,
|
|
3942
|
-
onUploadProgress
|
|
3948
|
+
onUploadProgress,
|
|
3949
|
+
onDownloadProgress
|
|
3943
3950
|
});
|
|
3951
|
+
const responseStrategies = strategies.filter(
|
|
3952
|
+
(strategy) => strategy.applyResponse
|
|
3953
|
+
);
|
|
3954
|
+
const strategyResponse = await this.applyStrategies(
|
|
3955
|
+
response,
|
|
3956
|
+
responseStrategies,
|
|
3957
|
+
"response"
|
|
3958
|
+
);
|
|
3944
3959
|
hitSource !== null && this.setCache(request, response);
|
|
3945
3960
|
this.expireCache(propertyKey);
|
|
3946
|
-
return this.handleResponse(
|
|
3961
|
+
return this.handleResponse(strategyResponse, false);
|
|
3947
3962
|
} catch (error) {
|
|
3948
3963
|
return this.handleError(error);
|
|
3949
3964
|
}
|
|
@@ -4021,16 +4036,9 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4021
4036
|
statusText: "get response data from cache",
|
|
4022
4037
|
config: { headers: new AxiosHeaders() }
|
|
4023
4038
|
};
|
|
4024
|
-
|
|
4025
|
-
(strategy) => strategy.applyResponse
|
|
4026
|
-
);
|
|
4027
|
-
const strategyResponse = await this.applyStrategies(
|
|
4028
|
-
cacheResponse,
|
|
4029
|
-
responseStrategies,
|
|
4030
|
-
"response"
|
|
4031
|
-
);
|
|
4032
|
-
return strategyResponse;
|
|
4039
|
+
return cacheResponse;
|
|
4033
4040
|
}
|
|
4041
|
+
return void 0;
|
|
4034
4042
|
}
|
|
4035
4043
|
initCacheManage(options) {
|
|
4036
4044
|
if (!this.cacheStorage && options !== void 0) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { ResponseData } from "./response.data";
|
|
1
2
|
export type ApiResponse<T> = Promise<{
|
|
2
3
|
data: T | null;
|
|
3
4
|
error: Error | null;
|
|
5
|
+
hitCache?: boolean;
|
|
4
6
|
}>;
|
|
5
|
-
export type ApiProxy<T, R extends {
|
|
6
|
-
data: any;
|
|
7
|
-
}> = {
|
|
7
|
+
export type ApiProxy<T, R extends {} = ResponseData, DK extends string = "data"> = {
|
|
8
8
|
[K in keyof T]: T[K] extends (...args: infer A) => any ? <D = any>(...args: A) => ApiResponse<R & {
|
|
9
|
-
|
|
9
|
+
[KK in DK]: D;
|
|
10
10
|
}> : T[K];
|
|
11
11
|
};
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
export interface ResponseErrorData<E> {
|
|
2
|
-
code: number;
|
|
3
|
-
message: string;
|
|
4
|
-
data: E;
|
|
5
|
-
}
|
|
6
1
|
export interface PaginationData<T> {
|
|
7
2
|
total: number;
|
|
8
3
|
page: number;
|
|
9
4
|
size: number;
|
|
10
5
|
record: T[];
|
|
11
6
|
}
|
|
12
|
-
export interface
|
|
7
|
+
export interface ResponseData<T = any> {
|
|
13
8
|
code: 0;
|
|
14
9
|
message: string;
|
|
15
10
|
data: T | PaginationData<T>;
|
|
16
11
|
}
|
|
17
|
-
export type ResponseData<T = any, E = any> = ResponseSuccessData<T> | ResponseErrorData<E>;
|