@nifrajs/core 2.8.2 → 2.9.1
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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/route-execution.d.ts +8 -2
- package/dist/internal/route-execution.d.ts.map +1 -1
- package/dist/node-direct.d.ts.map +1 -1
- package/dist/node-direct.js +3 -1
- package/dist/node-direct.js.map +1 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +26 -6
- package/dist/router/router.js.map +1 -1
- package/dist/server/context.d.ts +2 -0
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/cookies.d.ts.map +1 -1
- package/dist/server/cookies.js +4 -1
- package/dist/server/cookies.js.map +1 -1
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +16 -3
- package/dist/server/http.js.map +1 -1
- package/dist/server/node-outcome-hook.d.ts +78 -1
- package/dist/server/node-outcome-hook.d.ts.map +1 -1
- package/dist/server/node-outcome-hook.js +197 -1
- package/dist/server/node-outcome-hook.js.map +1 -1
- package/dist/server/node-outcome.d.ts +22 -2
- package/dist/server/node-outcome.d.ts.map +1 -1
- package/dist/server/node-outcome.js +86 -11
- package/dist/server/node-outcome.js.map +1 -1
- package/dist/server/query.d.ts +2 -0
- package/dist/server/query.d.ts.map +1 -1
- package/dist/server/query.js +27 -1
- package/dist/server/query.js.map +1 -1
- package/dist/server/request-context.d.ts +8 -1
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +23 -2
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/respond.d.ts +29 -3
- package/dist/server/respond.d.ts.map +1 -1
- package/dist/server/respond.js +279 -16
- package/dist/server/respond.js.map +1 -1
- package/dist/server/response-contract-lane.d.ts +17 -3
- package/dist/server/response-contract-lane.d.ts.map +1 -1
- package/dist/server/response-contract-lane.js +6 -3
- package/dist/server/response-contract-lane.js.map +1 -1
- package/dist/server/server-types.d.ts +37 -0
- package/dist/server/server-types.d.ts.map +1 -1
- package/dist/server/server.d.ts +151 -7
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +1163 -174
- package/dist/server/server.js.map +1 -1
- package/dist/server/static-headers.d.ts +47 -0
- package/dist/server/static-headers.d.ts.map +1 -0
- package/dist/server/static-headers.js +109 -0
- package/dist/server/static-headers.js.map +1 -0
- package/dist/server.d.ts +2 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/transport-codec.d.ts +15 -0
- package/dist/transport-codec.d.ts.map +1 -1
- package/dist/transport-codec.js +49 -10
- package/dist/transport-codec.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/internal/route-execution.ts +19 -1
- package/src/node-direct.ts +7 -1
- package/src/router/router.ts +24 -6
- package/src/server/context.ts +2 -0
- package/src/server/cookies.ts +4 -1
- package/src/server/http.ts +16 -3
- package/src/server/node-outcome-hook.ts +315 -1
- package/src/server/node-outcome.ts +100 -14
- package/src/server/query.ts +26 -1
- package/src/server/request-context.ts +23 -1
- package/src/server/respond.ts +386 -17
- package/src/server/response-contract-lane.ts +17 -3
- package/src/server/server-types.ts +42 -0
- package/src/server/server.ts +1618 -237
- package/src/server/static-headers.ts +142 -0
- package/src/server.ts +9 -0
- package/src/transport-codec.ts +55 -10
package/dist/server.d.ts
CHANGED
|
@@ -15,9 +15,10 @@ export type { InferInput, InferOutput, StandardIssue, StandardResult, StandardSc
|
|
|
15
15
|
export type { Context, Params, Platform, Prettify, ResponseControls, RouteSchema, } from "./server/context.js";
|
|
16
16
|
export { type CookieOptions, parseCookies, serializeCookie, signValue, unsignValue, } from "./server/cookies.js";
|
|
17
17
|
export { type DurableObjectNamespaceLike, type ExecutionContext, type ScheduledController, type ScheduledHandler, toFetchHandler, } from "./server/edge.js";
|
|
18
|
+
export { pathnameOf, type UrlParts, urlPartsOf } from "./server/http.js";
|
|
18
19
|
export { commonSecretPatterns, jsonLogger, type LogFields, type Logger, type RedactOptions, redactLogFields, silentLogger, } from "./server/logger.js";
|
|
19
20
|
export type { Registry, RouteInfo } from "./server/registry.js";
|
|
20
|
-
export { type AdmissionController, type AdmissionDecision, type AnyServer, defineIdentityPlugin, definePlugin, defineRouterPlugin, type Handler, type IdentityPlugin, type McpPromptDescriptor, type McpResourceDescriptor, type Middleware, type NifraPlugin, type NodeServeOutcome, type OnRequestResult, type PromptArgument, type PromptMessage, type ResponseFinalization, type RouteDescriptor, type RunningServer, Server, type ServerOptions, server, type ToolAnnotations, } from "./server/server.js";
|
|
21
|
+
export { type AdmissionController, type AdmissionDecision, type AnyServer, defineIdentityPlugin, definePlugin, defineRouterPlugin, type Handler, type IdentityPlugin, type McpPromptDescriptor, type McpResourceDescriptor, type Middleware, type NifraPlugin, type NodeRequestContext, type NodeRequestHook, type NodeResponseContext, type NodeResponseHook, type NodeServeOutcome, type OnRequestResult, type PromptArgument, type PromptMessage, type ResponseBodyHook, type ResponseBodyReplacement, type ResponseFinalization, type ResponseHeadersHook, type ResponseHeadersView, type RouteDescriptor, type RunningServer, Server, type ServerOptions, server, type ToolAnnotations, } from "./server/server.js";
|
|
21
22
|
export type { SSEContext, SSEInit, SSEMessage, SSEStream, TypedSSEStream, } from "./server/sse.js";
|
|
22
23
|
export type { NifraWebSocket, StandardWebSocket, WebSocketContext, WebSocketData, WebSocketHandler, WebSocketUpgradeOutcome, } from "./server/websocket.js";
|
|
23
24
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACnF,YAAY,EACV,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,aAAa,EAClB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,MAAM,EACN,KAAK,aAAa,EAClB,MAAM,EACN,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,SAAS,EACT,cAAc,GACf,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA"}
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACnF,YAAY,EACV,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,aAAa,EAClB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACxE,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,MAAM,EACN,KAAK,aAAa,EAClB,MAAM,EACN,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,SAAS,EACT,cAAc,GACf,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA"}
|
package/dist/server.js
CHANGED
|
@@ -13,6 +13,7 @@ export { isSameOriginRequest } from "./internal/same-origin.js";
|
|
|
13
13
|
export { METHODS, Router } from "./router/router.js";
|
|
14
14
|
export { parseCookies, serializeCookie, signValue, unsignValue, } from "./server/cookies.js";
|
|
15
15
|
export { toFetchHandler, } from "./server/edge.js";
|
|
16
|
+
export { pathnameOf, urlPartsOf } from "./server/http.js";
|
|
16
17
|
export { commonSecretPatterns, jsonLogger, redactLogFields, silentLogger, } from "./server/logger.js";
|
|
17
18
|
export { defineIdentityPlugin, definePlugin, defineRouterPlugin, Server, server, } from "./server/server.js";
|
|
18
19
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAe,MAAM,EAAoB,MAAM,oBAAoB,CAAA;AAkBnF,OAAO,EAEL,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAKL,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,oBAAoB,EACpB,UAAU,EAIV,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAIL,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAe,MAAM,EAAoB,MAAM,oBAAoB,CAAA;AAkBnF,OAAO,EAEL,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAKL,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAiB,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACxE,OAAO,EACL,oBAAoB,EACpB,UAAU,EAIV,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAIL,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAsBlB,MAAM,EAEN,MAAM,GAEP,MAAM,oBAAoB,CAAA"}
|
|
@@ -15,6 +15,12 @@ export interface TransportCodec {
|
|
|
15
15
|
export declare class TransportCodecError extends TypeError {
|
|
16
16
|
constructor(message: string, options?: ErrorOptions);
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Enforce the transport byte cap on already-read text - the same limit (and the same error) the
|
|
20
|
+
* streaming reader applies during a bounded read. Exported for callers that read a body through a
|
|
21
|
+
* native, non-streaming path (the typed client's in-process branch) and still owe the cap contract.
|
|
22
|
+
*/
|
|
23
|
+
export declare function assertTransportTextBounded(text: string, options: TransportDecodeOptions): void;
|
|
18
24
|
export declare const plainJsonCodec: TransportCodec;
|
|
19
25
|
export interface TransportCodecRegistry {
|
|
20
26
|
readonly fallback: TransportCodec;
|
|
@@ -37,6 +43,15 @@ export declare function encodeTransportResponse(value: unknown, codec?: Transpor
|
|
|
37
43
|
* than growing a second copy of this loop that could drift from it.
|
|
38
44
|
*/
|
|
39
45
|
export declare function readBoundedBytes(response: Response, options: TransportDecodeOptions): Promise<Uint8Array>;
|
|
46
|
+
/**
|
|
47
|
+
* Decode an ALREADY-READ transport body. The counterpart to {@link decodeTransportResponse} for a
|
|
48
|
+
* caller that obtained the text through its own bounded read - notably the typed client's
|
|
49
|
+
* in-process path, where the response body is same-process memory that was fully resident before
|
|
50
|
+
* the read, so the native `Response.text()` is safe and the streaming byte-cap loop would protect
|
|
51
|
+
* nothing while costing ~23x. The byte cap is still enforced here (identical error), just after
|
|
52
|
+
* the read instead of during it.
|
|
53
|
+
*/
|
|
54
|
+
export declare function decodeTransportText(text: string, contentType: string | null, registry?: TransportCodecRegistry, options?: TransportDecodeOptions): unknown;
|
|
40
55
|
export declare function decodeTransportResponse(response: Response, registry?: TransportCodecRegistry, options?: TransportDecodeOptions): Promise<unknown>;
|
|
41
56
|
export declare function encodeTransportFrame(value: unknown, codec?: TransportCodec): string;
|
|
42
57
|
export declare function decodeTransportFrame(frame: string, registry?: TransportCodecRegistry, options?: TransportDecodeOptions): unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-codec.d.ts","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;
|
|
1
|
+
{"version":3,"file":"transport-codec.d.ts","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAkCD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAU9F;AAID,eAAO,MAAM,cAAc,EAAE,cAY3B,CAAA;AAEF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAC1D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAChD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAA;CACxD;AAUD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,GAAE,cAA+B,GACxC,sBAAsB,CAgFxB;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAEnC,CAAA;AAEF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,EACtC,IAAI,GAAE,YAAiB,GACtB,QAAQ,CAKV;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAcD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAQT;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,OAAO,CAAC,CAQlB;AAQD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,GACrC,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAsBT"}
|
package/dist/transport-codec.js
CHANGED
|
@@ -36,14 +36,28 @@ function maxBytesOf(options) {
|
|
|
36
36
|
throw new RangeError("transport maxBytes must be a non-negative safe integer");
|
|
37
37
|
return maxBytes;
|
|
38
38
|
}
|
|
39
|
+
const BYTE_ENCODER = new TextEncoder();
|
|
39
40
|
function byteLength(text) {
|
|
40
|
-
return
|
|
41
|
+
return BYTE_ENCODER.encode(text).byteLength;
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Enforce the transport byte cap on already-read text - the same limit (and the same error) the
|
|
45
|
+
* streaming reader applies during a bounded read. Exported for callers that read a body through a
|
|
46
|
+
* native, non-streaming path (the typed client's in-process branch) and still owe the cap contract.
|
|
47
|
+
*/
|
|
48
|
+
export function assertTransportTextBounded(text, options) {
|
|
49
|
+
const maxBytes = maxBytesOf(options);
|
|
50
|
+
// Fast accept: UTF-8 emits at most 3 bytes per UTF-16 code unit, so `length * 3` bounds the
|
|
51
|
+
// encoded size from above - a body comfortably under the cap (the overwhelmingly common case
|
|
52
|
+
// against the 16 MB default) never pays a full re-encode just to prove it fits. Only a string
|
|
53
|
+
// within 3x of the cap needs the exact count.
|
|
54
|
+
if (text.length * 3 <= maxBytes)
|
|
55
|
+
return;
|
|
56
|
+
if (byteLength(text) > maxBytes) {
|
|
44
57
|
throw new TransportCodecError("transport payload exceeds maxBytes");
|
|
45
58
|
}
|
|
46
59
|
}
|
|
60
|
+
const assertBounded = assertTransportTextBounded;
|
|
47
61
|
export const plainJsonCodec = Object.freeze({
|
|
48
62
|
id: "json",
|
|
49
63
|
version: 1,
|
|
@@ -86,19 +100,26 @@ export function createTransportCodecRegistry(codecs, fallback = plainJsonCodec)
|
|
|
86
100
|
}
|
|
87
101
|
if (!byId.has(`${fallback.id}@${fallback.version}`))
|
|
88
102
|
throw new TypeError("transport fallback must be registered");
|
|
103
|
+
const jsonCodec = byId.get("json@1");
|
|
89
104
|
const forContentType = (contentType) => {
|
|
90
105
|
if (contentType === null || contentType.trim() === "")
|
|
91
106
|
return fallback;
|
|
107
|
+
// Direct probe before canonicalizing: a server-emitted content type is already lowercase with
|
|
108
|
+
// no stray spacing (nifra's own always is), so the common case skips the split/trim/join walk.
|
|
109
|
+
// The charset-suffixed JSON string is what `Response.json` (and nifra's respond path) emits on
|
|
110
|
+
// every JSON response - it resolves to the same `json@1` the parameter-stripping walk below
|
|
111
|
+
// would reach, just without paying the walk.
|
|
112
|
+
const exact = byMedia.get(contentType);
|
|
113
|
+
if (exact !== undefined)
|
|
114
|
+
return exact;
|
|
115
|
+
if (contentType === "application/json;charset=utf-8" && jsonCodec !== undefined)
|
|
116
|
+
return jsonCodec;
|
|
92
117
|
const canonical = canonicalMediaType(contentType);
|
|
93
118
|
const direct = byMedia.get(canonical);
|
|
94
119
|
if (direct !== undefined)
|
|
95
120
|
return direct;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const json = byId.get("json@1");
|
|
99
|
-
if (json !== undefined)
|
|
100
|
-
return json;
|
|
101
|
-
}
|
|
121
|
+
if (canonical.split(";")[0] === "application/json" && jsonCodec !== undefined)
|
|
122
|
+
return jsonCodec;
|
|
102
123
|
throw new TransportCodecError(`unsupported transport content type: ${contentType}`);
|
|
103
124
|
};
|
|
104
125
|
return Object.freeze({
|
|
@@ -197,9 +218,27 @@ export async function readBoundedBytes(response, options) {
|
|
|
197
218
|
}
|
|
198
219
|
return bytes;
|
|
199
220
|
}
|
|
221
|
+
// Shared decoder: `TextDecoder.decode` on a whole buffer is stateless, so one instance serves every
|
|
222
|
+
// call (constructing one costs ~115ns - it was previously built per response).
|
|
223
|
+
const FATAL_UTF8 = new TextDecoder("utf-8", { fatal: true });
|
|
200
224
|
async function readBoundedText(response, options) {
|
|
201
225
|
const bytes = await readBoundedBytes(response, options);
|
|
202
|
-
return decodeOrThrow(() =>
|
|
226
|
+
return decodeOrThrow(() => FATAL_UTF8.decode(bytes), "transport payload is not valid UTF-8");
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Decode an ALREADY-READ transport body. The counterpart to {@link decodeTransportResponse} for a
|
|
230
|
+
* caller that obtained the text through its own bounded read - notably the typed client's
|
|
231
|
+
* in-process path, where the response body is same-process memory that was fully resident before
|
|
232
|
+
* the read, so the native `Response.text()` is safe and the streaming byte-cap loop would protect
|
|
233
|
+
* nothing while costing ~23x. The byte cap is still enforced here (identical error), just after
|
|
234
|
+
* the read instead of during it.
|
|
235
|
+
*/
|
|
236
|
+
export function decodeTransportText(text, contentType, registry = defaultTransportCodecs, options = {}) {
|
|
237
|
+
assertBounded(text, options);
|
|
238
|
+
if (text === "")
|
|
239
|
+
return undefined;
|
|
240
|
+
const codec = registry.forContentType(contentType);
|
|
241
|
+
return decodeOrThrow(() => codec.decode(text), `malformed transport body for codec ${codec.id}@${codec.version}`);
|
|
203
242
|
}
|
|
204
243
|
export async function decodeTransportResponse(response, registry = defaultTransportCodecs, options = {}) {
|
|
205
244
|
const codec = registry.forContentType(response.headers.get("content-type"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-codec.js","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;AAC1C,MAAM,KAAK,GAAG,0BAA0B,CAAA;AAcxC,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChD,YAAY,OAAe,EAAE,OAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;IACnC,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,SAAS,aAAa,CAAI,MAAe,EAAE,OAAe;IACxD,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAA;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,mBAAmB;YAAE,MAAM,KAAK,CAAA;QACrD,MAAM,IAAI,mBAAmB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IACnD,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,OAA+B;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,iBAAiB,CAAA;IACtD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;QACjD,MAAM,IAAI,UAAU,CAAC,wDAAwD,CAAC,CAAA;IAChF,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,
|
|
1
|
+
{"version":3,"file":"transport-codec.js","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* read its own package.json at runtime. `scripts/version.ts` rewrites it on every release bump and
|
|
11
11
|
* `check:publish` asserts it equals `@nifrajs/core`'s package version.
|
|
12
12
|
*/
|
|
13
|
-
export const VERSION = "2.
|
|
13
|
+
export const VERSION = "2.9.1" as const
|
|
14
14
|
|
|
15
15
|
export type Version = typeof VERSION
|
|
16
16
|
|
|
@@ -44,6 +44,7 @@ export type RouteExecutionRunner = <T, R extends Registry, Ctx>(
|
|
|
44
44
|
signal: AbortSignal,
|
|
45
45
|
budget: RequestBudget,
|
|
46
46
|
platform: Platform | undefined,
|
|
47
|
+
nativeContext: boolean,
|
|
47
48
|
finalize: (result: unknown, set: CtxSet) => T,
|
|
48
49
|
wrapResponse: (response: Response) => T,
|
|
49
50
|
) => MaybePromise<T>
|
|
@@ -62,10 +63,11 @@ export type ContextRouteRunner = <T, R extends Registry, Ctx>(
|
|
|
62
63
|
export interface RouteExecutionPlan {
|
|
63
64
|
readonly run: RouteExecutionRunner
|
|
64
65
|
readonly fusedWeb: FusedWebRunner | undefined
|
|
66
|
+
readonly fusedBody: FusedBodyRunner | undefined
|
|
65
67
|
/** Which builder produced {@link fusedWeb} - a merge rebinds the closure to the executing server
|
|
66
68
|
* and must rebuild it with the SAME semantics (a query-fused route rebuilt as bare would skip its
|
|
67
69
|
* validation). `undefined` iff `fusedWeb` is. */
|
|
68
|
-
readonly fusedLane: "bare" | "query" | undefined
|
|
70
|
+
readonly fusedLane: "bare" | "body" | "query" | undefined
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
export interface RouteEntry {
|
|
@@ -92,6 +94,8 @@ export interface RouteEntry {
|
|
|
92
94
|
readonly beforeHandle: ReadonlyArray<RawBeforeHandle>
|
|
93
95
|
readonly afterHandle: ReadonlyArray<RawAfterHandle>
|
|
94
96
|
readonly onError: ReadonlyArray<RawErrorHandler>
|
|
97
|
+
/** Registration-specialized hook shape for the common derive + before middleware route. */
|
|
98
|
+
readonly lifecycleHookLane: "derive-before" | undefined
|
|
95
99
|
/** Wraps the matched route lifecycle. Empty for the common no-around path. */
|
|
96
100
|
readonly around: ReadonlyArray<RawAround>
|
|
97
101
|
/** The single immutable execution decision consumed by portable, Node-direct, and Bun-native paths. */
|
|
@@ -108,3 +112,17 @@ export type FusedWebRunner = (
|
|
|
108
112
|
platform: Platform | undefined,
|
|
109
113
|
nativeContext: boolean,
|
|
110
114
|
) => MaybePromise<Response>
|
|
115
|
+
|
|
116
|
+
/** Registration-compiled body lane. The finalizer receives the live context so Web can preserve lazy
|
|
117
|
+
* response controls while Node can emit its native outcome directly. */
|
|
118
|
+
export type FusedBodyRunner = <T>(
|
|
119
|
+
source: RequestSource,
|
|
120
|
+
params: Record<string, string>,
|
|
121
|
+
search: string | undefined,
|
|
122
|
+
signal: AbortSignal,
|
|
123
|
+
budget: RequestBudget,
|
|
124
|
+
platform: Platform | undefined,
|
|
125
|
+
nativeContext: boolean,
|
|
126
|
+
finalize: (result: unknown, set: CtxSet, ctx: RawContext) => T,
|
|
127
|
+
wrapResponse: (response: Response) => T,
|
|
128
|
+
) => MaybePromise<T>
|
package/src/node-direct.ts
CHANGED
|
@@ -6,14 +6,20 @@
|
|
|
6
6
|
* `resolveNode()` callers do. Same `.use()` install seam as `mcp()` / `idempotency()`.
|
|
7
7
|
*/
|
|
8
8
|
import { INSTALL_NODE_DIRECT } from "./server/install.ts"
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
nodeOutcomeFromResponse,
|
|
11
|
+
nodeOutcomeToResponse,
|
|
12
|
+
toNodeOutcome,
|
|
13
|
+
} from "./server/node-outcome.ts"
|
|
10
14
|
import type { NodeOutcomeRuntime } from "./server/node-outcome-hook.ts"
|
|
11
15
|
import type { IdentityPlugin } from "./server/plugin.ts"
|
|
12
16
|
import type { AnyServer } from "./server/server.ts"
|
|
13
17
|
|
|
14
18
|
const NODE_OUTCOME_RUNTIME: NodeOutcomeRuntime = {
|
|
15
19
|
toOutcome: toNodeOutcome,
|
|
20
|
+
toResponse: nodeOutcomeToResponse,
|
|
16
21
|
fromResponse: nodeOutcomeFromResponse,
|
|
22
|
+
jsonContentType: "application/json;charset=utf-8",
|
|
17
23
|
timeout: () => ({
|
|
18
24
|
kind: "response",
|
|
19
25
|
response: Response.json({ ok: false, error: "request_timeout" }, { status: 503 }),
|
package/src/router/router.ts
CHANGED
|
@@ -220,10 +220,19 @@ function resolve<T>(
|
|
|
220
220
|
params: Record<string, string>,
|
|
221
221
|
): RouterMatch<T> {
|
|
222
222
|
if (terminal.staticMatches !== undefined && params === EMPTY_PARAMS) {
|
|
223
|
+
// Real requests arrive pre-uppercased (HTTP methods are canonically uppercase; every runtime and
|
|
224
|
+
// client normalizes this) - try the cache under the raw method first so that overwhelmingly common
|
|
225
|
+
// case skips `toUpperCase()` entirely, matching the same already-uppercase fast path
|
|
226
|
+
// `resolveDirect` takes below. Falls back to the uppercase key (computed once) for a lowercase or
|
|
227
|
+
// mixed-case caller, so behavior is unchanged - only the common case gets cheaper.
|
|
228
|
+
const direct = terminal.staticMatches.get(method)
|
|
229
|
+
if (direct !== undefined) return direct
|
|
223
230
|
const upper = method.toUpperCase()
|
|
224
|
-
const cached = terminal.staticMatches.get(upper)
|
|
231
|
+
const cached = upper === method ? undefined : terminal.staticMatches.get(upper)
|
|
225
232
|
if (cached !== undefined) return cached
|
|
226
|
-
|
|
233
|
+
const cacheable =
|
|
234
|
+
terminal.handlers.has(upper) || (upper === "HEAD" && terminal.handlers.has("GET"))
|
|
235
|
+
if (!cacheable) return resolveDirect(terminal, method, params)
|
|
227
236
|
|
|
228
237
|
const res = resolveDirect(terminal, method, params)
|
|
229
238
|
terminal.staticMatches.set(upper, res)
|
|
@@ -241,11 +250,20 @@ function resolveDirect<T>(
|
|
|
241
250
|
return { found: true, payload: terminal.handlers.get(method)!, params }
|
|
242
251
|
}
|
|
243
252
|
const upper = method.toUpperCase()
|
|
244
|
-
if (upper
|
|
245
|
-
return { found:
|
|
253
|
+
if (upper !== method && terminal.handlers.has(upper)) {
|
|
254
|
+
return { found: true, payload: terminal.handlers.get(upper)!, params }
|
|
246
255
|
}
|
|
247
|
-
|
|
248
|
-
|
|
256
|
+
// RFC 9110 §9.3.2: HEAD is GET without the body. A route registered for GET answers HEAD with
|
|
257
|
+
// the GET handler; the serving runtime strips the body, so status + headers mirror GET exactly.
|
|
258
|
+
// An explicitly registered HEAD handler takes precedence via the has() checks above.
|
|
259
|
+
if (upper === "HEAD") {
|
|
260
|
+
const get = terminal.handlers.get("GET")
|
|
261
|
+
if (get !== undefined) return { found: true, payload: get, params }
|
|
262
|
+
}
|
|
263
|
+
const allowed = [...terminal.handlers.keys()]
|
|
264
|
+
// Advertise the implicit HEAD support granted above.
|
|
265
|
+
if (terminal.handlers.has("GET") && !terminal.handlers.has("HEAD")) allowed.push("HEAD")
|
|
266
|
+
return { found: false, reason: "method-not-allowed", allowed }
|
|
249
267
|
}
|
|
250
268
|
|
|
251
269
|
/**
|
package/src/server/context.ts
CHANGED
|
@@ -213,6 +213,8 @@ export interface Context<Path extends string = string, S extends RouteSchema = R
|
|
|
213
213
|
* everywhere (no more `c.req` vs `ctx.request` mismatch).
|
|
214
214
|
*/
|
|
215
215
|
readonly request: Request
|
|
216
|
+
/** Read one request header without materializing a Web `Request` on the Node adapter hot path. */
|
|
217
|
+
readonly header: (name: string) => string | null
|
|
216
218
|
readonly params: ParamsOf<S, Path>
|
|
217
219
|
readonly query: QueryOf<S>
|
|
218
220
|
readonly body: BodyOf<S>
|
package/src/server/cookies.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { requireSecretBytes } from "../internal/secret.ts"
|
|
9
|
+
import { internParseKey } from "./query.ts"
|
|
9
10
|
|
|
10
11
|
/** Attributes for a `Set-Cookie`. `expires` is a `Date`; `maxAge` is in **seconds**. */
|
|
11
12
|
export interface CookieOptions {
|
|
@@ -88,7 +89,9 @@ export function parseCookies(header: string | null | undefined): Record<string,
|
|
|
88
89
|
} else {
|
|
89
90
|
value = header.slice(valueStart, stop)
|
|
90
91
|
}
|
|
91
|
-
|
|
92
|
+
// Interned: cookie names repeat across requests, and V8 pays ~300ns to internalize a
|
|
93
|
+
// fresh sliced key on a null-proto store (see internParseKey).
|
|
94
|
+
out[internParseKey(name)] = safeDecode(value)
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
pos = end + 1
|
package/src/server/http.ts
CHANGED
|
@@ -51,8 +51,21 @@ export function urlPartsOf(url: string): UrlParts {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
// Extract the pathname WITHOUT a full WHATWG `new URL(req.url)` parse
|
|
55
|
-
//
|
|
54
|
+
// Extract the pathname WITHOUT a full WHATWG `new URL(req.url)` parse or a temporary `{ pathname,
|
|
55
|
+
// search }` pair. The request hot path only needs the path for routing; query extraction remains
|
|
56
|
+
// lazy in the request context.
|
|
56
57
|
export function pathnameOf(url: string): string {
|
|
57
|
-
|
|
58
|
+
const schemeEnd = url.indexOf("://")
|
|
59
|
+
const start = schemeEnd === -1 ? url.indexOf("/") : url.indexOf("/", schemeEnd + 3)
|
|
60
|
+
if (start === -1) return "/"
|
|
61
|
+
|
|
62
|
+
let end = url.length
|
|
63
|
+
for (let i = start; i < url.length; i++) {
|
|
64
|
+
const c = url.charCodeAt(i)
|
|
65
|
+
if (c === 63 /* ? */ || c === 35 /* # */) {
|
|
66
|
+
end = i
|
|
67
|
+
break
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return url.slice(start, end)
|
|
58
71
|
}
|