@nifrajs/core 2.10.0 → 2.12.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.
Files changed (180) hide show
  1. package/dist/assurance.d.ts +61 -3
  2. package/dist/assurance.d.ts.map +1 -1
  3. package/dist/assurance.js +152 -5
  4. package/dist/assurance.js.map +1 -1
  5. package/dist/capabilities.d.ts +9 -1
  6. package/dist/capabilities.d.ts.map +1 -1
  7. package/dist/capabilities.js +5 -1
  8. package/dist/capabilities.js.map +1 -1
  9. package/dist/diff.d.ts +2 -1
  10. package/dist/diff.d.ts.map +1 -1
  11. package/dist/diff.js +3 -1
  12. package/dist/diff.js.map +1 -1
  13. package/dist/errors.d.ts +1 -1
  14. package/dist/errors.d.ts.map +1 -1
  15. package/dist/errors.js.map +1 -1
  16. package/dist/evidence.d.ts +89 -0
  17. package/dist/evidence.d.ts.map +1 -0
  18. package/dist/evidence.js +170 -0
  19. package/dist/evidence.js.map +1 -0
  20. package/dist/execution-policy.d.ts +23 -0
  21. package/dist/execution-policy.d.ts.map +1 -0
  22. package/dist/execution-policy.js +28 -0
  23. package/dist/execution-policy.js.map +1 -0
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.js +1 -1
  26. package/dist/internal/route-assurance.d.ts +19 -0
  27. package/dist/internal/route-assurance.d.ts.map +1 -1
  28. package/dist/internal/route-assurance.js +38 -5
  29. package/dist/internal/route-assurance.js.map +1 -1
  30. package/dist/internal/route-execution.d.ts +18 -0
  31. package/dist/internal/route-execution.d.ts.map +1 -1
  32. package/dist/internal/route-execution.js +67 -1
  33. package/dist/internal/route-execution.js.map +1 -1
  34. package/dist/manifest.d.ts +5 -1
  35. package/dist/manifest.d.ts.map +1 -1
  36. package/dist/manifest.js +22 -4
  37. package/dist/manifest.js.map +1 -1
  38. package/dist/reflection.d.ts +5 -0
  39. package/dist/reflection.d.ts.map +1 -1
  40. package/dist/reflection.js +13 -4
  41. package/dist/reflection.js.map +1 -1
  42. package/dist/replay.d.ts +26 -0
  43. package/dist/replay.d.ts.map +1 -0
  44. package/dist/replay.js +63 -0
  45. package/dist/replay.js.map +1 -0
  46. package/dist/schema/standard.d.ts +2 -0
  47. package/dist/schema/standard.d.ts.map +1 -1
  48. package/dist/schema/standard.js +13 -0
  49. package/dist/schema/standard.js.map +1 -1
  50. package/dist/server/body.d.ts +49 -6
  51. package/dist/server/body.d.ts.map +1 -1
  52. package/dist/server/body.js +226 -8
  53. package/dist/server/body.js.map +1 -1
  54. package/dist/server/context.d.ts +20 -3
  55. package/dist/server/context.d.ts.map +1 -1
  56. package/dist/server/contract.d.ts +15 -3
  57. package/dist/server/contract.d.ts.map +1 -1
  58. package/dist/server/contract.js +22 -0
  59. package/dist/server/contract.js.map +1 -1
  60. package/dist/server/cookies.d.ts +26 -5
  61. package/dist/server/cookies.d.ts.map +1 -1
  62. package/dist/server/cookies.js +76 -9
  63. package/dist/server/cookies.js.map +1 -1
  64. package/dist/server/edge.d.ts.map +1 -1
  65. package/dist/server/edge.js +11 -0
  66. package/dist/server/edge.js.map +1 -1
  67. package/dist/server/header-case.d.ts +9 -0
  68. package/dist/server/header-case.d.ts.map +1 -0
  69. package/dist/server/header-case.js +54 -0
  70. package/dist/server/header-case.js.map +1 -0
  71. package/dist/server/headers.d.ts +8 -0
  72. package/dist/server/headers.d.ts.map +1 -0
  73. package/dist/server/headers.js +13 -0
  74. package/dist/server/headers.js.map +1 -0
  75. package/dist/server/node-outcome-hook.d.ts.map +1 -1
  76. package/dist/server/node-outcome-hook.js +7 -11
  77. package/dist/server/node-outcome-hook.js.map +1 -1
  78. package/dist/server/node-outcome.d.ts +8 -1
  79. package/dist/server/node-outcome.d.ts.map +1 -1
  80. package/dist/server/node-outcome.js +10 -3
  81. package/dist/server/node-outcome.js.map +1 -1
  82. package/dist/server/plugin.d.ts +66 -7
  83. package/dist/server/plugin.d.ts.map +1 -1
  84. package/dist/server/plugin.js +14 -10
  85. package/dist/server/plugin.js.map +1 -1
  86. package/dist/server/proto-guard.d.ts +30 -0
  87. package/dist/server/proto-guard.d.ts.map +1 -0
  88. package/dist/server/proto-guard.js +116 -0
  89. package/dist/server/proto-guard.js.map +1 -0
  90. package/dist/server/registry.d.ts +6 -2
  91. package/dist/server/registry.d.ts.map +1 -1
  92. package/dist/server/request-context.d.ts +24 -6
  93. package/dist/server/request-context.d.ts.map +1 -1
  94. package/dist/server/request-context.js +157 -30
  95. package/dist/server/request-context.js.map +1 -1
  96. package/dist/server/respond.d.ts +2 -2
  97. package/dist/server/respond.d.ts.map +1 -1
  98. package/dist/server/respond.js +34 -8
  99. package/dist/server/respond.js.map +1 -1
  100. package/dist/server/response-contract-lane.d.ts +1 -1
  101. package/dist/server/response-contract-lane.d.ts.map +1 -1
  102. package/dist/server/response-contract-lane.js +45 -13
  103. package/dist/server/response-contract-lane.js.map +1 -1
  104. package/dist/server/response-hooks.d.ts +10 -0
  105. package/dist/server/response-hooks.d.ts.map +1 -0
  106. package/dist/server/response-hooks.js +52 -0
  107. package/dist/server/response-hooks.js.map +1 -0
  108. package/dist/server/runtime-core.d.ts +12 -0
  109. package/dist/server/runtime-core.d.ts.map +1 -1
  110. package/dist/server/runtime-core.js +8 -0
  111. package/dist/server/runtime-core.js.map +1 -1
  112. package/dist/server/server-types.d.ts +60 -6
  113. package/dist/server/server-types.d.ts.map +1 -1
  114. package/dist/server/server.d.ts +80 -23
  115. package/dist/server/server.d.ts.map +1 -1
  116. package/dist/server/server.js +424 -213
  117. package/dist/server/server.js.map +1 -1
  118. package/dist/server/static-headers.d.ts +14 -3
  119. package/dist/server/static-headers.d.ts.map +1 -1
  120. package/dist/server/static-headers.js +28 -6
  121. package/dist/server/static-headers.js.map +1 -1
  122. package/dist/server/transport-lane.d.ts +8 -0
  123. package/dist/server/transport-lane.d.ts.map +1 -1
  124. package/dist/server/transport-lane.js +12 -8
  125. package/dist/server/transport-lane.js.map +1 -1
  126. package/dist/server/websocket.d.ts +3 -0
  127. package/dist/server/websocket.d.ts.map +1 -1
  128. package/dist/server/websocket.js +14 -0
  129. package/dist/server/websocket.js.map +1 -1
  130. package/dist/server.d.ts +2 -2
  131. package/dist/server.d.ts.map +1 -1
  132. package/dist/server.js +2 -2
  133. package/dist/server.js.map +1 -1
  134. package/dist/tool-catalog.d.ts +21 -0
  135. package/dist/tool-catalog.d.ts.map +1 -0
  136. package/dist/tool-catalog.js +16 -0
  137. package/dist/tool-catalog.js.map +1 -0
  138. package/dist/tool-contract.d.ts +238 -0
  139. package/dist/tool-contract.d.ts.map +1 -0
  140. package/dist/tool-contract.js +569 -0
  141. package/dist/tool-contract.js.map +1 -0
  142. package/package.json +26 -1
  143. package/src/assurance.ts +236 -6
  144. package/src/capabilities.ts +14 -1
  145. package/src/diff.ts +5 -2
  146. package/src/errors.ts +1 -0
  147. package/src/evidence.ts +319 -0
  148. package/src/execution-policy.ts +57 -0
  149. package/src/index.ts +1 -1
  150. package/src/internal/route-assurance.ts +67 -4
  151. package/src/internal/route-execution.ts +276 -1
  152. package/src/manifest.ts +27 -5
  153. package/src/reflection.ts +24 -4
  154. package/src/replay.ts +96 -0
  155. package/src/schema/standard.ts +16 -0
  156. package/src/server/body.ts +275 -7
  157. package/src/server/context.ts +23 -3
  158. package/src/server/contract.ts +43 -3
  159. package/src/server/cookies.ts +80 -10
  160. package/src/server/edge.ts +10 -0
  161. package/src/server/header-case.ts +54 -0
  162. package/src/server/headers.ts +11 -0
  163. package/src/server/node-outcome-hook.ts +6 -11
  164. package/src/server/node-outcome.ts +10 -2
  165. package/src/server/plugin.ts +87 -8
  166. package/src/server/proto-guard.ts +118 -0
  167. package/src/server/registry.ts +6 -2
  168. package/src/server/request-context.ts +242 -26
  169. package/src/server/respond.ts +35 -4
  170. package/src/server/response-contract-lane.ts +6 -17
  171. package/src/server/response-hooks.ts +51 -0
  172. package/src/server/runtime-core.ts +14 -0
  173. package/src/server/server-types.ts +66 -6
  174. package/src/server/server.ts +667 -287
  175. package/src/server/static-headers.ts +27 -3
  176. package/src/server/transport-lane.ts +19 -8
  177. package/src/server/websocket.ts +18 -2
  178. package/src/server.ts +7 -0
  179. package/src/tool-catalog.ts +40 -0
  180. package/src/tool-contract.ts +896 -0
