@snail-js/api 0.1.13 → 0.1.15

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.
Files changed (36) hide show
  1. package/README.md +223 -73
  2. package/README_EN.md +592 -0
  3. package/dist/cache/index.d.ts +6 -2
  4. package/dist/cache/indexDBCache.d.ts +7 -22
  5. package/dist/cache/localstorageCache.d.ts +7 -22
  6. package/dist/cache/memoryCache.d.ts +8 -23
  7. package/dist/core/index.d.ts +4 -1
  8. package/dist/core/snailApi.d.ts +22 -0
  9. package/dist/core/snailMethod.d.ts +54 -0
  10. package/dist/core/snailServer.d.ts +34 -0
  11. package/dist/core/snailSse.d.ts +20 -0
  12. package/dist/decorators/api.d.ts +9 -9
  13. package/dist/decorators/{param.d.ts → args.d.ts} +6 -0
  14. package/dist/decorators/cache.d.ts +11 -6
  15. package/dist/decorators/sse.d.ts +2 -3
  16. package/dist/decorators/strategy.d.ts +1 -1
  17. package/dist/index.d.ts +2 -2
  18. package/dist/snail-api.js +1125 -531
  19. package/dist/snail-api.umd.cjs +1126 -532
  20. package/dist/typings/api.option.d.ts +16 -0
  21. package/dist/typings/apiProxy.d.ts +5 -4
  22. package/dist/typings/cache.management.option.d.ts +16 -10
  23. package/dist/typings/cache.type.d.ts +17 -2
  24. package/dist/typings/index.d.ts +2 -1
  25. package/dist/typings/request.method.d.ts +9 -8
  26. package/dist/typings/response.data.d.ts +7 -3
  27. package/dist/typings/snail.method.d.ts +11 -0
  28. package/dist/typings/snail.option.d.ts +5 -1
  29. package/dist/typings/sse.d.ts +5 -1
  30. package/dist/typings/versioning.option.d.ts +2 -2
  31. package/dist/utils/function.d.ts +29 -8
  32. package/dist/versioning/index.d.ts +1 -0
  33. package/dist/versioning/versioning.d.ts +10 -5
  34. package/package.json +2 -1
  35. package/dist/core/snail.d.ts +0 -32
  36. package/dist/typings/api.config.d.ts +0 -9
package/README.md CHANGED
@@ -1,13 +1,16 @@
1
1
  <p>
2
2
  <img src="https://img.shields.io/badge/TypeScript-1e80ff"></img>
3
3
  <img src="https://img.shields.io/npm/v/axios?label=axios&labelColor=1e80ff&color=67C23A"></img>
4
+ <img src="https://img.shields.io/npm/v/reflect-metadata?label=reflect-metadata&labelColor=1e80ff&color=67C23A"></img>
4
5
  </p>
5
6
 
7
+ 中文文档|<a href='./README_EN.md'>English Document</a>
8
+
6
9
  ## 项目介绍
7
10
 
8
11
  - 基于 Axios 二次封装
9
12
  - 使用`reflect-metadata`创建和处理元数据
10
- - 提供装饰器方式定义请求,基本实例`Snail`,请求实例`Api`
13
+ - 提供装饰器定义请求请求的方式,支持所有请求方法和 SSE
11
14
 
12
15
  ## 安装
13
16
 
@@ -42,29 +45,29 @@
42
45
 
43
46
  ```typescript
44
47
  // service.ts
45
- import { Snail, Server } from "@snail-js/api";
48
+ import { SnailServer, Server } from "@snail-js/api";
46
49
 
47
50
  @Server({
48
51
  baseURL: "/api",
49
52
  timeout: 5000,
50
53
  })
51
- class BackEnd extends Snail {}
54
+ class BackEnd extends SnailServer {}
52
55
 
53
56
  export const Service = new BackEnd();
54
57
  ```
55
58
 
56
- 3. 创建请求实例
59
+ 3. 创建 Api 实例
57
60
 
58
61
  ```typescript
59
62
  // user.ts
60
- import { Api, Get, Post, Params, Data } from "@snail-js/api";
63
+ import { Api, Get, Post, Query, Data,SnailApi } from "@snail-js/api";
61
64
 
62
65
  import { Service } from "./service";
63
66
 
64
67
  @Api("user")
65
- class UserApi {
68
+ class UserApi extends SnailApi {
66
69
  @Get()
67
- get(@Params("id") id: string) {}
70
+ get(@Query("id") id: string) {}
68
71
 
69
72
  @Post()
70
73
  create(@Data() user: User) {}
@@ -78,47 +81,171 @@ export const userApi = Service.createApi(UserApi);
78
81
  ```typescript
