@snail-js/api 0.1.28 → 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 -4871
- package/dist/snail-api.umd.cjs +0 -4875
- 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
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SnailHttpStreamConnection, SnailHttpStreamOptions } from "../typings/stream.js";
|
|
2
|
+
import type { SnailLogger } from "./logger.js";
|
|
3
|
+
/** Everything the HTTP streaming transport needs. */
|
|
4
|
+
export interface HttpStreamInit {
|
|
5
|
+
/** Fully qualified url. */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Options from `@HttpStream(path, options)` with its request method. */
|
|
8
|
+
options: SnailHttpStreamOptions & {
|
|
9
|
+
method?: string;
|
|
10
|
+
};
|
|
11
|
+
/** Request payload. */
|
|
12
|
+
body: unknown;
|
|
13
|
+
/** Name used in log lines. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Extra headers (server-level, auth, …). */
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
/** Logger. */
|
|
18
|
+
logger: SnailLogger;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Streaming HTTP response.
|
|
22
|
+
*
|
|
23
|
+
* Uses `fetch` so the response body arrives as a `ReadableStream`, which works
|
|
24
|
+
* in browsers, Node 18+ and workers alike. The connection object is itself
|
|
25
|
+
* async-iterable, so callers write `for await (const chunk of stream)`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createHttpStream(init: HttpStreamInit): SnailHttpStreamConnection;
|
|
28
|
+
//# sourceMappingURL=http-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-stream.d.ts","sourceRoot":"","sources":["../../src/core/http-stream.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,OAAO,EAAE,sBAAsB,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,uBAAuB;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc;IACd,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,yBAAyB,CAwJhF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SnailLogLevel } from "../typings/server.js";
|
|
2
|
+
/**
|
|
3
|
+
* Level-gated logger.
|
|
4
|
+
*
|
|
5
|
+
* The pre-rewrite code called bare `console.log` from the middle of the request
|
|
6
|
+
* pipeline, which made a request library noisy by default and impossible to
|
|
7
|
+
* silence. Every diagnostic now goes through a logger whose level comes from
|
|
8
|
+
* `@Server({ logLevel })`, and the default level is `"silent"`.
|
|
9
|
+
*/
|
|
10
|
+
export interface SnailLogger {
|
|
11
|
+
/** Active level. */
|
|
12
|
+
readonly level: SnailLogLevel;
|
|
13
|
+
/** `true` when a message at `level` would be printed. */
|
|
14
|
+
enabled(level: Exclude<SnailLogLevel, "silent">): boolean;
|
|
15
|
+
error(message: string, ...rest: unknown[]): void;
|
|
16
|
+
warn(message: string, ...rest: unknown[]): void;
|
|
17
|
+
info(message: string, ...rest: unknown[]): void;
|
|
18
|
+
debug(message: string, ...rest: unknown[]): void;
|
|
19
|
+
}
|
|
20
|
+
/** Create a logger honouring `@Server({ logLevel })`. */
|
|
21
|
+
export declare function createLogger(level?: SnailLogLevel): SnailLogger;
|
|
22
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,oBAAoB;IACpB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,yDAAyD;IACzD,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC;IAC1D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,GAAE,aAAwB,GAAG,WAAW,CAqBzE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A dependency-free replacement for `reflect-metadata`.
|
|
3
|
+
*
|
|
4
|
+
* ## Why not `reflect-metadata`?
|
|
5
|
+
*
|
|
6
|
+
* TypeScript 7 dropped the ability to emit `design:*` metadata: enabling
|
|
7
|
+
* `emitDecoratorMetadata` is accepted but silently emits nothing (verified
|
|
8
|
+
* against `tsc` 7.0.2 — the `__metadata` helper is emitted, the calls are not).
|
|
9
|
+
* That removes the only capability `reflect-metadata` ever provided to this
|
|
10
|
+
* library: we have never needed inferred constructor parameter types, only the
|
|
11
|
+
* metadata our *own* decorators write.
|
|
12
|
+
*
|
|
13
|
+
* Dropping it buys three things:
|
|
14
|
+
* 1. no runtime polyfill to install or import at the app entry point;
|
|
15
|
+
* 2. one fewer entry in `dependencies` — axios stays the only one;
|
|
16
|
+
* 3. deterministic behaviour on every runtime (browser, Node, worker, edge)
|
|
17
|
+
* because the polyfill's `Reflect.defineMetadata` is not involved at all.
|
|
18
|
+
*
|
|
19
|
+
* Legacy decorators (`experimentalDecorators: true`) and parameter decorators
|
|
20
|
+
* remain fully supported by TypeScript 7.
|
|
21
|
+
*
|
|
22
|
+
* ## Storage model
|
|
23
|
+
*
|
|
24
|
+
* ```text
|
|
25
|
+
* WeakMap<owner, Map<slot, Map<key, value>>>
|
|
26
|
+
* │ └── the decorator's symbol key
|
|
27
|
+
* └── CLASS_SLOT for class metadata, else the method name
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* `owner` is always a *class* (constructor function). A decorator applied to a
|
|
31
|
+
* method or parameter receives the prototype, so {@link resolveOwner} maps it
|
|
32
|
+
* back to the class.
|
|
33
|
+
*
|
|
34
|
+
* ## Decorator application order (important)
|
|
35
|
+
*
|
|
36
|
+
* For `@Api("/u") class U { @Get() list(@Query("a") a: string) {} }` the
|
|
37
|
+
* runtime order is:
|
|
38
|
+
*
|
|
39
|
+
* ```text
|
|
40
|
+
* 1. parameter decorators (reverse index order)
|
|
41
|
+
* 2. method decorators
|
|
42
|
+
* 3. class decorators
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* Every writer below therefore *merges*; none of them may clobber an existing
|
|
46
|
+
* value. Array-shaped metadata is appended, never replaced.
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* Normalise whatever a decorator receives into the class that owns the metadata.
|
|
50
|
+
*
|
|
51
|
+
* - class decorator → the constructor itself
|
|
52
|
+
* - method / parameter decorator → `prototype.constructor`
|
|
53
|
+
* - a bare prototype passed by hand → `prototype.constructor`
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveOwner(target: unknown): object;
|
|
56
|
+
/**
|
|
57
|
+
* Write metadata, replacing any value previously written for the same
|
|
58
|
+
* (owner, slot, key) triple.
|
|
59
|
+
*/
|
|
60
|
+
export declare function defineMetadata(key: symbol, value: unknown, target: unknown, propertyKey?: PropertyKey): void;
|
|
61
|
+
/** Read metadata from exactly this owner, ignoring the prototype chain. */
|
|
62
|
+
export declare function getOwnMetadata<T = unknown>(key: symbol, target: unknown, propertyKey?: PropertyKey): T | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Read metadata, walking the class prototype chain so a base api class or a base
|
|
65
|
+
* server class can supply defaults to its subclasses.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getMetadata<T = unknown>(key: symbol, target: unknown, propertyKey?: PropertyKey): T | undefined;
|
|
68
|
+
/** `true` when {@link getMetadata} would find something. */
|
|
69
|
+
export declare function hasMetadata(key: symbol, target: unknown, propertyKey?: PropertyKey): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Append to array-shaped metadata, always creating a fresh array.
|
|
72
|
+
*
|
|
73
|
+
* Copy-on-write matters: several decorators legitimately contribute to one key
|
|
74
|
+
* (four `@Query()` parameters, a class-level `@Header()` plus a method-level
|
|
75
|
+
* one) and the array must never be shared with a base class.
|
|
76
|
+
*/
|
|
77
|
+
export declare function appendMetadata<T>(key: symbol, value: T, target: unknown, propertyKey?: PropertyKey): void;
|
|
78
|
+
/** Merge a record into record-shaped metadata (class-level `@Header` and friends). */
|
|
79
|
+
export declare function mergeMetadata<T extends object>(key: symbol, value: T, target: unknown, propertyKey?: PropertyKey): void;
|
|
80
|
+
/** Delete metadata from exactly this owner. Returns whether anything was removed. */
|
|
81
|
+
export declare function deleteMetadata(key: symbol, target: unknown, propertyKey?: PropertyKey): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Collect every method name that carries metadata for `key`, walking the class
|
|
84
|
+
* prototype chain from base to derived so subclasses may override.
|
|
85
|
+
*/
|
|
86
|
+
export declare function collectMethodKeys(key: symbol, target: unknown): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Test-only escape hatch: swap the registry for a fresh `WeakMap`. Existing
|
|
89
|
+
* owners become unreachable and are garbage collected.
|
|
90
|
+
*/
|
|
91
|
+
export declare function clearMetadataRegistry(): void;
|
|
92
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/core/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AASH;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CASpD;AAwBD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,WAAW,GACxB,IAAI,CAEN;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,CAAC,GAAG,OAAO,EACxC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,WAAW,GACxB,CAAC,GAAG,SAAS,CAEf;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,EACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,WAAW,GACxB,CAAC,GAAG,SAAS,CAUf;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAET;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,WAAW,GACxB,IAAI,CAGN;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC5C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,WAAW,GACxB,IAAI,CAGN;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAET;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAsBxE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata keys used by every `@snail-js/api` decorator.
|
|
3
|
+
*
|
|
4
|
+
* `Symbol.for` is used instead of plain `Symbol()` on purpose: a monorepo can
|
|
5
|
+
* easily end up with two copies of this package (one hoisted for the app, one
|
|
6
|
+
* nested under a dependency). Global symbol registration keeps both copies
|
|
7
|
+
* reading and writing the *same* metadata slots.
|
|
8
|
+
*/
|
|
9
|
+
/** `@Server(...)` options, stored on the server class. */
|
|
10
|
+
export declare const SNAIL_SERVER_OPTIONS: unique symbol;
|
|
11
|
+
/** `@Api(...)` options, stored on the api class. */
|
|
12
|
+
export declare const SNAIL_API_OPTIONS: unique symbol;
|
|
13
|
+
/** `@Get(...)` / `@Post(...)` / … options, stored per method. */
|
|
14
|
+
export declare const SNAIL_REQUEST_METHOD: unique symbol;
|
|
15
|
+
/** `@Params()` / `@Query()` / `@Data()` parameter descriptors, stored per method. */
|
|
16
|
+
export declare const SNAIL_PARAMS: unique symbol;
|
|
17
|
+
/** `@Header(...)` records, stored on the api class and per method. */
|
|
18
|
+
export declare const SNAIL_HEADERS: unique symbol;
|
|
19
|
+
/** `@UploadProgress(...)` callback, stored per method. */
|
|
20
|
+
export declare const SNAIL_UPLOAD_PROGRESS: unique symbol;
|
|
21
|
+
/** `@DownloadProgress(...)` callback, stored per method. */
|
|
22
|
+
export declare const SNAIL_DOWNLOAD_PROGRESS: unique symbol;
|
|
23
|
+
/** `@Sse(...)` options, stored on the stream class. */
|
|
24
|
+
export declare const SNAIL_SSE_OPTIONS: unique symbol;
|
|
25
|
+
/** `@SseEvent(...)` / `@OnSseOpen()` / `@OnSseError()` handlers, stored on the stream class. */
|
|
26
|
+
export declare const SNAIL_SSE_HANDLERS: unique symbol;
|
|
27
|
+
/** `@WebSocket(...)` options, stored on the stream class. */
|
|
28
|
+
export declare const SNAIL_WS_OPTIONS: unique symbol;
|
|
29
|
+
/** `@OnWsOpen()` / `@OnWsMessage()` / … handlers, stored on the stream class. */
|
|
30
|
+
export declare const SNAIL_WS_HANDLERS: unique symbol;
|
|
31
|
+
/** `@HttpStream(...)` options, stored per method. */
|
|
32
|
+
export declare const SNAIL_HTTP_STREAM: unique symbol;
|
|
33
|
+
/**
|
|
34
|
+
* Prefix reserved for third-party decorators built with
|
|
35
|
+
* {@link createParamDecorator} and friends.
|
|
36
|
+
*
|
|
37
|
+
* Plugin authors should namespace their key, e.g.
|
|
38
|
+
* `Symbol.for("@acme/snail-plugin:tenant")`, so two plugins can never collide.
|
|
39
|
+
*/
|
|
40
|
+
export declare const SNAIL_CUSTOM_KEY_PREFIX = "@snail-js/api:custom:";
|
|
41
|
+
//# sourceMappingURL=metadata.keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.keys.d.ts","sourceRoot":"","sources":["../../src/core/metadata.keys.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,eAA6C,CAAC;AAE/E,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,eAA0C,CAAC;AAEzE,iEAAiE;AACjE,eAAO,MAAM,oBAAoB,eAA6C,CAAC;AAE/E,qFAAqF;AACrF,eAAO,MAAM,YAAY,eAAqC,CAAC;AAE/D,sEAAsE;AACtE,eAAO,MAAM,aAAa,eAAsC,CAAC;AAEjE,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,eAA8C,CAAC;AAEjF,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,eAAgD,CAAC;AAErF,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,eAA0C,CAAC;AAEzE,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,eAA2C,CAAC;AAE3E,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,eAAyC,CAAC;AAEvE,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,eAA0C,CAAC;AAEzE,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,eAA0C,CAAC;AAEzE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { AxiosHeaders } from "axios";
|
|
2
|
+
import type { AxiosInstance, InternalAxiosRequestConfig } from "axios";
|
|
3
|
+
import type { SnailApiOptions, SnailMethodOptions, SnailMethodType } from "../typings/api.js";
|
|
4
|
+
import type { SnailParamDescriptor } from "../typings/args.js";
|
|
5
|
+
import type { SnailMeta } from "../typings/meta.js";
|
|
6
|
+
import type { SnailResult } from "../typings/response.js";
|
|
7
|
+
import type { ResolvedServerOptions } from "../typings/server.js";
|
|
8
|
+
import { SnailContext } from "./context.js";
|
|
9
|
+
import type { SnailLogger } from "./logger.js";
|
|
10
|
+
import type { PluginManager } from "./plugin-manager.js";
|
|
11
|
+
import type { SnailServer } from "./server.js";
|
|
12
|
+
/** Payload of the `codeError` event. */
|
|
13
|
+
export interface SnailCodeErrorEvent {
|
|
14
|
+
/** Business status code the backend returned. */
|
|
15
|
+
code: number | string | undefined;
|
|
16
|
+
/** Full parsed envelope. */
|
|
17
|
+
payload: unknown;
|
|
18
|
+
/** The `SnailResponseError` that will be thrown. */
|
|
19
|
+
error: unknown;
|
|
20
|
+
}
|
|
21
|
+
/** Events emitted by a {@link SnailMethod}. */
|
|
22
|
+
export interface SnailMethodEventMap<S, T, D extends string, C extends string, M extends string> {
|
|
23
|
+
success: SnailResult<S, T, D, C, M>;
|
|
24
|
+
error: unknown;
|
|
25
|
+
codeError: SnailCodeErrorEvent;
|
|
26
|
+
finish: undefined;
|
|
27
|
+
cache: undefined;
|
|
28
|
+
}
|
|
29
|
+
/** Everything `SnailMethod` needs, assembled by the proxy in `SnailServer`. */
|
|
30
|
+
export interface SnailMethodInit {
|
|
31
|
+
server: SnailServer<any, any, any, any>;
|
|
32
|
+
pluginManager: PluginManager;
|
|
33
|
+
axios: AxiosInstance;
|
|
34
|
+
apiClass: new () => unknown;
|
|
35
|
+
api: unknown;
|
|
36
|
+
apiName: string;
|
|
37
|
+
apiOptions: Required<SnailApiOptions>;
|
|
38
|
+
serverOptions: ResolvedServerOptions;
|
|
39
|
+
methodName: string;
|
|
40
|
+
methodType: SnailMethodType;
|
|
41
|
+
route: string;
|
|
42
|
+
methodOptions: SnailMethodOptions & {
|
|
43
|
+
url: string;
|
|
44
|
+
};
|
|
45
|
+
descriptors: readonly SnailParamDescriptor[];
|
|
46
|
+
headers: AxiosHeaders;
|
|
47
|
+
logger: SnailLogger;
|
|
48
|
+
/**
|
|
49
|
+
* Builds a fresh axios config for this method.
|
|
50
|
+
*
|
|
51
|
+
* A factory rather than a value: every `send()` must start from a clean config
|
|
52
|
+
* so mutations a plugin made during the previous send do not leak forward.
|
|
53
|
+
*/
|
|
54
|
+
requestConfig: () => InternalAxiosRequestConfig;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* One pending request.
|
|
58
|
+
*
|
|
59
|
+
* Created by calling a proxied api method — `userApi.getUser("1")` — and sent by
|
|
60
|
+
* calling {@link SnailMethod.send}. Nothing hits the network until `send()`.
|
|
61
|
+
*
|
|
62
|
+
* ## Why the context is built once and reset
|
|
63
|
+
*
|
|
64
|
+
* Framework adapters create the caller's reactive handles in their `initMeta`
|
|
65
|
+
* hook. Those handles must survive every re-send, so the context is constructed
|
|
66
|
+
* once and {@link SnailContext.reset} clears only the per-request fields. Calling
|
|
67
|
+
* `userApi.getUser()` twice would produce two independent sets of refs, which is
|
|
68
|
+
* exactly the bug the old `request()`-returns-fresh-state design had.
|
|
69
|
+
*/
|
|
70
|
+
export declare class SnailMethod<S = unknown, T = unknown, D extends string = "data", C extends string = "code", M extends string = "message"> {
|
|
71
|
+
/** `server.api.method`. */
|
|
72
|
+
readonly name: string;
|
|
73
|
+
/** Decorated method name. */
|
|
74
|
+
readonly methodName: string;
|
|
75
|
+
/** Request verb. */
|
|
76
|
+
readonly methodType: SnailMethodType;
|
|
77
|
+
/** Url template before `:placeholder` substitution. */
|
|
78
|
+
readonly route: string;
|
|
79
|
+
/** Arguments this instance was created with. `send(...args)` may override them. */
|
|
80
|
+
readonly args: readonly unknown[];
|
|
81
|
+
/**
|
|
82
|
+
* Caller-visible reactive values created by framework adapters.
|
|
83
|
+
*
|
|
84
|
+
* A live view of `context.meta`, so the handles an adapter created in
|
|
85
|
+
* `initMeta` stay stable across every re-send. Empty when no adapter plugin is
|
|
86
|
+
* installed.
|
|
87
|
+
*
|
|
88
|
+
* `loading` and `error` are typed by the {@link SnailMeta} interface; the
|
|
89
|
+
* envelope handles are named after the server's configured keys, so augment
|
|
90
|
+
* `SnailMeta` to type them.
|
|
91
|
+
*/
|
|
92
|
+
get meta(): SnailMeta & Record<string, unknown>;
|
|
93
|
+
/** The live request context. */
|
|
94
|
+
readonly context: SnailContext;
|
|
95
|
+
private readonly init;
|
|
96
|
+
private readonly emitter;
|
|
97
|
+
private controller;
|
|
98
|
+
private inFlight;
|
|
99
|
+
constructor(init: SnailMethodInit, args?: readonly unknown[]);
|
|
100
|
+
/** `true` while a request is in flight. */
|
|
101
|
+
get pending(): boolean;
|
|
102
|
+
/** Result of the most recent successful request. */
|
|
103
|
+
get result(): SnailResult<S, T, D, C, M> | undefined;
|
|
104
|
+
/** Error from the most recent failed request. */
|
|
105
|
+
get error(): unknown;
|
|
106
|
+
/** The final axios config of the most recent request. */
|
|
107
|
+
get request(): InternalAxiosRequestConfig;
|
|
108
|
+
/**
|
|
109
|
+
* Send the request.
|
|
110
|
+
*
|
|
111
|
+
* Any arguments given here replace the ones captured when the method was
|
|
112
|
+
* proxied, which is what lets a strategy own one instance and vary the
|
|
113
|
+
* arguments per call.
|
|
114
|
+
*
|
|
115
|
+
* ## One request in flight at a time
|
|
116
|
+
*
|
|
117
|
+
* A `SnailMethod` owns exactly one context, and that context is what holds the
|
|
118
|
+
* caller's reactive handles. Two overlapping `send()` calls would therefore
|
|
119
|
+
* race over the same `ctx.response`, and the slower response could land in the
|
|
120
|
+
* state the faster one already reported.
|
|
121
|
+
*
|
|
122
|
+
* Starting a second send therefore **aborts the first**, so the previous call
|
|
123
|
+
* rejects with a `SnailCancelledError` and "latest wins" holds. Callers that
|
|
124
|
+
* genuinely want two parallel requests should create two instances —
|
|
125
|
+
* `userApi.getUser("1")` and `userApi.getUser("2")` — which is also what makes
|
|
126
|
+
* the argument types line up.
|
|
127
|
+
*/
|
|
128
|
+
send(...args: unknown[]): Promise<SnailResult<S, T, D, C, M>>;
|
|
129
|
+
/**
|
|
130
|
+
* Cancel the in-flight request.
|
|
131
|
+
*
|
|
132
|
+
* `send()` rejects with a {@link SnailCancelledError}, which strategies treat
|
|
133
|
+
* as expected control flow rather than a failure.
|
|
134
|
+
*/
|
|
135
|
+
abort(reason?: unknown): void;
|
|
136
|
+
/** Subscribe to a successful request. Returns an unsubscribe function. */
|
|
137
|
+
onSuccess(listener: (result: SnailResult<S, T, D, C, M>) => void): () => void;
|
|
138
|
+
/** Subscribe to a failed request. */
|
|
139
|
+
onError(listener: (error: unknown) => void): () => void;
|
|
140
|
+
/**
|
|
141
|
+
* Subscribe to a rejected business code.
|
|
142
|
+
*
|
|
143
|
+
* Observation only: the request still rejects with a `SnailResponseError`, so
|
|
144
|
+
* this is the right place to raise a toast, not to recover.
|
|
145
|
+
*/
|
|
146
|
+
onCodeError(listener: (event: SnailCodeErrorEvent) => void): () => void;
|
|
147
|
+
/** Subscribe to settlement, successful or not. */
|
|
148
|
+
onFinish(listener: () => void): () => void;
|
|
149
|
+
/** Subscribe to a response served from a cache. */
|
|
150
|
+
onHitCache(listener: () => void): () => void;
|
|
151
|
+
/** Reset the context for a fresh send, superseding any request already in flight. */
|
|
152
|
+
private begin;
|
|
153
|
+
/**
|
|
154
|
+
* The transport step.
|
|
155
|
+
*
|
|
156
|
+
* Runs only when every `beforeRequest` hook called `next()`, i.e. only when the
|
|
157
|
+
* response has to come from the network. The `afterResponse` chain is *not* here
|
|
158
|
+
* — see {@link SnailMethod.send} for why it has to run on a cache hit too.
|
|
159
|
+
*/
|
|
160
|
+
private dispatch;
|
|
161
|
+
/** Validate the envelope and assemble the caller-facing result. */
|
|
162
|
+
private finalize;
|
|
163
|
+
/** Report a failure through the plugin hooks and the events, then rethrow it. */
|
|
164
|
+
private fail;
|
|
165
|
+
/**
|
|
166
|
+
* Turn axios' error vocabulary into ours.
|
|
167
|
+
*
|
|
168
|
+
* The rule is: **if the server answered, hand back axios' error unchanged** —
|
|
169
|
+
* it carries `response.status` and `response.data`, which applications and the
|
|
170
|
+
* auth strategies both branch on. Only when no response exists at all (DNS
|
|
171
|
+
* failure, offline, CORS rejection) is there nothing useful to preserve, so
|
|
172
|
+
* that case becomes a typed {@link SnailHttpError} with the axios error as its
|
|
173
|
+
* `cause`.
|
|
174
|
+
*/
|
|
175
|
+
private normalizeTransportError;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=method.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method.d.ts","sourceRoot":"","sources":["../../src/core/method.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { SnailPluginObject } from "../typings/plugin.js";
|
|
2
|
+
import type { ResolvedServerOptions } from "../typings/server.js";
|
|
3
|
+
import { type BoundHook } from "./plugin.js";
|
|
4
|
+
/** A plugin registered on one server. */
|
|
5
|
+
export interface RegisteredPlugin {
|
|
6
|
+
/** Plugin name. */
|
|
7
|
+
readonly name: string;
|
|
8
|
+
/** Chain ordering weight; higher runs first in the forward phase. */
|
|
9
|
+
readonly priority: number;
|
|
10
|
+
/** Registration sequence, used as a stable tie-breaker. */
|
|
11
|
+
readonly index: number;
|
|
12
|
+
/** The plugin object itself. */
|
|
13
|
+
readonly instance: SnailPluginObject<any>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Per-server plugin registry.
|
|
17
|
+
*
|
|
18
|
+
* ## Why this is not a singleton
|
|
19
|
+
*
|
|
20
|
+
* The pre-rewrite implementation kept one global manager plus a mutable
|
|
21
|
+
* `_server` pointer that every caller had to set with `switchServer()` before
|
|
22
|
+
* `getHooks()`. Any two servers in flight — or simply two interleaved `await`s —
|
|
23
|
+
* silently read the *wrong* server's plugins. Each `SnailServer` now owns its
|
|
24
|
+
* own manager and passes its name in the constructor, so that class of bug is
|
|
25
|
+
* unrepresentable.
|
|
26
|
+
*
|
|
27
|
+
* ## Ordering
|
|
28
|
+
*
|
|
29
|
+
* Plugins sort by `priority` descending, ties broken by registration order.
|
|
30
|
+
*
|
|
31
|
+
* - **Forward hooks** run highest-priority first, so an interceptor (`100`)
|
|
32
|
+
* installs before the cache (`-100`).
|
|
33
|
+
* - **Unwind hooks** run in the opposite direction, closing the onion: the
|
|
34
|
+
* plugin closest to the network reacts to the response first.
|
|
35
|
+
*
|
|
36
|
+
* ## Sync registration, async install
|
|
37
|
+
*
|
|
38
|
+
* `register()` is synchronous and returns immediately, so `Service.use(A).use(B)`
|
|
39
|
+
* chains naturally while a `dependsOn` mistake still throws on the spot. The
|
|
40
|
+
* `install` hooks themselves may be async; {@link PluginManager.ready} is awaited
|
|
41
|
+
* once per request, before any plugin hook runs.
|
|
42
|
+
*/
|
|
43
|
+
export declare class PluginManager {
|
|
44
|
+
private readonly serverName;
|
|
45
|
+
private readonly serverOptions;
|
|
46
|
+
private readonly registry;
|
|
47
|
+
private readonly order;
|
|
48
|
+
private readonly installTasks;
|
|
49
|
+
private sequence;
|
|
50
|
+
constructor(serverName: string, serverOptions: ResolvedServerOptions);
|
|
51
|
+
/** Number of registered plugins. */
|
|
52
|
+
get size(): number;
|
|
53
|
+
/** Resolves once every `install` hook has settled. */
|
|
54
|
+
get ready(): Promise<void>;
|
|
55
|
+
/** `true` when a plugin with this name is registered. */
|
|
56
|
+
has(name: string): boolean;
|
|
57
|
+
/** Read one registered plugin. */
|
|
58
|
+
get(name: string): RegisteredPlugin | undefined;
|
|
59
|
+
/** Registered plugin names in chain order (forward phase). */
|
|
60
|
+
names(): string[];
|
|
61
|
+
/** All registered plugins in chain order (forward phase). */
|
|
62
|
+
list(): RegisteredPlugin[];
|
|
63
|
+
/**
|
|
64
|
+
* Validate and register a plugin. Synchronous by design.
|
|
65
|
+
*
|
|
66
|
+
* Throws {@link SnailPluginError} for a nameless plugin, a duplicate name or
|
|
67
|
+
* an unsatisfied `dependsOn` — all before anything is mutated.
|
|
68
|
+
*/
|
|
69
|
+
register(plugin: SnailPluginObject<any>): void;
|
|
70
|
+
/** Unregister a plugin, running its `uninstall` hook first. */
|
|
71
|
+
remove(name: string): Promise<void>;
|
|
72
|
+
/** Remove every plugin, unwinding in reverse registration order. */
|
|
73
|
+
clear(): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Sorted plugin list.
|
|
76
|
+
*
|
|
77
|
+
* `"forward"` → priority descending (highest first).
|
|
78
|
+
* `"unwind"` → priority ascending (highest last).
|
|
79
|
+
*/
|
|
80
|
+
sorted(direction: "forward" | "unwind"): RegisteredPlugin[];
|
|
81
|
+
/** Hooks of one name, in the direction that hook traverses. */
|
|
82
|
+
hooks(hookName: string): BoundHook[];
|
|
83
|
+
/** `true` when at least one plugin implements `hookName`. */
|
|
84
|
+
hasHook(hookName: string): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Run a chain hook over every plugin, then `downstream`.
|
|
87
|
+
*
|
|
88
|
+
* A plugin that never calls `next()` stops the chain: `downstream` (for
|
|
89
|
+
* `beforeRequest`, the HTTP request itself) never runs. That is the mechanism
|
|
90
|
+
* behind a cache hit.
|
|
91
|
+
*/
|
|
92
|
+
runChain(hookName: string, ctx: unknown, downstream?: () => Promise<void> | void): Promise<void>;
|
|
93
|
+
/** Run a non-chain hook over every plugin, sequentially and awaited. */
|
|
94
|
+
runEffects(hookName: string, ...args: unknown[]): Promise<void>;
|
|
95
|
+
/** Run a non-chain hook synchronously — for constructor-time hooks. */
|
|
96
|
+
runEffectsSync(hookName: string, ...args: unknown[]): void;
|
|
97
|
+
/**
|
|
98
|
+
* Fold a value through every plugin's hook.
|
|
99
|
+
*
|
|
100
|
+
* Used by `requestInterceptor` / `responseInterceptor`, where each plugin may
|
|
101
|
+
* return a replacement for the value it received. Returning `undefined` keeps
|
|
102
|
+
* the previous value.
|
|
103
|
+
*/
|
|
104
|
+
reduce<T>(hookName: string, initial: T, ...args: unknown[]): T;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=plugin-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/core/plugin-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA6B,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAqBxD,yCAAyC;AACzC,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,aAAa;IAOtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAPhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAChE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA4B;IACzD,OAAO,CAAC,QAAQ,CAAK;IAErB,YACmB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,qBAAqB,EACnD;IAEJ,oCAAoC;IACpC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,sDAAsD;IACtD,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;IAED,yDAAyD;IACzD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzB;IAED,kCAAkC;IAClC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE9C;IAED,8DAA8D;IAC9D,KAAK,IAAI,MAAM,EAAE,CAEhB;IAED,6DAA6D;IAC7D,IAAI,IAAI,gBAAgB,EAAE,CAEzB;IAED;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAAG,IAAI,CAuE7C;IAED,+DAA+D;IACzD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBxC;IAED,oEAAoE;IAC9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAI3B;IAED;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,GAAG,gBAAgB,EAAE,CAU1D;IAED,+DAA+D;IAC/D,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CAgBnC;IAED,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQjC;IAED;;;;;;OAMG;IACG,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,OAAO,EACZ,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC,CAOf;IAED,wEAAwE;IAClE,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE;IAED,uEAAuE;IACvE,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAIzD;IAED;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAO7D;CACF"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { SnailMessages } from "../locale/types.js";
|
|
2
|
+
import type { SnailParamResolver } from "../typings/args.js";
|
|
3
|
+
import type { SnailPlugin, SnailPluginObject } from "../typings/plugin.js";
|
|
4
|
+
import type { ResolvedServerOptions } from "../typings/server.js";
|
|
5
|
+
/**
|
|
6
|
+
* Plugin machinery.
|
|
7
|
+
*
|
|
8
|
+
* ## Everything is a plugin
|
|
9
|
+
*
|
|
10
|
+
* The core ships *no* optional behaviour: caching, versioning, interceptors,
|
|
11
|
+
* validation, transformation and framework adapters are all plugins. Core owns
|
|
12
|
+
* exactly three things — the metadata written by decorators, the request
|
|
13
|
+
* pipeline, and this plugin lifecycle.
|
|
14
|
+
*
|
|
15
|
+
* ## Two kinds of hook
|
|
16
|
+
*
|
|
17
|
+
* - **Chain hooks** (`beforeRequest`, `afterResponse`) are Koa-style middleware:
|
|
18
|
+
* a hook receives `next`, may `await` it, and may decline to call it to stop
|
|
19
|
+
* the request. This is what makes cross-cutting concerns composable.
|
|
20
|
+
* - **Effect hooks** (`initMeta`, `beforeCreate`, `onError`, `afterRequest`) run
|
|
21
|
+
* sequentially and cannot influence control flow.
|
|
22
|
+
*/
|
|
23
|
+
/** Identity helper that preserves the option type of a plugin factory. */
|
|
24
|
+
export declare function definePlugin<O = unknown>(factory: SnailPlugin<O>): SnailPlugin<O>;
|
|
25
|
+
/** Building blocks handed to a plugin's `setup` function. */
|
|
26
|
+
export interface PluginSetupApi {
|
|
27
|
+
/** Name of the server this plugin was installed on. */
|
|
28
|
+
readonly serverName: string;
|
|
29
|
+
/** Fully resolved server options. */
|
|
30
|
+
readonly serverOptions: ResolvedServerOptions;
|
|
31
|
+
/** Names of the plugins registered before this one. */
|
|
32
|
+
readonly installedPlugins: readonly string[];
|
|
33
|
+
/**
|
|
34
|
+
* Register a custom parameter source usable as `@Source("key")`.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* api.defineParamSource("tenant", ({ ctx, value }) => {
|
|
39
|
+
* ctx.request.headers.set("x-tenant", String(value));
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
defineParamSource(source: string, resolver: SnailParamResolver): void;
|
|
44
|
+
/** Contribute translated messages for this plugin's own error output. */
|
|
45
|
+
addMessages(messages: SnailMessages): void;
|
|
46
|
+
/** Register cleanup to run when the plugin is uninstalled. */
|
|
47
|
+
onDispose(dispose: () => void | Promise<void>): void;
|
|
48
|
+
}
|
|
49
|
+
/** Declarative description accepted by {@link createPlugin}. */
|
|
50
|
+
export interface PluginDefinition<O, Hooks extends object> {
|
|
51
|
+
/** Unique plugin name. */
|
|
52
|
+
readonly name: string;
|
|
53
|
+
/** Execution order inside a chain; higher runs first. Defaults to `0`. */
|
|
54
|
+
readonly priority?: number;
|
|
55
|
+
/** Plugin names that must be registered first. */
|
|
56
|
+
readonly dependsOn?: readonly string[];
|
|
57
|
+
/**
|
|
58
|
+
* Runs once per server, at install time.
|
|
59
|
+
*
|
|
60
|
+
* Use it to register parameter sources, add messages, seed state or capture
|
|
61
|
+
* options in a closure. Return the lifecycle hooks.
|
|
62
|
+
*/
|
|
63
|
+
readonly setup?: (options: O, api: PluginSetupApi) => Hooks | void;
|
|
64
|
+
}
|
|
65
|
+
/** The lifecycle hooks a plugin may return, excluding registration plumbing. */
|
|
66
|
+
export type PluginHooks = Omit<SnailPluginObject, "name" | "priority" | "dependsOn" | "install" | "uninstall">;
|
|
67
|
+
/**
|
|
68
|
+
* Create a third-party plugin.
|
|
69
|
+
*
|
|
70
|
+
* This is the supported entry point for plugin authors. It validates the name,
|
|
71
|
+
* wires `install`/`uninstall`, exposes a scoped {@link PluginSetupApi} and keeps
|
|
72
|
+
* the hook object fully typed.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* interface TraceOptions { header?: string }
|
|
77
|
+
*
|
|
78
|
+
* export const Trace = createPlugin<TraceOptions, { onSend?: (url: string) => void }>({
|
|
79
|
+
* name: "trace",
|
|
80
|
+
* priority: 20,
|
|
81
|
+
* setup(options, api) {
|
|
82
|
+
* const header = options?.header ?? "x-trace-id";
|
|
83
|
+
* api.addMessages({ "trace.missing": "trace header %s is missing" });
|
|
84
|
+
* return {
|
|
85
|
+
* beforeRequest(ctx) {
|
|
86
|
+
* ctx.request.headers.set(header, crypto.randomUUID());
|
|
87
|
+
* }
|
|
88
|
+
* };
|
|
89
|
+
* }
|
|
90
|
+
* });
|
|
91
|
+
*
|
|
92
|
+
* Service.use(Trace({ header: "x-trace-id" }));
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function createPlugin<O = void, Hooks extends object = PluginHooks>(definition: PluginDefinition<O, Hooks>): SnailPlugin<O>;
|
|
96
|
+
/** One hook bound to the plugin that owns it. */
|
|
97
|
+
export interface BoundHook {
|
|
98
|
+
readonly pluginName: string;
|
|
99
|
+
readonly hook: (...args: any[]) => any;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Compose chain hooks into a single Koa-style function.
|
|
103
|
+
*
|
|
104
|
+
* The returned function runs `entries[0]` first (they are pre-sorted by the
|
|
105
|
+
* manager), handing each hook a `next` that advances the chain. When the chain
|
|
106
|
+
* is exhausted, `downstream` runs — that is where the manager splices in the
|
|
107
|
+
* actual HTTP request between `beforeRequest` and `afterResponse`.
|
|
108
|
+
*
|
|
109
|
+
* Calling `next()` twice from one hook throws {@link SnailHookError}; without
|
|
110
|
+
* that guard the second call silently re-runs the rest of the chain.
|
|
111
|
+
*/
|
|
112
|
+
export declare function composeChain(hookName: string, entries: readonly BoundHook[]): (ctx: unknown, downstream?: () => Promise<void> | void) => Promise<void>;
|
|
113
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/core/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAEV,WAAW,EAEX,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAK/D;;;;;;;;;;;;;;;;;GAiBG;AAEH,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAEjF;AAED,6DAA6D;AAC7D,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,qCAAqC;IACrC,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;IAE9C,uDAAuD;IACvD,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAE7C;;;;;;;;;OASG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAEtE,yEAAyE;IACzE,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAE3C,8DAA8D;IAC9D,SAAS,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACtD;AAED,gEAAgE;AAChE,MAAM,WAAW,gBAAgB,CAAC,CAAC,EAAE,KAAK,SAAS,MAAM;IACvD,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,cAAc,KAAK,KAAK,GAAG,IAAI,CAAC;CACpE;AAED,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,CAAC,CAAC;AAE/G;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,SAAS,MAAM,GAAG,WAAW,EACvE,UAAU,EAAE,gBAAgB,CAAC,CAAC,EAAE,KAAK,CAAC,GACrC,WAAW,CAAC,CAAC,CAAC,CA6ChB;AAED,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;CACxC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,SAAS,SAAS,EAAE,GAC5B,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAqC1E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SnailReconnectPolicy } from "../typings/stream.js";
|
|
2
|
+
/** A reconnect policy with every default applied. */
|
|
3
|
+
export type ResolvedReconnectPolicy = Required<SnailReconnectPolicy>;
|
|
4
|
+
/** Defaults used when a transport enables reconnecting without a policy. */
|
|
5
|
+
export declare const DEFAULT_RECONNECT_POLICY: ResolvedReconnectPolicy;
|
|
6
|
+
/**
|
|
7
|
+
* Normalise the `reconnect` option.
|
|
8
|
+
*
|
|
9
|
+
* Returns `undefined` when reconnecting is switched off, so callers can branch on
|
|
10
|
+
* a single falsy check instead of handling `false | undefined | policy`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveReconnectPolicy(policy: false | SnailReconnectPolicy | undefined): ResolvedReconnectPolicy | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Exponential backoff with optional full jitter.
|
|
15
|
+
*
|
|
16
|
+
* `attempt` is 1-based: `attempt: 1` returns the first delay. The result is
|
|
17
|
+
* always capped by `maxDelayMs`, so a long outage cannot push a retry hours out.
|
|
18
|
+
*/
|
|
19
|
+
export declare function backoffDelay(attempt: number, policy: ResolvedReconnectPolicy): number;
|
|
20
|
+
/** `true` when another attempt is allowed. */
|
|
21
|
+
export declare function canRetry(attempt: number, policy: ResolvedReconnectPolicy): boolean;
|
|
22
|
+
//# sourceMappingURL=reconnect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnect.d.ts","sourceRoot":"","sources":["../../src/core/reconnect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,qDAAqD;AACrD,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAErE,4EAA4E;AAC5E,eAAO,MAAM,wBAAwB,EAAE,uBAMtC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,KAAK,GAAG,oBAAoB,GAAG,SAAS,GAC/C,uBAAuB,GAAG,SAAS,CAIrC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,uBAAuB,GAC9B,MAAM,CAOR;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAElF"}
|