@@ -3,7 +3,8 @@
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 { AnyServer } from "./server.js";
6
+ import type { Registry } from "./registry.js";
7
+ import type { AnyServer, Server } from "./server.js";
7
8
  /**
8
9
  * A nifra **plugin**: a function that augments an app - calling `use`/`derive`/`decorate` and/or
9
10
  * registering routes - and returns it. Because `derive`/`decorate` are type-threaded, an **inline**
@@ -23,22 +24,79 @@ export type NifraPlugin<In extends AnyServer = AnyServer, Out extends AnyServer
23
24
  export type IdentityPlugin = (<S extends AnyServer>(app: S) => S) & {
24
25
  readonly pluginName?: string;
25
26
  };
27
+ /**
28
+ * A named plugin built with {@link defineContextPlugin}: it adds the context `D` to every handler
29
+ * downstream while threading the caller's route registry and existing context UNCHANGED. This is the
30
+ * type {@link definePlugin} cannot express - `definePlugin` infers its parameter from an untyped
31
+ * `(app) => ...` arrow, which lands on `AnyServer`, so `use` returns `Server<any, any>`.
32
+ */
33
+ export type ContextPlugin<D extends object> = (<R extends Registry, Ctx>(app: Server<R, Ctx>) => Server<R, Ctx & D>) & {
34
+ readonly pluginName?: string;
35
+ };
36
+ /**
37
+ * Define a named plugin that **adds typed context and nothing else** - the `derive` case - without
38
+ * collapsing the caller's types. `use` instantiates the generic signature against the concrete
39
+ * receiver, so `R` and `Ctx` come back unchanged with `D` intersected onto the context.
40
+ *
41
+ * Use this instead of {@link definePlugin} for every `(app) => app.derive(...)` plugin. `definePlugin`
42
+ * is only safe when the caller supplies `In`/`Out` explicitly; with the usual untyped arrow both
43
+ * default to `AnyServer` and the typed client silently collapses to `any`.
44
+ *
45
+ * ```ts
46
+ * export const requestId = defineContextPlugin<{ requestId: string }>("requestId", (app) =>
47
+ * app.derive(() => ({ requestId: crypto.randomUUID() })),
48
+ * )
49
+ * const api = server().get("/a", h).use(requestId).get("/b", h) // /a AND /b stay typed; c.requestId typed
50
+ * ```
51
+ */
52
+ export declare function defineContextPlugin<D extends object>(name: string, apply: <R extends Registry, Ctx>(app: Server<R, Ctx>) => Server<R, Ctx & D>): ContextPlugin<D>;
53
+ declare const COLLAPSED: unique symbol;
54
+ /**
55
+ * What {@link definePlugin} returns when its `apply` argument never pinned the input server type -
56
+ * the `definePlugin("x", (app) => ...)` arrow, where `app` falls back to `AnyServer`.
57
+ *
58
+ * It is deliberately **not callable**, so `app.use(thatPlugin)` is a type error at the call site
59
+ * instead of a silent widening to `Server<any, any>` that surfaces hundreds of lines away as
60
+ * `Property 'x' does not exist on type 'Promise<Result<unknown, unknown>>'` in the typed client.
61
+ *
62
+ * The plugin still works at runtime. To fix the type, pick the definer that matches what it does:
63
+ *
64
+ * - adds context via `derive`/`decorate` -> {@link defineContextPlugin}
65
+ * - mounts routes/hooks and adds NO context -> {@link defineRouterPlugin} ({@link defineIdentityPlugin})
66
+ * - genuinely needs `definePlugin`: annotate the parameter (`(app: typeof api) => ...`) or pass
67
+ * explicit type arguments (`definePlugin<typeof api, typeof api>(...)`).
68
+ */
69
+ export interface PluginTypeCollapsed {
70
+ readonly [COLLAPSED]: "definePlugin erased the caller's server type: use defineContextPlugin (adds context) or defineRouterPlugin (routes/hooks only), or pin the input type";
71
+ }
72
+ /**
73
+ * True when `S`'s route registry is `any` - i.e. nothing pinned the plugin's input server type, so
74
+ * every route type flowing through it is about to be widened away.
75
+ */
76
+ type ServerTypeUnpinned<S> = [S] extends [Server<infer R, any>] ? 0 extends 1 & R ? true : false : false;
77
+ export type DefinePluginResult<In extends AnyServer, Out extends AnyServer> = ServerTypeUnpinned<In> extends true ? PluginTypeCollapsed : NifraPlugin<In, Out>;
26
78
  /**
27
79
  * Name + ergonomics for a plugin that **adds typed context** (`derive`/`decorate`). `app.use(myPlugin)`
28
80
  * applies it once; a second `use` of the same name is skipped (idempotent), so plugins can depend on each
29
81
  * other without double-registering hooks.
30
82
  *
31
83
  * ```ts
32
- * export const requestId = definePlugin("requestId", (app) => app.derive(() => ({ requestId: uuid() })))
84
+ * export const requestId = definePlugin("requestId", (app: typeof api) =>
85
+ * app.derive(() => ({ requestId: uuid() })),
86
+ * )
33
87
  * app.use(requestId) // downstream handlers see c.requestId
34
88
  * ```
35
89
  *
36
- * FOOTGUN: only use this for a plugin that adds context. For a plugin that **mounts routes/hooks but adds
37
- * NO context** (an auth router, an audit logger), use {@link defineRouterPlugin} ({@link defineIdentityPlugin}).
38
- * `definePlugin((app) => app.get(...))` infers `app: Server<any, any>`, so `.use()` returns `Server<any, any>`
39
- * and your whole typed client silently collapses to `any` - no type error, no runtime error.
90
+ * This helper only threads types when the caller pins the input server type - by annotating the
91
+ * parameter as above, or with explicit type arguments. With a bare `(app) => ...` arrow `app` infers as
92
+ * `AnyServer`, which would widen the caller's whole route registry to `any`; that case now returns
93
+ * {@link PluginTypeCollapsed}, so `.use()` fails to compile with one error at the call site rather than
94
+ * producing a typed client full of `any`. Prefer a definer that cannot collapse at all:
95
+ *
96
+ * - adds context via `derive`/`decorate` -> {@link defineContextPlugin}
97
+ * - mounts routes/hooks and adds NO context -> {@link defineRouterPlugin} ({@link defineIdentityPlugin})
40
98
  */
