@nifrajs/core 1.13.0 → 2.1.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 (233) hide show
  1. package/README.md +37 -1
  2. package/dist/assurance.d.ts +11 -2
  3. package/dist/assurance.d.ts.map +1 -1
  4. package/dist/assurance.js +20 -0
  5. package/dist/assurance.js.map +1 -1
  6. package/dist/capabilities.d.ts +54 -2
  7. package/dist/capabilities.d.ts.map +1 -1
  8. package/dist/capabilities.js +240 -5
  9. package/dist/capabilities.js.map +1 -1
  10. package/dist/durable-adapters.d.ts +241 -0
  11. package/dist/durable-adapters.d.ts.map +1 -0
  12. package/dist/durable-adapters.js +697 -0
  13. package/dist/durable-adapters.js.map +1 -0
  14. package/dist/durable-execution.d.ts +349 -0
  15. package/dist/durable-execution.d.ts.map +1 -0
  16. package/dist/durable-execution.js +1173 -0
  17. package/dist/durable-execution.js.map +1 -0
  18. package/dist/effect-ledger.d.ts +9 -0
  19. package/dist/effect-ledger.d.ts.map +1 -0
  20. package/dist/effect-ledger.js +8 -0
  21. package/dist/effect-ledger.js.map +1 -0
  22. package/dist/effect-lifecycle.d.ts +42 -0
  23. package/dist/effect-lifecycle.d.ts.map +1 -0
  24. package/dist/effect-lifecycle.js +66 -0
  25. package/dist/effect-lifecycle.js.map +1 -0
  26. package/dist/effect-scope.d.ts +75 -0
  27. package/dist/effect-scope.d.ts.map +1 -0
  28. package/dist/effect-scope.js +177 -0
  29. package/dist/effect-scope.js.map +1 -0
  30. package/dist/idempotency-plugin.d.ts +13 -0
  31. package/dist/idempotency-plugin.d.ts.map +1 -0
  32. package/dist/idempotency-plugin.js +16 -0
  33. package/dist/idempotency-plugin.js.map +1 -0
  34. package/dist/index.d.ts +6 -35
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +6 -31
  37. package/dist/index.js.map +1 -1
  38. package/dist/internal/capability-runtime.d.ts +62 -1
  39. package/dist/internal/capability-runtime.d.ts.map +1 -1
  40. package/dist/internal/capability-runtime.js +11 -2
  41. package/dist/internal/capability-runtime.js.map +1 -1
  42. package/dist/internal/effect-execution.d.ts +16 -0
  43. package/dist/internal/effect-execution.d.ts.map +1 -0
  44. package/dist/internal/effect-execution.js +50 -0
  45. package/dist/internal/effect-execution.js.map +1 -0
  46. package/dist/internal/safe-equal.d.ts +20 -0
  47. package/dist/internal/safe-equal.d.ts.map +1 -0
  48. package/dist/internal/safe-equal.js +31 -0
  49. package/dist/internal/safe-equal.js.map +1 -0
  50. package/dist/ledger.d.ts +14 -6
  51. package/dist/ledger.d.ts.map +1 -1
  52. package/dist/ledger.js +31 -5
  53. package/dist/ledger.js.map +1 -1
  54. package/dist/mcp.d.ts +7 -0
  55. package/dist/mcp.d.ts.map +1 -0
  56. package/dist/mcp.js +56 -0
  57. package/dist/mcp.js.map +1 -0
  58. package/dist/node-direct.d.ts +5 -0
  59. package/dist/node-direct.d.ts.map +1 -0
  60. package/dist/node-direct.js +27 -0
  61. package/dist/node-direct.js.map +1 -0
  62. package/dist/reconciliation-worker.d.ts +108 -0
  63. package/dist/reconciliation-worker.d.ts.map +1 -0
  64. package/dist/reconciliation-worker.js +239 -0
  65. package/dist/reconciliation-worker.js.map +1 -0
  66. package/dist/reflection.d.ts +5 -0
  67. package/dist/reflection.d.ts.map +1 -1
  68. package/dist/reflection.js +2 -0
  69. package/dist/reflection.js.map +1 -1
  70. package/dist/server/client-ip.d.ts +35 -0
  71. package/dist/server/client-ip.d.ts.map +1 -0
  72. package/dist/server/client-ip.js +42 -0
  73. package/dist/server/client-ip.js.map +1 -0
  74. package/dist/server/context.d.ts +47 -2
  75. package/dist/server/context.d.ts.map +1 -1
  76. package/dist/server/contract.d.ts +14 -4
  77. package/dist/server/contract.d.ts.map +1 -1
  78. package/dist/server/contract.js +8 -2
  79. package/dist/server/contract.js.map +1 -1
  80. package/dist/server/http.d.ts +14 -0
  81. package/dist/server/http.d.ts.map +1 -0
  82. package/dist/server/http.js +45 -0
  83. package/dist/server/http.js.map +1 -0
  84. package/dist/server/idempotency-lane.d.ts +45 -0
  85. package/dist/server/idempotency-lane.d.ts.map +1 -0
  86. package/dist/server/idempotency-lane.js +205 -0
  87. package/dist/server/idempotency-lane.js.map +1 -0
  88. package/dist/server/install.d.ts +21 -0
  89. package/dist/server/install.d.ts.map +1 -0
  90. package/dist/server/install.js +21 -0
  91. package/dist/server/install.js.map +1 -0
  92. package/dist/server/ledger-lane.d.ts +53 -0
  93. package/dist/server/ledger-lane.d.ts.map +1 -0
  94. package/dist/server/ledger-lane.js +82 -0
  95. package/dist/server/ledger-lane.js.map +1 -0
  96. package/dist/server/mcp-hook.d.ts +28 -0
  97. package/dist/server/mcp-hook.d.ts.map +1 -0
  98. package/dist/server/mcp-hook.js +2 -0
  99. package/dist/server/mcp-hook.js.map +1 -0
  100. package/dist/server/node-outcome-hook.d.ts +9 -0
  101. package/dist/server/node-outcome-hook.d.ts.map +1 -0
  102. package/dist/server/node-outcome-hook.js +2 -0
  103. package/dist/server/node-outcome-hook.js.map +1 -0
  104. package/dist/server/node-outcome.d.ts +37 -0
  105. package/dist/server/node-outcome.d.ts.map +1 -0
  106. package/dist/server/node-outcome.js +75 -0
  107. package/dist/server/node-outcome.js.map +1 -0
  108. package/dist/server/plugin.d.ts +78 -0
  109. package/dist/server/plugin.d.ts.map +1 -0
  110. package/dist/server/plugin.js +57 -0
  111. package/dist/server/plugin.js.map +1 -0
  112. package/dist/server/query.d.ts +18 -0
  113. package/dist/server/query.d.ts.map +1 -0
  114. package/dist/server/query.js +102 -0
  115. package/dist/server/query.js.map +1 -0
  116. package/dist/server/registry.d.ts +31 -6
  117. package/dist/server/registry.d.ts.map +1 -1
  118. package/dist/server/request-context.d.ts +51 -0
  119. package/dist/server/request-context.d.ts.map +1 -0
  120. package/dist/server/request-context.js +184 -0
  121. package/dist/server/request-context.js.map +1 -0
  122. package/dist/server/respond.d.ts +17 -0
  123. package/dist/server/respond.d.ts.map +1 -0
  124. package/dist/server/respond.js +81 -0
  125. package/dist/server/respond.js.map +1 -0
  126. package/dist/server/runtime-core.d.ts +36 -0
  127. package/dist/server/runtime-core.d.ts.map +1 -0
  128. package/dist/server/runtime-core.js +51 -0
  129. package/dist/server/runtime-core.js.map +1 -0
  130. package/dist/server/server-types.d.ts +203 -0
  131. package/dist/server/server-types.d.ts.map +1 -0
  132. package/dist/server/server-types.js +2 -0
  133. package/dist/server/server-types.js.map +1 -0
  134. package/dist/server/server.d.ts +119 -345
  135. package/dist/server/server.d.ts.map +1 -1
  136. package/dist/server/server.js +247 -833
  137. package/dist/server/server.js.map +1 -1
  138. package/dist/server/sse-hook.d.ts +10 -0
  139. package/dist/server/sse-hook.d.ts.map +1 -0
  140. package/dist/server/sse-hook.js +2 -0
  141. package/dist/server/sse-hook.js.map +1 -0
  142. package/dist/server/sse.d.ts +7 -23
  143. package/dist/server/sse.d.ts.map +1 -1
  144. package/dist/server/sse.js +18 -0
  145. package/dist/server/sse.js.map +1 -1
  146. package/dist/server/transport-lane.d.ts +28 -0
  147. package/dist/server/transport-lane.d.ts.map +1 -0
  148. package/dist/server/transport-lane.js +106 -0
  149. package/dist/server/transport-lane.js.map +1 -0
  150. package/dist/server/websocket.d.ts +23 -1
  151. package/dist/server/websocket.d.ts.map +1 -1
  152. package/dist/server/websocket.js +10 -1
  153. package/dist/server/websocket.js.map +1 -1
  154. package/dist/server/ws-hook.d.ts +8 -11
  155. package/dist/server/ws-hook.d.ts.map +1 -1
  156. package/dist/server/ws-hook.js +7 -14
  157. package/dist/server/ws-hook.js.map +1 -1
  158. package/dist/server.d.ts +21 -0
  159. package/dist/server.d.ts.map +1 -0
  160. package/dist/server.js +16 -0
  161. package/dist/server.js.map +1 -0
  162. package/dist/transport-codec-rich.d.ts +8 -0
  163. package/dist/transport-codec-rich.d.ts.map +1 -0
  164. package/dist/transport-codec-rich.js +14 -0
  165. package/dist/transport-codec-rich.js.map +1 -0
  166. package/dist/transport-codec.d.ts +31 -0
  167. package/dist/transport-codec.d.ts.map +1 -0
  168. package/dist/transport-codec.js +190 -0
  169. package/dist/transport-codec.js.map +1 -0
  170. package/dist/transport-plugin.d.ts +3 -0
  171. package/dist/transport-plugin.d.ts.map +1 -0
  172. package/dist/transport-plugin.js +3 -0
  173. package/dist/transport-plugin.js.map +1 -0
  174. package/dist/wire.d.ts +58 -0
  175. package/dist/wire.d.ts.map +1 -0
  176. package/dist/wire.js +445 -0
  177. package/dist/wire.js.map +1 -0
  178. package/dist/ws.d.ts +16 -7
  179. package/dist/ws.d.ts.map +1 -1
  180. package/dist/ws.js +25 -10
  181. package/dist/ws.js.map +1 -1
  182. package/package.json +122 -6
  183. package/src/assurance.ts +36 -1
  184. package/src/capabilities.ts +306 -5
  185. package/src/durable-adapters.ts +1039 -0
  186. package/src/durable-execution.ts +1676 -0
  187. package/src/effect-ledger.ts +9 -0
  188. package/src/effect-lifecycle.ts +120 -0
  189. package/src/effect-scope.ts +267 -0
  190. package/src/idempotency-plugin.ts +17 -0
  191. package/src/index.ts +6 -133
  192. package/src/internal/capability-runtime.ts +87 -1
  193. package/src/internal/effect-execution.ts +70 -0
  194. package/src/internal/safe-equal.ts +27 -0
  195. package/src/ledger.ts +45 -11
  196. package/src/mcp.ts +65 -0
  197. package/src/node-direct.ts +37 -0
  198. package/src/reconciliation-worker.ts +372 -0
  199. package/src/reflection.ts +7 -0
  200. package/src/server/client-ip.ts +60 -0
  201. package/src/server/context.ts +50 -2
  202. package/src/server/contract.ts +26 -7
  203. package/src/server/http.ts +58 -0
  204. package/src/server/idempotency-lane.ts +321 -0
  205. package/src/server/install.ts +28 -0
  206. package/src/server/ledger-lane.ts +125 -0
  207. package/src/server/mcp-hook.ts +41 -0
  208. package/src/server/node-outcome-hook.ts +9 -0
  209. package/src/server/node-outcome.ts +112 -0
  210. package/src/server/plugin.ts +92 -0
  211. package/src/server/query.ts +119 -0
  212. package/src/server/registry.ts +36 -6
  213. package/src/server/request-context.ts +271 -0
  214. package/src/server/respond.ts +94 -0
  215. package/src/server/runtime-core.ts +74 -0
  216. package/src/server/server-types.ts +204 -0
  217. package/src/server/server.ts +448 -1314
  218. package/src/server/sse-hook.ts +14 -0
  219. package/src/server/sse.ts +26 -0
  220. package/src/server/transport-lane.ts +141 -0
  221. package/src/server/websocket.ts +35 -1
  222. package/src/server/ws-hook.ts +8 -19
  223. package/src/server.ts +92 -0
  224. package/src/transport-codec-rich.ts +20 -0
  225. package/src/transport-codec.ts +250 -0
  226. package/src/transport-plugin.ts +2 -0
  227. package/src/wire.ts +474 -0
  228. package/src/ws.ts +33 -10
  229. package/dist/invariants.d.ts +0 -70
  230. package/dist/invariants.d.ts.map +0 -1
  231. package/dist/invariants.js +0 -487
  232. package/dist/invariants.js.map +0 -1
  233. package/src/invariants.ts +0 -604