79
82
  import { userApi } from "./user";
80
83
 
81
- const res = await userApi.get("1");
82
- const { error, data } = res;
83
- if (error !== null) {
84
- console.log(data);
85
- }
84
+ const getUser = await userApi.get("1");
85
+ const { send, onSuccess, onError, onHitCache, on } = getUser;
86
+ const data = await send();
86
87
  ```
87
88
 
88
- ### Server 配置
89
-
90
- - `baseUrl`:同`Axios`,使用`vite.proxy`时,请使用`\`开头,直接跨域请求请填写完整地址
91
- - `Versioning`:版本管理器
92
- - type:管理器类型,enum:Uri,Head,Query,Custom
93
- - prifix:前缀,字符串;添加在版本号前面的字符,默认为`v`
94
- - defaultVersion:全局默认版本
95
- - timenout:全局超时时间,会被 Api 的 timeout 值覆盖
96
- - CacheManage:缓存管理器
97
- - type:缓存管理器类型,CacheType,`enum:localStorage,IndexDB,Memory`
98
- - ttl: 缓存过期时间
99
- - enableLog: 是否打印日志
89
+ ## `SnailMethod` 实例
90
+ - 调用`Service.createApi(ApiInstance)`后会为`ApiInstance`内被`RequestMethod`(如:@Get、@Post...)装饰的方法创建一个代理,返回一个函数,此函数包含请求参数,调用此函数返回`SnailMethod` 实例
91
+
92
+ ### `SnailMethod` 实例方法
93
+
94
+ - `send` 发送请求
95
+ _异步函数,发送当前请求_
96
+ - `onSuccess` 请求成功回调
97
+ _注册请求成功事件_
98
+ - `onError` 请求失败回调
99
+ _注册请求失败事件_
100
+ - `onHitCache` 请求命中缓存回调
101
+ _注册请求命中缓存事件_
102
+ - `onFinish` 请求完成回调
103
+ _注册请求完成事件_
104
+ - `on` 监听事件
105
+ _注册自定义事件_
106
+ - `emit` 触发事件
107
+ _触发自定义事件_
108
+ - `off` 取消监听事件
109
+ _取消自定义事件监听_
110
+
111
+
112
+ ### `SnailMethod` 实例属性
113
+ - response : AxiosResponse
114
+ - request : AxiosRequestConfig ,最终请求的request,这个request是被Versioning和Strategy处理过的
115
+ - version : string,最终请求的版本,如果没有开启Versioning则为undefine
116
+ - name : string,完整的SnailMethod名称,格式为`ServerName.ApiName.MethodName`
117
+ - error : Error | null,请求失败的错误信息,无错误为null
100
118
 
101
- ## Api 配置
119
+ ### Server 配置
102
120
 
103
- - url?: api 请求端点,与 Server 中的`baseUrl`拼接请求地址,不要使用`/`开头
104
- - timeout?: 请求超时时间;会覆盖`Server.timeout`
105
- - version?: 请求版本,会覆盖`Server.Versioning.defaultVersion`;
121
+ <table>
122
+ <tr>
123
+ <th>配置项</th>
124
+ <th>类型</th>
125
+ <th>是否必须</th>
126
+ <th>默认值</th>
127
+ <th>说明</th>
128
+ </tr>
129
+ <tr>
130
+ <td>name</td>
131
+ <td>string</td>
132
+ <td>否</td>
133
+ <td>默认使用继承`SnailServer`的类名作为name</td>
134
+ <td>server实例唯一标识,请勿与其他server重复</td>
135
+ </tr>
136
+ <tr>
137
+ <td>baseUrl</td>
138
+ <td>string</td>
139
+ <td>否</td>
140
+ <td>'\'</td>
141
+ <td>请求后端的api地址前缀,同`axios`的baseUrl</td>
142
+ </tr>
143
+ <tr>
144
+ <td>Versioning</td>
145
+ <td><a href="#versioningoption">VersioningOption</a></td>
146
+ <td>否</td>
147
+ <td>undefine</td>
148
+ <td>版本管理器配置,默认不开启</td>
149
+ </tr>
150
+ <tr>
151
+ <td>timeout</td>
152
+ <td>number</td>
153
+ <td>否</td>
154
+ <td>5000</td>
155
+ <td>单位:毫秒;全局超时时间,会被 Api 的 timeout 值覆盖</td>
156
+ </tr>
157
+ <tr>
158
+ <td>cacheManage</td>
159
+ <td>{type:CacheType,ttl:number}</td>
160
+ <td>否</td>
161
+ <td>{
162
+ type: CacheType.Memory,
163
+ ttl: 500
164
+ }</td>
165
+ <td>缓存管理器,ttl单位为秒</td>
166
+ </tr>
167
+ <tr>
168
+ <td>cacheFor</td>
169
+ <td>RequestMethod | RequestMethod[] | 'All' | 'all' </td>
170
+ <td>否</td>
171
+ <td>Get</td>
172
+ <td>要启用缓存的方法,默认仅开启Get缓存</td>
173
+ </tr>
174
+ <tr>
175
+ <td>enableLog</td>
176
+ <td>boolean</td>
177
+ <td>否</td>
178
+ <td>false</td>
179
+ <td>是否开启日志,用于调试</td>
180
+ </tr>
181
+ </table>
182
+
183
+ ### Api 配置
184
+ - 请使用`@Api()`装饰自定义Api类并继承`SnailApi`
185
+
186
+ <table>
187
+ <tr>
188
+ <th>配置项</th>
189
+ <th>类型</th>
190
+ <th>是否必须</th>
191
+ <th>默认值</th>
192
+ <th>说明</th>
193
+ </tr>
194
+ <tr>
195
+ <td>name</td>
196
+ <td>string</td>
197
+ <td>否</td>
198
+ <td>默认使用继承`SnailApi`的类名作为name</td>
199
+ <td>api实例唯一标识,请勿与其他api重复</td>
200
+ </tr>
201
+ <tr>
202
+ <td>timeout</td>
203
+ <td>number</td>
204
+ <td>否</td>
205
+ <td></td>
206
+ <td>请求超时时间;会覆盖Server的timeout设置</td>
207
+ </tr>
208
+ <tr>
209
+ <td>version</td>
210
+ <td>string</td>
211
+ <td>否</td>
212
+ <td></td>
213
+ <td>api版本号,会覆盖server的`defaultVersion`配置</td>
214
+ </tr>
215
+ </table>
106
216
 
107
217
  ## 请求方法装饰器
108
218
 
219
+ - 在`Api`类中使用,用于标记请求方法
109
220
  - 提供 axios 的全部请求方法`Get,Post,Head,Put,Delete,Patch,Options`
110
- - path?: string; 请求端点路径,与`baseUrl,api.url`共同拼接组成最终请求路径,不要使用`/`开头
221
+ - 参数: `path?: string`; 请求端点路径,与`baseUrl,api.url`共同拼接组成最终请求路径
111
222
 
112
223
  ## 参数装饰器
113
224
 
114
- ### 查询参数 `@Params`
225
+ ### 查询参数 `@Query`
115
226
 
116
- - `@Params(key?:string)`
227
+ - `@Query(key?:string)`
117
228
 
118
229
  - 单个参数使用
119
230
 
120
231
  ```typescript