41
- export declare function definePlugin<In extends AnyServer, Out extends AnyServer>(name: string, apply: (app: In) => Out): NifraPlugin<In, Out>;
99
+ export declare function definePlugin<In extends AnyServer, Out extends AnyServer>(name: string, apply: (app: In) => Out): DefinePluginResult<In, Out>;
42
100
  /**
43
101
  * Define a type-**identity** plugin: it registers routes/hooks as a side effect but returns the app with
44
102
  * its `Registry` + `Context` UNCHANGED. Use this (not {@link definePlugin}) for any plugin that doesn't
@@ -75,4 +133,5 @@ export declare function defineIdentityPlugin(name: string, apply: <S extends Any
75
133
  * ```
76
134
  */
77
135
  export declare const defineRouterPlugin: typeof defineIdentityPlugin;
136
+ export {};
78
137
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/server/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CAAC,EAAE,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,SAAS,SAAS,GAAG,EAAE,IAAI,CAAC,CACvF,GAAG,EAAE,EAAE,KACJ,GAAG,CAAC,GAAG;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5C;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,SAAS,EACtE,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,GAAG,GACtB,WAAW,CAAC,EAAE,EAAE,GAAG,CAAC,CAEtB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GACxC,cAAc,CAEhB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB,EAAE,OAAO,oBAA2C,CAAA"}
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;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,CAAC,EAAE,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,SAAS,SAAS,GAAG,EAAE,IAAI,CAAC,CACvF,GAAG,EAAE,EAAE,KACJ,GAAG,CAAC,GAAG;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5C;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,QAAQ,EAAE,GAAG,EACrE,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,KAChB,MAAM,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,CAAC,SAAS,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAC1E,aAAa,CAAC,CAAC,CAAC,CAElB;AAED,OAAO,CAAC,MAAM,SAAS,EAAE,OAAO,MAAM,CAAA;AAEtC;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,CAAC,SAAS,CAAC,EAAE,uJAAuJ,CAAA;CAC9K;AAED;;;GAGG;AAEH,KAAK,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,GAC3D,CAAC,SAAS,CAAC,GAAG,CAAC,GACb,IAAI,GACJ,KAAK,GACP,KAAK,CAAA;AAET,MAAM,MAAM,kBAAkB,CAAC,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,SAAS,IACxE,kBAAkB,CAAC,EAAE,CAAC,SAAS,IAAI,GAAG,mBAAmB,GAAG,WAAW,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;AAElF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,SAAS,EACtE,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,GAAG,GACtB,kBAAkB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;AAQ9B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GACxC,cAAc,CAEhB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB,EAAE,OAAO,oBAA2C,CAAA"}
@@ -1,18 +1,22 @@
1
1
  /**
2
- * Name + ergonomics for a plugin that **adds typed context** (`derive`/`decorate`). `app.use(myPlugin)`
3
- * applies it once; a second `use` of the same name is skipped (idempotent), so plugins can depend on each
4
- * other without double-registering hooks.
2
+ * Define a named plugin that **adds typed context and nothing else** - the `derive` case - without
3
+ * collapsing the caller's types. `use` instantiates the generic signature against the concrete
4
+ * receiver, so `R` and `Ctx` come back unchanged with `D` intersected onto the context.
5
+ *
6
+ * Use this instead of {@link definePlugin} for every `(app) => app.derive(...)` plugin. `definePlugin`
7
+ * is only safe when the caller supplies `In`/`Out` explicitly; with the usual untyped arrow both
8
+ * default to `AnyServer` and the typed client silently collapses to `any`.
5
9
  *
6
10
  * ```ts
7
- * export const requestId = definePlugin("requestId", (app) => app.derive(() => ({ requestId: uuid() })))
8
- * app.use(requestId) // downstream handlers see c.requestId
11
+ * export const requestId = defineContextPlugin<{ requestId: string }>("requestId", (app) =>
12
+ * app.derive(() => ({ requestId: crypto.randomUUID() })),
13
+ * )
14
+ * const api = server().get("/a", h).use(requestId).get("/b", h) // /a AND /b stay typed; c.requestId typed
9
15
  * ```
10
- *
11
- * FOOTGUN: only use this for a plugin that adds context. For a plugin that **mounts routes/hooks but adds
12
- * NO context** (an auth router, an audit logger), use {@link defineRouterPlugin} ({@link defineIdentityPlugin}).
13
- * `definePlugin((app) => app.get(...))` infers `app: Server<any, any>`, so `.use()` returns `Server<any, any>`
14
- * and your whole typed client silently collapses to `any` - no type error, no runtime error.
15
16
  */