@@ -1,15 +1,26 @@
1
- import { type IdempotencyStore } from "../idempotency.js";
2
- import { type CapabilityUseEvent } from "../internal/capability-runtime.js";
3
- import { type AssuranceEvidence } from "../internal/route-assurance.js";
4
- import { type EffectLedgerOptions } from "../ledger.js";
1
+ import { type RequestBudget } from "../budget.js";
2
+ import type { EffectLifecycleObserver } from "../effect-lifecycle.js";
3
+ import { type AroundCapabilityOptions, type CapabilityInterceptor } from "../internal/capability-runtime.js";
5
4
  import { type Method } from "../router/router.js";
6
5
  import type { InferOutput, StandardSchemaV1 } from "../schema/standard.js";
7
- import type { Context, Platform, RouteSchema } from "./context.js";
8
- import { type Logger } from "./logger.js";
9
- import type { AddRoute, EmptyRegistry, OutputOf, Registry, RouteInfoFor } from "./registry.js";
10
- import { type SSEInit, type TypedSSEStream } from "./sse.js";
6
+ import type { Context, Platform, ResponseControls, RouteSchema } from "./context.js";
7
+ import type { NodeServeOutcome } from "./node-outcome.js";
8
+ import type { NodeOutcomeRuntime } from "./node-outcome-hook.js";
9
+ import { type QueryValue, queryObjectOf, searchOf } from "./query.js";
10
+ import { CONTEXT_SEARCH, CONTEXT_SET, type HandlerResult } from "./runtime-core.js";
11
+ export type { NodeServeOutcome };
12
+ import type { IdempotencyRuntime } from "./idempotency-lane.js";
13
+ import { INSTALL_EFFECT_LEDGER, INSTALL_IDEMPOTENCY, INSTALL_MCP, INSTALL_NODE_DIRECT, INSTALL_SSE, INSTALL_WS } from "./install.js";
14
+ import type { EffectLedgerRuntime } from "./ledger-lane.js";
15
+ import type { McpRuntime } from "./mcp-hook.js";
16
+ import type { IdentityPlugin } from "./plugin.js";
17
+ import type { AddRoute, EmptyRegistry, OutputOf, Registry, RouteInfoFor, WsRouteInfoFor } from "./registry.js";
18
+ import type { AdmissionController, AdmissionDecision, McpPromptDescriptor, McpResourceDescriptor, Middleware, PromptArgument, PromptMessage, ResponseFinalization, RouteDescriptor, RunningServer, ServerOptions, ToolAnnotations } from "./server-types.js";
19
+ import type { SSEInit, TypedSSEStream } from "./sse.js";
20
+ import type { SseRuntime } from "./sse-hook.js";
11
21
  import type { WebSocketHandler, WebSocketUpgradeOutcome } from "./websocket.js";