121
232
  @Api("user")
233
+ class UserApi {
234
+ @Get()
235
+ get(@Query("id") id: string, @Query("sign") sign: string) {}
236
+ }
237
+ ```
238
+
239
+ > 传入 key,标记单个查询参数,拼接到请求`?k1=v1&k2=v2`
240
+
241
+ ### 路由参数 `@Params`
242
+
243
+ - `@Params(key?:string)`
244
+
245
+ - 单个参数使用
246
+
247
+ ```typescript
248
+ @Api("user/:id/:sign")
122
249
  class UserApi {
123
250
  @Get()
124
251
  get(@Params("id") id: string, @Params("sign") sign: string) {}
@@ -130,15 +257,15 @@ class UserApi {
130
257
  - 对象参数使用
131
258
 
132
259
  ```typescript
133
- class QueryParams {
260
+ class RouteParams {
134
261
  id: string;
135
262
  sign: string;
136
263
  }
137
264
 
138
- @Api("user")
265
+ @Api("user/:id/:sign")
139
266
  class UserApi {
140
267
  @Get()
141
- get(@Params() params: QueryParams) {}
268
+ get(@Params() params: RouteParams) {}
142
269
  }
143
270
  ```
144
271
 
@@ -147,15 +274,15 @@ class UserApi {
147
274
  - 混合使用
148
275
 
149
276
  ```typescript
150
- class QueryParams {
277
+ class RouteParams {
151
278
  id: string;
152
279
  sign: string;
153
280
  }
154
281
 
155
- @Api("user")
282
+ @Api("user/:id/:sign")
156
283
  class UserApi {
157
284
  @Get()
158
- get(@Params() params: QueryParams, @Params("a") a: number) {}
285
+ get(@Params() params: Query, @Params("a") a: number) {}
159
286
  }
160
287
  ```
161
288
 
@@ -166,12 +293,12 @@ class UserApi {
166
293
 
167
294
  ## 策略装饰器`@UseStrategy`
168
295
 
169
- - `@UseStrategy(Strategy[])`
296
+ - `@UseStrategy(...Strategy[])`
170
297
 
171
298
  ### 请求策略
172
299
 
173
300
  - 在请求发送前执行,后面的策略返回结果会覆盖前面的策略
174
- - 必须将处理后的 request 返回
301
+ - 若返回处理后的request,则使用处理后的 request 发送请求,否则使用原始 request 或上一个策略返回的request发送请求
175
302
 
176
303
  ```typescript
177
304
  class CustomStrategy extends Strategy {
@@ -187,29 +314,40 @@ class CustomStrategy extends Strategy {
187
314
  baseURL: "/api",
188
315
  timeout: 5000,
189
316
  })
190
- @UseStrategy(new CustomStrategy())
317
+ @UseStrategy(CustomStrategy)
191
318
  class BackEnd extends Snail<ShanheResponse> {}
192
319
  export const Service = new BackEnd();
320
+ // 创建Service实例后再注册策略
321
+ Service.registerStrategies(CustomStrategy);
193
322
 
194
323
  // 用在Api, 当Api下的方法请求时生效
195
324
  @Api("test")
196
- @UseStrategy(new CustomStrategy())
325
+ @UseStrategy(CustomStrategy)
197
326
  class Test {}
327
+ const TestApi = Service.createApi(Test);
328
+ // 创建Api实例后再注册策略
329
+ TestApi.registerStrategies(CustomStrategy);
198
330
 
199
331
  // 用在方法,此方法请求时生效
200
332
  @Api("test")
201
- @UseStrategy(new CustomStrategy())
333
+ @UseStrategy(CustomStrategy)
202
334
  class Test {
203
335
  @Get()
204
- @UseStrategy(new CustomStrategy())
336
+ @UseStrategy(CustomStrategy)
205
337
  get() {}
206
338
  }
339
+ // 发送请求前注册策略
340
+ const TestApi = Service.createApi(Test);
341
+ const getSomething = TestApi.get();
342
+ getSomething.registerStrategies(CustomStrategy);
343
+ { send, registerStrategies } = getSomething;
344
+
207
345
  ```
208
346
 
209
347
  ### 响应策略
210
348
 
211
349
  - 在收到服务器响应后执行
212
- - 必须将处理后的 response 返回
350
+ - 若返回处理后的response,则使用处理后的response进行下一个策略或返回,否则使用原始response或上一个策略返回的response返回
213
351
 
214
352
  ```typescript
215
353
  // 如何定义
@@ -244,7 +382,7 @@ class BackEnd extends Snail<ShanheResponse> {}
244
382
  export const Service = new BackEnd();
245
383
  ```
246
384
 
247
- #### `VersioningOption`类型
385
+ #### <a id="versioningoption">`VersioningOption`</a>类型
248
386
 
249
387
  ```typescript
250
388
  export enum VersioningType {
@@ -303,31 +441,33 @@ class Test {
303
441
 
304
442
  > 临时改变 api 版本,便于测试
305
443
 
306
- ### 缓存装饰器`@Cache`
444
+ ### 缓存装饰器`@HitSource`
307
445
 
308
- - `@Cache(string | null)`
309
- - 当设置为 null 时,此方法不应用缓存
310
- - 当设置为 string 时,应为此 Api 类下的方法名称,当设置的此名称方法被调用且正常响应时,被装饰的方法缓存失效
446
+ - `@HitSource(name:string)`
447
+ - 为被装饰的方法设置缓存失效源,当设置的名称方法被调用且正常响应时,被装饰的方法缓存失效
448
+ - name格式为:`serverName:apiName:methodName`
449
+ > 注意:若您配置了SnailServer/SnailApi的name选项,请使用此name作为名称,否则使用类名作为名称
311
450
 
312
451
  ```typescript
313
- @Api("test")
452
+ @Api("test",{name:'api1'})
453
+ @HitSource("api1")
314
454
  class Test {
315
455
  @Get("HelloWorld")
316
- @Cache("test2")
456
+ @HitSource("api1.test2")
317
457
  test1() {}
318
458
 
319
459
  @Post()
320
460
  test2() {}
321
461
 
322
462
  @Get()
323
- @Cache(null)
463
+ // Test类下任何请求成功,这个方法的缓存都会失效
464
+ @HitSource("api1")
324
465
  test3() {}
325
466
  }
326
467
  ```
327
468
 
328
469
  > 当请求`[Post]test`成功时,`[Get]test/HelloWorld`的缓存失效
329
- > 注意:`test2`方法请求成功的前提是需要设置`@Cache(null)`,否则仅第一次请求会发送,后续请求需等待缓存管理设置的 ttl 时间到期才会发送请求
330
- > 因此,若未设置`test2`方法的`@Cache(null)`,仅第一次请求会使`[Get]test/HelloWorld`的缓存失效,后续需等待 ttl 时间到期,才会继续失效
470
+ > 默认仅Get方法会进行缓存ing缓存,若要开启其他方法的缓存,请使用`@Server({cacheFor:'all'})`配置
331
471
 
332
472
  > `test3`方法请求成功时,不缓存
333
473
 
@@ -346,10 +486,8 @@ class Test {
346
486
  ### 创建 sse 端点
347
487
 
348
488
  ```typescript
349
- @Api("sse")
350
- class ServerSend {
351
- @Sse()
352
- create() {}
489
+ @Sse("sse")
490
+ class ServerSend extend SnailSse {
353
491
 
354
492
  @OnSseOpen()
355
493
  handleOpen(event: Event) {
@@ -379,8 +517,8 @@ export const Sse = Service.createSse(ServerSend);
379
517
 
380
518
  ### 服务端推送装饰器`@Sse`
381
519
 
382
- - `@Sse(path:string,options:{withCredentials: boolean})`
383
- - 创建一个服务端推送连接,返回一个函数,用于打开sse连接
520
+ - `@Sse(path:string,options?:{withCredentials?: boolean,version?: string;})`
521
+ - 创建一个服务端推送连接,返回一个函数,用于打开 sse 连接
384
522
  - 返回的打开函数调用后会返回`{eventSource:EventSource,close:function}`
385
523
  - eventSource: sse 连接实例
386
524
  - close: 关闭此 sse 连接的方法
@@ -406,11 +544,13 @@ export const Sse = Service.createSse(ServerSend);
406
544
  ### 默认返回类型
407
545
 
408
546
  ```typescript
409
- export interface ResponseData<T = any> {
410
- code: 0;
547
+ export type StandardResponseData<
548
+ T extends ResponseJsonData = Record<string, any>
549
+ > = {
550
+ code: number;
411
551
  message: string;
412
552
  data: T;
413
- }
553
+ };
414
554
  ```
415
555
 
416
556
  ### 定义返回类型
@@ -428,13 +568,13 @@ export class CustomResponse {
428
568
 
429
569
  ```typescript
430
570
  // service.ts
431
- import { Snail, Server } from "@snail-js/api";
571
+ import { SnailServer, Server } from "@snail-js/api";
432
572
 
433
573
  @Server({
434
574
  baseURL: "/api",
435
575
  timeout: 5000,
436
576
  })
437
- class BackEnd extends Snail<CustomResponse> {}
577
+ class BackEnd extends SnailServer<CustomResponse> {}
438
578
 
439
579
  export const Service = new BackEnd();
440
580
  ```
@@ -451,7 +591,11 @@ class User {
451
591
  age: number;
452
592
  }
453
593
 
454
- const res = await userApi.get<User>("1");
594
+ const getUser = userApi.get<User>("1");
595
+ const { send } = getUser;
596
+
597
+ const res = await send();
598
+
455
599
  // 默认情况,以data为key存储数据
456
600
  // res.data => CustomResponse & { data : User}
457
601
  ```
@@ -459,14 +603,16 @@ const res = await userApi.get<User>("1");
459
603
  > API 被调用的返回格式
460
604
 
461
605
  ```typescript
462
- const res = await userApi.get<User>("1");
606
+ const getUser = userApi.get<User>("1");
607
+ const { send } = getUser;
608
+ const res = await send();
463
609
 
464
- // res type
465
- {
466
- data: T;
467
- error: null | Error
468
- hitCache?: boolean
469
- }
610
+ // res.data => CustomResponse & { data: User }
611
+
612
+ const getUser = userApi.get<Blob>("1");
613
+ const { send } = getUser;
614
+ const res = await send();
615
+ // res => AxiosResponse<Blob>
470
616
  ```
471
617
 
472
618
  > `data: T`,后端响应数据;默认为`ResponseData<T = any>`类型;可由用户自定义修改
@@ -489,6 +635,10 @@ const res = await userApi.get<User>("1");
489
635
  // res.data => CustomResponse & { record : User}
490
636
  ```
491
637
 
638
+ ### 非json数据的返回
639
+ - 若后端返回的content-type不是json类型,send方法返回的将是`AxiosResponse`
640
+ - 若后端返回的content-type是json类型,send方法返回的将是`AxiosResponse.data`
641
+
492
642
  ### 代码仓库
493
643
 
494
644
  <p>