@snail-js/api 0.1.27 → 1.0.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/LICENSE +21 -0
- package/README.md +125 -605
- package/dist/adapter/plain.d.ts +12 -0
- package/dist/adapter/plain.d.ts.map +1 -0
- package/dist/adapter/react.d.ts +14 -0
- package/dist/adapter/react.d.ts.map +1 -0
- package/dist/adapter/registry.d.ts +16 -0
- package/dist/adapter/registry.d.ts.map +1 -0
- package/dist/adapter/vue.d.ts +15 -0
- package/dist/adapter/vue.d.ts.map +1 -0
- package/dist/chunks/custom-UchOSg_s.js +466 -0
- package/dist/chunks/custom-UchOSg_s.js.map +1 -0
- package/dist/chunks/download-lBC7oOTT.js +160 -0
- package/dist/chunks/download-lBC7oOTT.js.map +1 -0
- package/dist/chunks/object-Ct0w-h4i.js +74 -0
- package/dist/chunks/object-Ct0w-h4i.js.map +1 -0
- package/dist/chunks/plugin-D3RDffDG.js +742 -0
- package/dist/chunks/plugin-D3RDffDG.js.map +1 -0
- package/dist/chunks/react-C1em-gxy.js +62 -0
- package/dist/chunks/react-C1em-gxy.js.map +1 -0
- package/dist/chunks/request-qeRhihEF.js +40 -0
- package/dist/chunks/request-qeRhihEF.js.map +1 -0
- package/dist/chunks/response-D-ubkAFl.js +127 -0
- package/dist/chunks/response-D-ubkAFl.js.map +1 -0
- package/dist/chunks/use-download-FAjtdJ58.js +1816 -0
- package/dist/chunks/use-download-FAjtdJ58.js.map +1 -0
- package/dist/chunks/vue-Dd9EhkQ3.js +34 -0
- package/dist/chunks/vue-Dd9EhkQ3.js.map +1 -0
- package/dist/core/args.d.ts +54 -0
- package/dist/core/args.d.ts.map +1 -0
- package/dist/core/connection.d.ts +15 -0
- package/dist/core/connection.d.ts.map +1 -0
- package/dist/core/context.d.ts +124 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/http-stream.d.ts +28 -0
- package/dist/core/http-stream.d.ts.map +1 -0
- package/dist/core/logger.d.ts +22 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/metadata.d.ts +92 -0
- package/dist/core/metadata.d.ts.map +1 -0
- package/dist/core/metadata.keys.d.ts +41 -0
- package/dist/core/metadata.keys.d.ts.map +1 -0
- package/dist/core/method.d.ts +177 -0
- package/dist/core/method.d.ts.map +1 -0
- package/dist/core/plugin-manager.d.ts +106 -0
- package/dist/core/plugin-manager.d.ts.map +1 -0
- package/dist/core/plugin.d.ts +113 -0
- package/dist/core/plugin.d.ts.map +1 -0
- package/dist/core/reconnect.d.ts +22 -0
- package/dist/core/reconnect.d.ts.map +1 -0
- package/dist/core/resolve-stream.d.ts +45 -0
- package/dist/core/resolve-stream.d.ts.map +1 -0
- package/dist/core/resolve.d.ts +50 -0
- package/dist/core/resolve.d.ts.map +1 -0
- package/dist/core/response.d.ts +60 -0
- package/dist/core/response.d.ts.map +1 -0
- package/dist/core/server.d.ts +132 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/sse.d.ts +27 -0
- package/dist/core/sse.d.ts.map +1 -0
- package/dist/core/state-bag.d.ts +36 -0
- package/dist/core/state-bag.d.ts.map +1 -0
- package/dist/core/websocket.d.ts +29 -0
- package/dist/core/websocket.d.ts.map +1 -0
- package/dist/decorators/api.d.ts +24 -4
- package/dist/decorators/api.d.ts.map +1 -0
- package/dist/decorators/args.d.ts +77 -14
- package/dist/decorators/args.d.ts.map +1 -0
- package/dist/decorators/custom.d.ts +81 -0
- package/dist/decorators/custom.d.ts.map +1 -0
- package/dist/decorators/header.d.ts +22 -0
- package/dist/decorators/header.d.ts.map +1 -0
- package/dist/decorators/index.d.ts +17 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/methods.d.ts +33 -0
- package/dist/decorators/methods.d.ts.map +1 -0
- package/dist/decorators/progress.d.ts +24 -6
- package/dist/decorators/progress.d.ts.map +1 -0
- package/dist/decorators/server.d.ts +28 -7
- package/dist/decorators/server.d.ts.map +1 -0
- package/dist/decorators/stream.d.ts +113 -0
- package/dist/decorators/stream.d.ts.map +1 -0
- package/dist/default/options.d.ts +19 -0
- package/dist/default/options.d.ts.map +1 -0
- package/dist/error/base.d.ts +20 -0
- package/dist/error/base.d.ts.map +1 -0
- package/dist/error/decorator.d.ts +14 -0
- package/dist/error/decorator.d.ts.map +1 -0
- package/dist/error/hook.d.ts +14 -0
- package/dist/error/hook.d.ts.map +1 -0
- package/dist/error/index.d.ts +8 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/options.d.ts +12 -0
- package/dist/error/options.d.ts.map +1 -0
- package/dist/error/plugin.d.ts +11 -0
- package/dist/error/plugin.d.ts.map +1 -0
- package/dist/error/request.d.ts +29 -0
- package/dist/error/request.d.ts.map +1 -0
- package/dist/error/response.d.ts +36 -0
- package/dist/error/response.d.ts.map +1 -0
- package/dist/index.d.ts +56 -11
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2034 -0
- package/dist/index.js.map +1 -0
- package/dist/locale/en.d.ts +5 -0
- package/dist/locale/en.d.ts.map +1 -0
- package/dist/locale/index.d.ts +57 -0
- package/dist/locale/index.d.ts.map +1 -0
- package/dist/locale/types.d.ts +11 -0
- package/dist/locale/types.d.ts.map +1 -0
- package/dist/locale/zh.d.ts +5 -0
- package/dist/locale/zh.d.ts.map +1 -0
- package/dist/plugins/cache/adapters/indexeddb.d.ts +52 -0
- package/dist/plugins/cache/adapters/indexeddb.d.ts.map +1 -0
- package/dist/plugins/cache/adapters/memory.d.ts +60 -0
- package/dist/plugins/cache/adapters/memory.d.ts.map +1 -0
- package/dist/plugins/cache/adapters/web-storage.d.ts +43 -0
- package/dist/plugins/cache/adapters/web-storage.d.ts.map +1 -0
- package/dist/plugins/cache/decorators.d.ts +62 -0
- package/dist/plugins/cache/decorators.d.ts.map +1 -0
- package/dist/plugins/cache/index.d.ts +41 -0
- package/dist/plugins/cache/index.d.ts.map +1 -0
- package/dist/plugins/cache/key.d.ts +48 -0
- package/dist/plugins/cache/key.d.ts.map +1 -0
- package/dist/plugins/cache/manager.d.ts +124 -0
- package/dist/plugins/cache/manager.d.ts.map +1 -0
- package/dist/plugins/cache/plugin.d.ts +64 -0
- package/dist/plugins/cache/plugin.d.ts.map +1 -0
- package/dist/plugins/cache/type.d.ts +116 -0
- package/dist/plugins/cache/type.d.ts.map +1 -0
- package/dist/plugins/index.d.ts +75 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +2265 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/interceptor/decorators.d.ts +44 -0
- package/dist/plugins/interceptor/decorators.d.ts.map +1 -0
- package/dist/plugins/interceptor/index.d.ts +31 -0
- package/dist/plugins/interceptor/index.d.ts.map +1 -0
- package/dist/plugins/interceptor/manager.d.ts +27 -0
- package/dist/plugins/interceptor/manager.d.ts.map +1 -0
- package/dist/plugins/interceptor/plugin.d.ts +65 -0
- package/dist/plugins/interceptor/plugin.d.ts.map +1 -0
- package/dist/plugins/interceptor/type.d.ts +45 -0
- package/dist/plugins/interceptor/type.d.ts.map +1 -0
- package/dist/plugins/pool/index.d.ts +26 -0
- package/dist/plugins/pool/index.d.ts.map +1 -0
- package/dist/plugins/pool/plugin.d.ts +83 -0
- package/dist/plugins/pool/plugin.d.ts.map +1 -0
- package/dist/plugins/pool/scheduler.d.ts +153 -0
- package/dist/plugins/pool/scheduler.d.ts.map +1 -0
- package/dist/plugins/pool/type.d.ts +38 -0
- package/dist/plugins/pool/type.d.ts.map +1 -0
- package/dist/plugins/react/index.d.ts +20 -0
- package/dist/plugins/react/index.d.ts.map +1 -0
- package/dist/plugins/react/index.js +145 -0
- package/dist/plugins/react/index.js.map +1 -0
- package/dist/plugins/react/plugin.d.ts +33 -0
- package/dist/plugins/react/plugin.d.ts.map +1 -0
- package/dist/plugins/react/type.d.ts +32 -0
- package/dist/plugins/react/type.d.ts.map +1 -0
- package/dist/plugins/transform/decorators.d.ts +54 -0
- package/dist/plugins/transform/decorators.d.ts.map +1 -0
- package/dist/plugins/transform/hydrate.d.ts +47 -0
- package/dist/plugins/transform/hydrate.d.ts.map +1 -0
- package/dist/plugins/transform/index.d.ts +41 -0
- package/dist/plugins/transform/index.d.ts.map +1 -0
- package/dist/plugins/transform/plugin.d.ts +20 -0
- package/dist/plugins/transform/plugin.d.ts.map +1 -0
- package/dist/plugins/transform/type.d.ts +67 -0
- package/dist/plugins/transform/type.d.ts.map +1 -0
- package/dist/plugins/validate/decorators.d.ts +24 -0
- package/dist/plugins/validate/decorators.d.ts.map +1 -0
- package/dist/plugins/validate/index.d.ts +40 -0
- package/dist/plugins/validate/index.d.ts.map +1 -0
- package/dist/plugins/validate/plugin.d.ts +13 -0
- package/dist/plugins/validate/plugin.d.ts.map +1 -0
- package/dist/plugins/validate/type.d.ts +54 -0
- package/dist/plugins/validate/type.d.ts.map +1 -0
- package/dist/plugins/version/decorators.d.ts +22 -0
- package/dist/plugins/version/decorators.d.ts.map +1 -0
- package/dist/plugins/version/index.d.ts +23 -0
- package/dist/plugins/version/index.d.ts.map +1 -0
- package/dist/plugins/version/plugin.d.ts +13 -0
- package/dist/plugins/version/plugin.d.ts.map +1 -0
- package/dist/plugins/version/type.d.ts +47 -0
- package/dist/plugins/version/type.d.ts.map +1 -0
- package/dist/plugins/vue/index.d.ts +21 -0
- package/dist/plugins/vue/index.d.ts.map +1 -0
- package/dist/plugins/vue/index.js +114 -0
- package/dist/plugins/vue/index.js.map +1 -0
- package/dist/plugins/vue/plugin.d.ts +15 -0
- package/dist/plugins/vue/plugin.d.ts.map +1 -0
- package/dist/plugins/vue/type.d.ts +34 -0
- package/dist/plugins/vue/type.d.ts.map +1 -0
- package/dist/strategies/index.d.ts +2 -0
- package/dist/strategies/index.d.ts.map +1 -0
- package/dist/strategies/index.js +29 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/strategies/plain.d.ts +2 -0
- package/dist/strategies/plain.d.ts.map +1 -0
- package/dist/strategies/plain.js +23 -0
- package/dist/strategies/plain.js.map +1 -0
- package/dist/strategies/react.d.ts +2 -0
- package/dist/strategies/react.d.ts.map +1 -0
- package/dist/strategies/react.js +30 -0
- package/dist/strategies/react.js.map +1 -0
- package/dist/strategies/shared/adapter.d.ts +23 -0
- package/dist/strategies/shared/adapter.d.ts.map +1 -0
- package/dist/strategies/shared/dom.d.ts +53 -0
- package/dist/strategies/shared/dom.d.ts.map +1 -0
- package/dist/strategies/shared/error.d.ts +30 -0
- package/dist/strategies/shared/error.d.ts.map +1 -0
- package/dist/strategies/shared/method.d.ts +51 -0
- package/dist/strategies/shared/method.d.ts.map +1 -0
- package/dist/strategies/shared/public.d.ts +33 -0
- package/dist/strategies/shared/public.d.ts.map +1 -0
- package/dist/strategies/shared/queue.d.ts +30 -0
- package/dist/strategies/shared/queue.d.ts.map +1 -0
- package/dist/strategies/shared/retry.d.ts +51 -0
- package/dist/strategies/shared/retry.d.ts.map +1 -0
- package/dist/strategies/shared/state.d.ts +117 -0
- package/dist/strategies/shared/state.d.ts.map +1 -0
- package/dist/strategies/shared/timing.d.ts +53 -0
- package/dist/strategies/shared/timing.d.ts.map +1 -0
- package/dist/strategies/shared/watcher.d.ts +37 -0
- package/dist/strategies/shared/watcher.d.ts.map +1 -0
- package/dist/strategies/use-auto-request.d.ts +77 -0
- package/dist/strategies/use-auto-request.d.ts.map +1 -0
- package/dist/strategies/use-download.d.ts +103 -0
- package/dist/strategies/use-download.d.ts.map +1 -0
- package/dist/strategies/use-fetcher.d.ts +52 -0
- package/dist/strategies/use-fetcher.d.ts.map +1 -0
- package/dist/strategies/use-pagination.d.ts +101 -0
- package/dist/strategies/use-pagination.d.ts.map +1 -0
- package/dist/strategies/use-request.d.ts +50 -0
- package/dist/strategies/use-request.d.ts.map +1 -0
- package/dist/strategies/use-retriable-request.d.ts +46 -0
- package/dist/strategies/use-retriable-request.d.ts.map +1 -0
- package/dist/strategies/use-sse.d.ts +103 -0
- package/dist/strategies/use-sse.d.ts.map +1 -0
- package/dist/strategies/use-token-auth.d.ts +88 -0
- package/dist/strategies/use-token-auth.d.ts.map +1 -0
- package/dist/strategies/use-uploader.d.ts +88 -0
- package/dist/strategies/use-uploader.d.ts.map +1 -0
- package/dist/strategies/use-watcher.d.ts +69 -0
- package/dist/strategies/use-watcher.d.ts.map +1 -0
- package/dist/typings/adapter.d.ts +61 -0
- package/dist/typings/adapter.d.ts.map +1 -0
- package/dist/typings/api.d.ts +122 -0
- package/dist/typings/api.d.ts.map +1 -0
- package/dist/typings/args.d.ts +51 -0
- package/dist/typings/args.d.ts.map +1 -0
- package/dist/typings/index.d.ts +8 -12
- package/dist/typings/index.d.ts.map +1 -0
- package/dist/typings/meta.d.ts +44 -0
- package/dist/typings/meta.d.ts.map +1 -0
- package/dist/typings/plugin.d.ts +114 -0
- package/dist/typings/plugin.d.ts.map +1 -0
- package/dist/typings/response.d.ts +118 -0
- package/dist/typings/response.d.ts.map +1 -0
- package/dist/typings/server.d.ts +83 -0
- package/dist/typings/server.d.ts.map +1 -0
- package/dist/typings/stream.d.ts +150 -0
- package/dist/typings/stream.d.ts.map +1 -0
- package/dist/utils/download.d.ts +97 -0
- package/dist/utils/download.d.ts.map +1 -0
- package/dist/utils/emitter.d.ts +36 -0
- package/dist/utils/emitter.d.ts.map +1 -0
- package/dist/utils/index.d.ts +6 -1
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/is.d.ts +22 -0
- package/dist/utils/is.d.ts.map +1 -0
- package/dist/utils/object.d.ts +44 -0
- package/dist/utils/object.d.ts.map +1 -0
- package/dist/utils/url.d.ts +44 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/package.json +90 -27
- package/README_EN.md +0 -607
- package/dist/cache/index.d.ts +0 -9
- package/dist/cache/indexDBCache.d.ts +0 -13
- package/dist/cache/localstorageCache.d.ts +0 -10
- package/dist/cache/memoryCache.d.ts +0 -11
- package/dist/core/index.d.ts +0 -4
- package/dist/core/snailApi.d.ts +0 -22
- package/dist/core/snailMethod.d.ts +0 -49
- package/dist/core/snailServer.d.ts +0 -35
- package/dist/core/snailSse.d.ts +0 -20
- package/dist/decorators/cache.d.ts +0 -15
- package/dist/decorators/method.d.ts +0 -38
- package/dist/decorators/sse.d.ts +0 -30
- package/dist/decorators/strategy.d.ts +0 -10
- package/dist/decorators/versioning.d.ts +0 -16
- package/dist/eventEmmit/index.d.ts +0 -1
- package/dist/eventEmmit/snail.event.d.ts +0 -10
- package/dist/snail-api.js +0 -4868
- package/dist/snail-api.umd.cjs +0 -4872
- package/dist/strategies/jwtStrategy.d.ts +0 -4
- package/dist/typings/api.option.d.ts +0 -10
- package/dist/typings/apiProxy.d.ts +0 -8
- package/dist/typings/cache.management.option.d.ts +0 -25
- package/dist/typings/cache.type.d.ts +0 -23
- package/dist/typings/content.type.d.ts +0 -5
- package/dist/typings/request.body.d.ts +0 -3
- package/dist/typings/response.data.d.ts +0 -13
- package/dist/typings/snail.event.d.ts +0 -6
- package/dist/typings/snail.method.d.ts +0 -14
- package/dist/typings/snail.option.d.ts +0 -16
- package/dist/typings/sse.d.ts +0 -15
- package/dist/typings/strategy.d.ts +0 -5
- package/dist/typings/versioning.option.d.ts +0 -30
- package/dist/utils/function.d.ts +0 -31
- package/dist/versioning/index.d.ts +0 -1
- package/dist/versioning/versioning.d.ts +0 -12
package/README.md
CHANGED
|
@@ -1,678 +1,198 @@
|
|
|
1
|
-
|
|
2
|
-
<img src="https://img.shields.io/badge/TypeScript-1e80ff"></img>
|
|
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>
|
|
5
|
-
</p>
|
|
1
|
+
# @snail-js/api
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
> 装饰器驱动、一切皆插件的 TypeScript 请求管理库,仅基于 [axios](https://axios-http.com/)。
|
|
8
4
|
|
|
9
|
-
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://axios-http.com/)
|
|
7
|
+
[](./LICENSE)
|
|
10
8
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
9
|
+
- **装饰器驱动** — `@Server` / `@Api` / `@Get` 定义请求,设计思想来自 Nest.js
|
|
10
|
+
- **一切皆插件** — 缓存、拦截器、请求池、版本、校验、转换、框架适配全部是插件,核心只做三件事
|
|
11
|
+
- **零运行时依赖** — `dependencies` 是空的;axios 是 peer 依赖,也不需要 `reflect-metadata`
|
|
12
|
+
- **完整的类型推断** — 从方法声明的返回类型推断 `data` 类型,无需手写泛型
|
|
13
|
+
- **请求策略** — alova 风格的 `useRequest` / `usePagination` / `useRetriableRequest` / `useDownload` 等 hook
|
|
14
|
+
- **浏览器与服务端皆可** — 核心只用平台能力,没有 DOM 依赖;SSR 与 Node 服务同样适用
|
|
14
15
|
|
|
15
16
|
## 安装
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @snail-js/api axios
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`vue`、`react`、`zod` 都是**可选**的 peer 依赖,只有用到对应插件/策略时才需要安装。
|
|
18
23
|
|
|
19
|
-
##
|
|
24
|
+
## 快速开始
|
|
20
25
|
|
|
21
|
-
1.
|
|
26
|
+
### 1. 配置 TypeScript
|
|
22
27
|
|
|
23
28
|
```json
|
|
24
|
-
// tsconfig.json
|
|
25
29
|
{
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"baseUrl": ".",
|
|
30
|
-
// target 必须大于ES6
|
|
31
|
-
"target": "ESNext",
|
|
32
|
-
// lib 需要包含大于ES6的ES版本
|
|
33
|
-
"lib": ["ESNext", "DOM"],
|
|
34
|
-
// 包含reflect-metadata类型
|
|
35
|
-
"types": ["reflect-metadata"],
|
|
36
|
-
"emitDecoratorMetadata": true,
|
|
37
|
-
"experimentalDecorators": true,
|
|
38
|
-
|
|
39
|
-
"skipLibCheck": true,
|
|
40
|
-
"strictNullChecks": false
|
|
30
|
+
"compilerOptions": {
|
|
31
|
+
"experimentalDecorators": true
|
|
32
|
+
}
|
|
41
33
|
}
|
|
42
34
|
```
|
|
43
35
|
|
|
44
|
-
|
|
36
|
+
> **不需要** `reflect-metadata`,也**不需要** `emitDecoratorMetadata`。
|
|
37
|
+
> TypeScript 7 已不再产出 `design:*` 元数据,本库使用自己的元数据存储。
|
|
38
|
+
> 如果你从旧版本迁移,请参照[迁移指南](https://snail-js.github.io/api/guide/migration)。
|
|
39
|
+
|
|
40
|
+
### 2. 定义服务
|
|
45
41
|
|
|
46
|
-
```
|
|
42
|
+
```ts
|
|
47
43
|
// service.ts
|
|
48
|
-
import {
|
|
44
|
+
import { Server, SnailServer } from "@snail-js/api";
|
|
49
45
|
|
|
50
|
-
@Server({
|
|
51
|
-
baseURL: "/api",
|
|
52
|
-
timeout: 5000,
|
|
53
|
-
})
|
|
46
|
+
@Server({ baseURL: "/api", timeout: 5000 })
|
|
54
47
|
class BackEnd extends SnailServer {}
|
|
55
48
|
|
|
56
|
-
export const
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
3. 创建 Api 实例
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
// user.ts
|
|
63
|
-
import { Api, Get, Post, Query, Data, SnailApi } from "@snail-js/api";
|
|
64
|
-
|
|
65
|
-
import { Service } from "./service";
|
|
66
|
-
|
|
67
|
-
@Api("user")
|
|
68
|
-
class UserApi extends SnailApi {
|
|
69
|
-
@Get()
|
|
70
|
-
get(@Query("id") id: string) {}
|
|
71
|
-
|
|
72
|
-
@Post()
|
|
73
|
-
create(@Data() user: User) {}
|
|
74
|
-
}
|
|
75
|
-
// 创建并导出api
|
|
76
|
-
export const userApi = Service.createApi(UserApi);
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
3. 发送请求
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
import { userApi } from "./user";
|
|
83
|
-
|
|
84
|
-
const { send:getUser, onSuccess, onError, onHitCache } = await userApi.get();
|
|
85
|
-
|
|
86
|
-
const data = await getUser("1");
|
|
49
|
+
export const service = new BackEnd();
|
|
87
50
|
```
|
|
88
51
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- 调用`Service.createApi(ApiInstance)`后会为`ApiInstance`内被`RequestMethod`(如:@Get、@Post...)装饰的方法创建一个代理,返回一个函数,此函数包含请求参数,调用此函数返回`SnailMethod` 实例
|
|
92
|
-
|
|
93
|
-
### `SnailMethod` 实例方法
|
|
94
|
-
|
|
95
|
-
- `send` 发送请求
|
|
96
|
-
_异步函数,发送当前请求_
|
|
97
|
-
- `onSuccess` 请求成功回调
|
|
98
|
-
_注册请求成功事件_
|
|
99
|
-
- `onError` 请求失败回调
|
|
100
|
-
_注册请求失败事件_
|
|
101
|
-
- `onHitCache` 请求命中缓存回调
|
|
102
|
-
_注册请求命中缓存事件_
|
|
103
|
-
- `onFinish` 请求完成回调
|
|
104
|
-
_注册请求完成事件_
|
|
105
|
-
- `registerStrategies` 注册策略
|
|
106
|
-
_注册方法级策略_
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
### `SnailMethod` 实例属性
|
|
110
|
-
|
|
111
|
-
- response : AxiosResponse
|
|
112
|
-
- request : AxiosRequestConfig ,最终请求的 request,这个 request 是被 Versioning 和 Strategy 处理过的
|
|
113
|
-
- version : string,最终请求的版本,如果没有开启 Versioning 则为 undefine
|
|
114
|
-
- name : string,完整的 SnailMethod 名称,格式为`ServerName.ApiName.MethodName`
|
|
115
|
-
- error : Error | null,请求失败的错误信息,无错误为 null
|
|
116
|
-
|
|
117
|
-
### Server 配置
|
|
118
|
-
|
|
119
|
-
<table>
|
|
120
|
-
<tr>
|
|
121
|
-
<th>配置项</th>
|
|
122
|
-
<th>类型</th>
|
|
123
|
-
<th>是否必须</th>
|
|
124
|
-
<th>默认值</th>
|
|
125
|
-
<th>说明</th>
|
|
126
|
-
</tr>
|
|
127
|
-
<tr>
|
|
128
|
-
<td>name</td>
|
|
129
|
-
<td>string</td>
|
|
130
|
-
<td>否</td>
|
|
131
|
-
<td>默认使用继承`SnailServer`的类名作为name</td>
|
|
132
|
-
<td>server实例唯一标识,请勿与其他server重复</td>
|
|
133
|
-
</tr>
|
|
134
|
-
<tr>
|
|
135
|
-
<td>baseUrl</td>
|
|
136
|
-
<td>string</td>
|
|
137
|
-
<td>否</td>
|
|
138
|
-
<td>'\'</td>
|
|
139
|
-
<td>请求后端的api地址前缀,同`axios`的baseUrl</td>
|
|
140
|
-
</tr>
|
|
141
|
-
<tr>
|
|
142
|
-
<td>Versioning</td>
|
|
143
|
-
<td><a href="#versioningoption">VersioningOption</a></td>
|
|
144
|
-
<td>否</td>
|
|
145
|
-
<td>undefine</td>
|
|
146
|
-
<td>版本管理器配置,默认不开启</td>
|
|
147
|
-
</tr>
|
|
148
|
-
<tr>
|
|
149
|
-
<td>timeout</td>
|
|
150
|
-
<td>number</td>
|
|
151
|
-
<td>否</td>
|
|
152
|
-
<td>5000</td>
|
|
153
|
-
<td>单位:毫秒;全局超时时间,会被 Api 的 timeout 值覆盖</td>
|
|
154
|
-
</tr>
|
|
155
|
-
<tr>
|
|
156
|
-
<td>cacheManage</td>
|
|
157
|
-
<td>{type:CacheType,ttl:number}</td>
|
|
158
|
-
<td>否</td>
|
|
159
|
-
<td>{
|
|
160
|
-
type: CacheType.Memory,
|
|
161
|
-
ttl: 500
|
|
162
|
-
}</td>
|
|
163
|
-
<td>缓存管理器,ttl单位为秒</td>
|
|
164
|
-
</tr>
|
|
165
|
-
<tr>
|
|
166
|
-
<td>cacheFor</td>
|
|
167
|
-
<td>RequestMethod | RequestMethod[] | 'All' | 'all' </td>
|
|
168
|
-
<td>否</td>
|
|
169
|
-
<td>Get</td>
|
|
170
|
-
<td>要启用缓存的方法,默认仅开启Get缓存</td>
|
|
171
|
-
</tr>
|
|
172
|
-
<tr>
|
|
173
|
-
<td>serverStatusCodeRule</td>
|
|
174
|
-
<td><a href="#SnailServerStatusCodeRuleOptions">SnailServerStatusCodeRuleOptions</a></td>
|
|
175
|
-
<td>否</td>
|
|
176
|
-
<td>undefined</td>
|
|
177
|
-
<td>服务端状态码规则,若配置此项,rule函数返回false时会触发错误</td>
|
|
178
|
-
</tr>
|
|
179
|
-
<tr>
|
|
180
|
-
<td>enableLog</td>
|
|
181
|
-
<td>boolean</td>
|
|
182
|
-
<td>否</td>
|
|
183
|
-
<td>false</td>
|
|
184
|
-
<td>是否开启日志,用于调试</td>
|
|
185
|
-
</tr>
|
|
186
|
-
</table>
|
|
187
|
-
|
|
188
|
-
### Api 配置
|
|
189
|
-
|
|
190
|
-
- 请使用`@Api()`装饰自定义 Api 类并继承`SnailApi`
|
|
191
|
-
|
|
192
|
-
<table>
|
|
193
|
-
<tr>
|
|
194
|
-
<th>配置项</th>
|
|
195
|
-
<th>类型</th>
|
|
196
|
-
<th>是否必须</th>
|
|
197
|
-
<th>默认值</th>
|
|
198
|
-
<th>说明</th>
|
|
199
|
-
</tr>
|
|
200
|
-
<tr>
|
|
201
|
-
<td>name</td>
|
|
202
|
-
<td>string</td>
|
|
203
|
-
<td>否</td>
|
|
204
|
-
<td>默认使用继承`SnailApi`的类名作为name</td>
|
|
205
|
-
<td>api实例唯一标识,请勿与其他api重复</td>
|
|
206
|
-
</tr>
|
|
207
|
-
<tr>
|
|
208
|
-
<td>timeout</td>
|
|
209
|
-
<td>number</td>
|
|
210
|
-
<td>否</td>
|
|
211
|
-
<td></td>
|
|
212
|
-
<td>请求超时时间;会覆盖Server的timeout设置</td>
|
|
213
|
-
</tr>
|
|
214
|
-
<tr>
|
|
215
|
-
<td>version</td>
|
|
216
|
-
<td>string</td>
|
|
217
|
-
<td>否</td>
|
|
218
|
-
<td></td>
|
|
219
|
-
<td>api版本号,会覆盖server的`defaultVersion`配置</td>
|
|
220
|
-
</tr>
|
|
221
|
-
</table>
|
|
222
|
-
|
|
223
|
-
## 请求方法装饰器
|
|
224
|
-
|
|
225
|
-
- 在`Api`类中使用,用于标记请求方法
|
|
226
|
-
- 提供 axios 的全部请求方法`Get,Post,Head,Put,Delete,Patch,Options`
|
|
227
|
-
- 参数: `path?: string`; 请求端点路径,与`baseUrl,api.url`共同拼接组成最终请求路径
|
|
228
|
-
|
|
229
|
-
## 参数装饰器
|
|
230
|
-
|
|
231
|
-
### 查询参数 `@Query`
|
|
232
|
-
|
|
233
|
-
- `@Query(key?:string)`
|
|
234
|
-
|
|
235
|
-
- 单个参数使用
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
@Api("user")
|
|
239
|
-
class UserApi {
|
|
240
|
-
@Get()
|
|
241
|
-
get(@Query("id") id: string, @Query("sign") sign: string) {}
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
> 传入 key,标记单个查询参数,拼接到请求`?k1=v1&k2=v2`
|
|
246
|
-
|
|
247
|
-
### 路由参数 `@Params`
|
|
248
|
-
|
|
249
|
-
- `@Params(key?:string)`
|
|
250
|
-
|
|
251
|
-
- 单个参数使用
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
@Api("user/:id/:sign")
|
|
255
|
-
class UserApi {
|
|
256
|
-
@Get()
|
|
257
|
-
get(@Params("id") id: string, @Params("sign") sign: string) {}
|
|
258
|
-
}
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
> 传入 key,标记单个查询参数,拼接到请求`?k1=v1&k2=v2`
|
|
52
|
+
### 3. 定义 API
|
|
262
53
|
|
|
263
|
-
|
|
54
|
+
```ts
|
|
55
|
+
// user.api.ts
|
|
56
|
+
import { Api, Data, Get, Params, Post, Query } from "@snail-js/api";
|
|
57
|
+
import { service } from "./service";
|
|
264
58
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
sign: string;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
@Api("user/:id/:sign")
|
|
272
|
-
class UserApi {
|
|
273
|
-
@Get()
|
|
274
|
-
get(@Params() params: RouteParams) {}
|
|
275
|
-
}
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
> 不传入 key,会被标记为对象类型查询参数;也能自动拼接到请求
|
|
279
|
-
|
|
280
|
-
- 混合使用
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
class RouteParams {
|
|
284
|
-
id: string;
|
|
285
|
-
sign: string;
|
|
59
|
+
export interface User {
|
|
60
|
+
id: number;
|
|
61
|
+
name: string;
|
|
286
62
|
}
|
|
287
63
|
|
|
288
|
-
@Api("user
|
|
64
|
+
@Api("/user")
|
|
289
65
|
class UserApi {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
### 请求数据
|
|
296
|
-
|
|
297
|
-
- `@Data(key?:string)`
|
|
298
|
-
- 使用方式和`@Params`相同,也支持混合使用
|
|
299
|
-
|
|
300
|
-
## 策略装饰器`@UseStrategy`
|
|
301
|
-
|
|
302
|
-
- `@UseStrategy(...Strategy[])`
|
|
303
|
-
|
|
304
|
-
### 请求策略
|
|
305
|
-
|
|
306
|
-
- 在请求发送前执行,后面的策略返回结果会覆盖前面的策略
|
|
307
|
-
- 若返回处理后的 request,则使用处理后的 request 发送请求,否则使用原始 request 或上一个策略返回的 request 发送请求
|
|
308
|
-
|
|
309
|
-
```typescript
|
|
310
|
-
class CustomStrategy extends Strategy {
|
|
311
|
-
applyRequest(request: AxiosRequestConfig) {
|
|
312
|
-
request.headers["Access-Token"] = "abcde";
|
|
313
|
-
return request;
|
|
66
|
+
/** 方法体永远不会执行,它只用来声明参数类型和返回类型 */
|
|
67
|
+
@Get("/:id")
|
|
68
|
+
getUser(@Params("id") id: string, @Query("withProfile") withProfile?: boolean): Promise<User> {
|
|
69
|
+
return null!;
|
|
314
70
|
}
|
|
315
|
-
}
|
|
316
71
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
baseURL: "/api",
|
|
321
|
-
timeout: 5000,
|
|
322
|
-
})
|
|
323
|
-
@UseStrategy(CustomStrategy)
|
|
324
|
-
class BackEnd extends Snail<ShanheResponse> {}
|
|
325
|
-
export const Service = new BackEnd();
|
|
326
|
-
// 创建Service实例后再注册策略
|
|
327
|
-
Service.registerStrategies(CustomStrategy);
|
|
328
|
-
|
|
329
|
-
// 用在Api, 当Api下的方法请求时生效
|
|
330
|
-
@Api("test")
|
|
331
|
-
@UseStrategy(CustomStrategy)
|
|
332
|
-
class Test {}
|
|
333
|
-
const TestApi = Service.createApi(Test);
|
|
334
|
-
// 创建Api实例后再注册策略
|
|
335
|
-
TestApi.registerStrategies(CustomStrategy);
|
|
336
|
-
|
|
337
|
-
// 用在方法,此方法请求时生效
|
|
338
|
-
@Api("test")
|
|
339
|
-
@UseStrategy(CustomStrategy)
|
|
340
|
-
class Test {
|
|
341
|
-
@Get()
|
|
342
|
-
@UseStrategy(CustomStrategy)
|
|
343
|
-
get() {}
|
|
344
|
-
}
|
|
345
|
-
// 发送请求前注册策略
|
|
346
|
-
const TestApi = Service.createApi(Test);
|
|
347
|
-
const getSomething = TestApi.get();
|
|
348
|
-
{ send, registerStrategies } = getSomething;
|
|
349
|
-
getSomething.registerStrategies(CustomStrategy);
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### 响应策略
|
|
355
|
-
|
|
356
|
-
- 在收到服务器响应后执行
|
|
357
|
-
- 若返回处理后的 response,则使用处理后的 response 进行下一个策略或返回,否则使用原始 response 或上一个策略返回的 response 返回
|
|
358
|
-
|
|
359
|
-
```typescript
|
|
360
|
-
// 如何定义
|
|
361
|
-
class CustomStrategy extends Strategy {
|
|
362
|
-
applyResponse(response: AxiosResponse) {
|
|
363
|
-
const { status } = response;
|
|
364
|
-
if (status == 200) {
|
|
365
|
-
// do something
|
|
366
|
-
}
|
|
367
|
-
return response;
|
|
72
|
+
@Post("/")
|
|
73
|
+
createUser(@Data() payload: Omit<User, "id">): Promise<User> {
|
|
74
|
+
return null!;
|
|
368
75
|
}
|
|
369
76
|
}
|
|
370
|
-
```
|
|
371
77
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
### 版本管理器`@Versioning(VersioningOption)`
|
|
375
|
-
|
|
376
|
-
- 全局管理版本
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
@Server({
|
|
380
|
-
baseURL: "/api",
|
|
381
|
-
timeout: 5000,
|
|
382
|
-
})
|
|
383
|
-
@Versioning({
|
|
384
|
-
type: VersioningType.Header,
|
|
385
|
-
defaultVersion: "0.1.0",
|
|
386
|
-
})
|
|
387
|
-
class BackEnd extends Snail<ShanheResponse> {}
|
|
388
|
-
|
|
389
|
-
export const Service = new BackEnd();
|
|
78
|
+
export const userApi = service.createApi(UserApi);
|
|
390
79
|
```
|
|
391
80
|
|
|
392
|
-
|
|
81
|
+
### 4. 发起请求
|
|
393
82
|
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
Query,
|
|
399
|
-
Custom,
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
interface VersioningCommonOption {
|
|
403
|
-
defaultVersion: string;
|
|
404
|
-
}
|
|
83
|
+
```ts
|
|
84
|
+
// 调用被装饰的方法不会发送请求,它只创建一个待发送的请求对象
|
|
85
|
+
const method = userApi.getUser("1");
|
|
86
|
+
const { data, code, message, fromCache } = await method.send();
|
|
405
87
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
prefix?: string;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
export interface VersioningHeaderOption extends VersioningCommonOption {
|
|
412
|
-
type: VersioningType.Header;
|
|
413
|
-
header?: string;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
export interface VersioningQueryOption extends VersioningCommonOption {
|
|
417
|
-
type: VersioningType.Query;
|
|
418
|
-
key?: string;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
export interface VersioningCustomOption extends VersioningCommonOption {
|
|
422
|
-
type: VersioningType.Custom;
|
|
423
|
-
extractor: (requestOptions: unknown) => {
|
|
424
|
-
url: string;
|
|
425
|
-
headers: Record<string, any>;
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
export type VersioningOption =
|
|
430
|
-
| VersioningUriOption
|
|
431
|
-
| VersioningHeaderOption
|
|
432
|
-
| VersioningQueryOption
|
|
433
|
-
| VersioningCustomOption;
|
|
88
|
+
// data 已经被推断为 User —— 无需手写泛型,也不会有 any
|
|
89
|
+
console.log(data.name);
|
|
434
90
|
```
|
|
435
91
|
|
|
436
|
-
|
|
92
|
+
单个方法实例可以重复使用,参数可以在 `send()` 时覆盖:
|
|
437
93
|
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
// 当rule函数返回false时,会触发错误
|
|
443
|
-
rule: (statusCode: number) => boolean;
|
|
444
|
-
// response.data中服务端状态码的key,默认为code
|
|
445
|
-
key?: string;
|
|
446
|
-
}
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
### 临时版本修改器`@Version`
|
|
450
|
-
|
|
451
|
-
- 临时改变方法请求的版本
|
|
452
|
-
|
|
453
|
-
```typescript
|
|
454
|
-
@Api("test")
|
|
455
|
-
class Test {
|
|
456
|
-
@Get("HelloWorld")
|
|
457
|
-
@Version("0.2.0")
|
|
458
|
-
test() {}
|
|
459
|
-
}
|
|
94
|
+
```ts
|
|
95
|
+
const method = userApi.getUser();
|
|
96
|
+
await method.send("1");
|
|
97
|
+
await method.send("2");
|
|
460
98
|
```
|
|
461
99
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
### 缓存装饰器`@HitSource`
|
|
465
|
-
|
|
466
|
-
- `@HitSource(name:string)`
|
|
467
|
-
- 为被装饰的方法设置缓存失效源,当设置的名称方法被调用且正常响应时,被装饰的方法缓存失效
|
|
468
|
-
- name 格式为:`serverName:apiName:methodName`
|
|
469
|
-
> 注意:若您配置了 SnailServer/SnailApi 的 name 选项,请使用此 name 作为名称,否则使用类名作为名称
|
|
100
|
+
## 返回结构
|
|
470
101
|
|
|
471
|
-
|
|
472
|
-
@Api("test", { name: "api1" })
|
|
473
|
-
@HitSource("api1")
|
|
474
|
-
class Test {
|
|
475
|
-
@Get("HelloWorld")
|
|
476
|
-
@HitSource("api1.test2")
|
|
477
|
-
test1() {}
|
|
102
|
+
后端返回的数据默认遵循下面的结构:
|
|
478
103
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
@Get()
|
|
483
|
-
// Test类下任何请求成功,这个方法的缓存都会失效
|
|
484
|
-
@HitSource("api1")
|
|
485
|
-
test3() {}
|
|
486
|
-
}
|
|
104
|
+
```json
|
|
105
|
+
{ "code": 0, "message": "ok", "data": {} }
|
|
487
106
|
```
|
|
488
107
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
> `test3`方法请求成功时,不缓存
|
|
493
|
-
|
|
494
|
-
> 注意:要使用缓存,请配置`@Server({CacheManage})`缓存管理器
|
|
495
|
-
|
|
496
|
-
### 上传进度装饰器`@UploadProgress`
|
|
497
|
-
|
|
498
|
-
- `@UploadProgress((progressEvent: AxiosProgressEvent) => void)`
|
|
499
|
-
|
|
500
|
-
### 下载进度装饰器`@DownloadProgress`
|
|
501
|
-
|
|
502
|
-
- `@DownloadProgress((progressEvent: AxiosProgressEvent) => void)`
|
|
503
|
-
|
|
504
|
-
## Server Send Event 服务端推送
|
|
505
|
-
|
|
506
|
-
### 创建 sse 端点
|
|
507
|
-
|
|
508
|
-
```typescript
|
|
509
|
-
@Sse("sse")
|
|
510
|
-
class ServerSend extend SnailSse {
|
|
511
|
-
|
|
512
|
-
@OnSseOpen()
|
|
513
|
-
handleOpen(event: Event) {
|
|
514
|
-
console.log("sse-open:", event);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
@OnSseError()
|
|
518
|
-
handleError(event: Event) {
|
|
519
|
-
console.log("sse-error:", event);
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// 处理默认message事件
|
|
523
|
-
@SseEvent()
|
|
524
|
-
handleEvent(event: MessageEvent) {
|
|
525
|
-
console.log("sse-event[message]:", event.data);
|
|
526
|
-
}
|
|
108
|
+
三个字段名都可以通过 `@Server({ codeKey, messageKey, dataKey })` 修改;
|
|
109
|
+
结构本身可以通过 `declare module` 重定义:
|
|
527
110
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
111
|
+
```ts
|
|
112
|
+
declare module "@snail-js/api" {
|
|
113
|
+
interface SnailEnvelopeSchema {
|
|
114
|
+
status: number;
|
|
115
|
+
msg: string;
|
|
116
|
+
result: unknown;
|
|
532
117
|
}
|
|
533
118
|
}
|
|
534
|
-
|
|
535
|
-
export const Sse = Service.createSse(ServerSend);
|
|
536
119
|
```
|
|
537
120
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
- `@Sse(path:string,options?:{withCredentials?: boolean,version?: string;})`
|
|
541
|
-
- 创建一个服务端推送连接,返回一个函数,用于打开 sse 连接
|
|
542
|
-
- 返回的打开函数调用后会返回`{eventSource:EventSource,close:function}`
|
|
543
|
-
- eventSource: sse 连接实例
|
|
544
|
-
- close: 关闭此 sse 连接的方法
|
|
545
|
-
|
|
546
|
-
### 注册`onopen`装饰器`@OnSseOpen`
|
|
547
|
-
|
|
548
|
-
- 当`@Sse`装饰的方法被调用时,将`@OnSseOpen`装饰的方法注册为`@Sse`装饰的方法返回的`EventSource`实例`onopen`处理函数
|
|
549
|
-
|
|
550
|
-
### 注册`onerror`装饰器`@OnSseError`
|
|
121
|
+
`send()` 返回一个 `SnailResult`,而不是裸的信封:
|
|
551
122
|
|
|
552
|
-
|
|
123
|
+
| 字段 | 说明 |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| `data` | **已解包**的业务数据,绝大多数情况下你只需要它 |
|
|
126
|
+
| `envelope` | 完整信封 `{ code, message, data }` |
|
|
127
|
+
| `response` | 原始 axios 响应 |
|
|
128
|
+
| `code` / `message` | 业务状态码与消息 |
|
|
129
|
+
| `fromCache` | 是否来自缓存 |
|
|
130
|
+
| `config` | 最终生效的请求配置 |
|
|
553
131
|
|
|
554
|
-
|
|
132
|
+
## 插件
|
|
555
133
|
|
|
556
|
-
|
|
557
|
-
- 未传入`eventName`,默认注册为`message`事件处理器
|
|
558
|
-
- 传入`eventName`,注册为对应名称的事件处理器
|
|
134
|
+
插件从子路径按需引入,未使用的插件会被打包器完全剔除:
|
|
559
135
|
|
|
560
|
-
|
|
136
|
+
```ts
|
|
137
|
+
import { Cache, Interceptor, RequestPool, Versioning } from "@snail-js/api/plugins";
|
|
561
138
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
export type StandardResponseData<
|
|
568
|
-
T extends ResponseJsonData = Record<string, any>
|
|
569
|
-
> = {
|
|
570
|
-
code: number;
|
|
571
|
-
message: string;
|
|
572
|
-
data: T;
|
|
573
|
-
};
|
|
139
|
+
service
|
|
140
|
+
.use(Interceptor())
|
|
141
|
+
.use(Versioning({ type: "header", defaultVersion: "1.0.0" }))
|
|
142
|
+
.use(Cache({ ttl: 60, l2: "localStorage" }))
|
|
143
|
+
.use(RequestPool({ concurrency: 4, maxQueue: 50, queueTimeout: 10000 }));
|
|
574
144
|
```
|
|
575
145
|
|
|
576
|
-
|
|
146
|
+
`use()` 是同步且可链式调用的,插件名重复或依赖缺失会在调用时立即抛错。
|
|
577
147
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
export class CustomResponse {
|
|
582
|
-
status_code: number;
|
|
583
|
-
msg: string;
|
|
584
|
-
}
|
|
585
|
-
```
|
|
148
|
+
请求池用来给并发设上限:浏览器的队列是先进先出、不可见、无法排优先级的,
|
|
149
|
+
一个页面的并发爆发会把用户真正在等的那条请求挤到后面。它排在缓存**之后**,
|
|
150
|
+
所以缓存能答的请求不会占用并发额度。
|
|
586
151
|
|
|
587
|
-
|
|
152
|
+
## 请求策略
|
|
588
153
|
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
import { SnailServer, Server } from "@snail-js/api";
|
|
154
|
+
```ts
|
|
155
|
+
import { useDownload, useRequest } from "@snail-js/api/strategies";
|
|
592
156
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
timeout: 5000,
|
|
596
|
-
})
|
|
597
|
-
class BackEnd extends SnailServer<CustomResponse> {}
|
|
157
|
+
const { loading, data, error, send, bind } = useRequest(userApi.getUser);
|
|
158
|
+
await send("1");
|
|
598
159
|
|
|
599
|
-
|
|
160
|
+
// 下载:只 await「换取临时链接」的那次请求,文件本身交给浏览器原生下载
|
|
161
|
+
const { download } = useDownload(reportApi.create);
|
|
162
|
+
await download({ from: "2026-01-01" });
|
|
600
163
|
```
|
|
601
164
|
|
|
602
|
-
|
|
165
|
+
默认适配 Vue 的响应式状态(`ref`);React 用户请从
|
|
166
|
+
`@snail-js/api/strategies/react` 引入,无框架场景请从
|
|
167
|
+
`@snail-js/api/strategies/plain` 引入。
|
|
603
168
|
|
|
604
|
-
|
|
605
|
-
|
|
169
|
+
不想把整个文件读进 JavaScript 内存时用 `useDownload`:它 await 的只是让服务端
|
|
170
|
+
生成临时下载链接的那次请求,随后用 `<a>` 触发浏览器原生下载 —— 有进度、可断点
|
|
171
|
+
续传、不占内存。`useDownload` 属于策略而非插件,因为它是一次明确的用户动作,
|
|
172
|
+
而不是作用于所有请求的横切关注点。
|
|
606
173
|
|
|
607
|
-
|
|
608
|
-
id: number;
|
|
609
|
-
name: string;
|
|
610
|
-
tel: string;
|
|
611
|
-
age: number;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
const getUser = userApi.get<User>();
|
|
615
|
-
const { send } = getUser;
|
|
616
|
-
|
|
617
|
-
const res = await send("1");
|
|
618
|
-
|
|
619
|
-
// 默认情况,以data为key存储数据
|
|
620
|
-
// res.data => CustomResponse & { data : User}
|
|
621
|
-
```
|
|
622
|
-
|
|
623
|
-
> API 被调用的返回格式
|
|
174
|
+
## 文档
|
|
624
175
|
|
|
625
|
-
|
|
626
|
-
const getUser = userApi.get<User>();
|
|
627
|
-
const { send } = getUser;
|
|
628
|
-
const res = await send("1");
|
|
176
|
+
完整文档:<https://snail-js.github.io/api>
|
|
629
177
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
// res => AxiosResponse<Blob>
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
> `data: T`,后端响应数据;默认为`ResponseData<T = any>`类型;可由用户自定义修改
|
|
639
|
-
|
|
640
|
-
> `error: null | Error` ; 请求过程中的错误包含在此,可先判断 error 是否为 null 再进行数据处理
|
|
641
|
-
|
|
642
|
-
> `hitCache?: boolean`; 标识请求是否击中缓存;若从缓存获得数据,则不会发送请求。
|
|
643
|
-
|
|
644
|
-
4. 若后端返回数据不是以 data 为 key 包含数据
|
|
645
|
-
|
|
646
|
-
```typescript
|
|
647
|
-
@Server({
|
|
648
|
-
baseURL: "/api",
|
|
649
|
-
timeout: 5000,
|
|
650
|
-
})
|
|
651
|
-
class BackEnd extends Snail<CustomResponse, "records"> {}
|
|
652
|
-
|
|
653
|
-
const res = await userApi.get<User>();
|
|
654
|
-
// 自定义数据key
|
|
655
|
-
// res.data => CustomResponse & { records : User}
|
|
656
|
-
```
|
|
178
|
+
- [快速开始](https://snail-js.github.io/api/guide/getting-started)
|
|
179
|
+
- [装饰器参考](https://snail-js.github.io/api/guide/decorators)
|
|
180
|
+
- [插件生命周期](https://snail-js.github.io/api/guide/plugin-lifecycle)([English](https://snail-js.github.io/api/guide/plugin-lifecycle_EN))
|
|
181
|
+
- [编写插件](https://snail-js.github.io/api/guide/plugin-authoring)
|
|
182
|
+
- [从 0.1.x 迁移](https://snail-js.github.io/api/guide/migration)
|
|
657
183
|
|
|
658
|
-
|
|
184
|
+
## 设计说明
|
|
659
185
|
|
|
660
|
-
|
|
661
|
-
- 若后端返回的 content-type 是 json 类型,send 方法返回的将是`AxiosResponse.data`
|
|
186
|
+
核心只负责三件事,其余全部是插件:
|
|
662
187
|
|
|
663
|
-
|
|
188
|
+
1. 装饰器写入的元数据;
|
|
189
|
+
2. 请求管线;
|
|
190
|
+
3. 插件生命周期(Koa 风格中间件 + 双向洋葱模型)。
|
|
664
191
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
</a>
|
|
669
|
-
</p>
|
|
670
|
-
<p>
|
|
671
|
-
<a href="https://github.com/limingchang/snail">
|
|
672
|
-
<img src="https://img.shields.io/badge/snail-js?style=flat&label=github&labelColor=F56C6C&link=https%3A%2F%2Fgihub.com%2Flimingchang%2Fsnail"></img>
|
|
673
|
-
</a>
|
|
674
|
-
</p>
|
|
192
|
+
内置插件使用的公开 API 与第三方插件完全相同 —— 不存在内部特权通道。如果你在编写插件,
|
|
193
|
+
请阅读[插件生命周期](https://snail-js.github.io/api/guide/plugin-lifecycle)(英文原文见
|
|
194
|
+
[Plugin lifecycle](https://snail-js.github.io/api/guide/plugin-lifecycle_EN))。
|
|
675
195
|
|
|
676
|
-
|
|
196
|
+
## License
|
|
677
197
|
|
|
678
|
-
|
|
198
|
+
[MIT](./LICENSE)
|