12
- type MaybePromise<T> = T | Promise<T>;
22
+ import type { WsRuntime } from "./ws-hook.js";
23
+ export type MaybePromise<T> = T | Promise<T>;
13
24
  /**
14
25
  * Internal request view. A real Web `Request` already satisfies this shape, so Web/edge runtimes pass
15
26
  * their `Request` **directly** (zero wrapper allocation on the hot path — `request` is simply absent and
@@ -39,8 +50,27 @@ type EmptyContext = NonNullable<unknown>;
39
50
  type EnvOf<Ctx> = Ctx extends {
40
51
  readonly env: infer E;
41
52
  } ? E : unknown;
42
- /** A handler returns a `Response` (used as-is) or any value (serialized to JSON). */
43
- type HandlerResult = Response | unknown;
53
+ /** Internal, path-erased runtime context. The typed `Context<Path, S>` is a structural view of this. */
54
+ export interface RawContext {
55
+ readonly req: Request;
56
+ readonly request: Request;
57
+ readonly json: (body: unknown, init?: ResponseInit | number) => Response;
58
+ readonly text: (body: string, init?: ResponseInit | number) => Response;
59
+ params: Record<string, string>;
60
+ query: unknown;
61
+ readonly cookies: Readonly<Record<string, string>>;
62
+ body: unknown;
63
+ readonly set: ResponseControls;
64
+ readonly [CONTEXT_SET]: () => CtxSet | undefined;
65
+ readonly [CONTEXT_SEARCH]: string;
66
+ readonly signal: AbortSignal;
67
+ readonly budget: RequestBudget;
68
+ readonly env: unknown;
69
+ readonly clientIp: string | undefined;
70
+ readonly waitUntil: (promise: Promise<unknown>) => void;
71
+ readonly boundedBody: (maxBytes?: number) => Promise<Uint8Array>;
72
+ readonly boundedJson: <T = unknown>(maxBytes?: number) => Promise<T>;
73
+ }
44
74
  export type OnRequestResult = Response | Request | undefined;
45
75
  /** The handler's permitted return type. When the route declares a `response` schema, the return is
46
76
  * constrained to the contract's type (or a raw `Response`) — so the implementation can't drift from the
@@ -53,312 +83,18 @@ type ResponseOf<S extends RouteSchema> = S extends {
53
83
  * any accumulated middleware context `Ctx` (from `derive`/`decorate`).
54
84
  */
