@nifrajs/core 3.5.0 → 4.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/README.md +26 -0
- package/dist/assurance.d.ts +7 -0
- package/dist/assurance.d.ts.map +1 -1
- package/dist/assurance.js +39 -3
- package/dist/assurance.js.map +1 -1
- package/dist/capabilities.d.ts +20 -2
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +47 -15
- package/dist/capabilities.js.map +1 -1
- package/dist/diff.d.ts +2 -1
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +26 -2
- package/dist/diff.js.map +1 -1
- package/dist/durable-adapters.d.ts.map +1 -1
- package/dist/durable-adapters.js +16 -3
- package/dist/durable-adapters.js.map +1 -1
- package/dist/durable-effect.d.ts.map +1 -1
- package/dist/durable-effect.js +6 -3
- package/dist/durable-effect.js.map +1 -1
- package/dist/edge-kit.d.ts +2 -0
- package/dist/edge-kit.d.ts.map +1 -1
- package/dist/edge-kit.js +2 -0
- package/dist/edge-kit.js.map +1 -1
- package/dist/effect-lifecycle.d.ts.map +1 -1
- package/dist/effect-lifecycle.js +2 -1
- package/dist/effect-lifecycle.js.map +1 -1
- package/dist/effect-scope.d.ts.map +1 -1
- package/dist/effect-scope.js +1 -1
- package/dist/effect-scope.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/evidence.d.ts +24 -1
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +168 -13
- package/dist/evidence.js.map +1 -1
- package/dist/idempotency.d.ts +31 -0
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +40 -8
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/code-unit-order.d.ts +7 -0
- package/dist/internal/code-unit-order.d.ts.map +1 -0
- package/dist/internal/code-unit-order.js +9 -0
- package/dist/internal/code-unit-order.js.map +1 -0
- package/dist/internal/durable-saga-protocol.d.ts.map +1 -1
- package/dist/internal/durable-saga-protocol.js +2 -0
- package/dist/internal/durable-saga-protocol.js.map +1 -1
- package/dist/internal/route-catalog.d.ts +6 -6
- package/dist/internal/route-catalog.d.ts.map +1 -1
- package/dist/internal/route-catalog.js +20 -18
- package/dist/internal/route-catalog.js.map +1 -1
- package/dist/internal/route-compiler.d.ts +7 -6
- package/dist/internal/route-compiler.d.ts.map +1 -1
- package/dist/internal/route-compiler.js +36 -4
- package/dist/internal/route-compiler.js.map +1 -1
- package/dist/internal/route-execution.d.ts +7 -3
- package/dist/internal/route-execution.d.ts.map +1 -1
- package/dist/internal/route-execution.js.map +1 -1
- package/dist/internal/route-lanes.d.ts +1 -0
- package/dist/internal/route-lanes.d.ts.map +1 -1
- package/dist/internal/route-lanes.js +34 -29
- package/dist/internal/route-lanes.js.map +1 -1
- package/dist/internal/route-program.d.ts +8 -2
- package/dist/internal/route-program.d.ts.map +1 -1
- package/dist/internal/route-program.js +222 -20
- package/dist/internal/route-program.js.map +1 -1
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +8 -5
- package/dist/ledger.js.map +1 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +41 -37
- package/dist/manifest.js.map +1 -1
- package/dist/mount.d.ts +36 -0
- package/dist/mount.d.ts.map +1 -1
- package/dist/mount.js +32 -0
- package/dist/mount.js.map +1 -1
- package/dist/reflection.d.ts +26 -0
- package/dist/reflection.d.ts.map +1 -1
- package/dist/reflection.js +65 -1
- package/dist/reflection.js.map +1 -1
- package/dist/response-observer.d.ts +1 -1
- package/dist/response-observer.d.ts.map +1 -1
- package/dist/response-observer.js.map +1 -1
- package/dist/router/overlap.d.ts +23 -0
- package/dist/router/overlap.d.ts.map +1 -0
- package/dist/router/overlap.js +224 -0
- package/dist/router/overlap.js.map +1 -0
- package/dist/router/pattern.d.ts +117 -2
- package/dist/router/pattern.d.ts.map +1 -1
- package/dist/router/pattern.js +283 -23
- package/dist/router/pattern.js.map +1 -1
- package/dist/router/router.d.ts +18 -4
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +51 -44
- package/dist/router/router.js.map +1 -1
- package/dist/server/auth.d.ts +53 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +9 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/bare-error-lane.d.ts +12 -7
- package/dist/server/bare-error-lane.d.ts.map +1 -1
- package/dist/server/bare-error-lane.js +13 -11
- package/dist/server/bare-error-lane.js.map +1 -1
- package/dist/server/body-lane.d.ts +20 -2
- package/dist/server/body-lane.d.ts.map +1 -1
- package/dist/server/body-lane.js +26 -7
- package/dist/server/body-lane.js.map +1 -1
- package/dist/server/body-parser.d.ts +68 -0
- package/dist/server/body-parser.d.ts.map +1 -0
- package/dist/server/body-parser.js +172 -0
- package/dist/server/body-parser.js.map +1 -0
- package/dist/server/body.d.ts.map +1 -1
- package/dist/server/body.js +62 -7
- package/dist/server/body.js.map +1 -1
- package/dist/server/client-ip.d.ts +8 -0
- package/dist/server/client-ip.d.ts.map +1 -1
- package/dist/server/client-ip.js +8 -0
- package/dist/server/client-ip.js.map +1 -1
- package/dist/server/context.d.ts +71 -6
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/contract.d.ts +15 -5
- package/dist/server/contract.d.ts.map +1 -1
- package/dist/server/contract.js +25 -4
- package/dist/server/contract.js.map +1 -1
- package/dist/server/core-copies.d.ts +2 -0
- package/dist/server/core-copies.d.ts.map +1 -0
- package/dist/server/core-copies.js +20 -0
- package/dist/server/core-copies.js.map +1 -0
- package/dist/server/edge.d.ts.map +1 -1
- package/dist/server/edge.js +2 -0
- package/dist/server/edge.js.map +1 -1
- package/dist/server/http.d.ts +11 -0
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +36 -0
- package/dist/server/http.js.map +1 -1
- package/dist/server/idempotency-lane.d.ts +6 -0
- package/dist/server/idempotency-lane.d.ts.map +1 -1
- package/dist/server/idempotency-lane.js +130 -73
- package/dist/server/idempotency-lane.js.map +1 -1
- package/dist/server/install.d.ts +4 -0
- package/dist/server/install.d.ts.map +1 -1
- package/dist/server/install.js +4 -0
- package/dist/server/install.js.map +1 -1
- package/dist/server/methods.d.ts +45 -0
- package/dist/server/methods.d.ts.map +1 -0
- package/dist/server/methods.js +37 -0
- package/dist/server/methods.js.map +1 -0
- package/dist/server/multipart.d.ts +63 -0
- package/dist/server/multipart.d.ts.map +1 -0
- package/dist/server/multipart.js +374 -0
- package/dist/server/multipart.js.map +1 -0
- package/dist/server/node-outcome-hook.d.ts +20 -0
- package/dist/server/node-outcome-hook.d.ts.map +1 -1
- package/dist/server/node-outcome-hook.js +15 -6
- package/dist/server/node-outcome-hook.js.map +1 -1
- package/dist/server/not-found-answer.d.ts +40 -0
- package/dist/server/not-found-answer.d.ts.map +1 -0
- package/dist/server/not-found-answer.js +56 -0
- package/dist/server/not-found-answer.js.map +1 -0
- package/dist/server/not-found.d.ts +23 -0
- package/dist/server/not-found.d.ts.map +1 -0
- package/dist/server/not-found.js +81 -0
- package/dist/server/not-found.js.map +1 -0
- package/dist/server/plugin.d.ts +26 -1
- package/dist/server/plugin.d.ts.map +1 -1
- package/dist/server/plugin.js.map +1 -1
- package/dist/server/proto-guard.d.ts +18 -5
- package/dist/server/proto-guard.d.ts.map +1 -1
- package/dist/server/proto-guard.js +114 -9
- package/dist/server/proto-guard.js.map +1 -1
- package/dist/server/query.d.ts +7 -0
- package/dist/server/query.d.ts.map +1 -1
- package/dist/server/query.js +47 -0
- package/dist/server/query.js.map +1 -1
- package/dist/server/registry.d.ts +13 -2
- package/dist/server/registry.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +11 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +33 -19
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/request-lineage.d.ts +8 -0
- package/dist/server/request-lineage.d.ts.map +1 -0
- package/dist/server/request-lineage.js +14 -0
- package/dist/server/request-lineage.js.map +1 -0
- package/dist/server/request-target.d.ts +31 -0
- package/dist/server/request-target.d.ts.map +1 -0
- package/dist/server/request-target.js +44 -0
- package/dist/server/request-target.js.map +1 -0
- package/dist/server/respond.d.ts +1 -1
- package/dist/server/respond.d.ts.map +1 -1
- package/dist/server/respond.js +16 -4
- package/dist/server/respond.js.map +1 -1
- package/dist/server/response-contract-lane.d.ts +19 -1
- package/dist/server/response-contract-lane.d.ts.map +1 -1
- package/dist/server/response-contract-lane.js +59 -14
- package/dist/server/response-contract-lane.js.map +1 -1
- package/dist/server/response-observer-runtime.d.ts +9 -5
- package/dist/server/response-observer-runtime.d.ts.map +1 -1
- package/dist/server/response-observer-runtime.js +10 -6
- package/dist/server/response-observer-runtime.js.map +1 -1
- package/dist/server/runtime-core.d.ts +2 -0
- package/dist/server/runtime-core.d.ts.map +1 -1
- package/dist/server/runtime-core.js.map +1 -1
- package/dist/server/server-types.d.ts +53 -3
- package/dist/server/server-types.d.ts.map +1 -1
- package/dist/server/server.d.ts +191 -19
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +1206 -218
- package/dist/server/server.js.map +1 -1
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js +10 -7
- package/dist/server/sse.js.map +1 -1
- package/dist/server/static-headers.d.ts +3 -0
- package/dist/server/static-headers.d.ts.map +1 -1
- package/dist/server/static-headers.js +19 -1
- package/dist/server/static-headers.js.map +1 -1
- package/dist/server/transport-lane.d.ts +8 -0
- package/dist/server/transport-lane.d.ts.map +1 -1
- package/dist/server/transport-lane.js +9 -8
- package/dist/server/transport-lane.js.map +1 -1
- package/dist/server/validation.d.ts.map +1 -1
- package/dist/server/validation.js +5 -1
- package/dist/server/validation.js.map +1 -1
- package/dist/server/websocket.d.ts +10 -3
- package/dist/server/websocket.d.ts.map +1 -1
- package/dist/server/websocket.js +7 -4
- package/dist/server/websocket.js.map +1 -1
- package/dist/server/ws-bun.d.ts +2 -0
- package/dist/server/ws-bun.d.ts.map +1 -1
- package/dist/server/ws-bun.js +6 -3
- package/dist/server/ws-bun.js.map +1 -1
- package/dist/server/ws-hook.d.ts +2 -1
- package/dist/server/ws-hook.d.ts.map +1 -1
- package/dist/server.d.ts +7 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -1
- package/dist/server.js.map +1 -1
- package/dist/single-copy-register.js +5 -0
- package/dist/single-copy-register.js.map +1 -1
- package/dist/single-copy.d.ts +46 -3
- package/dist/single-copy.d.ts.map +1 -1
- package/dist/single-copy.js +125 -12
- package/dist/single-copy.js.map +1 -1
- package/dist/tool-contract.d.ts +23 -0
- package/dist/tool-contract.d.ts.map +1 -1
- package/dist/tool-contract.js +37 -3
- package/dist/tool-contract.js.map +1 -1
- package/dist/transport-codec.d.ts.map +1 -1
- package/dist/transport-codec.js +2 -1
- package/dist/transport-codec.js.map +1 -1
- package/package.json +27 -2
- package/src/assurance.ts +52 -2
- package/src/capabilities.ts +81 -22
- package/src/diff.ts +31 -6
- package/src/durable-adapters.ts +20 -3
- package/src/durable-effect.ts +10 -3
- package/src/edge-kit.ts +7 -0
- package/src/effect-lifecycle.ts +5 -1
- package/src/effect-scope.ts +2 -1
- package/src/errors.ts +3 -0
- package/src/evidence.ts +237 -12
- package/src/idempotency.ts +72 -8
- package/src/index.ts +40 -3
- package/src/internal/code-unit-order.ts +8 -0
- package/src/internal/durable-saga-protocol.ts +2 -0
- package/src/internal/route-catalog.ts +19 -18
- package/src/internal/route-compiler.ts +62 -13
- package/src/internal/route-execution.ts +13 -3
- package/src/internal/route-lanes.ts +37 -28
- package/src/internal/route-program.ts +434 -20
- package/src/ledger.ts +11 -5
- package/src/manifest.ts +41 -36
- package/src/mount.ts +62 -0
- package/src/reflection.ts +84 -1
- package/src/response-observer.ts +1 -0
- package/src/router/overlap.ts +258 -0
- package/src/router/pattern.ts +349 -25
- package/src/router/router.ts +76 -51
- package/src/server/auth.ts +75 -0
- package/src/server/bare-error-lane.ts +12 -11
- package/src/server/body-lane.ts +46 -6
- package/src/server/body-parser.ts +241 -0
- package/src/server/body.ts +82 -9
- package/src/server/client-ip.ts +9 -0
- package/src/server/context.ts +219 -12
- package/src/server/contract.ts +54 -9
- package/src/server/core-copies.ts +21 -0
- package/src/server/edge.ts +2 -0
- package/src/server/http.ts +34 -0
- package/src/server/idempotency-lane.ts +147 -72
- package/src/server/install.ts +6 -0
- package/src/server/methods.ts +143 -0
- package/src/server/multipart.ts +424 -0
- package/src/server/node-outcome-hook.ts +40 -7
- package/src/server/not-found-answer.ts +109 -0
- package/src/server/not-found.ts +121 -0
- package/src/server/plugin.ts +45 -1
- package/src/server/proto-guard.ts +128 -9
- package/src/server/query.ts +49 -0
- package/src/server/registry.ts +17 -2
- package/src/server/request-context.ts +44 -16
- package/src/server/request-lineage.ts +15 -0
- package/src/server/request-target.ts +46 -0
- package/src/server/respond.ts +14 -3
- package/src/server/response-contract-lane.ts +97 -16
- package/src/server/response-observer-runtime.ts +37 -8
- package/src/server/runtime-core.ts +2 -0
- package/src/server/server-types.ts +59 -2
- package/src/server/server.ts +1613 -269
- package/src/server/sse.ts +10 -8
- package/src/server/static-headers.ts +22 -1
- package/src/server/transport-lane.ts +17 -9
- package/src/server/validation.ts +7 -1
- package/src/server/websocket.ts +23 -9
- package/src/server/ws-bun.ts +8 -3
- package/src/server/ws-hook.ts +2 -1
- package/src/server.ts +38 -2
- package/src/single-copy-register.ts +5 -0
- package/src/single-copy.ts +160 -12
- package/src/tool-contract.ts +66 -3
- package/src/transport-codec.ts +2 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** The not-found rules (see `./not-found.ts`), shared by `notFound()` and the edge server. */
|
|
2
|
+
import type { Platform } from "./context.js";
|
|
3
|
+
import { type ResponseResult } from "./runtime-core.js";
|
|
4
|
+
import type { MaybePromise, RequestSource } from "./server.js";
|
|
5
|
+
/** What a {@link NotFoundHandler} is given: the request line and headers of a request no route matched. */
|
|
6
|
+
export interface NotFoundInput<Env = unknown> {
|
|
7
|
+
/** The request method, exactly as received. Always a token a route could be registered under. */
|
|
8
|
+
readonly method: string;
|
|
9
|
+
/** The request URL, exactly as received. */
|
|
10
|
+
readonly url: string;
|
|
11
|
+
/** The path the router looked up, exactly as received: NOT percent-decoded, so `/a%2Fb` stays
|
|
12
|
+
* `/a%2Fb`. Escape it before writing it into a body. */
|
|
13
|
+
readonly pathname: string;
|
|
14
|
+
/** The request headers. */
|
|
15
|
+
readonly headers: Headers;
|
|
16
|
+
/** Read one request header (case-insensitive), or `null` when it is absent. */
|
|
17
|
+
header(name: string): string | null;
|
|
18
|
+
/** Aborts when the server's `requestTimeoutMs` elapses before the handler settles. Never aborts
|
|
19
|
+
* when no timeout is configured. */
|
|
20
|
+
readonly signal: AbortSignal;
|
|
21
|
+
/** The platform inputs (`env`, `waitUntil`, the caller address) the serving adapter supplied. */
|
|
22
|
+
readonly platform: Platform<Env> | undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Answers a request no route matched. Return a `Response`, or `undefined` for the default `404`.
|
|
26
|
+
* May be async; a thrown `Response` is treated like a returned one.
|
|
27
|
+
*/
|
|
28
|
+
export type NotFoundHandler<Env = unknown> = (input: NotFoundInput<Env>) => MaybePromise<Response | undefined>;
|
|
29
|
+
/** @internal The read-only view a {@link NotFoundHandler} receives. `url` and `headers` stay getters
|
|
30
|
+
* so a source that builds them on demand is not forced to for a handler that never reads them. */
|
|
31
|
+
export declare function notFoundInput<Env>(source: RequestSource, pathname: string, platform: Platform<Env> | undefined, signal?: AbortSignal): NotFoundInput<Env>;
|
|
32
|
+
/**
|
|
33
|
+
* @internal Run a {@link NotFoundHandler} and turn what it produced into the answer. One function
|
|
34
|
+
* for every server that has a `404` site, so the rules above hold identically on each of them.
|
|
35
|
+
* `wrap` lifts a response into the caller's output type; `failed` renders the fault answer.
|
|
36
|
+
*/
|
|
37
|
+
export declare function answerNotFound<T, Env>(handler: NotFoundHandler<Env>, input: NotFoundInput<Env>, wrap: (response: Response | ResponseResult) => T, failed: (error: unknown) => T): MaybePromise<T>;
|
|
38
|
+
/** @internal What the kernel calls at its `404` site once a handler is installed. */
|
|
39
|
+
export type NotFoundLane = <T>(host: unknown, source: RequestSource, pathname: string, platform: Platform<unknown> | undefined, wrap: (response: Response | ResponseResult) => T, onTimeout: () => T) => MaybePromise<T>;
|
|
40
|
+
//# sourceMappingURL=not-found-answer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found-answer.d.ts","sourceRoot":"","sources":["../../src/server/not-found-answer.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE9D,2GAA2G;AAC3G,MAAM,WAAW,aAAa,CAAC,GAAG,GAAG,OAAO;IAC1C,iGAAiG;IACjG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB;4DACwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,+EAA+E;IAC/E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACnC;wCACoC;IACpC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,iGAAiG;IACjG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;CAC7C;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,GAAG,GAAG,OAAO,IAAI,CAC3C,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,KACtB,YAAY,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAA;AAEvC;kGACkG;AAClG,wBAAgB,aAAa,CAAC,GAAG,EAC/B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,SAAS,EACnC,MAAM,GAAE,WAAmC,GAC1C,aAAa,CAAC,GAAG,CAAC,CAcpB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EACnC,OAAO,EAAE,eAAe,CAAC,GAAG,CAAC,EAC7B,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,KAAK,CAAC,EAChD,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,GAC5B,YAAY,CAAC,CAAC,CAAC,CA+BjB;AAED,qFAAqF;AACrF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,EAC3B,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,SAAS,EACvC,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,KAAK,CAAC,EAChD,SAAS,EAAE,MAAM,CAAC,KACf,YAAY,CAAC,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isRoutableMethod, plainError } from "./http.js";
|
|
2
|
+
import { getNeverAbortSignal, headerOf } from "./runtime-core.js";
|
|
3
|
+
/** @internal The read-only view a {@link NotFoundHandler} receives. `url` and `headers` stay getters
|
|
4
|
+
* so a source that builds them on demand is not forced to for a handler that never reads them. */
|
|
5
|
+
export function notFoundInput(source, pathname, platform, signal = getNeverAbortSignal()) {
|
|
6
|
+
return {
|
|
7
|
+
method: source.method,
|
|
8
|
+
pathname,
|
|
9
|
+
signal,
|
|
10
|
+
platform,
|
|
11
|
+
get url() {
|
|
12
|
+
return source.url;
|
|
13
|
+
},
|
|
14
|
+
get headers() {
|
|
15
|
+
return source.headers;
|
|
16
|
+
},
|
|
17
|
+
header: (name) => headerOf(source, name),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @internal Run a {@link NotFoundHandler} and turn what it produced into the answer. One function
|
|
22
|
+
* for every server that has a `404` site, so the rules above hold identically on each of them.
|
|
23
|
+
* `wrap` lifts a response into the caller's output type; `failed` renders the fault answer.
|
|
24
|
+
*/
|
|
25
|
+
export function answerNotFound(handler, input, wrap, failed) {
|
|
26
|
+
if (!isRoutableMethod(input.method))
|
|
27
|
+
return wrap(plainError(404, "not_found"));
|
|
28
|
+
const settle = (value, thrown) => {
|
|
29
|
+
if (value instanceof Response) {
|
|
30
|
+
// A status below 200 is `Response.error()`: a network-error marker, not an answer.
|
|
31
|
+
if (value.bodyUsed || value.status < 200) {
|
|
32
|
+
return failed(new TypeError("notFound handler answered with an unusable Response"));
|
|
33
|
+
}
|
|
34
|
+
// A miss is never a success. The body and headers are the handler's; the status is not.
|
|
35
|
+
return wrap(value.status < 300
|
|
36
|
+
? new Response(value.body, { status: 404, headers: value.headers })
|
|
37
|
+
: value);
|
|
38
|
+
}
|
|
39
|
+
if (thrown)
|
|
40
|
+
return failed(value);
|
|
41
|
+
if (value === undefined)
|
|
42
|
+
return wrap(plainError(404, "not_found"));
|
|
43
|
+
return failed(new TypeError("notFound handler must return a Response or undefined"));
|
|
44
|
+
};
|
|
45
|
+
let result;
|
|
46
|
+
try {
|
|
47
|
+
result = handler(input);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return settle(error, true);
|
|
51
|
+
}
|
|
52
|
+
return result instanceof Promise
|
|
53
|
+
? result.then((value) => settle(value, false), (error) => settle(error, true))
|
|
54
|
+
: settle(result, false);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=not-found-answer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found-answer.js","sourceRoot":"","sources":["../../src/server/not-found-answer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAuB,MAAM,mBAAmB,CAAA;AA+BtF;kGACkG;AAClG,MAAM,UAAU,aAAa,CAC3B,MAAqB,EACrB,QAAgB,EAChB,QAAmC,EACnC,SAAsB,mBAAmB,EAAE;IAE3C,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,IAAI,GAAG;YACL,OAAO,MAAM,CAAC,GAAG,CAAA;QACnB,CAAC;QACD,IAAI,OAAO;YACT,OAAO,MAAM,CAAC,OAAO,CAAA;QACvB,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;KACzC,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,OAA6B,EAC7B,KAAyB,EACzB,IAAgD,EAChD,MAA6B;IAE7B,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAA;IAC9E,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,MAAe,EAAK,EAAE;QACpD,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,mFAAmF;YACnF,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACzC,OAAO,MAAM,CAAC,IAAI,SAAS,CAAC,qDAAqD,CAAC,CAAC,CAAA;YACrF,CAAC;YACD,wFAAwF;YACxF,OAAO,IAAI,CACT,KAAK,CAAC,MAAM,GAAG,GAAG;gBAChB,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;gBACnE,CAAC,CAAC,KAAK,CACV,CAAA;QACH,CAAC;QACD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;QAChC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAA;QAClE,OAAO,MAAM,CAAC,IAAI,SAAS,CAAC,sDAAsD,CAAC,CAAC,CAAA;IACtF,CAAC,CAAA;IACD,IAAI,MAA0C,CAAA;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,MAAM,YAAY,OAAO;QAC9B,CAAC,CAAC,MAAM,CAAC,IAAI,CACT,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAC/B;QACH,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAC3B,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type NotFoundHandler } from "./not-found-answer.js";
|
|
2
|
+
import type { IdentityPlugin } from "./plugin.js";
|
|
3
|
+
export type { NotFoundHandler, NotFoundInput } from "./not-found-answer.js";
|
|
4
|
+
/**
|
|
5
|
+
* Answer requests no route matched with a handler of your own: `app.use(notFound(handler))`.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { notFound } from "@nifrajs/core/not-found"
|
|
9
|
+
*
|
|
10
|
+
* const app = server().use(
|
|
11
|
+
* notFound(({ pathname }) => Response.json({ ok: false, error: "no_such_route", pathname })),
|
|
12
|
+
* )
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* The answer is a `404` whatever `2xx` status the handler gives it; see the module notes for the
|
|
16
|
+
* full rules. The server's `requestTimeoutMs` bounds an async handler and aborts `input.signal`.
|
|
17
|
+
*
|
|
18
|
+
* A server takes one handler, and it belongs to the server that listens: applying `notFound()` a
|
|
19
|
+
* second time throws, and so does applying it inside a `group()` (a miss has no prefix to scope it
|
|
20
|
+
* to). A server composed into another with `merge()` does not carry its handler along.
|
|
21
|
+
*/
|
|
22
|
+
export declare function notFound<Env = unknown>(handler: NotFoundHandler<Env>): IdentityPlugin;
|
|
23
|
+
//# sourceMappingURL=not-found.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found.d.ts","sourceRoot":"","sources":["../../src/server/not-found.ts"],"names":[],"mappings":"AAaA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAgB3E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,GAAG,GAAG,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,cAAc,CA+DrF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `notFound()` handler's rules:
|
|
3
|
+
* - Only for a `404`: a wrong method stays a `405`, a malformed path a `400`, a mount's `404` its own.
|
|
4
|
+
* - It sees the request line and headers, never the body: an unrouted request has no body limit.
|
|
5
|
+
* - A method token no route could take gets the default `404`, as it skips `onRequest` hooks.
|
|
6
|
+
* - A `2xx` is sent as a `404`; a `3xx`, `410` or other error status is sent as built.
|
|
7
|
+
* - Fails closed: a throw or an unsendable value is logged and answered with the plain `500`.
|
|
8
|
+
*/
|
|
9
|
+
import { emitRequestErrorLog } from "./bare-error-lane.js";
|
|
10
|
+
import { plainError } from "./http.js";
|
|
11
|
+
import { INSTALL_NOT_FOUND } from "./install.js";
|
|
12
|
+
import { answerNotFound, notFoundInput, } from "./not-found-answer.js";
|
|
13
|
+
/**
|
|
14
|
+
* Answer requests no route matched with a handler of your own: `app.use(notFound(handler))`.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { notFound } from "@nifrajs/core/not-found"
|
|
18
|
+
*
|
|
19
|
+
* const app = server().use(
|
|
20
|
+
* notFound(({ pathname }) => Response.json({ ok: false, error: "no_such_route", pathname })),
|
|
21
|
+
* )
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* The answer is a `404` whatever `2xx` status the handler gives it; see the module notes for the
|
|
25
|
+
* full rules. The server's `requestTimeoutMs` bounds an async handler and aborts `input.signal`.
|
|
26
|
+
*
|
|
27
|
+
* A server takes one handler, and it belongs to the server that listens: applying `notFound()` a
|
|
28
|
+
* second time throws, and so does applying it inside a `group()` (a miss has no prefix to scope it
|
|
29
|
+
* to). A server composed into another with `merge()` does not carry its handler along.
|
|
30
|
+
*/
|
|
31
|
+
export function notFound(handler) {
|
|
32
|
+
if (typeof handler !== "function")
|
|
33
|
+
throw new TypeError("notFound() needs a handler function");
|
|
34
|
+
const lane = (host, source, pathname, platform, wrap, onTimeout) => {
|
|
35
|
+
const { requestTimeoutMs, logger, errorLogDetail } = host;
|
|
36
|
+
const env = platform;
|
|
37
|
+
const failed = (error) => {
|
|
38
|
+
// A logger that throws must not decide the answer: the fault is still the plain `500`.
|
|
39
|
+
try {
|
|
40
|
+
emitRequestErrorLog(logger, errorLogDetail, error, { req: source });
|
|
41
|
+
}
|
|
42
|
+
catch { }
|
|
43
|
+
return wrap(plainError(500, "internal_error"));
|
|
44
|
+
};
|
|
45
|
+
if (requestTimeoutMs === 0) {
|
|
46
|
+
return answerNotFound(handler, notFoundInput(source, pathname, env), wrap, failed);
|
|
47
|
+
}
|
|
48
|
+
const controller = new AbortController();
|
|
49
|
+
const answer = answerNotFound(handler, notFoundInput(source, pathname, env, controller.signal), wrap, failed);
|
|
50
|
+
if (!(answer instanceof Promise))
|
|
51
|
+
return answer;
|
|
52
|
+
// The same bound a matched route gets: abort the signal, answer the timeout, discard the late
|
|
53
|
+
// result. Both arms are attached, so a handler that settles after the deadline is still observed.
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
const timer = setTimeout(() => {
|
|
56
|
+
controller.abort();
|
|
57
|
+
resolve(onTimeout());
|
|
58
|
+
}, requestTimeoutMs);
|
|
59
|
+
answer.then((value) => {
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
resolve(value);
|
|
62
|
+
}, (error) => {
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
reject(error);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
const apply = (app) => {
|
|
69
|
+
const host = app;
|
|
70
|
+
if (host.notFoundLane !== undefined) {
|
|
71
|
+
throw new TypeError("notFound() is already applied to this server");
|
|
72
|
+
}
|
|
73
|
+
if (host.routePrefix !== "") {
|
|
74
|
+
throw new TypeError("notFound() inside a group answers nothing - apply it to the parent server");
|
|
75
|
+
}
|
|
76
|
+
host[INSTALL_NOT_FOUND](lane);
|
|
77
|
+
return app;
|
|
78
|
+
};
|
|
79
|
+
return apply;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=not-found.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-found.js","sourceRoot":"","sources":["../../src/server/not-found.ts"],"names":[],"mappings":"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"}
|
package/dist/server/plugin.d.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* `use`/`derive`/`decorate` and/or registering routes) and returns it; these helpers attach a name
|
|
4
4
|
* for idempotent dedupe and pin the type-threading so `.use()` preserves the caller's typed server.
|
|
5
5
|
*/
|
|
6
|
-
import type {
|
|
6
|
+
import type { Method } from "../router/router.js";
|
|
7
|
+
import type { RouteSchema } from "./context.js";
|
|
8
|
+
import type { AddRoute, Registry, RouteInfoFor } from "./registry.js";
|
|
7
9
|
import type { AnyServer, Server } from "./server.js";
|
|
8
10
|
/**
|
|
9
11
|
* A nifra **plugin**: a function that augments an app - calling `use`/`derive`/`decorate` and/or
|
|
@@ -50,6 +52,29 @@ export type ContextPlugin<D extends object> = (<R extends Registry, Ctx>(app: Se
|
|
|
50
52
|
* ```
|
|
51
53
|
*/
|
|
52
54
|
export declare function defineContextPlugin<D extends object>(name: string, apply: <R extends Registry, Ctx>(app: Server<R, Ctx>) => Server<R, Ctx & D>): ContextPlugin<D>;
|
|
55
|
+
declare const METHOD_ROUTES: unique symbol;
|
|
56
|
+
/**
|
|
57
|
+
* What `all()` and `method()` from `@nifrajs/core/methods` return: a plugin for `app.use()` that
|
|
58
|
+
* registers one handler under the methods `M` of `Path`. It is opaque - apply it with `use`, which
|
|
59
|
+
* reads the route's types from it and adds them to the app's registry.
|
|
60
|
+
*/
|
|
61
|
+
export interface MethodRoutesPlugin<M extends string, Path extends string, S extends RouteSchema, Output, Ctx> {
|
|
62
|
+
readonly [METHOD_ROUTES]: {
|
|
63
|
+
readonly methods: M;
|
|
64
|
+
readonly path: Path;
|
|
65
|
+
readonly schema: S;
|
|
66
|
+
readonly output: Output;
|
|
67
|
+
/** The context the handler was written against; the app must provide at least this. */
|
|
68
|
+
readonly context: (context: Ctx) => void;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** The standard methods among `M`, as the registry keys them. A custom token contributes none. */
|
|
72
|
+
type StandardMethodOf<M extends string> = Extract<Uppercase<M>, Method>;
|
|
73
|
+
/**
|
|
74
|
+
* The registry after a {@link MethodRoutesPlugin} is applied: `Path` gains the standard methods
|
|
75
|
+
* among `M`. A method outside the standard set is served but not typed, so it adds nothing.
|
|
76
|
+
*/
|
|
77
|
+
export type WithMethodRoutes<R extends Registry, M extends string, Path extends string, S extends RouteSchema, Output, HookOutput> = [StandardMethodOf<M>] extends [never] ? R : AddRoute<R, StandardMethodOf<M>, Path, RouteInfoFor<Path, S, Output, HookOutput>>;
|
|
53
78
|
declare const COLLAPSED: unique symbol;
|
|
54
79
|
/**
|
|
55
80
|
* What {@link definePlugin} returns when its `apply` argument never pinned the input server type -
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/server/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/server/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/server/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/server/plugin.ts"],"names":[],"mappings":"AA2CA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,KAA2E;IAE3E,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAqB,CAAA;AACvE,CAAC;AAwGD,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,KAAoC;IAEpC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;AACnD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAY;AACZ,iGAAiG;AACjG,2FAA2F;AAC3F,mGAAmG;AACnG,8FAA8F;AAC9F,KAAqD;IAErD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAoC,CAAA;AACtF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgC,oBAAoB,CAAA"}
|
|
@@ -20,11 +20,24 @@ export type ProtoPoisoning = "reject" | "strip" | "ignore";
|
|
|
20
20
|
*/
|
|
21
21
|
export declare function parseJsonGuarded(text: string, policy: ProtoPoisoning): unknown;
|
|
22
22
|
/**
|
|
23
|
-
* The policy applied to an already-parsed value - the native-`json()` lane, which never holds
|
|
24
|
-
* raw text
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
23
|
+
* The policy applied to an already-parsed JSON value - the native-`json()` lane, which never holds
|
|
24
|
+
* the raw text. Escapes are resolved by the time a key is an own property, so a `\u`-spelled
|
|
25
|
+
* `__proto__` and a literal one look identical here. Cost is one iterative pass over the value's
|
|
26
|
+
* object nodes; `"ignore"` skips even that. The walk assumes a tree, which JSON always is; a
|
|
27
|
+
* transport codec's output goes through {@link guardDecodedValue}. Throws the reject singleton;
|
|
28
|
+
* callers map it to their lane's flat error.
|
|
28
29
|
*/
|
|
29
30
|
export declare function guardParsedValue(value: unknown, policy: ProtoPoisoning): unknown;
|
|
31
|
+
/**
|
|
32
|
+
* The policy for a value a transport codec decoded. Unlike `JSON.parse` output that can be a graph -
|
|
33
|
+
* a codec that keeps references, as the rich wire codec does, returns shared nodes and cycles - while
|
|
34
|
+
* everything downstream (validators, handlers, serializers) walks a body as a tree. So a cycle is
|
|
35
|
+
* refused, and shared nodes may add at most {@link MAX_SHARED_EXPANSION} nodes to the tree they expand
|
|
36
|
+
* to: forty levels of doubled references fit in 2KB and expand to 2^40 paths. Map and Set members are
|
|
37
|
+
* walked like properties. These shape rules hold under every policy, `"ignore"` included.
|
|
38
|
+
*
|
|
39
|
+
* A `RegExp` is refused unless `patterns` allows it: a pattern from the client is code, and one with
|
|
40
|
+
* catastrophic backtracking stalls the event loop the moment anything runs it.
|
|
41
|
+
*/
|
|
42
|
+
export declare function guardDecodedValue(value: unknown, policy: ProtoPoisoning, patterns?: boolean): unknown;
|
|
30
43
|
//# sourceMappingURL=proto-guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proto-guard.d.ts","sourceRoot":"","sources":["../../src/server/proto-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAK1D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAE9E;AAED
|
|
1
|
+
{"version":3,"file":"proto-guard.d.ts","sourceRoot":"","sources":["../../src/server/proto-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AAK1D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAE9E;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAGhF;AAiGD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,cAAc,EACtB,QAAQ,UAAQ,GACf,OAAO,CAuBT"}
|
|
@@ -23,11 +23,12 @@ export function parseJsonGuarded(text, policy) {
|
|
|
23
23
|
return guardParsedValue(JSON.parse(text), policy);
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* The policy applied to an already-parsed value - the native-`json()` lane, which never holds
|
|
27
|
-
* raw text
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
26
|
+
* The policy applied to an already-parsed JSON value - the native-`json()` lane, which never holds
|
|
27
|
+
* the raw text. Escapes are resolved by the time a key is an own property, so a `\u`-spelled
|
|
28
|
+
* `__proto__` and a literal one look identical here. Cost is one iterative pass over the value's
|
|
29
|
+
* object nodes; `"ignore"` skips even that. The walk assumes a tree, which JSON always is; a
|
|
30
|
+
* transport codec's output goes through {@link guardDecodedValue}. Throws the reject singleton;
|
|
31
|
+
* callers map it to their lane's flat error.
|
|
31
32
|
*/
|
|
32
33
|
export function guardParsedValue(value, policy) {
|
|
33
34
|
if (policy === "ignore")
|
|
@@ -77,10 +78,10 @@ function sweep(root, policy) {
|
|
|
77
78
|
// `for-in`, not `Object.keys()`: the keys array would be an allocation per node (~2x the whole
|
|
78
79
|
// walk on measured bodies, both engines, at realistic widths; V8 only prefers `Object.keys` on
|
|
79
80
|
// 200+-property dictionary-mode objects). On JSON.parse output the two enumerate identically -
|
|
80
|
-
// own enumerable string keys, nothing enumerable on the prototype chain.
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
81
|
+
// own enumerable string keys, nothing enumerable on the prototype chain. Were a value with
|
|
82
|
+
// enumerable INHERITED properties handed in, `for-in` would sweep those too, which only
|
|
83
|
+
// over-sweeps - a poisoned inherited subtree rejects rather than slips through. A
|
|
84
|
+
// *non-enumerable* own `__proto__` is the one shape this misses, and it is
|
|
84
85
|
// not the poisoning shape: `JSON.parse` never produces one, and the merges that carry the
|
|
85
86
|
// payload onward (spread, `Object.assign`, key loops) copy enumerable own keys only.
|
|
86
87
|
for (const key in record) {
|
|
@@ -113,4 +114,108 @@ function sweep(root, policy) {
|
|
|
113
114
|
}
|
|
114
115
|
return root;
|
|
115
116
|
}
|
|
117
|
+
/** How many nodes shared references may add to a decoded value, counted as a tree walk visits it. */
|
|
118
|
+
const MAX_SHARED_EXPANSION = 100_000;
|
|
119
|
+
/** Thrown (reused singleton, mapped like {@link POISONED}) for a decoded value no tree walk can finish,
|
|
120
|
+
* or one holding a pattern the caller did not allow. */
|
|
121
|
+
const NOT_A_TREE = /* @__PURE__ */ new Error("decoded_value_not_a_tree");
|
|
122
|
+
/** Marks a node whose subtree is still being walked: meeting it again then is a cycle. */
|
|
123
|
+
const ON_PATH = -1;
|
|
124
|
+
/**
|
|
125
|
+
* The policy for a value a transport codec decoded. Unlike `JSON.parse` output that can be a graph -
|
|
126
|
+
* a codec that keeps references, as the rich wire codec does, returns shared nodes and cycles - while
|
|
127
|
+
* everything downstream (validators, handlers, serializers) walks a body as a tree. So a cycle is
|
|
128
|
+
* refused, and shared nodes may add at most {@link MAX_SHARED_EXPANSION} nodes to the tree they expand
|
|
129
|
+
* to: forty levels of doubled references fit in 2KB and expand to 2^40 paths. Map and Set members are
|
|
130
|
+
* walked like properties. These shape rules hold under every policy, `"ignore"` included.
|
|
131
|
+
*
|
|
132
|
+
* A `RegExp` is refused unless `patterns` allows it: a pattern from the client is code, and one with
|
|
133
|
+
* catastrophic backtracking stalls the event loop the moment anything runs it.
|
|
134
|
+
*/
|
|
135
|
+
export function guardDecodedValue(value, policy, patterns = false) {
|
|
136
|
+
if (value === null || typeof value !== "object")
|
|
137
|
+
return value;
|
|
138
|
+
const sizes = new Map();
|
|
139
|
+
const frames = [openDecoded(value, policy, patterns, sizes)];
|
|
140
|
+
let expanded = 0;
|
|
141
|
+
for (let frame = frames.at(-1); frame !== undefined; frame = frames.at(-1)) {
|
|
142
|
+
const child = frame.children[frame.next];
|
|
143
|
+
if (child !== undefined) {
|
|
144
|
+
frame.next++;
|
|
145
|
+
const known = sizes.get(child);
|
|
146
|
+
if (known === undefined)
|
|
147
|
+
frames.push(openDecoded(child, policy, patterns, sizes));
|
|
148
|
+
else if (known === ON_PATH)
|
|
149
|
+
throw NOT_A_TREE;
|
|
150
|
+
else
|
|
151
|
+
frame.size += known;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
frames.pop();
|
|
155
|
+
sizes.set(frame.node, frame.size);
|
|
156
|
+
const parent = frames.at(-1);
|
|
157
|
+
if (parent === undefined)
|
|
158
|
+
expanded = frame.size;
|
|
159
|
+
else
|
|
160
|
+
parent.size += frame.size;
|
|
161
|
+
}
|
|
162
|
+
if (expanded - sizes.size > MAX_SHARED_EXPANSION)
|
|
163
|
+
throw NOT_A_TREE;
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
function openDecoded(node, policy, patterns, sizes) {
|
|
167
|
+
if (!patterns && node instanceof RegExp)
|
|
168
|
+
throw NOT_A_TREE;
|
|
169
|
+
sizes.set(node, ON_PATH);
|
|
170
|
+
return { node, children: decodedChildren(node, policy), next: 0, size: 1 };
|
|
171
|
+
}
|
|
172
|
+
function decodedChildren(node, policy) {
|
|
173
|
+
const children = [];
|
|
174
|
+
const add = (value) => {
|
|
175
|
+
if (value !== null && typeof value === "object")
|
|
176
|
+
children.push(value);
|
|
177
|
+
};
|
|
178
|
+
if (Array.isArray(node)) {
|
|
179
|
+
for (let i = 0; i < node.length; i++)
|
|
180
|
+
add(node[i]);
|
|
181
|
+
return children;
|
|
182
|
+
}
|
|
183
|
+
if (node instanceof Map) {
|
|
184
|
+
for (const [key, value] of node) {
|
|
185
|
+
add(key);
|
|
186
|
+
add(value);
|
|
187
|
+
}
|
|
188
|
+
return children;
|
|
189
|
+
}
|
|
190
|
+
if (node instanceof Set) {
|
|
191
|
+
for (const item of node)
|
|
192
|
+
add(item);
|
|
193
|
+
return children;
|
|
194
|
+
}
|
|
195
|
+
// Binary and scalar wrappers carry no keys to poison; `for-in` over a typed array would enumerate
|
|
196
|
+
// every index.
|
|
197
|
+
if (ArrayBuffer.isView(node) ||
|
|
198
|
+
node instanceof ArrayBuffer ||
|
|
199
|
+
node instanceof Date ||
|
|
200
|
+
node instanceof RegExp ||
|
|
201
|
+
node instanceof URL) {
|
|
202
|
+
return children;
|
|
203
|
+
}
|
|
204
|
+
for (const key in node) {
|
|
205
|
+
const value = Reflect.get(node, key);
|
|
206
|
+
if (policy !== "ignore" &&
|
|
207
|
+
(key === "__proto__" ||
|
|
208
|
+
(key === "constructor" &&
|
|
209
|
+
value !== null &&
|
|
210
|
+
typeof value === "object" &&
|
|
211
|
+
Object.hasOwn(value, "prototype")))) {
|
|
212
|
+
if (policy === "reject")
|
|
213
|
+
throw POISONED;
|
|
214
|
+
Reflect.deleteProperty(node, key);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
add(value);
|
|
218
|
+
}
|
|
219
|
+
return children;
|
|
220
|
+
}
|
|
116
221
|
//# sourceMappingURL=proto-guard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proto-guard.js","sourceRoot":"","sources":["../../src/server/proto-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,kGAAkG;AAClG,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;AAElD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,MAAsB;IACnE,OAAO,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAA;AACnD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"proto-guard.js","sourceRoot":"","sources":["../../src/server/proto-guard.ts"],"names":[],"mappings":"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"}
|
package/dist/server/query.d.ts
CHANGED
|
@@ -10,6 +10,13 @@ export type QueryValue = string | string[];
|
|
|
10
10
|
/** Return a value-equal, likely-internalized copy of a parsed record key. See the note above. */
|
|
11
11
|
export declare function internParseKey(key: string): string;
|
|
12
12
|
export declare function queryObjectOf(search: string): Record<string, QueryValue>;
|
|
13
|
+
/**
|
|
14
|
+
* `application/json` or an `application/*+json` type, with or without parameters, compared as a media
|
|
15
|
+
* type rather than searched as a substring. A substring test also matches `text/plain; x=application/json`,
|
|
16
|
+
* whose essence is `text/plain` - a type a browser sends cross-origin with credentials and no preflight,
|
|
17
|
+
* so a JSON route would parse a body no CORS policy ever saw.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isJsonMediaType(contentType: string): boolean;
|
|
13
20
|
/** `application/x-www-form-urlencoded`, with or without a charset suffix. */
|
|
14
21
|
export declare function isUrlEncodedForm(contentType: string): boolean;
|
|
15
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/server/query.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAMhD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;mDAImD;AACnD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;AAgB1C,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlD;AAsCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAyBxE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAK7D;AAID;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,cAAc,CAAC,CActD"}
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/server/query.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAMhD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;mDAImD;AACnD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;AAgB1C,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlD;AAsCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAyBxE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAyC5D;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAK7D;AAID;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,cAAc,CAAC,CActD"}
|
package/dist/server/query.js
CHANGED
|
@@ -99,6 +99,53 @@ export function queryObjectOf(search) {
|
|
|
99
99
|
}
|
|
100
100
|
return out;
|
|
101
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* `application/json` or an `application/*+json` type, with or without parameters, compared as a media
|
|
104
|
+
* type rather than searched as a substring. A substring test also matches `text/plain; x=application/json`,
|
|
105
|
+
* whose essence is `text/plain` - a type a browser sends cross-origin with credentials and no preflight,
|
|
106
|
+
* so a JSON route would parse a body no CORS policy ever saw.
|
|
107
|
+
*/
|
|
108
|
+
export function isJsonMediaType(contentType) {
|
|
109
|
+
// The spellings common clients send, by exact match.
|
|
110
|
+
if (contentType === "application/json" ||
|
|
111
|
+
contentType === "application/json; charset=utf-8" ||
|
|
112
|
+
contentType === "application/json;charset=UTF-8") {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
// Every other lowercase `application/json` spelling, parameters or not, without slicing or lowercasing.
|
|
116
|
+
if (contentType.startsWith("application/json")) {
|
|
117
|
+
let delimiter = 16;
|
|
118
|
+
while (delimiter < contentType.length) {
|
|
119
|
+
const char = contentType.charCodeAt(delimiter);
|
|
120
|
+
if (char !== 32 /* SP */ && char !== 9 /* HTAB */)
|
|
121
|
+
break;
|
|
122
|
+
delimiter++;
|
|
123
|
+
}
|
|
124
|
+
if (delimiter === contentType.length || contentType.charCodeAt(delimiter) === 59 /* ; */) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Lowercase `application/*+json` spellings by the same rules as the parse below, without allocating.
|
|
129
|
+
if (contentType.startsWith("application/")) {
|
|
130
|
+
const params = contentType.indexOf(";", 12);
|
|
131
|
+
let end = params === -1 ? contentType.length : params;
|
|
132
|
+
while (end > 12) {
|
|
133
|
+
const char = contentType.charCodeAt(end - 1);
|
|
134
|
+
if (char !== 32 /* SP */ && char !== 9 /* HTAB */)
|
|
135
|
+
break;
|
|
136
|
+
end--;
|
|
137
|
+
}
|
|
138
|
+
if (end >= 17 && contentType.startsWith("+json", end - 5)) {
|
|
139
|
+
const space = contentType.indexOf(" ", 12);
|
|
140
|
+
if (space === -1 || space >= end)
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const semi = contentType.indexOf(";");
|
|
145
|
+
const essence = (semi === -1 ? contentType : contentType.slice(0, semi)).trim().toLowerCase();
|
|
146
|
+
return (essence === "application/json" ||
|
|
147
|
+
(essence.startsWith("application/") && essence.endsWith("+json") && !essence.includes(" ")));
|
|
148
|
+
}
|
|
102
149
|
/** `application/x-www-form-urlencoded`, with or without a charset suffix. */
|
|
103
150
|
export function isUrlEncodedForm(contentType) {
|
|
104
151
|
return (contentType === "application/x-www-form-urlencoded" ||
|
package/dist/server/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/server/query.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAIlD,+FAA+F;AAC/F,oGAAoG;AACpG,oGAAoG;AACpG,2DAA2D;AAC3D,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;AAC/B,CAAC;AASD,iGAAiG;AACjG,kGAAkG;AAClG,gGAAgG;AAChG,8FAA8F;AAC9F,kGAAkG;AAClG,mGAAmG;AACnG,8FAA8F;AAC9F,kGAAkG;AAClG,yDAAyD;AACzD,MAAM,wBAAwB,GAAG,OAAQ,UAAgC,CAAC,GAAG,KAAK,WAAW,CAAA;AAC7F,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAA;AAClD,MAAM,oBAAoB,GAAG,IAAI,CAAA;AACjC,MAAM,oBAAoB,GAAG,EAAE,CAAA;AAE/B,iGAAiG;AACjG,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,wBAAwB;QAAE,OAAO,GAAG,CAAA;IACxC,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACrC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAA;IACjC,IAAI,GAAG,CAAC,MAAM,GAAG,oBAAoB,IAAI,gBAAgB,CAAC,IAAI,IAAI,oBAAoB;QAAE,OAAO,GAAG,CAAA;IAClG,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAC9B,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;8EAG8E;AAC9E,SAAS,aAAa,CAAC,GAA+B,EAAE,MAAc,EAAE,KAAa;IACnF,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;IACzB,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IAClB,CAAC;SAAM,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAc;IACzC,uFAAuF;IACvF,+EAA+E;IAC/E,MAAM,GAAG,GAA+B,MAAM,CAAC,MAAM,CAAC,IAAI,CAA+B,CAAA;IACzF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,iGAAiG;AACjG,0DAA0D;AAC1D,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAA+B,CAAA;AAEpF,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACzD,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,WAAW,CAAA;IAE9C,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAC9B,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO;YAAE,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAA;IAC9E,CAAC;IAED,MAAM,GAAG,GAA+B,MAAM,CAAC,MAAM,CAAC,IAAI,CAA+B,CAAA;IACzF,IAAI,GAAG,GAAG,KAAK,CAAA;IACf,OAAO,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QACpC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAA;QAC5C,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;YACd,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;YACnC,MAAM,KAAK,GAAG,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;YAC9C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACpC,MAAM,KAAK,GAAG,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;YAC/D,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;QAChC,CAAC;QACD,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,MAAK;QACrB,GAAG,GAAG,GAAG,GAAG,CAAC,CAAA;IACf,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,CACL,WAAW,KAAK,mCAAmC;QACnD,WAAW,CAAC,UAAU,CAAC,oCAAoC,CAAC,CAC7D,CAAA;AACH,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAA;AAEtC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAkB,EAClB,QAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAClD,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,MAAM,KAAK,GAAG;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,mBAAmB,CAAC;YACtC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAA;IAC/C,CAAC;IACD,MAAM,GAAG,GAA+B,MAAM,CAAC,MAAM,CAAC,IAAI,CAA+B,CAAA;IACzF,yFAAyF;IACzF,iEAAiE;IACjE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,eAAe,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAChF,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/server/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BinaryResponse, RawResponse } from "../binary.js";
|
|
2
2
|
import type { InferInput, InferOutput, StandardSchemaV1 } from "../schema/standard.js";
|
|
3
|
-
import type { Params, RouteSchema } from "./context.js";
|
|
3
|
+
import type { Params, RoutePaths, RouteSchema } from "./context.js";
|
|
4
4
|
import type { StatusResponse } from "./runtime-core.js";
|
|
5
5
|
/**
|
|
6
6
|
* One route's input/output shape as the **client** will consume it. `query`/`body`
|
|
@@ -138,11 +138,22 @@ export type WsRouteInfoFor<Path extends string, In extends StandardSchemaV1 | un
|
|
|
138
138
|
* `.merge()` them (each group is a short chain; a merge is one `R & R2` intersection with no
|
|
139
139
|
* per-call context work), or contract-first `implement()` (the registry is one object type declared
|
|
140
140
|
* upfront - no grow-R-per-call, so no ceiling at all).
|
|
141
|
+
*
|
|
142
|
+
* A path ending in optional parameters is keyed once per concrete path it serves (`RoutePaths`), all
|
|
143
|
+
* sharing the one route info, so `/users/:id?` adds `/users` and `/users/:id`.
|
|
141
144
|
*/
|
|
142
145
|
export type AddRoute<R extends Registry, Method extends string, Path extends string, Info extends RouteInfo> = R & {
|
|
143
|
-
[P in Path]: {
|
|
146
|
+
[P in RoutePaths<Path>]: {
|
|
144
147
|
[M in Method]: Info;
|
|
145
148
|
};
|
|
146
149
|
};
|
|
150
|
+
/** Join a group prefix and a route path the way `Server.group` does at runtime: a group's `/` route
|
|
151
|
+
* serves the prefix itself (no trailing slash), every other path is appended verbatim. */
|
|
152
|
+
export type JoinRoutePath<Prefix extends string, Path extends string> = Path extends "/" ? Prefix : `${Prefix}${Path}`;
|
|
153
|
+
/** Re-key a registry under a static path prefix. Route info (params, schemas, responses) is carried
|
|
154
|
+
* unchanged: a prefix is static text, so it adds no params and cannot change any route's contract. */
|
|
155
|
+
export type PrefixRegistry<Prefix extends string, R extends Registry> = {
|
|
156
|
+
[Path in keyof R & string as JoinRoutePath<Prefix, Path>]: R[Path];
|
|
157
|
+
};
|
|
147
158
|
export {};
|
|
148
159
|
//# sourceMappingURL=registry.d.ts.map
|