17
+ export function defineContextPlugin(name, apply) {
18
+ return Object.assign(apply, { pluginName: name });
19
+ }
16
20
  export function definePlugin(name, apply) {
17
21
  return Object.assign(apply, { pluginName: name });
18
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/server/plugin.ts"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,KAAuB;IAEvB,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAyB,CAAA;AAC3E,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,KAAyC;IAEzC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAmB,CAAA;AACrE,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgC,oBAAoB,CAAA"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/server/plugin.ts"],"names":[],"mappings":"AAuCA;;;;;;;;;;;;;;;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;AA8DD,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,EACZ,KAAyC;IAEzC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAmB,CAAA;AACrE,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgC,oBAAoB,CAAA"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Prototype-poisoning guard for the JSON body lane - the check behind `c.boundedJson` and the
3
+ * schema path. A single walk of the parsed value, never a reviver (a reviver taxes every key of
4
+ * every parse, including the parses that carry no object at all).
5
+ *
6
+ * No raw-text pre-scan: the Fastify-style `text.includes('"__proto__"')` filter is a pessimization
7
+ * on 2026 engines. A quoted-name search runs a general substring algorithm over the whole body,
8
+ * while the walk only touches the nodes the parse already built. Measured on Node 26 and Bun 1.3,
9
+ * three `includes()` calls cost 2-4x the walk on every body shape an API actually receives
10
+ * (records, strings, nested objects); the scan only wins on a body that is mostly a flat array of
11
+ * numbers, where it saves ~1.5us on a 9KB payload that spends 20us in `JSON.parse` regardless.
12
+ * Dropping the tier also removes an escape-analysis obligation - the scan had to route every `\u`
13
+ * to the walk, because `_` spells `_`.
14
+ */
15
+ export type ProtoPoisoning = "reject" | "strip" | "ignore";
16
+ /**
17
+ * `JSON.parse` + the poisoning policy. Returns the parsed value (stripped in place under
18
+ * `"strip"`); throws on invalid JSON or - via the same catch path - on a rejected poisoning, so
19
+ * a poisoned payload is indistinguishable from malformed JSON to the caller.
20
+ */
21
+ export declare function parseJsonGuarded(text: string, policy: ProtoPoisoning): unknown;
22
+ /**
23
+ * The policy applied to an already-parsed value - the native-`json()` lane, which never holds the
24
+ * raw text, and the transport codecs, which parse with their own decoder. Escapes are resolved by
25
+ * the time a key is an own property, so a `\u`-spelled `__proto__` and a literal one look identical
26
+ * here. Cost is one iterative pass over the value's object nodes; `"ignore"` skips even that.
27
+ * Throws the reject singleton; callers map it to their lane's flat error.
28
+ */
29
+ export declare function guardParsedValue(value: unknown, policy: ProtoPoisoning): unknown;
30
+ //# sourceMappingURL=proto-guard.d.ts.map
@@ -0,0 +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;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAGhF"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Prototype-poisoning guard for the JSON body lane - the check behind `c.boundedJson` and the
3
+ * schema path. A single walk of the parsed value, never a reviver (a reviver taxes every key of
4
+ * every parse, including the parses that carry no object at all).
5
+ *
6
+ * No raw-text pre-scan: the Fastify-style `text.includes('"__proto__"')` filter is a pessimization
7
+ * on 2026 engines. A quoted-name search runs a general substring algorithm over the whole body,
8
+ * while the walk only touches the nodes the parse already built. Measured on Node 26 and Bun 1.3,
9
+ * three `includes()` calls cost 2-4x the walk on every body shape an API actually receives
10
+ * (records, strings, nested objects); the scan only wins on a body that is mostly a flat array of
11
+ * numbers, where it saves ~1.5us on a 9KB payload that spends 20us in `JSON.parse` regardless.
12
+ * Dropping the tier also removes an escape-analysis obligation - the scan had to route every `\u`
13
+ * to the walk, because `_` spells `_`.
14
+ */
15
+ /** Thrown (as a reused singleton - never surfaced, always mapped to a flat 400) on `"reject"`. */
16
+ const POISONED = new Error("json_proto_poisoning");
17
+ /**
18
+ * `JSON.parse` + the poisoning policy. Returns the parsed value (stripped in place under
19
+ * `"strip"`); throws on invalid JSON or - via the same catch path - on a rejected poisoning, so
20
+ * a poisoned payload is indistinguishable from malformed JSON to the caller.
21
+ */
22
+ export function parseJsonGuarded(text, policy) {
23
+ return guardParsedValue(JSON.parse(text), policy);
24
+ }
25
+ /**
26
+ * The policy applied to an already-parsed value - the native-`json()` lane, which never holds the
27
+ * raw text, and the transport codecs, which parse with their own decoder. Escapes are resolved by
28
+ * the time a key is an own property, so a `\u`-spelled `__proto__` and a literal one look identical
29
+ * here. Cost is one iterative pass over the value's object nodes; `"ignore"` skips even that.
30
+ * Throws the reject singleton; callers map it to their lane's flat error.
31
+ */
32
+ export function guardParsedValue(value, policy) {
33
+ if (policy === "ignore")
34
+ return value;
35
+ return sweep(value, policy);
36
+ }
37
+ /**
38
+ * Iterative deep-walk (adversarial nesting must not blow the call stack). An own key
39
+ * `__proto__`, or an own `constructor` whose value carries an own `prototype`, is the poisoning
40
+ * shape - `JSON.parse` creates these as plain data properties, and the blast radius is whatever
41
+ * downstream merge/assign later copies them onto a real prototype. A string *value* of
42
+ * `"__proto__"` is legal data and never triggers.
43
+ */
44
+ /** Reused walk stack - `sweep` is synchronous and single-threaded, and a thrown rejection can
45
+ * leave residue, so each entry clears it. Saves one array allocation per swept request. */
46
+ const STACK = [];
47
+ function sweep(root, policy) {
48
+ if (root === null || typeof root !== "object")
49
+ return root;
50
+ const stack = STACK;
51
+ stack.length = 0;
52
+ stack.push(root);
53
+ while (stack.length > 0) {
54
+ const node = stack.pop();
55
+ if (Array.isArray(node)) {
56
+ // Only objects are stacked, here and below: a scalar carries no keys, so pushing it just to
57
+ // pop and type-test it is pure stack traffic. Filtering at the push site measured 1.5-3x
58
+ // faster on every body shape, both engines - the win grows with how scalar-heavy the body is.
59
+ //
60
+ // Indexed, not `for...of`: JSC allocates an array iterator per loop and calls `next()` per
61
+ // element, and it does not escape either. Measured on Bun 1.3 the iterator form costs 4x on
62
+ // an array of records, 8x on strings, and 12x on numbers - a 9KB numeric body walked in 27us
63
+ // instead of 2.2us, which at the 1MB default cap is milliseconds of CPU an attacker picks.
64
+ // V8 optimizes the iterator away, so on Node the two forms measure identical; the indexed
65
+ // loop is simply the form that is fast on both.
66
+ for (let i = 0; i < node.length; i++) {
67
+ const item = node[i];
68
+ if (item !== null && typeof item === "object")
69
+ stack.push(item);
70
+ }
71
+ continue;
72
+ }
73
+ const record = node;
74
+ // One pass, not two `Object.hasOwn` probes plus a walk: the suspect names are checked against
75
+ // the keys the walk already enumerates, so a clean node pays two pointer-comparisons per key
76
+ // instead of two hash lookups per node (measured ~30ns/request cheaper on a typical API body).
77
+ // `for-in`, not `Object.keys()`: the keys array would be an allocation per node (~2x the whole
78
+ // walk on measured bodies, both engines, at realistic widths; V8 only prefers `Object.keys` on
79
+ // 200+-property dictionary-mode objects). On JSON.parse output the two enumerate identically -
80
+ // own enumerable string keys, nothing enumerable on the prototype chain. A custom transport
81
+ // codec could hand `guardParsedValue` an object with enumerable INHERITED properties; `for-in`
82
+ // sweeps those too, which only over-sweeps - a poisoned inherited subtree rejects rather than
83
+ // slips through. A *non-enumerable* own `__proto__` is the one shape this misses, and it is
84
+ // not the poisoning shape: `JSON.parse` never produces one, and the merges that carry the
85
+ // payload onward (spread, `Object.assign`, key loops) copy enumerable own keys only.
86
+ for (const key in record) {
87
+ const value = record[key];
88
+ const nested = value !== null && typeof value === "object";
89
+ // Keep the hot clean-key check branch-local and cheap. JSON keys are strings, and the length
90
+ // + first-code-unit guards avoid a full string comparison for the overwhelming majority of
91
+ // fields while preserving exact equality for the two security-sensitive names.
92
+ if (key.length === 9 && key.charCodeAt(0) === 95 /* _ */ && key === "__proto__") {
93
+ if (policy === "reject")
94
+ throw POISONED;
95
+ // biome-ignore lint/complexity/useLiteralKeys: bracket access keeps the guarded key an explicit string, never a prototype walk
96
+ delete record["__proto__"];
97
+ continue;
98
+ }
99
+ if (key.length === 11 &&
100
+ key.charCodeAt(0) === 99 /* c */ &&
101
+ key === "constructor" &&
102
+ nested &&
103
+ Object.hasOwn(value, "prototype")) {
104
+ if (policy === "reject")
105
+ throw POISONED;
106
+ // biome-ignore lint/complexity/useLiteralKeys: bracket access keeps the guarded key an explicit string, never a prototype walk
107
+ delete record["constructor"];
108
+ continue;
109
+ }
110
+ if (nested)
111
+ stack.push(value);
112
+ }
113
+ }
114
+ return root;
115
+ }
116
+ //# sourceMappingURL=proto-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proto-guard.js","sourceRoot":"","sources":["../../src/server/proto-guard.ts"],"names":[],"mappings":"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"}
@@ -27,12 +27,16 @@ export interface RouteInfo {
27
27
  export type Registry = Record<string, Record<string, RouteInfo>>;
28
28
  /** The empty registry (no routes). `NonNullable<unknown>` is `{}` without tripping noBannedTypes. */
29
29
  export type EmptyRegistry = NonNullable<unknown>;
30
+ /** The client-visible request inputs use the schema's INPUT side: the registry describes what a
31
+ * caller must SEND over the wire (pre-validation), not what the handler receives after parsing. With
32
+ * a Zod `.default()`/transform the two differ - `InferOutput` would force the client to supply
33
+ * fields the schema fills in. (Same rule as the WS `in` channel below.) */
30
34
  type RegistryBody<S extends RouteSchema> = S extends {
31
35
  body: infer B extends StandardSchemaV1;
32
- } ? InferOutput<B> : never;
36
+ } ? InferInput<B> : never;
33
37
  type RegistryQuery<S extends RouteSchema> = S extends {
34
38
  query: infer Q extends StandardSchemaV1;
35
- } ? InferOutput<Q> : never;
39
+ } ? InferInput<Q> : never;
36
40
  /** The client-visible output: the declared `response` contract when present (so the client sees the
37
41
  * contract, not the handler's incidental return), otherwise the inferred handler output. */