55
85
  export type Handler<Path extends string, S extends RouteSchema = RouteSchema, Ctx = EmptyContext> = (ctx: Context<Path, S> & Ctx) => MaybePromise<ResponseOf<S>>;
56
- /**
57
- * The outcome of a capacity-admission decision. `admitted` requests carry a `release` the server calls
58
- * exactly once when the response is finalized; a shed request carries a ready `429` Response.
59
- */
60
- export type AdmissionDecision = {
61
- readonly admitted: true;
62
- release(): void;
63
- } | {
64
- readonly admitted: false;
65
- readonly response: Response;
66
- };
67
- /**
68
- * A capacity-admission gate. Decides, per request, whether the instance has capacity to run it now —
69
- * bounding *concurrency*, which rate limits (frequency) and deadlines (duration) do not. Provide an
70
- * implementation (see `@nifrajs/middleware`'s `createAdmissionController`) as {@link ServerOptions.admission}.
71
- *
72
- * Enabling it trades the fused native-route lane for native matching + this gate (the gate cannot be a
73
- * per-request `onRequest` hook without disabling native routes entirely); when unset, the request path
74
- * is untouched.
75
- */
76
- export interface AdmissionController {
77
- admit(req: Request): AdmissionDecision | Promise<AdmissionDecision>;
78
- }
79
- export interface ServerOptions {
80
- /**
81
- * Max request body size (bytes), enforced **only when a route declares a body schema** — the cap
82
- * lives in the schema-validated read path. Default 1_000_000.
83
- *
84
- * A route WITHOUT a body schema (raw body, file upload, BYO-validation) that reads `c.req` directly
85
- * is not auto-bounded — use **`c.boundedBody(maxBytes?)`** / **`c.boundedJson(maxBytes?)`**, which
86
- * apply this same cap (override per route by passing `maxBytes` — larger for an upload endpoint,
87
- * smaller to tighten one).
88
- */
89
- readonly maxBodyBytes?: number;
90
- /** Max inbound WebSocket message size (bytes) when `listen()`ing on Bun — frames over this are rejected
91
- * by the runtime before reaching your handler (so a huge frame can't be JSON-parsed into memory).
92
- * Default: `maxBodyBytes` (1 MB). */
93
- readonly wsMaxPayloadBytes?: number;
94
- /** Per-request timeout (ms): a slower request gets a 503 and `ctx.signal` aborts. 0 disables (default). */
95
- readonly requestTimeoutMs?: number;
96
- /**
97
- * Admit the public `x-nifra-deadline` header and let it shorten local work. Disabled by default:
98
- * services that participate in trusted cross-service deadline propagation opt in explicitly,
99
- * while ordinary/public HTTP routes pay no header-admission tax and ignore hostile client values.
100
- */
101
- readonly acceptInboundDeadlines?: boolean;
102
- /**
103
- * Maximum time accepted from an inbound `x-nifra-deadline`, in milliseconds. An incoming absolute
104
- * deadline may shorten this cap (and `requestTimeoutMs`, when configured), never extend it.
105
- * Default 30_000; applies only when `acceptInboundDeadlines` is enabled and the header is present.
106
- */
107
- readonly maxInboundDeadlineMs?: number;
108
- /** When `listen()`ing, install SIGTERM/SIGINT handlers that gracefully `stop()`. Default false. */
109
- readonly gracefulSignals?: boolean;
110
- /**
111
- * Capacity-admission gate (see {@link AdmissionController}). Bounds concurrent in-flight work so a
112
- * healthy instance sheds load (`429` + `Retry-After`) instead of accepting more than it can finish.
113
- * Off by default. Enabling it disables the fused native-route fast path (requests route through the
114
- * shared matched lane where the gate runs); when unset, the request path pays nothing.
115
- */
116
- readonly admission?: AdmissionController;
117
- /**
118
- * Optional token-only observation hook called by `useCapability(c, id)`. It receives no request,
119
- * parameters, body, tenant, or values. Routes without capability declarations keep the old hot path.
120
- */
121
- readonly onCapabilityUse?: (event: CapabilityUseEvent) => void;
122
- /**
123
- * Enable the per-request effect ledger. Each route that declares `schema.capabilities` gets a
124
- * bounded, token-only ledger; `useCapability(c, id, …)` appends one entry per effect, and the sink
125
- * receives the sealed ledger when the response settles (only when it recorded entries). Token-only
126
- * by construction — capability ids, phases, counters, digests; never payloads, values, or the
127
- * concrete URL (the route *pattern* is recorded). Enabling it moves capability-declaring routes off
128
- * the fused fast path (they need a per-request context + a settle step); all other routes are
129
- * unaffected, and when unset the request path pays nothing.
130
- */
131
- readonly effectLedger?: EffectLedgerOptions;
132
- /**
133
- * Default store backing routes that declare `schema.idempotency` without their own `store`. Defaults
134
- * to a shared in-process {@link MemoryIdempotencyStore} (created lazily on first idempotent route).
135
- * Inject a durable store here to make request-scoped dedupe survive restarts app-wide.
136
- */
137
- readonly idempotencyStore?: IdempotencyStore;
138
- /** Structured logger for framework events (redacts secrets). Default: JSON to stderr. */
139
- readonly logger?: Logger;
140
- /**
141
- * App-wide fallback fired when a route **without its own `onValidationError`** fails body/query
142
- * validation. Same contract as the per-route hook (`(issues, ctx, kind) => Response | repaired-value |
143
- * undefined`): a route's own hook takes precedence, and a route can fall through to the plain `422` by
144
- * returning `undefined`. Use it for one app-wide error envelope (like tRPC's `errorFormatter` /
145
- * Fastify's `setErrorHandler`) instead of repeating a formatter per route.
146
- */
147
- readonly onValidationError?: RouteSchema["onValidationError"];
148
- }
149
- /**
150
- * MCP tool safety hints, surfaced in `tools/list`, that tell an agent how risky a `.tool()` call is — so it
151
- * can decide whether to auto-invoke or confirm first. All optional; an omitted hint means "unknown". Mirrors
152
- * the MCP spec's tool `annotations`.
153
- */
154
- export interface ToolAnnotations {
155
- /** Human-readable display title for the tool, distinct from the machine `name`. */
156
- readonly title?: string;
157
- /** The tool does not modify its environment (a pure read). */
158
- readonly readOnlyHint?: boolean;
159
- /** The tool may perform destructive updates — only meaningful when `readOnlyHint` is not `true`. */
160
- readonly destructiveHint?: boolean;
161
- /** Repeated calls with the same arguments have no additional effect beyond the first. */
162
- readonly idempotentHint?: boolean;
163
- /** The tool interacts with external entities (an "open world" beyond this server). */
164
- readonly openWorldHint?: boolean;
165
- }
166
- /**
167
- * A registered route's public descriptor — method, path, and input schemas. The
168
- * router trie discards the original patterns, so this flat list is what lets tools
169
- * (e.g. `toOpenAPI`) enumerate routes after registration.
170
- */
171
- export interface RouteDescriptor {
172
- readonly method: Method;
173
- readonly path: string;
174
- readonly schema: RouteSchema | undefined;
175
- /** Effective enforcement evidence, populated only during reflection/introspection. */
176
- readonly assurance?: readonly AssuranceEvidence[];
177
- /** Normalized declared effect tokens, populated only when the route declares any. */
178
- readonly capabilities?: readonly string[];
179
- readonly tool?: {
180
- readonly name: string;
181
- readonly description: string;
182
- readonly annotations?: ToolAnnotations;
183
- };
184
- }
185
- /** A message in an MCP prompt's rendered output (see {@link Server.prompt}). */
186
- export interface PromptMessage {
187
- readonly role: "user" | "assistant";
188
- readonly content: {
189
- readonly type: "text";
190
- readonly text: string;
191
- };
192
- }
193
- /** One declared argument of an MCP prompt, surfaced in `prompts/list`. */
194
- export interface PromptArgument {
195
- readonly name: string;
196
- readonly description?: string;
197
- readonly required?: boolean;
198
- }
199
- /** An app-declared MCP resource — read-only data an agent can fetch through `nifra mcp`. */
200
- export interface McpResourceDescriptor {
201
- readonly uri: string;
202
- readonly name: string;
203
- readonly description?: string;
204
- readonly mimeType?: string;
205
- readonly read: () => MaybePromise<string | {
206
- readonly text: string;
207
- readonly mimeType?: string;
208
- }>;
209
- }
210
- /** An app-declared MCP prompt — a reusable prompt template an agent can fetch through `nifra mcp`. */
211
- export interface McpPromptDescriptor {
212
- readonly name: string;
213
- readonly description: string;
214
- readonly arguments?: readonly PromptArgument[];
215
- readonly handler: (args: Record<string, string>) => MaybePromise<readonly PromptMessage[]>;
216
- }
217
- /**
218
- * The handle `listen()` returns — the slice of Bun's server nifra holds and exposes.
219
- * Declared explicitly (rather than `ReturnType<typeof Bun.serve>`) so the public type
220
- * surface doesn't leak the ambient `Bun` global into consumers' `.d.ts` resolution.
221
- */
222
- export interface RunningServer {
223
- readonly port: number;
224
- readonly hostname: string;
225
- readonly pendingRequests: number;
226
- stop(closeActiveConnections?: boolean): void;
227
- }
228
- /**
229
- * A bundle of lifecycle hooks applied together via {@link Server.use} — the unit
230
- * `@nifrajs/middleware` ships (cors, security headers, rate-limit). Every hook is
231
- * optional and wired to its lifecycle point. Middleware is context-agnostic (sees
232
- * the base `Context`); `use` does no context-type merging — the full type-merging
233
- * plugin system is deferred, and `.use` is reserved as its future entry point.
234
- */
235
- export interface Middleware {
236
- readonly name?: string;
237
- readonly onRequest?: (req: Request, platform?: Platform) => MaybePromise<OnRequestResult>;
238
- readonly around?: <T>(context: Context, next: () => MaybePromise<T>) => MaybePromise<T>;
239
- readonly beforeHandle?: (context: Context) => MaybePromise<unknown>;
240
- readonly afterHandle?: (result: unknown, context: Context) => MaybePromise<unknown>;
241
- readonly onResponse?: (response: Response, req: Request) => MaybePromise<Response>;
242
- readonly onResponseFinalized?: (outcome: ResponseFinalization, req: Request) => MaybePromise<void>;
243
- readonly onError?: (error: unknown, context: Context) => MaybePromise<unknown>;
244
- }
245
- /** The terminal response-pipeline outcome observed after every transforming `onResponse` hook. */
246
- export interface ResponseFinalization {
247
- /** The final response, or the last response available when a transformation failed. */
248
- readonly response: Response;
249
- /** A response-hook failure. Terminal observers run fail-open before the error is rethrown. */
250
- readonly error?: unknown;
251
- }
86
+ export type { AdmissionController, AdmissionDecision, McpPromptDescriptor, McpResourceDescriptor, Middleware, PromptArgument, PromptMessage, ResponseFinalization, RouteDescriptor, RunningServer, ServerOptions, ToolAnnotations, };
252
87
  export type AnyServer = Server<any, any>;
253
- /**
254
- * A nifra **plugin**: a function that augments an app — calling `use`/`derive`/`decorate` and/or
255
- * registering routes — and returns it. Because `derive`/`decorate` are type-threaded, an **inline**
256
- * `app.use((a) => a.derive(...).decorate(...))` carries the added context to handlers defined after
257
- * it (the `use` overload is generic over the concrete `this`). Wrap with {@link definePlugin} to
258
- * attach a name for idempotent dedupe (applying the same named plugin twice — e.g. transitively — is
259
- * a no-op).
260
- */
261
- export type NifraPlugin<In extends AnyServer = AnyServer, Out extends AnyServer = In> = ((app: In) => Out) & {
262
- readonly pluginName?: string;
263
- };
264
- /**
265
- * A named type-identity plugin built with {@link defineIdentityPlugin}. It returns the same concrete
266
- * server type it receives, preserving the caller's typed registry and context across `.use()` while
267
- * still allowing the plugin to register runtime hooks or handlers.
268
- */
269
- export type IdentityPlugin = (<S extends AnyServer>(app: S) => S) & {
270
- readonly pluginName?: string;
271
- };
272
- /**
273
- * Name + ergonomics for a plugin that **adds typed context** (`derive`/`decorate`). `app.use(myPlugin)`
274
- * applies it once; a second `use` of the same name is skipped (idempotent), so plugins can depend on each
275
- * other without double-registering hooks.
276
- *
277
- * ```ts
278
- * export const requestId = definePlugin("requestId", (app) => app.derive(() => ({ requestId: uuid() })))
279
- * app.use(requestId) // downstream handlers see c.requestId
280
- * ```
281
- *
282
- * FOOTGUN: only use this for a plugin that adds context. For a plugin that **mounts routes/hooks but adds
283
- * NO context** (an auth router, an audit logger), use {@link defineRouterPlugin} ({@link defineIdentityPlugin}).
284
- * `definePlugin((app) => app.get(...))` infers `app: Server<any, any>`, so `.use()` returns `Server<any, any>`
285
- * and your whole typed client silently collapses to `any` — no type error, no runtime error.
286
- */
287
- export declare function definePlugin<In extends AnyServer, Out extends AnyServer>(name: string, apply: (app: In) => Out): NifraPlugin<In, Out>;
288
- /**
289
- * Define a type-**identity** plugin: it registers routes/hooks as a side effect but returns the app with
290
- * its `Registry` + `Context` UNCHANGED. Use this (not {@link definePlugin}) for any plugin that doesn't
291
- * add context types — e.g. one mounting an auth handler. It threads the caller's *concrete* server type
292
- * through `use`, so routes declared after `app.use(plugin)` keep their types.
293
- *
294
- * Why a dedicated helper: `definePlugin((app) => app)` infers `app: Server<any, any>`, so `use` returns
295
- * `Server<any, any>` and the whole typed client collapses to `any`. The explicit generic return type here
296
- * (which a plain `Object.assign` can't preserve) is what keeps `use` returning the precise server type.
297
- *
298
- * ```ts
299
- * export const audit = defineIdentityPlugin("audit", (app) => app.onResponse(logResponse))
300
- * const api = server().get("/a", h).use(audit).get("/b", h) // /a AND /b stay typed
301
- * ```
302
- */
303
- export declare function defineIdentityPlugin(name: string, apply: <S extends AnyServer>(app: S) => S): IdentityPlugin;
304
- /**
305
- * Alias of {@link defineIdentityPlugin} with a name that says what it's FOR: a plugin that **mounts
306
- * routes/hooks but adds no context type** (an auth router, an audit logger). Use this — not
307
- * {@link definePlugin} — for any such plugin, or the typed client silently collapses to `any`. The
308
- * "identity" in {@link defineIdentityPlugin} refers to the type-identity it preserves; `defineRouterPlugin`
309
- * is the same thing under a clearer name.
310
- *
311
- * Mount routes as a **side effect**, then return the app unchanged (registering via `.get`/`.post` would
312
- * change the type away from the identity `S`; the mounted routes run but aren't in the caller's typed
313
- * registry — that's the trade that keeps everything else typed):
314
- *
315
- * ```ts
316
- * export const scim = defineRouterPlugin("scim", (app) => {
317
- * app.get("/scim/v2/Users", listUsers) // side effect: mounted at runtime
318
- * return app // return S unchanged → routes added after .use(scim) stay typed
319
- * })
320
- * const api = server().get("/a", h).use(scim).get("/b", h) // /a AND /b stay typed
321
- * ```
322
- */
323
- export declare const defineRouterPlugin: typeof defineIdentityPlugin;
324
- interface UrlParts {
325
- readonly pathname: string;
326
- readonly search: string;
327
- }
328
- export declare function urlPartsOf(url: string): UrlParts;
329
- export declare function pathnameOf(url: string): string;
330
- export declare function searchOf(url: string): string;
331
- /** A query value: a single occurrence is a string; a repeated key promotes to a string[] so an
332
- * array query schema (`t.array(t.string())`) can validate `?tag=a&tag=b` — last-wins silently
333
- * dropped values before (audit 2026-06). Single-occurrence keys stay plain strings, so existing
334
- * `t.string()` schemas are untouched; a repeated key against a string schema now FAILS validation
335
- * (an explicit 400 beats silently picking one). */
336
- export type QueryValue = string | string[];
337
- export declare function queryObjectOf(search: string): Record<string, QueryValue>;
338
- /**
339
- * What {@link Server.resolveNode} returns: either a plain-data render the `@nifrajs/node` adapter writes
340
- * to the socket directly (`kind: "json"` — status + headers + cookies + a pre-stringified body, **no**
341
- * undici `Response` built or drained), a marked buffered response body (`kind: "body"` — e.g.
342
- * @nifrajs/web's non-deferred SSR HTML), or a `Response` (`kind: "response"`) for everything else
343
- * (redirects, 404/405/errors, unmarked or streaming bodies). Internal to the nifra↔node bridge.
344
- */
345
- export type NodeServeOutcome = {
346
- readonly kind: "response";
347
- readonly response: Response;
348
- } | {
349
- readonly kind: "json";
350
- readonly status: number;
351
- /** `c.set.headers` backing, or `undefined` when the handler never set a header. */
352
- readonly headers: Readonly<Record<string, string>> | undefined;
353
- /** Queued `Set-Cookie` lines, or `undefined`; the adapter emits one header line each. */
354
- readonly cookies: readonly string[] | undefined;
355
- /** The JSON body already stringified, or `null` for an empty (204) response. */
356
- readonly body: string | null;
357
- } | {
358
- readonly kind: "body";
359
- readonly status: number;
360
- readonly headers: Readonly<Record<string, string | readonly string[]>> | undefined;
361
- readonly body: string | Uint8Array;
88
+ export { defineIdentityPlugin, definePlugin, defineRouterPlugin, type NifraPlugin, } from "./plugin.js";
89
+ export type { IdentityPlugin };
90
+ export { pathnameOf, urlPartsOf } from "./http.js";
91
+ export { type QueryValue, queryObjectOf, searchOf };
92
+ /** `ctx.set` carrying the lazy backings (`_headers`, `_cookies`) so `toResponse` can skip allocating
93
+ * anything when no handler touched `c.set.*`. Server-internal. */
94
+ export type CtxSet = ResponseControls & {
95
+ _headers?: Record<string, string>;
96
+ /** Accumulated `Set-Cookie` values — a list, since a `Record` would collapse multiple cookies. */
97
+ _cookies?: string[];
362
98
  };
363
99
  /**
364
100
  * The inline server. Routes are chainable and fully type-inferred. `derive`/
@@ -380,6 +116,8 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
380
116
  private readonly maxBodyBytes;
381
117
  private readonly wsMaxPayloadBytes;
382
118
  private readonly requestTimeoutMs;
119
+ /** Opt-in caller-IP trust declaration; `undefined` = socket peer only, no forwarded header believed. */
120
+ private readonly clientIpTrust;
383
121
  private readonly acceptInboundDeadlines;
384
122
  private readonly maxInboundDeadlineMs;
385
123
  private readonly deadlineAdmissionOptions;
@@ -387,11 +125,22 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
387
125
  /** Capacity-admission gate; `undefined` = off (the request path pays nothing). */
388
126
  private readonly capacityGate;
389
127
  private readonly onCapabilityUse;
390
- /** Effect-ledger defaults pinned at construction; per-route `ledgered` copies add route identity. */
391
- private readonly effectLedger;
392
- /** App-wide idempotency store (explicit option, else a lazily-created in-process default). */
393
- private readonly configuredIdempotencyStore;
394
- private lazyIdempotencyStore;
128
+ private readonly capabilityInterceptors;
129
+ private readonly capabilityObservers;
130
+ /** The installed effect-ledger runtime (owns the sink + per-route resolution + settle), or
131
+ * `undefined` when the effect-ledger plugin is not installed. */
132
+ private effectLedgerRuntime;
133
+ /** The installed idempotency runtime (owns the app-wide default store + the dedupe lane), or
134
+ * `undefined` when the idempotency plugin is not installed. */
135
+ private idempotencyRuntime;
136
+ /** Installed opt-in runtime for `.tool()`/`.resource()`/`.prompt()`; `undefined` until `.use(mcp())`. */
137
+ private mcpRuntime;
138
+ /** Installed Node-direct renderer for direct `resolveNode()` callers; `undefined` until `.use(nodeDirect())`. */
139
+ private nodeOutcomeRuntime;
140
+ /** Installed streaming runtime for `.sse()` routes; `undefined` until `.use(streaming())`. */
141
+ private sseRuntime;
142
+ /** Installed WebSocket runtime for `.ws()` routes; `undefined` until `.use(websocket())`. */
143
+ private wsRuntime;
395
144
  private readonly logger;
396
145
  /** App-wide validation-error fallback; a route's own `schema.onValidationError` takes precedence. */
397
146
  private readonly defaultOnValidationError?;
@@ -435,6 +184,14 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
435
184
  * a Web `Response`. The first registered wrapper is outermost.
436
185
  */
437
186
  around(fn: <T>(context: Context & Ctx, next: () => MaybePromise<T>) => MaybePromise<T>): this;
187
+ /**
188
+ * Asynchronously admit each subsequent `executeCapability()` call before its owned effect runs.
189
+ * Interceptors receive token-only metadata plus an abort signal and must call `next()` exactly once
190
+ * to admit. Returning without `next()`, timing out, aborting, or throwing fails the effect closed.
191
+ */
192
+ aroundCapability(interceptor: CapabilityInterceptor, options?: AroundCapabilityOptions): this;
193
+ /** Observe token-only admission/execution lifecycle events for subsequent capability routes. */
194
+ observeCapability(observer: EffectLifecycleObserver): this;
438
195
  /** Transform the handler's result before it is serialized. Order-scoped. */
439
196
  afterHandle(fn: (result: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;
440
197
  /** Handle a thrown error; a non-`undefined` return becomes the response (else the default 500). Order-scoped. */
@@ -474,7 +231,8 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
474
231
  * JSON-serialized into the SSE `data:` field. The typed client sees the marker and grows a
475
232
  * `.subscribe(onEvent)` for the route with the same payload type — end-to-end typed streaming.
476
233
  *
477
- * const app = server().sse("/feed", { sse: t.object({ id: t.integer(), title: t.string() }) },
234
+ * import { streaming } from "@nifrajs/core/sse" // .use(streaming()) enables .sse()
235
+ * const app = server().use(streaming()).sse("/feed", { sse: t.object({ id: t.integer(), title: t.string() }) },
478
236
  * async (c, stream) => {
479
237
  * stream.send({ id: 1, title: "hello" }) // typed
480
238
  * await waitForDisconnect(stream.signal)
@@ -498,6 +256,19 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
498
256
  patch<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, "PATCH", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;
499
257
  delete<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, "DELETE", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;
500
258
  delete<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, "DELETE", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;
259
+ /**
260
+ * Declare an **MCP tool** an agent can call (via `nifra mcp`, or a mounted MCP endpoint): a typed
261
+ * `POST /_nifra/tool/<name>` route whose `input`/`output` schemas contract the call and surface in
262
+ * `tools/list`. Requires `.use(mcp())` - without it, `.tool()` is a registration error, so an
263
+ * ordinary HTTP app never bundles the MCP wiring. Siblings: {@link resource}, {@link prompt}.
264
+ *
265
+ * import { mcp } from "@nifrajs/core/mcp"
266
+ * const app = server().use(mcp()).tool(
267
+ * "search",
268
+ * { description: "Search posts", input: t.object({ q: t.string() }) },
269
+ * ({ q }) => findPosts(q),
270
+ * )
271
+ */
501
272
  tool<Name extends string, S extends {
502
273
  description: string;
503
274
  input: StandardSchemaV1;
@@ -539,9 +310,15 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
539
310
  * adapter (`listen()`, `@nifrajs/node`, `@nifrajs/deno`, `toFetchHandler`) — not by bare `app.fetch`, which
540
311
  * has no socket (a WS path through `app.fetch` is a normal HTTP response).
541
312
  *
313
+ * The route also enters the type-level registry (under the pseudo-method `"WS"`), so the typed
314
+ * client grows a `.ws()` handle for it: `messageSchema` types what the client may `send`,
315
+ * `sendSchema` types the frames it receives. Passing explicit type arguments (`ws<MyData>(…)`)
316
+ * defeats path-literal inference and skips the registry entry - the route still serves, it is just
317
+ * invisible to `client<App>`; prefer typing `data` via `upgrade()`'s return.
318
+ *
542
319
  * app.ws("/chat", { open: (ws) => ws.send("hi"), message: (ws, data) => ws.send(data) })
543
320
  */
544
- ws<Data = unknown, Schema extends StandardSchemaV1 | undefined = undefined>(path: string, handler: WebSocketHandler<Data, EnvOf<Ctx>, Schema>): this;
321
+ ws<Data = unknown, Schema extends StandardSchemaV1 | undefined = undefined, Send extends StandardSchemaV1 | undefined = undefined, Path extends string = string>(path: Path, handler: WebSocketHandler<Data, EnvOf<Ctx>, Schema, Send>): string extends Path ? Server<R, Ctx> : Server<AddRoute<R, "WS", Path, WsRouteInfoFor<Path, Schema, Send>>, Ctx>;
545
322
  /**
546
323
  * Broadcast `data` to every WebSocket connection subscribed to `topic` (via `ws.subscribe(topic)`).
547
324
  * In-process and **single-instance** (see {@link TopicRegistry}) — a multi-instance deploy must bridge
@@ -567,10 +344,19 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
567
344
  /** Collapse route-invariant lifecycle decisions into one runner at registration. The request path
568
345
  * performs no eligibility ladder: it supplies request state to this already-selected plan. */
569
346
  private compileExecutionPlan;
570
- /** Resolve a route's declared idempotency into a pinned store + defaults, or `undefined` when off. */
571
- private resolveIdempotency;
572
- /** The app-wide idempotency store: the configured one, else a lazily-created shared in-process store. */
573
- private defaultIdempotencyStore;
347
+ /** The idempotency lane's bridge back into the normal matched lanes, resolved to a concrete Response
348
+ * (the lane buffers the body, then replays it through the route's real validation + handler). */
349
+ private idempotencyRunLanes;
350
+ /** @internal Symbol-keyed install seam for the `idempotency()` plugin. Off the public typed surface. */
351
+ [INSTALL_IDEMPOTENCY](runtime: IdempotencyRuntime): void;
352
+ /** @internal Symbol-keyed install seam for the `mcp()` plugin. Off the public typed surface. */
353
+ [INSTALL_MCP](runtime: McpRuntime): void;
354
+ /** @internal Symbol-keyed install seam for the `nodeDirect()` plugin. Off the public typed surface. */
355
+ [INSTALL_NODE_DIRECT](runtime: NodeOutcomeRuntime): void;
356
+ /** @internal Symbol-keyed install seam for the `streaming()` plugin. Off the public typed surface. */
357
+ [INSTALL_SSE](runtime: SseRuntime): void;
358
+ /** @internal Symbol-keyed install seam for the `websocket()` plugin. Off the public typed surface. */
359
+ [INSTALL_WS](runtime: WsRuntime): void;
574
360
  /**
575
361
  * Merge another server's routes into this one — the composition escape hatch for large apps.
576
362
  *
@@ -630,7 +416,7 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
630
416
  * render differs.
631
417
  */
632
418
  resolveNode(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;
633
- resolveNodeSource(source: RequestSource, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;
419
+ resolveNodeSource(source: RequestSource, platform?: Platform<EnvOf<Ctx>>, suppliedRuntime?: NodeOutcomeRuntime): MaybePromise<NodeServeOutcome>;
634
420
  /**
635
421
  * Resolve a WebSocket upgrade — the seam every serving adapter uses. Returns `pass` (not a WS
636
422
  * upgrade for a registered route → handle as normal HTTP), `reject` (a WS route matched but
@@ -651,6 +437,9 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
651
437
  * produces the 503. The Web `fetch` and `resolveNode` are thin callers over this one routing +
652
438
  * context + lifecycle implementation — no duplication across the trust boundary.
653
439
  */
440
+ /** Apply the `clientIp` trust declaration to the adapter's raw socket peer, returning a platform
441
+ * whose `clientIp` is the derived caller. Only called when a trust declaration is configured. */
442
+ private deriveClientIp;
654
443
  private dispatch;
655
444
  /**
656
445
  * onRequest short-circuit path. Synchronous as long as every hook returns synchronously (the
@@ -672,24 +461,10 @@ export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyConte
672
461
  private routeAndRun;
673
462
  /** Run a route that has already been matched by the runtime or Nifra's portable router. */
674
463
  private runMatched;
675
- /**
676
- * Idempotency dedupe lane. Reads the `Idempotency-Key`, fingerprints the request, and consults the
677
- * store: a fresh key runs the handler (via {@link runMatchedLanes} with the body buffered) and stores
678
- * the response; a repeat key replays it without re-running; a key reused with a different body or an
679
- * in-flight duplicate is rejected. Every branch materializes a `Response`, then adapts to `T` via the
680
- * caller's `wrapResponse`, so it works on the Web fetch path and the Node-native outcome path alike.
681
- */
682
- private runIdempotent;
683
464
  /** Supply request-specific deadline state to the route's precompiled execution plan. */
684
465
  private runMatchedLanes;
685
- /**
686
- * Seal a ledgered request and deliver the sealed ledger to the sink. An empty ledger (declared
687
- * capabilities, none exercised) is not delivered — there is nothing to audit. This post-effect
688
- * ledger is observational: transactional/durable audit belongs in
689
- * the owned effect transaction, so a sink outage must not turn a successful effect into a retryable
690
- * 500 that can duplicate it.
691
- */
692
- private settleEffectLedger;
466
+ /** @internal Symbol-keyed install seam for the `effectLedger()` plugin. Off the public typed surface. */
467
+ [INSTALL_EFFECT_LEDGER](runtime: EffectLedgerRuntime): void;
693
468
  /** The narrowest bare route: a syntactic `() => ...` handler cannot observe the context argument, so
694
469
  * successful requests can skip allocating `RequestContext`. Errors still allocate one for logging. */
695
470
  private runContextlessBare;
@@ -874,5 +649,4 @@ export declare function toFetchHandler<Env = unknown>(app: {
874
649
  fetch(request: Request, env: Env, ctx: ExecutionContext): MaybePromise<Response>;
875
650
  scheduled?(controller: ScheduledController, env: Env, ctx: ExecutionContext): MaybePromise<void>;
876
651
  };
877
- export {};
878
652
  //# sourceMappingURL=server.d.ts.map