38
42
  type RegistryOutput<S extends RouteSchema, Output> = S extends {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/server/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/server/registry.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import type { RequestBudget } from "../budget.js";
8
8
  import type { Platform } from "./context.js";
9
+ import { type ProtoPoisoning } from "./proto-guard.js";
9
10
  import { CONTEXT_SEARCH, CONTEXT_SET } from "./runtime-core.js";
10
11
  import type { CtxSet, RawContext, RequestSource } from "./server.js";
11
12
  export declare class RequestContext implements RawContext {
@@ -18,18 +19,20 @@ export declare class RequestContext implements RawContext {
18
19
  private setValue;
19
20
  private queryValue;
20
21
  private queryReady;
22
+ private headersValue;
21
23
  private cookiesValue;
22
24
  private readonly source;
23
25
  private readonly maxBodyBytes;
24
- constructor(source: RequestSource, params: Record<string, string>, maxBodyBytes: number);
25
- constructor(source: RequestSource, params: Record<string, string>, search: string | undefined, signal: AbortSignal, budget: RequestBudget, platform: Platform | undefined, maxBodyBytes: number);
26
+ private readonly protoPoisoning;
27
+ constructor(source: RequestSource, params: Record<string, string>, maxBodyBytes: number, protoPoisoning?: ProtoPoisoning);
28
+ constructor(source: RequestSource, params: Record<string, string>, search: string | undefined, signal: AbortSignal, budget: RequestBudget, platform: Platform | undefined, maxBodyBytes: number, protoPoisoning?: ProtoPoisoning);
26
29
  /**
27
30
  * The no-timeout context: `c.signal`/`c.budget` fall back to the never-abort signal and the
28
31
  * unbounded budget, which is exactly what the request would have been handed, so the two slots
29
32
  * are left unwritten instead of initialized. `search` carries the router's already-split query
30
33
  * string when it has one; `undefined` leaves `c.query` to re-scan the URL lazily.
31
34
  */
32
- static native(source: RequestSource, params: Record<string, string>, search: string | undefined, maxBodyBytes: number, platform?: Platform): RequestContext;
35
+ static native(source: RequestSource, params: Record<string, string>, search: string | undefined, maxBodyBytes: number, platform?: Platform, protoPoisoning?: ProtoPoisoning): RequestContext;
33
36
  [CONTEXT_SET](): CtxSet | undefined;
34
37
  get [CONTEXT_SEARCH](): string;
35
38
  get set(): CtxSet;
@@ -41,6 +44,8 @@ export declare class RequestContext implements RawContext {
41
44
  get req(): Request;
42
45
  get request(): Request;
43
46
  header(name: string): string | null;
47
+ get headers(): Record<string, string>;
48
+ set headers(value: Record<string, string>);
44
49
  json(body: unknown, init?: ResponseInit | number): Response;
45
50
  text(body: string, init?: ResponseInit | number): Response;
46
51
  get query(): unknown;
@@ -50,9 +55,22 @@ export declare class RequestContext implements RawContext {
50
55
  boundedJson<T = unknown>(maxBytes?: number): Promise<T>;
51
56
  }
52
57
  /**
53
- * Read a JSON body with the same byte cap used by schema validation and `c.boundedJson`.
54
- * Non-chunked, framed requests with an in-cap `Content-Length` use the runtime-native `req.json()`;
58
+ * Read a JSON body with the same byte cap used by schema validation and `c.boundedJson`, then
59
+ * parse it through the prototype-poisoning guard (`protoPoisoning`, default `"reject"` - a
60
+ * poisoned payload answers the same flat 400 as malformed JSON). Non-chunked, framed requests
61
+ * with an in-cap `Content-Length` take the runtime's fused `json()` and walk the parsed value;
55
62
  * chunked or length-less requests fall back to the streaming byte-cap guard.
56
63
  */
57
- export declare function readBoundedJsonSource(req: RequestSource, maxBytes: number): Promise<unknown | Response>;
64
+ /**
65
+ * Deliberately **not** `async`: the framed lane is the hot path for every JSON POST, and an async
66
+ * wrapper costs a coroutine frame, a wrapper promise, and an extra microtask hop on top of the one
67
+ * the body read already pays (~90ns/request on Node, measured). The lane returns the body read's
68
+ * own promise chain instead, and only the streaming fallback - which is already doing IO in a loop
69
+ * - runs as an async function. Callers that `await` the result are unaffected.
70
+ */
71
+ type JsonResultContinuation<T> = (result: unknown | Response) => T | Promise<T>;
72
+ type JsonErrorContinuation<T> = (error: unknown) => T | Promise<T>;
73
+ export declare function readBoundedJsonSource(req: RequestSource, maxBytes: number, protoPoisoning?: ProtoPoisoning): Promise<unknown | Response>;
74
+ export declare function readBoundedJsonSource<T>(req: RequestSource, maxBytes: number, protoPoisoning: ProtoPoisoning, onResult: JsonResultContinuation<T>, onError: JsonErrorContinuation<T>): Promise<T>;
75
+ export {};
58
76
  //# sourceMappingURL=request-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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"}