@nifrajs/cli 1.3.0 → 1.3.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/cli.js +1 -1
- package/dist/mcp-http.js +1 -1
- package/docs/llms-full.txt +2 -2
- package/docs/types.json +510 -24
- package/package.json +7 -7
- package/src/cli.ts +1 -1
- package/src/mcp-http.ts +1 -1
package/dist/cli.js
CHANGED
|
@@ -68,7 +68,7 @@ routes/ from the current directory. Run from your project root.
|
|
|
68
68
|
Port: \`dev\` and \`start\` share the default ${DEFAULT_DEV_PORT}. Override with \`--port <n>\` (alias \`-p\`) or the
|
|
69
69
|
\`PORT\` env var (\`--port\` wins over \`PORT\`, which wins over the default).`;
|
|
70
70
|
// Kept in lockstep with packages/cli/package.json by check:publish's version-consistency gate.
|
|
71
|
-
const CLI_VERSION = "1.3.
|
|
71
|
+
const CLI_VERSION = "1.3.1";
|
|
72
72
|
// A render adapter + nifra server are opaque to the CLI (it just forwards them); cast at the seam.
|
|
73
73
|
const asAdapter = (v) => v;
|
|
74
74
|
const asBunPlugins = (v) => v;
|
package/dist/mcp-http.js
CHANGED
|
@@ -19,7 +19,7 @@ import { loadTypesCorpus } from "./types-search.js";
|
|
|
19
19
|
// tool factory + the transport core from one entry: `import { respondMcpHttp, docsTools } from "@nifrajs/cli/mcp"`.
|
|
20
20
|
export { docsTools } from "./mcp-docs-tools.js";
|
|
21
21
|
// Kept in lockstep with packages/cli/package.json by check:publish's version-consistency gate.
|
|
22
|
-
const VERSION = "1.3.
|
|
22
|
+
const VERSION = "1.3.1";
|
|
23
23
|
const SERVER_INFO = { name: "nifra-docs", version: VERSION };
|
|
24
24
|
const DOCS_HEALTH = "nifra docs MCP — POST JSON-RPC 2.0 here (methods: initialize, tools/list, tools/call). Tools: nifra_docs, nifra_example.";
|
|
25
25
|
/** The two project-independent tools, reading the package's bundled corpus from disk (CLI use). */
|
package/docs/llms-full.txt
CHANGED
|
@@ -4190,7 +4190,7 @@ export const GetUser = {
|
|
|
4190
4190
|
### Runtime validation
|
|
4191
4191
|
|
|
4192
4192
|
Attach the schema to a route. Path params, query, and body are validated at the runtime
|
|
4193
|
-
boundary _before_ your handler runs — invalid input is rejected with a
|
|
4193
|
+
boundary _before_ your handler runs — invalid input is rejected with a 422, so the
|
|
4194
4194
|
handler only ever sees well-formed data.
|
|
4195
4195
|
|
|
4196
4196
|
```ts
|
|
@@ -5821,7 +5821,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
5821
5821
|
|
|
5822
5822
|
## @nifrajs/core
|
|
5823
5823
|
|
|
5824
|
-
`AnyServer`, `attachWebSocket`, `commonSecretPatterns`, `Context`, `ContextForOp`, `ContractShape`, `CookieOptions`, `defineContract`, `defineIdentityPlugin`, `definePlugin`, `defineRouterPlugin`, `DurableObjectNamespaceLike`, `ExecutionContext`, `FRAMEWORK_NAME`, `FrameworkError`, `FrameworkName`, `Handler`, `HandlersFor`, `IdentityPlugin`, `implement`, `InferInput`, `InferOutput`, `jsonLogger`, `LogFields`, `Logger`, `Method`, `METHODS`, `Middleware`, `NifraPlugin`, `NifraWebSocket`, `NodeServeOutcome`, `OnRequestResult`, `OperationDef`, `Params`, `parseCookies`, `Platform`, `Prettify`, `redactLogFields`, `RedactOptions`, `Registry`, `RegistryFor`, `RegistryFromImpl`, `ResponseControls`, `ResponseDef`, `robots`, `RobotsOptions`, `RobotsRule`, `RouteConfigError`, `RouteConfigErrorCode`, `RouteDescriptor`, `RouteInfo`, `Router`, `RouterMatch`, `RouteSchema`, `RunningServer`, `ScheduledController`, `ScheduledHandler`, `serializeCookie`, `server`, `Server`, `ServerOptions`, `SignatureEncoding`, `signValue`, `silentLogger`, `sitemap`, `SitemapChangeFreq`, `SitemapEntry`, `SitemapOptions`, `sse`, `SSEContext`, `SSEInit`, `SSEMessage`, `SSEStream`, `StandardIssue`, `StandardResult`, `StandardSchemaV1`, `StandardTypes`, `StandardWebSocket`, `toFetchHandler`, `TopicRegistry`, `unsignValue`, `validateStandard`, `ValidationOutcome`, `verifyWebhook`, `VerifyWebhookOptions`, `Version`, `VERSION`, `WebhookFailureReason`, `WebhookProvider`, `WebhookResult`, `WebSocketContext`, `WebSocketData`, `WebSocketHandler`, `WebSocketUpgradeOutcome`
|
|
5824
|
+
`AnyServer`, `attachWebSocket`, `commonSecretPatterns`, `Context`, `ContextForOp`, `ContractShape`, `CookieOptions`, `defineContract`, `defineIdentityPlugin`, `definePlugin`, `defineRouterPlugin`, `DurableObjectNamespaceLike`, `ExecutionContext`, `FRAMEWORK_NAME`, `FrameworkError`, `FrameworkName`, `Handler`, `HandlersFor`, `IdentityPlugin`, `implement`, `InferInput`, `InferOutput`, `jsonLogger`, `LogFields`, `Logger`, `McpPromptDescriptor`, `McpResourceDescriptor`, `Method`, `METHODS`, `Middleware`, `NifraPlugin`, `NifraWebSocket`, `NodeServeOutcome`, `OnRequestResult`, `OperationDef`, `Params`, `parseCookies`, `Platform`, `Prettify`, `PromptArgument`, `PromptMessage`, `redactLogFields`, `RedactOptions`, `Registry`, `RegistryFor`, `RegistryFromImpl`, `ResponseControls`, `ResponseDef`, `robots`, `RobotsOptions`, `RobotsRule`, `RouteConfigError`, `RouteConfigErrorCode`, `RouteDescriptor`, `RouteInfo`, `Router`, `RouterMatch`, `RouteSchema`, `RunningServer`, `ScheduledController`, `ScheduledHandler`, `serializeCookie`, `server`, `Server`, `ServerOptions`, `SignatureEncoding`, `signValue`, `silentLogger`, `sitemap`, `SitemapChangeFreq`, `SitemapEntry`, `SitemapOptions`, `sse`, `SSEContext`, `SSEInit`, `SSEMessage`, `SSEStream`, `StandardIssue`, `StandardResult`, `StandardSchemaV1`, `StandardTypes`, `StandardWebSocket`, `toFetchHandler`, `ToolAnnotations`, `TopicRegistry`, `unsignValue`, `validateStandard`, `ValidationOutcome`, `verifyWebhook`, `VerifyWebhookOptions`, `Version`, `VERSION`, `WebhookFailureReason`, `WebhookProvider`, `WebhookResult`, `WebSocketContext`, `WebSocketData`, `WebSocketHandler`, `WebSocketUpgradeOutcome`
|
|
5825
5825
|
|
|
5826
5826
|
## @nifrajs/cron
|
|
5827
5827
|
|
package/docs/types.json
CHANGED
|
@@ -148,6 +148,13 @@
|
|
|
148
148
|
"signature": "export interface AppLike {\n fetch(request: Request): Response | Promise<Response>;\n}",
|
|
149
149
|
"doc": "/** Anything with a Web-standard fetch handler — a nifra app, or any `(Request) => Response`. Declared\n * structurally so this package has zero dependency on `@nifrajs/core`. */"
|
|
150
150
|
},
|
|
151
|
+
{
|
|
152
|
+
"name": "AppLike",
|
|
153
|
+
"kind": "interface",
|
|
154
|
+
"package": "@nifrajs/testing",
|
|
155
|
+
"signature": "export interface AppLike {\n fetch(request: Request): Response | Promise<Response>;\n}",
|
|
156
|
+
"doc": "/** The minimal shape a nifra `server()` app satisfies — its own `fetch`. */"
|
|
157
|
+
},
|
|
151
158
|
{
|
|
152
159
|
"name": "applyDoctorAutoFix",
|
|
153
160
|
"kind": "function",
|
|
@@ -176,6 +183,13 @@
|
|
|
176
183
|
"signature": "export declare function assertAuthableDb(db: DbChoice): void;",
|
|
177
184
|
"doc": "/**\n * Guard `--auth` against a DB whose ORM has no clean better-auth adapter. Throws an actionable error\n * for Kysely (passing a raw dialect to better-auth is manual wiring we won't fake-scaffold). Called by\n * the CLI before scaffolding so the failure is early and explains the fix.\n */"
|
|
178
185
|
},
|
|
186
|
+
{
|
|
187
|
+
"name": "assertSafeKey",
|
|
188
|
+
"kind": "function",
|
|
189
|
+
"package": "@nifrajs/storage",
|
|
190
|
+
"signature": "export declare function assertSafeKey(key: string): void;",
|
|
191
|
+
"doc": "/** Throw {@link StorageKeyError} unless `key` is a safe relative storage key. */"
|
|
192
|
+
},
|
|
179
193
|
{
|
|
180
194
|
"name": "attachWebSocket",
|
|
181
195
|
"kind": "function",
|
|
@@ -280,6 +294,13 @@
|
|
|
280
294
|
"signature": "export declare function backendRoutes(backend: unknown): RouteDesc[];",
|
|
281
295
|
"doc": "/** Read the backend's registered routes, if it's a `server()` with a `.routes()` method. */"
|
|
282
296
|
},
|
|
297
|
+
{
|
|
298
|
+
"name": "Backoff",
|
|
299
|
+
"kind": "type",
|
|
300
|
+
"package": "@nifrajs/jobs",
|
|
301
|
+
"signature": "export type Backoff = (attempt: number) => number;",
|
|
302
|
+
"doc": "/** ms to wait before the next attempt, given the number of attempts already made (1-based). */"
|
|
303
|
+
},
|
|
283
304
|
{
|
|
284
305
|
"name": "base64UrlDecode",
|
|
285
306
|
"kind": "function",
|
|
@@ -533,6 +554,12 @@
|
|
|
533
554
|
"signature": "export declare function cache(options: CacheOptions): Middleware;",
|
|
534
555
|
"doc": "/**\n * Full response cache for small, cacheable responses. Use a shared `store` in production. The\n * middleware honors `Cache-Control` by default, avoids `Set-Cookie`, caps stored bytes, emits `Age`,\n * and keeps `Vary` headers aligned with the cache key.\n */"
|
|
535
556
|
},
|
|
557
|
+
{
|
|
558
|
+
"name": "Cache",
|
|
559
|
+
"kind": "interface",
|
|
560
|
+
"package": "@nifrajs/cache",
|
|
561
|
+
"signature": "export interface Cache {\n /** The cached value for `key`, or `undefined` if missing/expired. Pass `T` for the value type. */\n get<T = unknown>(key: string): Promise<T | undefined>;\n /** Whether a live (non-expired) entry exists. */\n has(key: string): Promise<boolean>;\n /** Store `value` under `key`. */\n set<T>(key: string, value: T, options?: SetOptions): Promise<void>;\n delete(key: string): Promise<void>;\n /** Drop every entry tagged `tag`. */\n invalidateTag(tag: string): Promise<void>;\n clear(): Promise<void>;\n /**\n * Cache-aside: return the cached value, or run `loader`, store the result, and return it. Stampede-safe\n * (concurrent misses for one key share a single `loader` call) and SWR-aware (a stale-but-live value is\n * returned immediately while a deduped background refresh runs). A throwing `loader` is NOT cached.\n */\n wrap<T>(key: string, loader: () => T, options?: WrapOptions): Promise<Awaited<T>>;\n}"
|
|
562
|
+
},
|
|
536
563
|
{
|
|
537
564
|
"name": "cacheControl",
|
|
538
565
|
"kind": "function",
|
|
@@ -565,12 +592,25 @@
|
|
|
565
592
|
"signature": "export interface CachedResponse {\n /** The rendered document (UTF-8 HTML, fully buffered). */\n readonly body: string;\n readonly status: number;\n /** Response headers to replay (e.g. `content-type`). */\n readonly headers: Readonly<Record<string, string>>;\n /** When this entry was stored, via the injected clock (ms epoch). */\n readonly storedAt: number;\n /** Freshness window (ms): `now - storedAt >= revalidate` ⇒ stale (serve it, regenerate behind it). */\n readonly revalidate: number;\n}",
|
|
566
593
|
"doc": "/** A cached SSR response — the bytes + metadata a {@link CacheStore} persists. */"
|
|
567
594
|
},
|
|
595
|
+
{
|
|
596
|
+
"name": "CacheOptions",
|
|
597
|
+
"kind": "interface",
|
|
598
|
+
"package": "@nifrajs/cache",
|
|
599
|
+
"signature": "export interface CacheOptions {\n /** Storage adapter. Default: a fresh {@link MemoryCache}. */\n readonly store?: CacheStore;\n /** Default TTL (ms) for `set`/`wrap` when none is given. Default 60_000. */\n readonly defaultTtlMs?: number;\n /** Injectable clock (tests). Default `() => Date.now()`. */\n readonly now?: () => number;\n /** Called when a background SWR revalidation throws. Default: `console.error`. */\n readonly onError?: (error: unknown, key: string) => void;\n}"
|
|
600
|
+
},
|
|
568
601
|
{
|
|
569
602
|
"name": "CacheOptions",
|
|
570
603
|
"kind": "interface",
|
|
571
604
|
"package": "@nifrajs/middleware",
|
|
572
605
|
"signature": "export interface CacheOptions {\n readonly store: ResponseCacheStore;\n /** Time to live in milliseconds. */\n readonly ttlMs: number;\n /** Methods cached. Default `[\"GET\", \"HEAD\"]`. */\n readonly methods?: readonly string[];\n /** Status predicate. Default: `200` only. */\n readonly status?: (status: number) => boolean;\n /** Header names included in the cache key and emitted in `Vary`. */\n readonly vary?: readonly string[];\n /** Custom cache key. Receives the normalized `vary` headers through the request itself. */\n readonly key?: (request: Request) => string;\n /** Maximum response bytes to store. Default `1_000_000`. Larger responses pass through. */\n readonly maxBytes?: number;\n /** Respect request `Cache-Control: no-cache/no-store`. Default `true`. */\n readonly respectRequestCacheControl?: boolean;\n /** Respect response `Cache-Control: private/no-store`. Default `true`. */\n readonly respectResponseCacheControl?: boolean;\n /** Cache responses with `Set-Cookie`. Default `false`. */\n readonly cacheSetCookie?: boolean;\n /** Cache responses to requests bearing `Authorization` or `Cookie` even when the response is not\n * explicitly `Cache-Control: public` (or `s-maxage`). Default `false`: a shared cache must not store a\n * personalized response (RFC 9111 §3.5), or it would be replayed to other users. Leave this off unless\n * the cached route is genuinely the same for every caller. */\n readonly cacheAuthenticated?: boolean;\n /** Response header for cache status. Default `\"x-nifra-cache\"`; set `false` to disable. */\n readonly cacheStatusHeader?: string | false;\n}"
|
|
573
606
|
},
|
|
607
|
+
{
|
|
608
|
+
"name": "CacheStore",
|
|
609
|
+
"kind": "interface",
|
|
610
|
+
"package": "@nifrajs/cache",
|
|
611
|
+
"signature": "export interface CacheStore {\n /** The live entry for `key`, or `undefined` if missing or hard-expired (`now >= expiresAt`). */\n get(key: string): StoredEntry | undefined | Promise<StoredEntry | undefined>;\n /** Store `entry` under `key`, indexed by `tags` for {@link CacheStore.invalidateTag}. */\n set(key: string, entry: StoredEntry, tags: readonly string[]): void | Promise<void>;\n delete(key: string): void | Promise<void>;\n /** Drop every entry carrying `tag`. */\n invalidateTag(tag: string): void | Promise<void>;\n clear(): void | Promise<void>;\n}",
|
|
612
|
+
"doc": "/**\n * Raw key→entry storage. The default {@link MemoryCache} is in-process; implement this over CF KV /\n * Redis / etc. for a cache shared across instances. All methods may be sync or async — the cache awaits them.\n */"
|
|
613
|
+
},
|
|
574
614
|
{
|
|
575
615
|
"name": "CacheStore",
|
|
576
616
|
"kind": "interface",
|
|
@@ -596,7 +636,7 @@
|
|
|
596
636
|
"name": "CheckResult",
|
|
597
637
|
"kind": "interface",
|
|
598
638
|
"package": "@nifrajs/cli",
|
|
599
|
-
"signature": "export interface CheckResult {\n readonly ok: boolean;\n readonly typecheck: \"pass\" | \"fail\" | \"skipped\";\n readonly diagnostics: readonly CheckDiagnostic[];\n}",
|
|
639
|
+
"signature": "export interface CheckResult {\n readonly ok: boolean;\n readonly typecheck: \"pass\" | \"fail\" | \"skipped\";\n readonly diagnostics: readonly CheckDiagnostic[];\n /** Set only when the caller passed `maxDiagnostics` and there were more — `diagnostics` then holds the\n * first `shown` of `total`. It caps the serialized size so the `nifra_check` MCP tool can't emit a\n * message large enough to break the stdio transport; fix the shown diagnostics and re-run for the rest. */\n readonly truncated?: {\n readonly shown: number;\n readonly total: number;\n };\n}",
|
|
600
640
|
"doc": "/** The structured result of a full check — what `--json` prints and the `nifra_check` MCP tool returns. */"
|
|
601
641
|
},
|
|
602
642
|
{
|
|
@@ -695,7 +735,7 @@
|
|
|
695
735
|
"name": "collectCheckResult",
|
|
696
736
|
"kind": "function",
|
|
697
737
|
"package": "@nifrajs/cli",
|
|
698
|
-
"signature": "export declare function collectCheckResult(cwd: string, opts?: {\n readonly lintsOnly?: boolean;\n readonly signal?: AbortSignal;\n}): Promise<CheckResult>;",
|
|
738
|
+
"signature": "export declare function collectCheckResult(cwd: string, opts?: {\n readonly lintsOnly?: boolean;\n readonly signal?: AbortSignal;\n /** Cap the returned `diagnostics` to this many (adds {@link CheckResult.truncated}). The MCP tool sets\n * it so a huge project can't produce a transport-breaking result; the CLI leaves it unset (all shown). */\n readonly maxDiagnostics?: number;\n}): Promise<CheckResult>;",
|
|
699
739
|
"doc": "/** Run the three checks and assemble a structured, machine-readable result. The single source the CLI\n * report, `--json`, and the MCP tool all render from. */"
|
|
700
740
|
},
|
|
701
741
|
{
|
|
@@ -909,6 +949,20 @@
|
|
|
909
949
|
"signature": "export type ContractShape = Record<string, OperationDef>;",
|
|
910
950
|
"doc": "/** A contract: named operations. Names are the handler keys and OpenAPI operationIds. */"
|
|
911
951
|
},
|
|
952
|
+
{
|
|
953
|
+
"name": "cookieJar",
|
|
954
|
+
"kind": "function",
|
|
955
|
+
"package": "@nifrajs/testing",
|
|
956
|
+
"signature": "export declare function cookieJar(): CookieJar;",
|
|
957
|
+
"doc": "/** Create an empty cookie jar. */"
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
"name": "CookieJar",
|
|
961
|
+
"kind": "interface",
|
|
962
|
+
"package": "@nifrajs/testing",
|
|
963
|
+
"signature": "export interface CookieJar {\n /** The current `Cookie` request-header value (`\"a=1; b=2\"`, or `\"\"` when empty). */\n header(): string;\n /** Set the `Cookie` header on `headers` when the jar is non-empty. */\n applyTo(headers: Headers): void;\n /** Absorb every `Set-Cookie` on a response (setting or, on removal, deleting each). */\n store(response: {\n headers: Headers;\n }): void;\n set(name: string, value: string): void;\n get(name: string): string | undefined;\n clear(): void;\n readonly size: number;\n}",
|
|
964
|
+
"doc": "/**\n * A tiny cookie jar for in-process tests — parses `Set-Cookie` off responses and emits a `Cookie`\n * request header, so a login → authenticated-request flow works without threading headers by hand. It\n * honours removal (`Max-Age=0` / a past `Expires`) so logout clears the cookie; other attributes\n * (Domain/Path/Secure/SameSite) are ignored — everything is same-origin in-process.\n */"
|
|
965
|
+
},
|
|
912
966
|
{
|
|
913
967
|
"name": "CookieOptions",
|
|
914
968
|
"kind": "interface",
|
|
@@ -942,6 +996,13 @@
|
|
|
942
996
|
"signature": "export declare function createBunWsHandlers(topics: TopicRegistry): BunWsHandlers;",
|
|
943
997
|
"doc": "/** The shared Bun `websocket` dispatcher config for one app — each connection's\n * `ws.data.handler` is the matched route's handler, set by `server.upgrade`. */"
|
|
944
998
|
},
|
|
999
|
+
{
|
|
1000
|
+
"name": "createCache",
|
|
1001
|
+
"kind": "function",
|
|
1002
|
+
"package": "@nifrajs/cache",
|
|
1003
|
+
"signature": "export declare function createCache(options?: CacheOptions): Cache;",
|
|
1004
|
+
"doc": "/** Create a cache over the given (or a fresh in-memory) store. */"
|
|
1005
|
+
},
|
|
945
1006
|
{
|
|
946
1007
|
"name": "createCachedAppLoader",
|
|
947
1008
|
"kind": "function",
|
|
@@ -1035,6 +1096,13 @@
|
|
|
1035
1096
|
"signature": "export interface CreateQueryResult<T> {\n /** Reactive accessor for the {@link QueryState} (`status`/`data`/`error`/`isFetching`/`updatedAt`). */\n readonly state: Accessor<QueryState<T>>;\n /** Force a refetch (ignores `staleTime`). */\n readonly refetch: () => Promise<T>;\n}",
|
|
1036
1097
|
"doc": "/** A query's reactive state accessor plus `refetch`. */"
|
|
1037
1098
|
},
|
|
1099
|
+
{
|
|
1100
|
+
"name": "createQueue",
|
|
1101
|
+
"kind": "function",
|
|
1102
|
+
"package": "@nifrajs/jobs",
|
|
1103
|
+
"signature": "export declare function createQueue(options?: QueueOptions): Queue;",
|
|
1104
|
+
"doc": "/** Create a job queue. Define jobs, enqueue payloads, and `start()` a worker (or `drain()` once). */"
|
|
1105
|
+
},
|
|
1038
1106
|
{
|
|
1039
1107
|
"name": "createScheduler",
|
|
1040
1108
|
"kind": "function",
|
|
@@ -1193,6 +1261,13 @@
|
|
|
1193
1261
|
"package": "@nifrajs/middleware",
|
|
1194
1262
|
"signature": "export declare function decodeBase64(input: string): Uint8Array<ArrayBuffer> | null;"
|
|
1195
1263
|
},
|
|
1264
|
+
{
|
|
1265
|
+
"name": "decodeCursor",
|
|
1266
|
+
"kind": "function",
|
|
1267
|
+
"package": "@nifrajs/schema",
|
|
1268
|
+
"signature": "export declare function decodeCursor<T = unknown>(cursor: string | null | undefined): T | undefined;",
|
|
1269
|
+
"doc": "/** Decode a cursor back to its value. Returns `undefined` for a null/empty/malformed cursor — treat that\n * as \"start from the beginning\" rather than erroring on a client-supplied string. */"
|
|
1270
|
+
},
|
|
1196
1271
|
{
|
|
1197
1272
|
"name": "DecodedImage",
|
|
1198
1273
|
"kind": "interface",
|
|
@@ -1502,6 +1577,19 @@
|
|
|
1502
1577
|
"package": "@nifrajs/web",
|
|
1503
1578
|
"signature": "export interface EnableDraftOptions {\n /** Cookie lifetime in **seconds** (default `3600` = 1h). Keep it short — draft is an editor session. */\n readonly maxAgeSeconds?: number;\n /** Cookie `Path` (default `\"/\"`). */\n readonly path?: string;\n /** Override the `Secure` attribute (defaults to `true` — secure-by-default). Pass `false` only for\n * local `http://` dev, where a `Secure` cookie isn't stored. */\n readonly secure?: boolean;\n}"
|
|
1504
1579
|
},
|
|
1580
|
+
{
|
|
1581
|
+
"name": "encodeCursor",
|
|
1582
|
+
"kind": "function",
|
|
1583
|
+
"package": "@nifrajs/schema",
|
|
1584
|
+
"signature": "export declare function encodeCursor(value: unknown): string;",
|
|
1585
|
+
"doc": "/** Encode any JSON-serializable value (e.g. the last row's sort key) into an opaque cursor string. */"
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
"name": "EnqueueOptions",
|
|
1589
|
+
"kind": "interface",
|
|
1590
|
+
"package": "@nifrajs/jobs",
|
|
1591
|
+
"signature": "export interface EnqueueOptions {\n /** Delay before the job becomes eligible. Ignored if `runAt` is set. */\n readonly delayMs?: number;\n /** Absolute epoch-ms eligibility time. Overrides `delayMs`. */\n readonly runAt?: number;\n}"
|
|
1592
|
+
},
|
|
1505
1593
|
{
|
|
1506
1594
|
"name": "ensureDefaultFormats",
|
|
1507
1595
|
"kind": "function",
|
|
@@ -1627,6 +1715,40 @@
|
|
|
1627
1715
|
"signature": "export interface ExecutionContext {\n waitUntil(promise: Promise<unknown>): void;\n}",
|
|
1628
1716
|
"doc": "/** A Cloudflare Workers-style execution context (the `fetch` 3rd arg). Structural — only\n * `waitUntil` is used; declared here so `@nifrajs/core` needs no Workers type dependency. */"
|
|
1629
1717
|
},
|
|
1718
|
+
{
|
|
1719
|
+
"name": "exponentialBackoff",
|
|
1720
|
+
"kind": "function",
|
|
1721
|
+
"package": "@nifrajs/jobs",
|
|
1722
|
+
"signature": "export declare function exponentialBackoff(options?: ExponentialOptions): Backoff;",
|
|
1723
|
+
"doc": "/** Exponential backoff: `baseMs * 2^(attempt-1)`, capped at `maxMs`, with optional jitter. */"
|
|
1724
|
+
},
|
|
1725
|
+
{
|
|
1726
|
+
"name": "ExponentialOptions",
|
|
1727
|
+
"kind": "interface",
|
|
1728
|
+
"package": "@nifrajs/jobs",
|
|
1729
|
+
"signature": "export interface ExponentialOptions {\n /** Delay before the FIRST retry (attempt 1). Default 1000. */\n readonly baseMs?: number;\n /** Upper bound on the delay. Default 30_000. */\n readonly maxMs?: number;\n /** Full-jitter fraction in [0,1]: the delay is scaled by `1 - jitter*rand`. Default 0 (deterministic). */\n readonly jitter?: number;\n /** Injectable randomness for jitter (tests). Default `Math.random`. */\n readonly random?: () => number;\n}"
|
|
1730
|
+
},
|
|
1731
|
+
{
|
|
1732
|
+
"name": "extractBackendPrompts",
|
|
1733
|
+
"kind": "function",
|
|
1734
|
+
"package": "@nifrajs/cli",
|
|
1735
|
+
"signature": "export declare function extractBackendPrompts(backend: unknown): McpPrompt[];",
|
|
1736
|
+
"doc": "/** Extract MCP prompts registered via `.prompt()` on the Nifra backend. Exported for the surfacing test. */"
|
|
1737
|
+
},
|
|
1738
|
+
{
|
|
1739
|
+
"name": "extractBackendResources",
|
|
1740
|
+
"kind": "function",
|
|
1741
|
+
"package": "@nifrajs/cli",
|
|
1742
|
+
"signature": "export declare function extractBackendResources(backend: unknown): McpResource[];",
|
|
1743
|
+
"doc": "/** Extract MCP resources registered via `.resource()` on the Nifra backend. Exported for the surfacing test. */"
|
|
1744
|
+
},
|
|
1745
|
+
{
|
|
1746
|
+
"name": "extractBackendTools",
|
|
1747
|
+
"kind": "function",
|
|
1748
|
+
"package": "@nifrajs/cli",
|
|
1749
|
+
"signature": "export declare function extractBackendTools(backend: unknown): McpTool[];",
|
|
1750
|
+
"doc": "/** Extract tools registered via .tool() routes on the Nifra backend. Exported for the test that proves a\n * `server().tool()` route surfaces in `tools/list` and executes through `tools/call`. */"
|
|
1751
|
+
},
|
|
1630
1752
|
{
|
|
1631
1753
|
"name": "FEATURE_IDS",
|
|
1632
1754
|
"kind": "const",
|
|
@@ -1724,6 +1846,20 @@
|
|
|
1724
1846
|
"signature": "export type FetchRouteData = (path: string, match: RouteMatch, signal?: AbortSignal) => Promise<unknown>;",
|
|
1725
1847
|
"doc": "/** How a router fetches a route's loader data on navigation. `signal` aborts a superseded fetch\n * (and its deferred stream). */"
|
|
1726
1848
|
},
|
|
1849
|
+
{
|
|
1850
|
+
"name": "FieldKey",
|
|
1851
|
+
"kind": "type",
|
|
1852
|
+
"package": "@nifrajs/web",
|
|
1853
|
+
"signature": "export type FieldKey<App, Path extends string, Method extends string> = [\n RouteBody<App, Path, Method>\n] extends [never] ? never : keyof RouteBody<App, Path, Method> & string;",
|
|
1854
|
+
"doc": "/** The valid field names for that route's body — the schema's keys as a string union. */"
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
"name": "FieldProps",
|
|
1858
|
+
"kind": "type",
|
|
1859
|
+
"package": "@nifrajs/web",
|
|
1860
|
+
"signature": "export type FieldProps = Record<string, unknown>;",
|
|
1861
|
+
"doc": "/** Extra attributes merged into the returned input props (id, type, defaultValue, placeholder, …). */"
|
|
1862
|
+
},
|
|
1727
1863
|
{
|
|
1728
1864
|
"name": "filePathToPattern",
|
|
1729
1865
|
"kind": "function",
|
|
@@ -1738,6 +1874,12 @@
|
|
|
1738
1874
|
"signature": "export declare function filePathToPatterns(file: string): string[];",
|
|
1739
1875
|
"doc": "/**\n * Derive **every** nifra router pattern a route file maps to (relative to the routes dir):\n * `index` → the parent path, `[id]` → `:id`, `[...slug]` → `*slug` (catch-all, captures the rest of\n * the path into one param), `(group)` folders are dropped from the URL (organization only), and an\n * optional `[[lang]]` expands the set — once with the segment present (`:lang`) and once absent. A file\n * with no optionals yields exactly one pattern. Throws on an invalid param or a catch-all that isn't\n * the last segment.\n */"
|
|
1740
1876
|
},
|
|
1877
|
+
{
|
|
1878
|
+
"name": "FileStorage",
|
|
1879
|
+
"kind": "class",
|
|
1880
|
+
"package": "@nifrajs/storage",
|
|
1881
|
+
"signature": "export declare class FileStorage implements StorageAdapter {\n private readonly root;\n constructor(root: string);\n /** Resolve `key` to an absolute path, asserting it stays inside `root` (defense-in-depth on top of `assertSafeKey`). */\n private pathFor;\n put(key: string, data: StorageData, _options?: PutOptions): Promise<void>;\n get(key: string): Promise<StorageObject | null>;\n delete(key: string): Promise<void>;\n exists(key: string): Promise<boolean>;\n list(options?: ListOptions): Promise<string[]>;\n private walk;\n}"
|
|
1882
|
+
},
|
|
1741
1883
|
{
|
|
1742
1884
|
"name": "FileType",
|
|
1743
1885
|
"kind": "interface",
|
|
@@ -1752,6 +1894,13 @@
|
|
|
1752
1894
|
"signature": "export declare function fillRoutePattern(pattern: string, params: Record<string, string>): {\n path: string;\n missing: string[];\n};",
|
|
1753
1895
|
"doc": "/**\n * Substitute a route pattern's `:param` segments with concrete values: `/users/:id` + `{id:\"7\"}` →\n * `/users/7`. Returns the filled path plus any params that had no value (a `getStaticPaths` bug) so\n * the caller can skip rather than emit a path with a literal `:name`. Shared by the SSG driver and\n * {@link enumeratePrerenderedPaths}.\n */"
|
|
1754
1896
|
},
|
|
1897
|
+
{
|
|
1898
|
+
"name": "fixedBackoff",
|
|
1899
|
+
"kind": "const",
|
|
1900
|
+
"package": "@nifrajs/jobs",
|
|
1901
|
+
"signature": "export declare const fixedBackoff: (ms: number) => Backoff;",
|
|
1902
|
+
"doc": "/** Fixed delay before every retry. */"
|
|
1903
|
+
},
|
|
1755
1904
|
{
|
|
1756
1905
|
"name": "Flags",
|
|
1757
1906
|
"kind": "interface",
|
|
@@ -1831,6 +1980,19 @@
|
|
|
1831
1980
|
"signature": "export declare function formatTraceparent(traceId: string, spanId: string, sampled: boolean): string;",
|
|
1832
1981
|
"doc": "/** Format a `traceparent` header value (version `00`). */"
|
|
1833
1982
|
},
|
|
1983
|
+
{
|
|
1984
|
+
"name": "formFor",
|
|
1985
|
+
"kind": "function",
|
|
1986
|
+
"package": "@nifrajs/web",
|
|
1987
|
+
"signature": "export declare function formFor<App, Path extends RoutePaths<App>, Method extends string = \"post\">(): FormHandle<App, Path, Method>;",
|
|
1988
|
+
"doc": "/**\n * Bind a form to a backend route's body schema at the type level. `App` is `typeof backend`; `Path` is\n * constrained to the app's real routes (a wrong path is a type error); `Method` defaults to `\"post\"`.\n */"
|
|
1989
|
+
},
|
|
1990
|
+
{
|
|
1991
|
+
"name": "FormHandle",
|
|
1992
|
+
"kind": "interface",
|
|
1993
|
+
"package": "@nifrajs/web",
|
|
1994
|
+
"signature": "export interface FormHandle<App, Path extends string, Method extends string> {\n /** Input props for a schema field. `name` is constrained to the body's keys — a typo, or a field the\n * schema doesn't have, is a COMPILE error. Spread onto an element: `<input {...f.field(\"text\")} />`. */\n field<K extends FieldKey<App, Path, Method>>(name: K, props?: FieldProps): FieldProps & {\n name: K;\n };\n /** `formData.get`, key-constrained to the body's fields — reading an orphan key won't compile. */\n read<K extends FieldKey<App, Path, Method>>(form: FormData, name: K): FormEntry;\n /** `formData.getAll`, key-checked the same way. */\n readAll<K extends FieldKey<App, Path, Method>>(form: FormData, name: K): FormEntries;\n}"
|
|
1995
|
+
},
|
|
1834
1996
|
{
|
|
1835
1997
|
"name": "Framework",
|
|
1836
1998
|
"kind": "type",
|
|
@@ -1875,8 +2037,8 @@
|
|
|
1875
2037
|
"name": "fromTypeBox",
|
|
1876
2038
|
"kind": "function",
|
|
1877
2039
|
"package": "@nifrajs/schema",
|
|
1878
|
-
"signature": "export declare function fromTypeBox<T extends TSchema>(schema: T): NifraSchema<T>;",
|
|
1879
|
-
"doc": "/**\n * Wrap a TypeBox schema as a `NifraSchema`.\n *\n * **Validation is fast where it can be, and works everywhere.** The first `validate`\n * builds a compiled `TypeCompiler` validator (codegen via `new Function`) and memoizes\n * it — composing schemas (`t.object({ a: t.string() })`) never compiles the inner\n * pieces; only a schema actually used to validate a request pays the one-time codegen\n * cost. On Bun and Node this is the only path and it is untouched.\n *\n * Edge runtimes (Cloudflare Workers, Vercel Edge, Deno Deploy) **forbid dynamic code\n * generation**, so that first compile throws there. We catch it once per schema and\n * fall back to TypeBox's eval-free `Value` checker — same semantics (and same global\n * `FormatRegistry`, so `t.string({ format })` behaves identically), no `new Function`.\n * The branch is decided once and memoized, so the hot path is a single check either way.\n *\n * Exposed (not just used internally by `t`) so a TypeBox schema authored directly can\n * be adapted without leaving the Standard Schema world.\n */"
|
|
2040
|
+
"signature": "export declare function fromTypeBox<T extends TSchema>(schema: T, options?: {\n readonly coerce?: boolean;\n}): NifraSchema<T>;",
|
|
2041
|
+
"doc": "/**\n * Wrap a TypeBox schema as a `NifraSchema`.\n *\n * **Validation is fast where it can be, and works everywhere.** The first `validate`\n * builds a compiled `TypeCompiler` validator (codegen via `new Function`) and memoizes\n * it — composing schemas (`t.object({ a: t.string() })`) never compiles the inner\n * pieces; only a schema actually used to validate a request pays the one-time codegen\n * cost. On Bun and Node this is the only path and it is untouched.\n *\n * Edge runtimes (Cloudflare Workers, Vercel Edge, Deno Deploy) **forbid dynamic code\n * generation**, so that first compile throws there. We catch it once per schema and\n * fall back to TypeBox's eval-free `Value` checker — same semantics (and same global\n * `FormatRegistry`, so `t.string({ format })` behaves identically), no `new Function`.\n * The branch is decided once and memoized, so the hot path is a single check either way.\n *\n * Exposed (not just used internally by `t`) so a TypeBox schema authored directly can\n * be adapted without leaving the Standard Schema world.\n *\n * `options.coerce` runs TypeBox's `Value.Convert` (string→number/integer/boolean, per the schema)\n * BEFORE validating. Query values always arrive as strings (`?limit=20` → `\"20\"`), so a query schema\n * with a numeric field can't validate without this — it's how `t.pageQuery` yields a real `number`.\n * Leave it OFF (the default) for body/JSON schemas: a JSON number is already a number, and coercing\n * would silently accept `\"20\"` where the contract said `20`.\n */"
|
|
1880
2042
|
},
|
|
1881
2043
|
{
|
|
1882
2044
|
"name": "generateClientEntry",
|
|
@@ -1891,6 +2053,12 @@
|
|
|
1891
2053
|
"package": "@nifrajs/web",
|
|
1892
2054
|
"signature": "export interface GenerateClientEntryOptions {\n /** Module specifier for the adapter's client runtime (exports `mountRouter`), e.g.\n * `\"@nifrajs/web-solid/client\"`. */\n readonly clientModule: string;\n /** Turn a route/layout source file (relative to the routes dir) into an import specifier. */\n readonly resolve: (file: string) => string;\n}"
|
|
1893
2055
|
},
|
|
2056
|
+
{
|
|
2057
|
+
"name": "generateLlmsTxt",
|
|
2058
|
+
"kind": "function",
|
|
2059
|
+
"package": "@nifrajs/web",
|
|
2060
|
+
"signature": "export declare function generateLlmsTxt(full: boolean, pageRoutes: ReadonlyArray<{\n readonly pattern: string;\n readonly id: string;\n}>, backend: unknown): Promise<string>;"
|
|
2061
|
+
},
|
|
1894
2062
|
{
|
|
1895
2063
|
"name": "generateServerEntry",
|
|
1896
2064
|
"kind": "function",
|
|
@@ -2581,6 +2749,61 @@
|
|
|
2581
2749
|
"signature": "export declare const issue: (message: string) => {\n readonly issues: ReadonlyArray<StandardIssue>;\n};",
|
|
2582
2750
|
"doc": "/** A single issue. Messages NEVER include the variable's value — it may be a secret. */"
|
|
2583
2751
|
},
|
|
2752
|
+
{
|
|
2753
|
+
"name": "JobContext",
|
|
2754
|
+
"kind": "interface",
|
|
2755
|
+
"package": "@nifrajs/jobs",
|
|
2756
|
+
"signature": "export interface JobContext {\n readonly id: string;\n readonly name: string;\n /** 1 on the first run, 2 on the first retry, … */\n readonly attempt: number;\n}",
|
|
2757
|
+
"doc": "/** What a handler receives alongside the payload: identity + which attempt this is (1-based). */"
|
|
2758
|
+
},
|
|
2759
|
+
{
|
|
2760
|
+
"name": "JobCounts",
|
|
2761
|
+
"kind": "interface",
|
|
2762
|
+
"package": "@nifrajs/jobs",
|
|
2763
|
+
"signature": "export interface JobCounts {\n /** Eligible or waiting, not currently leased. */\n readonly pending: number;\n /** Leased and in flight. */\n readonly active: number;\n /** Dead-lettered (exhausted retries). */\n readonly dead: number;\n}"
|
|
2764
|
+
},
|
|
2765
|
+
{
|
|
2766
|
+
"name": "JobDefinition",
|
|
2767
|
+
"kind": "interface",
|
|
2768
|
+
"package": "@nifrajs/jobs",
|
|
2769
|
+
"signature": "export interface JobDefinition<Payload> {\n readonly handler: JobHandler<Payload>;\n /** Optional Standard Schema — validates the payload at `enqueue` (the trust boundary); a failure throws. */\n readonly input?: StandardSchemaV1<Payload>;\n /** `number` is shorthand for `{ attempts }`. */\n readonly retries?: number | RetryPolicy;\n}",
|
|
2770
|
+
"doc": "/** A job definition registered on a queue. */"
|
|
2771
|
+
},
|
|
2772
|
+
{
|
|
2773
|
+
"name": "JobError",
|
|
2774
|
+
"kind": "class",
|
|
2775
|
+
"package": "@nifrajs/jobs",
|
|
2776
|
+
"signature": "export declare class JobError extends Error {\n readonly name = \"JobError\";\n}",
|
|
2777
|
+
"doc": "/** Thrown for a misuse of the queue API (duplicate/unknown job name). */"
|
|
2778
|
+
},
|
|
2779
|
+
{
|
|
2780
|
+
"name": "JobHandle",
|
|
2781
|
+
"kind": "interface",
|
|
2782
|
+
"package": "@nifrajs/jobs",
|
|
2783
|
+
"signature": "export interface JobHandle<Payload> {\n readonly name: string;\n enqueue(payload: Payload, options?: EnqueueOptions): Promise<string>;\n}",
|
|
2784
|
+
"doc": "/** A typed handle to enqueue a defined job. */"
|
|
2785
|
+
},
|
|
2786
|
+
{
|
|
2787
|
+
"name": "JobHandler",
|
|
2788
|
+
"kind": "type",
|
|
2789
|
+
"package": "@nifrajs/jobs",
|
|
2790
|
+
"signature": "export type JobHandler<Payload> = (payload: Payload, ctx: JobContext) => void | Promise<void>;",
|
|
2791
|
+
"doc": "/** A job processor. A throw/rejection routes to `onError` and triggers retry/dead-letter — never crashes the worker. */"
|
|
2792
|
+
},
|
|
2793
|
+
{
|
|
2794
|
+
"name": "JobStore",
|
|
2795
|
+
"kind": "interface",
|
|
2796
|
+
"package": "@nifrajs/jobs",
|
|
2797
|
+
"signature": "export interface JobStore {\n /** Persist a new job; return its id. */\n enqueue(job: {\n name: string;\n payload: unknown;\n runAt: number;\n maxAttempts: number;\n }): string | Promise<string>;\n /** Atomically claim up to `limit` jobs due at/before `now`, hiding them for `leaseMs`. */\n lease(now: number, limit: number, leaseMs: number): StoredJob[] | Promise<StoredJob[]>;\n /** A job finished successfully — remove it. */\n complete(id: string): void | Promise<void>;\n /** A job failed but has attempts left — bump its attempt count and reschedule for `runAt`. */\n retry(id: string, runAt: number): void | Promise<void>;\n /** A job exhausted its attempts — move it to the dead-letter set with the last error. */\n deadLetter(id: string, error: string): void | Promise<void>;\n /** Snapshot counts (observability + tests). */\n counts(): JobCounts | Promise<JobCounts>;\n}",
|
|
2798
|
+
"doc": "/**\n * Persistence + leasing for the queue. The default {@link MemoryJobStore} is single-process (dev / a\n * single long-running server); implement this over Redis/Postgres/etc. for durability or multiple\n * workers. All methods may be sync or async — the queue awaits them.\n */"
|
|
2799
|
+
},
|
|
2800
|
+
{
|
|
2801
|
+
"name": "JobValidationError",
|
|
2802
|
+
"kind": "class",
|
|
2803
|
+
"package": "@nifrajs/jobs",
|
|
2804
|
+
"signature": "export declare class JobValidationError extends Error {\n readonly job: string;\n readonly issues: ReadonlyArray<{\n readonly message: string;\n }>;\n readonly name = \"JobValidationError\";\n constructor(job: string, issues: ReadonlyArray<{\n readonly message: string;\n }>);\n}",
|
|
2805
|
+
"doc": "/** Thrown by `enqueue` when the payload fails the job's `input` schema (validation at the trust boundary). */"
|
|
2806
|
+
},
|
|
2584
2807
|
{
|
|
2585
2808
|
"name": "jsonError",
|
|
2586
2809
|
"kind": "function",
|
|
@@ -2765,6 +2988,12 @@
|
|
|
2765
2988
|
"signature": "export interface LinkDescriptor {\n readonly rel?: string;\n readonly href?: string;\n readonly hreflang?: string;\n readonly crossorigin?: string;\n readonly media?: string;\n readonly sizes?: string;\n readonly type?: string;\n readonly as?: string;\n readonly integrity?: string;\n readonly referrerpolicy?: string;\n readonly fetchpriority?: string;\n readonly title?: string;\n readonly imagesrcset?: string;\n readonly imagesizes?: string;\n readonly color?: string;\n readonly disabled?: boolean;\n readonly [attr: string]: string | boolean | undefined;\n}",
|
|
2766
2989
|
"doc": "/**\n * One `<link>` tag's attributes for a route/layout's `meta.link`. The common HTML `<link>` attributes\n * are spelled out and **optional** so a typed partial like `{ rel, href, hreflang }` is assignable —\n * the previous `Record<string, string>` required *every* value to be a present string, which rejected\n * exactly that idiomatic shape (the bug this fixes). The index signature keeps custom/`data-*` attrs\n * (and any future standard attr) passing without a cast; `boolean` covers boolean attributes like\n * `disabled` (rendered as a bare attribute when `true`, omitted when `false`), and `undefined` lets a\n * caller spread in a conditionally-absent attribute. Attribute *names* are still shape-validated and\n * values HTML-escaped at render — a widened type never widens the injection surface.\n */"
|
|
2767
2990
|
},
|
|
2991
|
+
{
|
|
2992
|
+
"name": "ListOptions",
|
|
2993
|
+
"kind": "interface",
|
|
2994
|
+
"package": "@nifrajs/storage",
|
|
2995
|
+
"signature": "export interface ListOptions {\n /** Only keys starting with this prefix. */\n readonly prefix?: string;\n /** Cap the number of keys returned. */\n readonly limit?: number;\n}"
|
|
2996
|
+
},
|
|
2768
2997
|
{
|
|
2769
2998
|
"name": "load",
|
|
2770
2999
|
"kind": "function",
|
|
@@ -2963,8 +3192,8 @@
|
|
|
2963
3192
|
"name": "MCP_CLI_VERSION",
|
|
2964
3193
|
"kind": "const",
|
|
2965
3194
|
"package": "create-nifra",
|
|
2966
|
-
"signature": "export declare const MCP_CLI_VERSION:
|
|
2967
|
-
"doc": "/**\n * The `@nifrajs/cli` version the launch command pins to.
|
|
3195
|
+
"signature": "export declare const MCP_CLI_VERSION: string;",
|
|
3196
|
+
"doc": "/**\n * The `@nifrajs/cli` version the launch command pins to — DERIVED at load time from this package's own\n * `version`, never hardcoded. `fixed` changeset versioning ([[\"@nifrajs/*\", \"create-nifra\", \"nifra\"]] in\n * `.changeset/config.json`) bumps `create-nifra` and `@nifrajs/cli` in lockstep, so `create-nifra@x`\n * always means `@nifrajs/cli@x`. Deriving it here means a release bump has nothing to forget to update —\n * there is no stale literal to drift (the 1.0.0 cut shipped a beta pin exactly this way). `check:publish`\n * still asserts it equals `@nifrajs/cli`'s version as a belt-and-suspenders guard on the `fixed` link.\n *\n * Resolves correctly under BOTH export conditions: the `bun` export runs `src/agent-files.ts`\n * (`../package.json` → the package root) and the tsc `default` export runs `dist/agent-files.js`\n * (`../package.json` → the same root, since `dist/` sits beside the manifest). npm always ships a\n * package's own `package.json`, so the read can't miss at install time.\n *\n * Why pin at all instead of `bunx @nifrajs/cli mcp`: `bunx` keys its cache on the exact version spec.\n * An UNPINNED spec resolves to the `latest` tag once, then `bunx` reuses that cached copy on every\n * later spawn WITHOUT re-checking the registry — so an editor that once launched an older `@nifrajs/cli`\n * keeps respawning the stale binary even after a newer one is published (the MCP server silently runs\n * old code). Pinning the exact version makes the version part of the cache key, so each release fetches\n * fresh and a stale cache can never shadow it. The cost: an already-scaffolded app's `.mcp.json` freezes\n * at its scaffold-time version until `nifra init-agents` is re-run — an acceptable, deterministic trade.\n */"
|
|
2968
3197
|
},
|
|
2969
3198
|
{
|
|
2970
3199
|
"name": "MCP_CONFIG",
|
|
@@ -2984,7 +3213,7 @@
|
|
|
2984
3213
|
"name": "MCP_SERVER_ARGS",
|
|
2985
3214
|
"kind": "const",
|
|
2986
3215
|
"package": "create-nifra",
|
|
2987
|
-
"signature": "export declare const MCP_SERVER_ARGS: readonly [
|
|
3216
|
+
"signature": "export declare const MCP_SERVER_ARGS: readonly [`@nifrajs/cli@${string}`, \"mcp\"];"
|
|
2988
3217
|
},
|
|
2989
3218
|
{
|
|
2990
3219
|
"name": "MCP_SERVER_COMMAND",
|
|
@@ -3033,6 +3262,13 @@
|
|
|
3033
3262
|
"package": "@nifrajs/mcp",
|
|
3034
3263
|
"signature": "export interface McpPrompt {\n readonly name: string;\n readonly description: string;\n readonly arguments?: readonly {\n readonly name: string;\n readonly description?: string;\n readonly required?: boolean;\n }[];\n readonly handler: (args: Record<string, unknown>) => Promise<readonly McpPromptMessage[]>;\n}"
|
|
3035
3264
|
},
|
|
3265
|
+
{
|
|
3266
|
+
"name": "McpPromptDescriptor",
|
|
3267
|
+
"kind": "interface",
|
|
3268
|
+
"package": "@nifrajs/core",
|
|
3269
|
+
"signature": "export interface McpPromptDescriptor {\n readonly name: string;\n readonly description: string;\n readonly arguments?: readonly PromptArgument[];\n readonly handler: (args: Record<string, string>) => MaybePromise<readonly PromptMessage[]>;\n}",
|
|
3270
|
+
"doc": "/** An app-declared MCP prompt — a reusable prompt template an agent can fetch through `nifra mcp`. */"
|
|
3271
|
+
},
|
|
3036
3272
|
{
|
|
3037
3273
|
"name": "McpPromptMessage",
|
|
3038
3274
|
"kind": "interface",
|
|
@@ -3057,6 +3293,13 @@
|
|
|
3057
3293
|
"package": "@nifrajs/mcp",
|
|
3058
3294
|
"signature": "export interface McpResource {\n readonly uri: string;\n readonly name: string;\n readonly description?: string;\n readonly mimeType?: string;\n /** Descriptor `_meta` (MCP Apps: CSP / domain / border render hints under `ui`). */\n readonly _meta?: Record<string, unknown>;\n readonly read: () => Promise<{\n readonly text: string;\n readonly mimeType?: string;\n }>;\n}"
|
|
3059
3295
|
},
|
|
3296
|
+
{
|
|
3297
|
+
"name": "McpResourceDescriptor",
|
|
3298
|
+
"kind": "interface",
|
|
3299
|
+
"package": "@nifrajs/core",
|
|
3300
|
+
"signature": "export interface McpResourceDescriptor {\n readonly uri: string;\n readonly name: string;\n readonly description?: string;\n readonly mimeType?: string;\n readonly read: () => MaybePromise<string | {\n readonly text: string;\n readonly mimeType?: string;\n }>;\n}",
|
|
3301
|
+
"doc": "/** An app-declared MCP resource — read-only data an agent can fetch through `nifra mcp`. */"
|
|
3302
|
+
},
|
|
3060
3303
|
{
|
|
3061
3304
|
"name": "McpServer",
|
|
3062
3305
|
"kind": "interface",
|
|
@@ -3080,8 +3323,14 @@
|
|
|
3080
3323
|
"name": "McpTool",
|
|
3081
3324
|
"kind": "interface",
|
|
3082
3325
|
"package": "@nifrajs/mcp",
|
|
3083
|
-
"signature": "export interface McpTool {\n readonly name: string;\n readonly description: string;\n readonly inputSchema: Record<string, unknown>;\n readonly _meta?: Record<string, unknown>;\n readonly handler: (args: Record<string, unknown>, context: McpToolContext) => Promise<string | McpToolResult>;\n}"
|
|
3084
|
-
|
|
3326
|
+
"signature": "export interface McpTool {\n readonly name: string;\n readonly description: string;\n readonly inputSchema: Record<string, unknown>;\n readonly annotations?: McpToolAnnotations;\n readonly _meta?: Record<string, unknown>;\n readonly handler: (args: Record<string, unknown>, context: McpToolContext) => Promise<string | McpToolResult>;\n}"
|
|
3327
|
+
},
|
|
3328
|
+
{
|
|
3329
|
+
"name": "McpToolAnnotations",
|
|
3330
|
+
"kind": "interface",
|
|
3331
|
+
"package": "@nifrajs/mcp",
|
|
3332
|
+
"signature": "export interface McpToolAnnotations {\n readonly title?: string;\n readonly readOnlyHint?: boolean;\n readonly destructiveHint?: boolean;\n readonly idempotentHint?: boolean;\n readonly openWorldHint?: boolean;\n}",
|
|
3333
|
+
"doc": "/** MCP tool safety hints (`readOnlyHint`/`destructiveHint`/…) surfaced in `tools/list`, per the MCP spec. */"
|
|
3085
3334
|
},
|
|
3086
3335
|
{
|
|
3087
3336
|
"name": "McpToolContext",
|
|
@@ -3117,6 +3366,18 @@
|
|
|
3117
3366
|
"signature": "export interface McpWidget {\n readonly uri: string;\n readonly resource: McpResource;\n readonly meta: Record<string, unknown>;\n}",
|
|
3118
3367
|
"doc": "/** A widget: the resource to register on the server, its `ui://` URI, and the `_meta` link for its tool. */"
|
|
3119
3368
|
},
|
|
3369
|
+
{
|
|
3370
|
+
"name": "MemoryCache",
|
|
3371
|
+
"kind": "class",
|
|
3372
|
+
"package": "@nifrajs/cache",
|
|
3373
|
+
"signature": "export declare class MemoryCache implements CacheStore {\n private readonly rows;\n private readonly tagIndex;\n private readonly maxEntries;\n private readonly now;\n constructor(options?: MemoryCacheOptions);\n get(key: string): StoredEntry | undefined;\n set(key: string, entry: StoredEntry, tags: readonly string[]): void;\n delete(key: string): void;\n invalidateTag(tag: string): void;\n clear(): void;\n /** Live entry count (for observability/tests). */\n size(): number;\n /** Remove a key and unlink it from every tag set it belonged to. */\n private evict;\n}"
|
|
3374
|
+
},
|
|
3375
|
+
{
|
|
3376
|
+
"name": "MemoryCacheOptions",
|
|
3377
|
+
"kind": "interface",
|
|
3378
|
+
"package": "@nifrajs/cache",
|
|
3379
|
+
"signature": "export interface MemoryCacheOptions {\n /** Evict the least-recently-used entry once the count exceeds this. `0` (default) = unbounded. */\n readonly maxEntries?: number;\n /** Injectable clock (tests). Default `() => Date.now()`. */\n readonly now?: () => number;\n}"
|
|
3380
|
+
},
|
|
3120
3381
|
{
|
|
3121
3382
|
"name": "MemoryCacheStore",
|
|
3122
3383
|
"kind": "class",
|
|
@@ -3143,6 +3404,13 @@
|
|
|
3143
3404
|
"package": "@nifrajs/middleware",
|
|
3144
3405
|
"signature": "export interface MemoryIdempotencyStoreOptions {\n /** Allow the in-memory store in production. Off by default — a per-instance store can't dedupe across instances. */\n readonly allowInProduction?: boolean;\n}"
|
|
3145
3406
|
},
|
|
3407
|
+
{
|
|
3408
|
+
"name": "MemoryJobStore",
|
|
3409
|
+
"kind": "class",
|
|
3410
|
+
"package": "@nifrajs/jobs",
|
|
3411
|
+
"signature": "export declare class MemoryJobStore implements JobStore {\n private readonly jobs;\n private readonly dead;\n private seq;\n private readonly idFor;\n constructor(options?: {\n idFor?: () => string;\n });\n enqueue(job: {\n name: string;\n payload: unknown;\n runAt: number;\n maxAttempts: number;\n }): string;\n lease(now: number, limit: number, leaseMs: number): StoredJob[];\n complete(id: string): void;\n retry(id: string, runAt: number): void;\n deadLetter(id: string, error: string): void;\n counts(now?: number): JobCounts;\n /** The dead-letter queue — inspect/requeue failed jobs (not part of the {@link JobStore} contract). */\n deadLetters(): DeadRecord[];\n}",
|
|
3412
|
+
"doc": "/** Construct an in-memory job store. `idFor` is injectable for deterministic tests. */"
|
|
3413
|
+
},
|
|
3146
3414
|
{
|
|
3147
3415
|
"name": "MemoryResponseCache",
|
|
3148
3416
|
"kind": "class",
|
|
@@ -3168,6 +3436,12 @@
|
|
|
3168
3436
|
"package": "@nifrajs/auth",
|
|
3169
3437
|
"signature": "export interface MemorySessionStoreOptions {\n /** Allow the in-memory store in production. Off by default — per-instance sessions don't hold across\n * instances and are lost on restart. */\n readonly allowInProduction?: boolean;\n /** Hard cap on stored sessions; the oldest-inserted is evicted past it (default 10_000). */\n readonly max?: number;\n}"
|
|
3170
3438
|
},
|
|
3439
|
+
{
|
|
3440
|
+
"name": "MemoryStorage",
|
|
3441
|
+
"kind": "class",
|
|
3442
|
+
"package": "@nifrajs/storage",
|
|
3443
|
+
"signature": "export declare class MemoryStorage implements StorageAdapter {\n private readonly objects;\n put(key: string, data: StorageData, options?: PutOptions): Promise<void>;\n get(key: string): Promise<StorageObject | null>;\n delete(key: string): Promise<void>;\n exists(key: string): Promise<boolean>;\n list(options?: ListOptions): Promise<string[]>;\n}"
|
|
3444
|
+
},
|
|
3171
3445
|
{
|
|
3172
3446
|
"name": "MemoryStore",
|
|
3173
3447
|
"kind": "class",
|
|
@@ -3402,6 +3676,13 @@
|
|
|
3402
3676
|
"signature": "export interface NifraWebSocket<Data = unknown> {\n /** Send a text (`string`) or binary (`ArrayBuffer`/typed-array) frame. No-op once closed. */\n send(data: string | ArrayBufferView | ArrayBuffer): void;\n /** Close the connection (optional code 1000–4999 + short reason). */\n close(code?: number, reason?: string): void;\n /** `WebSocket.readyState` (0 CONNECTING · 1 OPEN · 2 CLOSING · 3 CLOSED). */\n readonly readyState: number;\n /** Join a pub/sub topic — `app.publish(topic, data)` then reaches this connection. Idempotent. */\n subscribe(topic: string): void;\n /** Leave a pub/sub topic. Idempotent. (All topics are dropped automatically on close.) */\n unsubscribe(topic: string): void;\n /** Per-connection state — seeded by `upgrade()`, mutable for the connection's lifetime. */\n data: Data;\n /** Escape hatch to the runtime's native socket (Bun `ServerWebSocket`, Web `WebSocket`, `ws`). */\n readonly raw: unknown;\n}",
|
|
3403
3677
|
"doc": "/** The portable socket handed to WS lifecycle callbacks. Each adapter wraps its native socket. */"
|
|
3404
3678
|
},
|
|
3679
|
+
{
|
|
3680
|
+
"name": "noBackoff",
|
|
3681
|
+
"kind": "const",
|
|
3682
|
+
"package": "@nifrajs/jobs",
|
|
3683
|
+
"signature": "export declare const noBackoff: Backoff;",
|
|
3684
|
+
"doc": "/** No delay — retry immediately. */"
|
|
3685
|
+
},
|
|
3405
3686
|
{
|
|
3406
3687
|
"name": "NodeBuiltinFinding",
|
|
3407
3688
|
"kind": "interface",
|
|
@@ -3427,7 +3708,7 @@
|
|
|
3427
3708
|
"kind": "function",
|
|
3428
3709
|
"package": "@nifrajs/web",
|
|
3429
3710
|
"signature": "export declare function normalizeRolldownPlugins(plugins: readonly unknown[], isRolldown: boolean): readonly unknown[];",
|
|
3430
|
-
"doc": "/**\n * Strip `optimizeDeps.rollupOptions.jsx` from a plugin's `config` hook output when running under\n * rolldown-vite — the source of the scary, harmless `Warning: Invalid input options … \"jsx\" Invalid\n * key: Expected never but received \"jsx\"` on `nifra dev`.\n *\n * Why it happens: `@vitejs/plugin-react@4.x` (and peers) target an *older* rolldown-vite optimizeDeps\n * API — they inject `optimizeDeps.rollupOptions.jsx` to tell the dep pre-bundler to transform JSX. Vite\n * 8's rolldown dep-optimizer renamed that surface to `optimizeDeps.rolldownOptions` (and moved jsx under\n * `transform.jsx`), so the stale `rollupOptions.jsx` is an unrecognized input option → the warning. It's\n * a version-skew artifact, not a real misconfig: the route source JSX transform runs through the\n * plugin's own `transform` hook (untouched here), and node_modules deps that get pre-bundled almost\n * never contain raw JSX — so dropping the dead key changes no behavior and keeps HMR/Fast Refresh\n * intact. We *strip* (rather than translate to `rolldownOptions`) so the fix is version-agnostic: a\n * plugin already emitting the correct `rolldownOptions` is left untouched, and a future plugin bump that\n * stops emitting `rollupOptions.jsx` makes this a no-op.\n *\n * Scoped narrowly: only the `optimizeDeps.rollupOptions.jsx` key is removed, only under rolldown-vite,\n * and only from the value a plugin's `config` hook returns. Non-rolldown Vite is passed through verbatim.\n */"
|
|
3711
|
+
"doc": "/**\n * Strip `optimizeDeps.rollupOptions.jsx` from a plugin's `config` hook output when running under\n * rolldown-vite — the source of the scary, harmless `Warning: Invalid input options … \"jsx\" Invalid\n * key: Expected never but received \"jsx\"` on `nifra dev`.\n *\n * Why it happens: `@vitejs/plugin-react@4.x` (and peers) target an *older* rolldown-vite optimizeDeps\n * API — they inject `optimizeDeps.rollupOptions.jsx` to tell the dep pre-bundler to transform JSX. Vite\n * 8's rolldown dep-optimizer renamed that surface to `optimizeDeps.rolldownOptions` (and moved jsx under\n * `transform.jsx`), so the stale `rollupOptions.jsx` is an unrecognized input option → the warning. It's\n * a version-skew artifact, not a real misconfig: the route source JSX transform runs through the\n * plugin's own `transform` hook (untouched here), and node_modules deps that get pre-bundled almost\n * never contain raw JSX — so dropping the dead key changes no behavior and keeps HMR/Fast Refresh\n * intact. We *strip* (rather than translate to `rolldownOptions`) so the fix is version-agnostic: a\n * plugin already emitting the correct `rolldownOptions` is left untouched, and a future plugin bump that\n * stops emitting `rollupOptions.jsx` makes this a no-op.\n *\n * Scoped narrowly: only the `optimizeDeps.rollupOptions.jsx` key is removed, only under rolldown-vite,\n * and only from the value a plugin's `config` hook returns. Non-rolldown Vite is passed through verbatim.\n *\n * FLATTEN FIRST: a Vite plugin factory may return an ARRAY of plugins — `@vitejs/plugin-react`'s `react()`\n * returns `[vite:react-babel, vite:react-refresh]`, and it's `react:react-babel`'s `config` hook that emits\n * the offending `optimizeDeps.rollupOptions.jsx`. `nifra.config.ts` writes `vitePlugins = [react()]`, so the\n * plugin list arrives NESTED (`[[babel, refresh]]`). Without flattening, `.map` sees the inner array (which\n * has no `config`), leaves it untouched, and Vite — which flattens plugin arrays itself before running them\n * — then executes the un-stripped babel hook, so the warning survives. Flattening here (Vite accepts a flat\n * list identically) is what lets the strip reach every real plugin.\n */"
|
|
3431
3712
|
},
|
|
3432
3713
|
{
|
|
3433
3714
|
"name": "number",
|
|
@@ -3560,6 +3841,13 @@
|
|
|
3560
3841
|
"signature": "export declare function packageOf(spec: string): string | undefined;",
|
|
3561
3842
|
"doc": "/**\n * Resolve an import specifier to the npm package name it would install as, or `undefined` when it isn't\n * an npm dependency at all (a relative/absolute path, a runtime builtin, or a malformed scope like the\n * `@/…` path-alias convention). `@scope/name/sub` → `@scope/name`; `name/sub` → `name`.\n */"
|
|
3562
3843
|
},
|
|
3844
|
+
{
|
|
3845
|
+
"name": "Page",
|
|
3846
|
+
"kind": "interface",
|
|
3847
|
+
"package": "@nifrajs/schema",
|
|
3848
|
+
"signature": "export interface Page<Item> {\n readonly items: Item[];\n readonly nextCursor: string | null;\n}",
|
|
3849
|
+
"doc": "/** A cursor-pagination page — matches the shape of `t.paginated(item)`. */"
|
|
3850
|
+
},
|
|
3563
3851
|
{
|
|
3564
3852
|
"name": "PageRouteInput",
|
|
3565
3853
|
"kind": "interface",
|
|
@@ -3574,6 +3862,13 @@
|
|
|
3574
3862
|
"signature": "export declare function pageRoutesSection(manifest: Manifest | undefined): string;",
|
|
3575
3863
|
"doc": "/** Markdown section listing the file-routed pages (URL pattern → source file). */"
|
|
3576
3864
|
},
|
|
3865
|
+
{
|
|
3866
|
+
"name": "paginate",
|
|
3867
|
+
"kind": "function",
|
|
3868
|
+
"package": "@nifrajs/schema",
|
|
3869
|
+
"signature": "export declare function paginate<Row>(rows: readonly Row[], limit: number, cursorOf: (row: Row) => unknown): Page<Row>;",
|
|
3870
|
+
"doc": "/**\n * Build a page from rows you fetched with `limit + 1`. If the extra row came back there are more pages:\n * drop it and emit a `nextCursor` from the last KEPT row via `cursorOf`; otherwise `nextCursor` is `null`.\n *\n * const rows = await db.notes.after(decodeCursor(query.cursor)).take(limit + 1)\n * return paginate(rows, limit, (note) => note.id)\n */"
|
|
3871
|
+
},
|
|
3577
3872
|
{
|
|
3578
3873
|
"name": "Params",
|
|
3579
3874
|
"kind": "type",
|
|
@@ -3909,6 +4204,20 @@
|
|
|
3909
4204
|
"signature": "export declare function projectTools(cwd: string, loadAppCached?: (outDirName?: string) => Promise<LoadedApp>): McpTool[];",
|
|
3910
4205
|
"doc": "/** Build the project-scoped tools for `cwd`. */"
|
|
3911
4206
|
},
|
|
4207
|
+
{
|
|
4208
|
+
"name": "PromptArgument",
|
|
4209
|
+
"kind": "interface",
|
|
4210
|
+
"package": "@nifrajs/core",
|
|
4211
|
+
"signature": "export interface PromptArgument {\n readonly name: string;\n readonly description?: string;\n readonly required?: boolean;\n}",
|
|
4212
|
+
"doc": "/** One declared argument of an MCP prompt, surfaced in `prompts/list`. */"
|
|
4213
|
+
},
|
|
4214
|
+
{
|
|
4215
|
+
"name": "PromptMessage",
|
|
4216
|
+
"kind": "interface",
|
|
4217
|
+
"package": "@nifrajs/core",
|
|
4218
|
+
"signature": "export interface PromptMessage {\n readonly role: \"user\" | \"assistant\";\n readonly content: {\n readonly type: \"text\";\n readonly text: string;\n };\n}",
|
|
4219
|
+
"doc": "/** A message in an MCP prompt's rendered output (see {@link Server.prompt}). */"
|
|
4220
|
+
},
|
|
3912
4221
|
{
|
|
3913
4222
|
"name": "PROTOCOL_VERSION",
|
|
3914
4223
|
"kind": "const",
|
|
@@ -3930,6 +4239,12 @@
|
|
|
3930
4239
|
"signature": "export declare function publicEnvDefines(prefix: string, env: Readonly<Record<string, string | undefined>>): Record<string, string>;",
|
|
3931
4240
|
"doc": "/**\n * The `process.env.<NAME>` → `JSON.stringify(value)` define entries for every env var whose name\n * carries `prefix` (the Vite/Next public-env convention). Exposing ONLY the prefixed vars is the\n * security boundary: an unprefixed var (a secret) never gets a define, so the bare `process.env`\n * define resolves it to `undefined` in the client bundle. An empty `prefix` exposes nothing (the\n * opt-out). Pure + exported so the prefix/redaction contract is unit-testable without a real build.\n */"
|
|
3932
4241
|
},
|
|
4242
|
+
{
|
|
4243
|
+
"name": "PutOptions",
|
|
4244
|
+
"kind": "interface",
|
|
4245
|
+
"package": "@nifrajs/storage",
|
|
4246
|
+
"signature": "export interface PutOptions {\n /** MIME type stored alongside the object (returned by `get`). */\n readonly contentType?: string;\n /** Arbitrary string metadata stored with the object. */\n readonly metadata?: Readonly<Record<string, string>>;\n}"
|
|
4247
|
+
},
|
|
3933
4248
|
{
|
|
3934
4249
|
"name": "QueryClient",
|
|
3935
4250
|
"kind": "interface",
|
|
@@ -3990,12 +4305,44 @@
|
|
|
3990
4305
|
"signature": "export type QueryValue = string | string[];",
|
|
3991
4306
|
"doc": "/** A query value: a single occurrence is a string; a repeated key promotes to a string[] so an\n * array query schema (`t.array(t.string())`) can validate `?tag=a&tag=b` — last-wins silently\n * dropped values before (audit 2026-06). Single-occurrence keys stay plain strings, so existing\n * `t.string()` schemas are untouched; a repeated key against a string schema now FAILS validation\n * (an explicit 400 beats silently picking one). */"
|
|
3992
4307
|
},
|
|
4308
|
+
{
|
|
4309
|
+
"name": "Queue",
|
|
4310
|
+
"kind": "interface",
|
|
4311
|
+
"package": "@nifrajs/jobs",
|
|
4312
|
+
"signature": "export interface Queue {\n /** Register a typed job. Throws now (not at run time) on a duplicate name. */\n define<Payload>(name: string, definition: JobDefinition<Payload>): JobHandle<Payload>;\n /** Enqueue by name (the {@link JobHandle} is the typed alternative). */\n enqueue(name: string, payload: unknown, options?: EnqueueOptions): Promise<string>;\n /** Run ONE poll round: lease up to `concurrency` due jobs, run them, await them. Returns the count run.\n * Re-entrant-safe (a concurrent call returns the in-flight round). Used by `start()` and by Workers. */\n process(): Promise<number>;\n /** Process repeatedly until no job is due (one-shot batch drain). */\n drain(): Promise<number>;\n /** Start the background worker (Bun/Node/Deno). */\n start(options?: WorkerOptions): Worker;\n /** Current store counts. */\n counts(): JobCounts | Promise<JobCounts>;\n /** The underlying store (for dead-letter inspection, custom drivers). */\n readonly store: JobStore;\n}"
|
|
4313
|
+
},
|
|
4314
|
+
{
|
|
4315
|
+
"name": "QueueOptions",
|
|
4316
|
+
"kind": "interface",
|
|
4317
|
+
"package": "@nifrajs/jobs",
|
|
4318
|
+
"signature": "export interface QueueOptions {\n /** Persistence. Default: a fresh {@link MemoryJobStore} (single-process). */\n readonly store?: JobStore;\n /** Called when a handler throws (before retry/dead-letter). Default: `console.error`. A throwing handler here is swallowed. */\n readonly onError?: (error: unknown, jobName: string) => void;\n /** Injectable clock (tests). Default `() => Date.now()`. */\n readonly now?: () => number;\n /** Default attempts for jobs that don't set `retries`. Default 3. */\n readonly defaultAttempts?: number;\n /** Default backoff for jobs that don't set one. Default {@link exponentialBackoff}. */\n readonly backoff?: Backoff;\n}"
|
|
4319
|
+
},
|
|
3993
4320
|
{
|
|
3994
4321
|
"name": "quotedHeaderValue",
|
|
3995
4322
|
"kind": "function",
|
|
3996
4323
|
"package": "@nifrajs/middleware",
|
|
3997
4324
|
"signature": "export declare function quotedHeaderValue(value: string): string;"
|
|
3998
4325
|
},
|
|
4326
|
+
{
|
|
4327
|
+
"name": "R2BucketLike",
|
|
4328
|
+
"kind": "interface",
|
|
4329
|
+
"package": "@nifrajs/storage",
|
|
4330
|
+
"signature": "export interface R2BucketLike {\n put(key: string, value: ArrayBuffer | ArrayBufferView, options?: {\n httpMetadata?: {\n contentType?: string;\n };\n customMetadata?: Record<string, string>;\n }): Promise<unknown>;\n get(key: string): Promise<(R2ObjectLike & {\n arrayBuffer(): Promise<ArrayBuffer>;\n }) | null>;\n head(key: string): Promise<R2ObjectLike | null>;\n delete(key: string): Promise<void>;\n list(options?: {\n prefix?: string;\n limit?: number;\n }): Promise<{\n objects: ReadonlyArray<{\n key: string;\n }>;\n }>;\n}",
|
|
4331
|
+
"doc": "/** The slice of the R2 bucket binding this adapter calls. `env.<BUCKET>` satisfies it. */"
|
|
4332
|
+
},
|
|
4333
|
+
{
|
|
4334
|
+
"name": "R2ObjectLike",
|
|
4335
|
+
"kind": "interface",
|
|
4336
|
+
"package": "@nifrajs/storage",
|
|
4337
|
+
"signature": "export interface R2ObjectLike {\n readonly size: number;\n readonly httpMetadata?: {\n readonly contentType?: string;\n };\n readonly customMetadata?: Record<string, string>;\n}",
|
|
4338
|
+
"doc": "/** The slice of R2's object metadata this adapter reads. */"
|
|
4339
|
+
},
|
|
4340
|
+
{
|
|
4341
|
+
"name": "R2Storage",
|
|
4342
|
+
"kind": "class",
|
|
4343
|
+
"package": "@nifrajs/storage",
|
|
4344
|
+
"signature": "export declare class R2Storage implements StorageAdapter {\n private readonly bucket;\n constructor(bucket: R2BucketLike);\n put(key: string, data: StorageData, options?: PutOptions): Promise<void>;\n get(key: string): Promise<StorageObject | null>;\n delete(key: string): Promise<void>;\n exists(key: string): Promise<boolean>;\n list(options?: ListOptions): Promise<string[]>;\n}"
|
|
4345
|
+
},
|
|
3999
4346
|
{
|
|
4000
4347
|
"name": "rateLimit",
|
|
4001
4348
|
"kind": "function",
|
|
@@ -4156,7 +4503,7 @@
|
|
|
4156
4503
|
"name": "RegistryFromImpl",
|
|
4157
4504
|
"kind": "type",
|
|
4158
4505
|
"package": "@nifrajs/core",
|
|
4159
|
-
"signature": "export type RegistryFromImpl<C extends ContractShape, H extends HandlersFor<C>> = {\n [P in C[keyof C][\"path\"]]: {\n [K in keyof C as C[K][\"path\"] extends P ? C[K][\"method\"] : never]: {\n readonly params: Params<C[K][\"path\"]>;\n readonly query: OpQuery<C[K]>;\n readonly body: OpBody<C[K]>;\n readonly output: C[K] extends {\n response: infer R extends StandardSchemaV1;\n } ? InferOutput<R> : H[K] extends AnyFn ? OutputOf<H[K]> : unknown;\n };\n };\n};",
|
|
4506
|
+
"signature": "export type RegistryFromImpl<C extends ContractShape, H extends HandlersFor<C>> = {\n [P in C[keyof C][\"path\"]]: {\n [K in keyof C as C[K][\"path\"] extends P ? C[K][\"method\"] : never]: {\n readonly params: Params<C[K][\"path\"]>;\n readonly query: OpQuery<C[K]>;\n readonly body: OpBody<C[K]>;\n readonly output: C[K] extends {\n response: infer R extends StandardSchemaV1;\n } ? InferOutput<R> : H[K] extends AnyFn ? OutputOf<H[K]> : unknown;\n readonly errors: OpErrors<C[K]>;\n };\n };\n};",
|
|
4160
4507
|
"doc": "/**\n * The registry produced by `implement`: input from the contract op; `output` is the declared `response`\n * contract when present (it wins — exactly as in the inline path), else the bound HANDLER's return — so\n * the implemented server stays route-for-route identical to the equivalent inline server (the\n * mode-conformance guarantee), and a contract-typed client and a `typeof app`-typed client agree.\n */"
|
|
4161
4508
|
},
|
|
4162
4509
|
{
|
|
@@ -4422,6 +4769,13 @@
|
|
|
4422
4769
|
"signature": "export declare function resolvePlugins(field: PluginsField | undefined): Promise<unknown[]>;",
|
|
4423
4770
|
"doc": "/** Normalize a {@link PluginsField} (array | thunk | undefined) to a fresh array, awaiting a thunk. */"
|
|
4424
4771
|
},
|
|
4772
|
+
{
|
|
4773
|
+
"name": "resolveProjectDir",
|
|
4774
|
+
"kind": "function",
|
|
4775
|
+
"package": "@nifrajs/cli",
|
|
4776
|
+
"signature": "export declare function resolveProjectDir(root: string, dir: string | undefined): string | null;",
|
|
4777
|
+
"doc": "/**\n * Resolve an optional `dir` tool argument — a subdirectory of the project root the caller wants to scope a\n * check/test to (e.g. `nifra check` on `app/` when the MCP server's root is a monorepo). Returns the\n * absolute target, or `null` if `dir` escapes the root (a path-traversal guard: no `..` out, no absolute\n * path elsewhere). `undefined`/empty → the root itself.\n */"
|
|
4778
|
+
},
|
|
4425
4779
|
{
|
|
4426
4780
|
"name": "resolveServerOnlyChains",
|
|
4427
4781
|
"kind": "function",
|
|
@@ -4480,8 +4834,14 @@
|
|
|
4480
4834
|
"name": "Result",
|
|
4481
4835
|
"kind": "type",
|
|
4482
4836
|
"package": "@nifrajs/client",
|
|
4483
|
-
"signature": "export type Result<Data> = {\n readonly ok: true;\n readonly status: number;\n readonly data: Data;\n readonly error: null;\n} | {\n readonly ok: false;\n readonly status: number;\n readonly data:
|
|
4484
|
-
"doc": "/**\n * The outcome of a client call. The client never throws — inspect `ok`
|
|
4837
|
+
"signature": "export type Result<Data, ErrData = unknown> = {\n readonly ok: true;\n readonly status: number;\n readonly data: Data;\n readonly error: null;\n} | {\n readonly ok: false;\n readonly status: number;\n readonly data: ErrData;\n readonly error: ApiError;\n};",
|
|
4838
|
+
"doc": "/**\n * The outcome of a client call. The client never throws — inspect `ok` to branch.\n * `data` is the parsed response body, **typed by `ok`**: on success it's the route's\n * response type; on failure it's the parsed error body, typed from the route's\n * `errors` contract (`unknown` when the route declares none, `null` on a transport\n * error with no response body). `error` is always the server's normalized\n * `{ error, issues? }` summary on failure (or a transport error), `null` on success.\n */"
|
|
4839
|
+
},
|
|
4840
|
+
{
|
|
4841
|
+
"name": "RetryPolicy",
|
|
4842
|
+
"kind": "interface",
|
|
4843
|
+
"package": "@nifrajs/jobs",
|
|
4844
|
+
"signature": "export interface RetryPolicy {\n /** Total attempts before dead-lettering (incl. the first). Default 3. `1` = no retries. */\n readonly attempts: number;\n /** Delay before each retry. Default {@link exponentialBackoff}. */\n readonly backoff?: Backoff;\n}"
|
|
4485
4845
|
},
|
|
4486
4846
|
{
|
|
4487
4847
|
"name": "revalidate",
|
|
@@ -4543,6 +4903,13 @@
|
|
|
4543
4903
|
"signature": "export declare const ROUTE_GLOBAL = \"__NIFRA_ROUTE__\";",
|
|
4544
4904
|
"doc": "/** Global the server writes the matched route id into; the client uses it to pick the chain. */"
|
|
4545
4905
|
},
|
|
4906
|
+
{
|
|
4907
|
+
"name": "RouteBody",
|
|
4908
|
+
"kind": "type",
|
|
4909
|
+
"package": "@nifrajs/web",
|
|
4910
|
+
"signature": "export type RouteBody<App, Path extends string, Method extends string> = Path extends keyof RegistryOf<App> ? Uppercase<Method> extends keyof RegistryOf<App>[Path] ? (RegistryOf<App>[Path][Uppercase<Method>] & RouteInfo)[\"body\"] : never : never;",
|
|
4911
|
+
"doc": "/** The body object type of `App`'s `Method Path` route (`never` when the route declares no body). */"
|
|
4912
|
+
},
|
|
4546
4913
|
{
|
|
4547
4914
|
"name": "RouteConfigError",
|
|
4548
4915
|
"kind": "class",
|
|
@@ -4561,7 +4928,7 @@
|
|
|
4561
4928
|
"name": "RouteDescriptor",
|
|
4562
4929
|
"kind": "interface",
|
|
4563
4930
|
"package": "@nifrajs/core",
|
|
4564
|
-
"signature": "export interface RouteDescriptor {\n readonly method: Method;\n readonly path: string;\n readonly schema: RouteSchema | undefined;\n}",
|
|
4931
|
+
"signature": "export interface RouteDescriptor {\n readonly method: Method;\n readonly path: string;\n readonly schema: RouteSchema | undefined;\n readonly tool?: {\n readonly name: string;\n readonly description: string;\n readonly annotations?: ToolAnnotations;\n };\n}",
|
|
4565
4932
|
"doc": "/**\n * A registered route's public descriptor — method, path, and input schemas. The\n * router trie discards the original patterns, so this flat list is what lets tools\n * (e.g. `toOpenAPI`) enumerate routes after registration.\n */"
|
|
4566
4933
|
},
|
|
4567
4934
|
{
|
|
@@ -4575,14 +4942,14 @@
|
|
|
4575
4942
|
"name": "RouteInfo",
|
|
4576
4943
|
"kind": "interface",
|
|
4577
4944
|
"package": "@nifrajs/core",
|
|
4578
|
-
"signature": "export interface RouteInfo {\n readonly params: object;\n readonly query: unknown;\n readonly body: unknown;\n readonly output: unknown;\n}",
|
|
4945
|
+
"signature": "export interface RouteInfo {\n readonly params: object;\n readonly query: unknown;\n readonly body: unknown;\n readonly output: unknown;\n /** Union of the route's declared error-response body types (from `schema.errors`); `unknown` when the\n * route declares none. Surfaced by the typed client as the failure `errorData`. */\n readonly errors?: unknown;\n}",
|
|
4579
4946
|
"doc": "/**\n * One route's input/output shape as the **client** will consume it. `query`/`body`\n * are `never` when the route declares no schema for them, so the client can detect\n * \"this route takes no body\" via `[body] extends [never]`. `output` is the\n * handler's raw return type (the client applies `Jsonify` when reading it).\n */"
|
|
4580
4947
|
},
|
|
4581
4948
|
{
|
|
4582
4949
|
"name": "RouteInfoFor",
|
|
4583
4950
|
"kind": "type",
|
|
4584
4951
|
"package": "@nifrajs/core",
|
|
4585
|
-
"signature": "export type RouteInfoFor<Path extends string, S extends RouteSchema, Output> = {\n readonly params: Params<Path>;\n readonly query: RegistryQuery<S>;\n readonly body: RegistryBody<S>;\n readonly output: RegistryOutput<S, Output>;\n};",
|
|
4952
|
+
"signature": "export type RouteInfoFor<Path extends string, S extends RouteSchema, Output> = {\n readonly params: Params<Path>;\n readonly query: RegistryQuery<S>;\n readonly body: RegistryBody<S>;\n readonly output: RegistryOutput<S, Output>;\n readonly errors: RegistryErrors<S>;\n};",
|
|
4586
4953
|
"doc": "/** Build a {@link RouteInfo} from a route's path, schema, and handler output type. */"
|
|
4587
4954
|
},
|
|
4588
4955
|
{
|
|
@@ -4627,6 +4994,13 @@
|
|
|
4627
4994
|
"signature": "export interface RouteModule {\n readonly default: unknown;\n readonly loader?: Loader;\n readonly action?: Action;\n readonly meta?: MetaInput;\n /**\n * Opt this route out of nifra's full-document client hydration. The server still renders the full\n * HTML document, loaders/actions still run, and native links/forms still work; the generated app\n * client, route chunks, and loader globals are omitted for hard navigations. Intended for static or\n * island-hydrated pages where interactivity is mounted by smaller, explicit client entries.\n */\n readonly hydrate?: boolean;\n /**\n * Opt a **static** route (no `:param`/`*`) into build-time prerendering (SSG): `prerenderRoutes`\n * (from `@nifrajs/web/build`) renders it to a static `index.html` at build. The loader runs at build\n * with the in-process `api` (build-safe data only — no per-request cookies/secrets); `defer()` on a\n * prerendered route resolves at build. For **dynamic** routes use {@link getStaticPaths} instead.\n */\n readonly prerender?: boolean;\n /**\n * Enumerate the concrete params to prerender for a **dynamic** (`:param`) route — the SSG path list\n * (blogs/docs/etc.). Runs at build; `prerenderRoutes` renders one `index.html` per returned path.\n */\n readonly getStaticPaths?: GetStaticPaths;\n /**\n * ISR freshness for this route, in **seconds**. `createWebApp` emits it as an `x-nifra-revalidate`\n * response header that `withISR` reads to set the page's cache TTL (overriding the wrapper's\n * default). Older-than-`revalidate` cached pages are served stale while regenerating.\n */\n readonly revalidate?: number;\n /**\n * No-framework island bundles (`@nifrajs/web/islands`) to load on this route, as `<script\n * type=\"module\">` in the document tail. Loaded **regardless of `hydrate`** — pair with\n * `export const hydrate = false` for a static page that ships zero framework JS and mounts\n * interactivity through `<Island>` markers + `mountIslands` enhancers instead.\n */\n readonly islandScripts?: readonly string[];\n}",
|
|
4628
4995
|
"doc": "/** A route module — the default component + optional loader / action / meta. */"
|
|
4629
4996
|
},
|
|
4997
|
+
{
|
|
4998
|
+
"name": "RoutePaths",
|
|
4999
|
+
"kind": "type",
|
|
5000
|
+
"package": "@nifrajs/web",
|
|
5001
|
+
"signature": "export type RoutePaths<App> = keyof RegistryOf<App> & string;",
|
|
5002
|
+
"doc": "/** Every route path the app declares — constrains `Path`, so a wrong path is itself a type error. */"
|
|
5003
|
+
},
|
|
4630
5004
|
{
|
|
4631
5005
|
"name": "routePathToFile",
|
|
4632
5006
|
"kind": "function",
|
|
@@ -4666,7 +5040,7 @@
|
|
|
4666
5040
|
"name": "RouteSchema",
|
|
4667
5041
|
"kind": "interface",
|
|
4668
5042
|
"package": "@nifrajs/core",
|
|
4669
|
-
"signature": "export interface RouteSchema {\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n /** Optional **response contract**. When declared: the handler's return is type-checked against it\n * (the implementation can't drift from the contract), the typed client sees THIS as the response type\n * (the contract — not the handler's incidental return), and it's emitted into OpenAPI/JSON-Schema so\n * tooling and coding agents can read the exact shape. It is **not** validated at runtime (zero\n * hot-path cost) — purely a compile-time + introspection contract. */\n readonly response?: StandardSchemaV1;\n}",
|
|
5043
|
+
"signature": "export interface RouteSchema {\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n /** Optional **response contract**. When declared: the handler's return is type-checked against it\n * (the implementation can't drift from the contract), the typed client sees THIS as the response type\n * (the contract — not the handler's incidental return), and it's emitted into OpenAPI/JSON-Schema so\n * tooling and coding agents can read the exact shape. It is **not** validated at runtime (zero\n * hot-path cost) — purely a compile-time + introspection contract. */\n readonly response?: StandardSchemaV1;\n /**\n * Optional **error-response contract**: a map of HTTP status code → the Standard Schema of that error's\n * body. Declares a route's failure modes so they flow into OpenAPI (as non-2xx `responses`), the\n * `/llms.txt` context, and other introspection — the whole contract, not just the happy path, is legible\n * to tooling and coding agents. Like `response`, it is **not** validated at runtime (zero hot-path cost);\n * it's a compile-time + introspection contract. Example: `{ 404: NotFound, 409: Conflict }`. */\n readonly errors?: Readonly<Record<number, StandardSchemaV1>>;\n /**\n * Hook fired when the request fails `body`/`query` validation, before the handler runs. `kind` says\n * which input failed (`\"body\"` | `\"query\"`). Its return value selects one of three outcomes (may be async):\n * - a **`Response`** → returned as-is, short-circuiting the route (custom error envelope, redirect, …).\n * - **any other value** → treated as a repaired payload and **re-validated once** against the same\n * schema. If it now passes, the handler runs with it; if it still fails, the original `422` stands.\n * Re-validation means a bad return can't bypass the schema — the trust boundary holds.\n * - **`undefined`** → give up; the original validation `422` is returned unchanged.\n * A route hook **overrides** the app-wide default set via `server({ onValidationError })`; return\n * `undefined` to fall through to the plain `422` even when an app default exists. Typical uses: a custom\n * error envelope, coercing the input, or prompting an LLM to repair the payload (re-validated, so it can't\n * bypass the schema).\n */\n readonly onValidationError?: (issues: ReadonlyArray<StandardIssue>, ctx: Context, kind: \"body\" | \"query\") => Response | unknown | Promise<Response | unknown>;\n}",
|
|
4670
5044
|
"doc": "/** Per-route input schemas. Each is any Standard Schema (zod/valibot/arktype/…). */"
|
|
4671
5045
|
},
|
|
4672
5046
|
{
|
|
@@ -5112,7 +5486,7 @@
|
|
|
5112
5486
|
"name": "Server",
|
|
5113
5487
|
"kind": "class",
|
|
5114
5488
|
"package": "@nifrajs/core",
|
|
5115
|
-
"signature": "export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext> {\n private readonly router;\n /** WebSocket routes, matched separately at upgrade time (a GET + `Upgrade: websocket`). */\n private readonly wsRouter;\n private wsRouteCount;\n /** In-process pub/sub backing `ws.subscribe(topic)` + `app.publish(topic, data)` (single-instance).\n * Created by the first `app.ws()` via the `@nifrajs/core/ws` runtime — `undefined` until then, so a\n * no-WebSocket app never constructs (or bundles) it. */\n private topics;\n private readonly routeList;\n private readonly maxBodyBytes;\n private readonly wsMaxPayloadBytes;\n private readonly requestTimeoutMs;\n private readonly gracefulSignals;\n private readonly logger;\n private bunServer;\n private readonly derives;\n private readonly decorations;\n private readonly beforeHandleHooks;\n private readonly afterHandleHooks;\n private readonly onErrorHooks;\n private readonly aroundHooks;\n private readonly onRequestHooks;\n private readonly onResponseHooks;\n private readonly responseRequests;\n /** Names of plugins/middleware already applied via `use` — for idempotent dedupe. */\n private readonly appliedPlugins;\n constructor(options?: ServerOptions);\n /** Add a per-request, computed context extension for subsequent routes. */\n derive<D extends object>(fn: (context: Context & Ctx) => MaybePromise<D>): Server<R, Ctx & D>;\n /** Add a static context value for subsequent routes. */\n decorate<const K extends string, V>(key: K, value: V): Server<R, Ctx & Record<K, V>>;\n /**\n * Run before routing on the raw request. Return a `Response` to short-circuit, or a replacement\n * `Request` to continue routing with a rewritten method/URL/headers. Global.\n */\n onRequest(fn: (req: Request) => MaybePromise<OnRequestResult>): this;\n /** Run after validation, before the handler; a non-`undefined` return short-circuits. Order-scoped. */\n beforeHandle(fn: (context: Context & Ctx) => MaybePromise<unknown>): this;\n /**\n * Wrap the matched route lifecycle for subsequent routes. This is intentionally generic over the\n * route output, so wrappers like async context storage do not force Node's direct JSON path through\n * a Web `Response`. The first registered wrapper is outermost.\n */\n around(fn: <T>(context: Context & Ctx, next: () => MaybePromise<T>) => MaybePromise<T>): this;\n /** Transform the handler's result before it is serialized. Order-scoped. */\n afterHandle(fn: (result: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Handle a thrown error; a non-`undefined` return becomes the response (else the default 500). Order-scoped. */\n onError(fn: (error: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Transform every outgoing response — success, error, 404, 405, short-circuit. Global. */\n onResponse(fn: (response: Response, req: Request) => MaybePromise<Response>): this;\n /**\n * Apply a type-**identity** plugin ({@link IdentityPlugin}, from {@link defineIdentityPlugin}) — it\n * registers routes/hooks but doesn't change the types, so this returns `this` with the route registry\n * and context fully intact. This overload exists specifically so a *named* identity plugin (e.g.\n * `@nifrajs/better-auth`) threads the registry: its `& { pluginName }` intersection would otherwise\n * defeat the generic inference of the transforming overload below and collapse the result to `any`.\n */\n use(plugin: IdentityPlugin): this;\n /**\n * Apply a **plugin function** — `(app) => app`, typically built with {@link definePlugin}. It's\n * called with `this` and its result is returned, so an inline plugin's `derive`/`decorate` thread\n * the added context to handlers defined after `use` (the overload is generic over the concrete\n * `this`). A named plugin already applied is skipped (idempotent dedupe).\n */\n use<Out extends AnyServer>(plugin: (app: this) => Out): Out;\n /**\n * Apply a {@link Middleware} bundle — wire each hook it provides to its lifecycle point. Returns\n * `this` (no context-type merging); call it before the routes its `beforeHandle`/`afterHandle`\n * should cover (those are order-scoped; `onRequest`/`onResponse` are global). A named bundle already\n * applied is skipped (idempotent).\n */\n use(mw: Middleware): this;\n get<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n get<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n post<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n post<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n put<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n put<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n patch<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PATCH\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n 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>;\n 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>;\n 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>;\n /**\n * Register a **WebSocket** route. The connection upgrades on a `GET` to `path` carrying\n * `Upgrade: websocket`; the optional `handler.upgrade(c)` runs in the request context first and may\n * reject (return a `Response`) or seed per-connection `ws.data`. WebSockets are served by the\n * adapter (`listen()`, `@nifrajs/node`, `@nifrajs/deno`, `toFetchHandler`) — not by bare `app.fetch`, which\n * has no socket (a WS path through `app.fetch` is a normal HTTP response).\n *\n * app.ws(\"/chat\", { open: (ws) => ws.send(\"hi\"), message: (ws, data) => ws.send(data) })\n */\n ws<Data = unknown, Schema extends StandardSchemaV1 | undefined = undefined>(path: string, handler: WebSocketHandler<Data, EnvOf<Ctx>, Schema>): this;\n /**\n * Broadcast `data` to every WebSocket connection subscribed to `topic` (via `ws.subscribe(topic)`).\n * In-process and **single-instance** (see {@link TopicRegistry}) — a multi-instance deploy must bridge\n * an external fan-out (Redis, a Durable Object) to this. A no-op when nobody is subscribed.\n */\n publish(topic: string, data: string | ArrayBufferView | ArrayBuffer): void;\n private route;\n /**\n * Low-level route registration shared by the inline builder and `implement()`.\n * Captures the server's current `derive`/`decorate` chain into the route — this\n * is the \"compiled\", order-scoped per-route chain.\n */\n register(method: Method, path: string, schema: RouteSchema | undefined, handler: (context: never) => unknown): void;\n /**\n * Enumerate the registered routes (method, path, input schemas), in registration\n * order. Powers `toOpenAPI` and other introspection; the router trie itself no\n * longer holds the original patterns.\n */\n routes(): ReadonlyArray<RouteDescriptor>;\n /**\n * Resolve a `Request` to a `Response` — the whole lifecycle, testable without a port. The\n * optional `platform` carries edge inputs (`env`, `waitUntil`); edge adapters pass it, and\n * Bun/Node/Deno omit it (then `c.env` is `undefined` and `c.waitUntil` runs fire-and-forget).\n */\n fetch(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<Response>;\n private fetchSource;\n /**\n * Like {@link fetch}, but renders a plain-data result **without** building a Web `Response` — the\n * `@nifrajs/node` adapter serializes the returned primitives straight to the socket, skipping the undici\n * `Response` build + body drain (the bulk of the Node bridge cost, measured ≈4µs/req). A handler that\n * returns a `Response`, an error/short-circuit, or any registered `onResponse` hook falls back to the\n * full Web path (`{ kind: \"response\" }`), so behavior is identical — only the common JSON-data case is\n * faster. Same lifecycle as {@link fetch} (body cap, validation, hooks all run); only the final\n * render differs.\n */\n resolveNode(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;\n resolveNodeSource(source: RequestSource, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;\n /**\n * Resolve a WebSocket upgrade — the seam every serving adapter uses. Returns `pass` (not a WS\n * upgrade for a registered route → handle as normal HTTP), `reject` (a WS route matched but\n * `upgrade()` rejected, or the path was malformed → return `response`), or `upgrade` (perform the\n * runtime upgrade, then dispatch the native socket's events to `handler`, seeding `ws.data` with\n * `data`). Runs the route's `upgrade(c)` guard in a real request context. Synchronous unless\n * `upgrade()` is async; a throw rejects with a flat 500 (no detail leaked).\n */\n resolveWebSocketUpgrade(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<WebSocketUpgradeOutcome>;\n /** Bun `fetch` when WS routes exist: try a WS upgrade first, else run the normal HTTP lifecycle.\n * `undefined` ⇒ Bun owns the upgraded socket; a `Response` ⇒ a normal reply or a rejected upgrade.\n * (The socket dispatch itself lives in `ws-bun.ts`, loaded via `@nifrajs/core/ws`.) */\n private bunFetchWithWebSocket;\n /**\n * The shared lifecycle, generic over how the final value is rendered: `finalize` turns a handler's\n * result + `set` into the output `T` (`toResponse` → a Web `Response`; `toNodeOutcome` → node-direct\n * primitives), `wrapResponse` lifts an early/error `Response` into that same `T`, and `onTimeout`\n * produces the 503. The Web `fetch` and `resolveNode` are thin callers over this one routing +\n * context + lifecycle implementation — no duplication across the trust boundary.\n */\n private dispatch;\n /**\n * onRequest short-circuit path. Synchronous as long as every hook returns synchronously (the\n * common case — e.g. CORS returning `undefined` for a non-preflight request): an `async` version\n * here put EVERY request of any app with one onRequest hook onto the promise machinery, profiled\n * at ~13% of a realistic request. The first hook that returns a Promise hands the REMAINING\n * hooks to the async continuation; behavior is identical.\n */\n private runWithOnRequest;\n /** Async tail of {@link runWithOnRequest}: applies the first awaited hook's outcome, then runs\n * the remaining hooks (awaiting freely — we're already async here). */\n private continueOnRequest;\n private takeResponseRequest;\n /**\n * Route → build context → run. Synchronous through to the handler for a **bare** route\n * ({@link RouteEntry.bare}), so a sync handler produces its result with zero promise allocations;\n * routes with validation/hooks keep the full async {@link runLifecycle}, unchanged.\n */\n private routeAndRun;\n /** The narrowest bare route: a syntactic `() => ...` handler cannot observe the context argument, so\n * successful requests can skip allocating `RequestContext`. Errors still allocate one for logging. */\n private runContextlessBare;\n private contextlessBareError;\n /**\n * The synchronous fast path for a {@link RouteEntry.bare} route: apply static decorations, call the\n * handler, render the result — **no `await`** unless the handler itself returns a promise. It mirrors\n * the bare slice of {@link runLifecycle} (which a bare route would otherwise no-op through) and shares\n * {@link logRequestError}; a bare route has no `onError` hooks, so error handling is fully synchronous\n * (a thrown `Response` is control flow; anything else is a logged flat 500). This is where nifra skips\n * the per-request async-frame tax — the same win codegen routers get, but without `eval`.\n */\n private runBare;\n /** Bare-route error rendering — identical to {@link runLifecycle}'s catch minus the (absent) onError\n * loop: a thrown `Response` is returned as deliberate control flow; anything else is logged + 500. */\n /**\n * Build a route's fused Web lane (see {@link RouteEntry.fusedWeb}). Composition happens once at\n * registration; the returned closure is what every request to the route runs. Behavior is\n * byte-identical to the generic `runBare`/`runContextlessBare` + `toResponse` pair — same\n * decoration order, same error routing (thrown `Response` = control flow; anything else logs and\n * 500s), same respond semantics (the lifecycle parity suite pins it).\n */\n private buildFusedWeb;\n private bareError;\n private runWithAround;\n private runAround;\n private runBodyOnly;\n /** Validate + run the handler for the bodyOnly path — shared by the inline fast path and the\n * streaming fallback. A method (not per-request closures) so the hot path allocates nothing\n * beyond the one `.then` continuation. */\n private finishBodyOnly;\n private applyBodyValidation;\n private runQueryOnly;\n /** Validate-result → set `ctx.query` → run handler. A method (not a per-request closure), the\n * query analogue of {@link applyBodyValidation}. */\n private applyQueryValidation;\n /**\n * Thread the response through each global `onResponse` hook. Stays SYNCHRONOUS until a hook\n * actually returns a Promise — an `async` version forced a promise + microtask on EVERY response\n * of any app with an onResponse hook (cors/securityHeaders/etag/timing all use onResponse), the\n * same ~13%/req tax the onRequest walk was de-async'd to avoid. The first async hook hands the\n * rest to {@link continueOnResponse}.\n */\n private applyOnResponse;\n /** Async tail of {@link applyOnResponse}: runs the remaining hooks once one has gone async. */\n private continueOnResponse;\n /**\n * Bound the response time. On timeout we abort `ctx.signal` (so cancellation-aware\n * handlers can bail) and return 503; the in-flight work keeps running but its\n * result is discarded — JS can't forcibly cancel a promise.\n */\n private withTimeout;\n /**\n * The post-match lifecycle: validate → derive → beforeHandle → handler → afterHandle, with onError.\n * Generic over the render: a success value goes through `finalize(result, set)` (a Web `Response`, or\n * node-direct primitives); an early/error `Response` (validation, thrown, 500) through `wrapResponse`.\n */\n private runLifecycle;\n private handleLifecycleError;\n /** Log an unhandled request error to the (redacting) logger — shared by {@link runLifecycle} and the\n * bare fast path ({@link bareError}) so both record the same fields. Never throws; never leaks. */\n private logRequestError;\n private readAndValidateBody;\n /**\n * Read the body as text, capped at `maxBodyBytes`. Rejects (`null`) on a\n * `Content-Length` over the cap *before* buffering, and aborts mid-stream once the\n * running byte count exceeds it — so a lying or absent length can't force us to\n * buffer an oversized payload.\n *\n * Fast path: when a non-chunked request carries a `Content-Length` within the cap,\n * a native `req.json()` is already bounded — under HTTP/1.1 + HTTP/2 framing the\n * runtime delivers at most `Content-Length` bytes — so we skip the manual stream\n * loop and a separate text decode. It trusts the wire\n * *framing*, not the header value: nifra only ever receives framed Requests from the\n * runtime's HTTP server, never a hand-built one with a mismatched length. Chunked or\n * length-less bodies fall through to the streaming byte-cap guard below.\n */\n private readBoundedJson;\n /**\n * Start a `Bun.serve` instance bound to `port` (use `0` for an ephemeral port).\n *\n * `reusePort` sets `SO_REUSEPORT` so **multiple processes can bind the same port** and the kernel\n * load-balances connections across them — the standard way to use every core (Bun is\n * single-threaded per process). Spawn one process per core, each calling\n * `app.listen(PORT, { reusePort: true })`; see `examples/cluster.ts`. Every process must opt in,\n * and all of them must be the same app. Linux balances ~evenly; macOS accepts the flag but may\n * favor one socket (fine for dev, measure on Linux for production numbers).\n */\n listen(port: number, options?: {\n readonly reusePort?: boolean;\n }): RunningServer;\n /**\n * Gracefully stop: wait for in-flight requests to finish (up to `drainMs`), then\n * issue a single terminal stop — graceful if everything drained, forced if\n * stragglers remain. Safe to call when not listening.\n *\n * The Bun semantics: poll `pendingRequests` (awaiting\n * `stop()`'s promise drops in-flight requests), and decide graceful-vs-forced in\n * ONE call (Bun can't escalate an already-graceful `stop()` to a forced close).\n * New connections may be accepted during the drain window; in a real deploy the\n * load balancer has already stopped routing here, and `drainMs` bounds it.\n */\n stop({ drainMs }?: {\n drainMs?: number;\n }): Promise<void>;\n private installSignalHandlers;\n}",
|
|
5489
|
+
"signature": "export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext> {\n private readonly router;\n /** WebSocket routes, matched separately at upgrade time (a GET + `Upgrade: websocket`). */\n private readonly wsRouter;\n private wsRouteCount;\n /** In-process pub/sub backing `ws.subscribe(topic)` + `app.publish(topic, data)` (single-instance).\n * Created by the first `app.ws()` via the `@nifrajs/core/ws` runtime — `undefined` until then, so a\n * no-WebSocket app never constructs (or bundles) it. */\n private topics;\n private readonly routeList;\n private readonly maxBodyBytes;\n private readonly wsMaxPayloadBytes;\n private readonly requestTimeoutMs;\n private readonly gracefulSignals;\n private readonly logger;\n /** App-wide validation-error fallback; a route's own `schema.onValidationError` takes precedence. */\n private readonly defaultOnValidationError?;\n private bunServer;\n private readonly derives;\n private readonly decorations;\n private readonly beforeHandleHooks;\n private readonly afterHandleHooks;\n private readonly onErrorHooks;\n private readonly aroundHooks;\n private readonly onRequestHooks;\n private readonly onResponseHooks;\n private readonly responseRequests;\n /** Names of plugins/middleware already applied via `use` — for idempotent dedupe. */\n private readonly appliedPlugins;\n /** App-declared MCP resources / prompts (via {@link resource} / {@link prompt}), read by `nifra mcp`. */\n private readonly mcpResourceList;\n private readonly mcpPromptList;\n constructor(options?: ServerOptions);\n /** Add a per-request, computed context extension for subsequent routes. */\n derive<D extends object>(fn: (context: Context & Ctx) => MaybePromise<D>): Server<R, Ctx & D>;\n /** Add a static context value for subsequent routes. */\n decorate<const K extends string, V>(key: K, value: V): Server<R, Ctx & Record<K, V>>;\n /**\n * Run before routing on the raw request. Return a `Response` to short-circuit, or a replacement\n * `Request` to continue routing with a rewritten method/URL/headers. Global.\n */\n onRequest(fn: (req: Request) => MaybePromise<OnRequestResult>): this;\n /** Run after validation, before the handler; a non-`undefined` return short-circuits. Order-scoped. */\n beforeHandle(fn: (context: Context & Ctx) => MaybePromise<unknown>): this;\n /**\n * Wrap the matched route lifecycle for subsequent routes. This is intentionally generic over the\n * route output, so wrappers like async context storage do not force Node's direct JSON path through\n * a Web `Response`. The first registered wrapper is outermost.\n */\n around(fn: <T>(context: Context & Ctx, next: () => MaybePromise<T>) => MaybePromise<T>): this;\n /** Transform the handler's result before it is serialized. Order-scoped. */\n afterHandle(fn: (result: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Handle a thrown error; a non-`undefined` return becomes the response (else the default 500). Order-scoped. */\n onError(fn: (error: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Transform every outgoing response — success, error, 404, 405, short-circuit. Global. */\n onResponse(fn: (response: Response, req: Request) => MaybePromise<Response>): this;\n /**\n * Apply a type-**identity** plugin ({@link IdentityPlugin}, from {@link defineIdentityPlugin}) — it\n * registers routes/hooks but doesn't change the types, so this returns `this` with the route registry\n * and context fully intact. This overload exists specifically so a *named* identity plugin (e.g.\n * `@nifrajs/better-auth`) threads the registry: its `& { pluginName }` intersection would otherwise\n * defeat the generic inference of the transforming overload below and collapse the result to `any`.\n */\n use(plugin: IdentityPlugin): this;\n /**\n * Apply a **plugin function** — `(app) => app`, typically built with {@link definePlugin}. It's\n * called with `this` and its result is returned, so an inline plugin's `derive`/`decorate` thread\n * the added context to handlers defined after `use` (the overload is generic over the concrete\n * `this`). A named plugin already applied is skipped (idempotent dedupe).\n */\n use<Out extends AnyServer>(plugin: (app: this) => Out): Out;\n /**\n * Apply a {@link Middleware} bundle — wire each hook it provides to its lifecycle point. Returns\n * `this` (no context-type merging); call it before the routes its `beforeHandle`/`afterHandle`\n * should cover (those are order-scoped; `onRequest`/`onResponse` are global). A named bundle already\n * applied is skipped (idempotent).\n */\n use(mw: Middleware): this;\n get<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n get<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n post<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n post<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n put<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n put<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n patch<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PATCH\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n 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>;\n 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>;\n 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>;\n tool<Name extends string, S extends {\n description: string;\n input: StandardSchemaV1;\n output?: StandardSchemaV1;\n annotations?: ToolAnnotations;\n }, H extends (input: InferOutput<S[\"input\"]>, ctx: Context & Ctx) => MaybePromise<S[\"output\"] extends StandardSchemaV1 ? InferOutput<S[\"output\"]> : unknown>>(name: Name, config: S, handler: H): Server<AddRoute<R, \"POST\", `/_nifra/tool/${Name}`, RouteInfoFor<`/_nifra/tool/${Name}`, S[\"output\"] extends StandardSchemaV1 ? {\n body: S[\"input\"];\n response: S[\"output\"];\n } : {\n body: S[\"input\"];\n }, OutputOf<H>>>, Ctx>;\n /**\n * Declare an MCP **resource** — read-only data an agent can fetch through `nifra mcp` (app config, a\n * generated document, …). `read` runs in the app process, so capture whatever app state it needs in the\n * closure. `uri` is the MCP resource identifier (e.g. `\"myapp://config\"`). The sibling of {@link tool}\n * for the resource half of MCP.\n */\n resource(uri: string, config: {\n readonly name: string;\n readonly description?: string;\n readonly mimeType?: string;\n }, read: McpResourceDescriptor[\"read\"]): Server<R, Ctx>;\n /**\n * Declare an MCP **prompt** — a reusable prompt template an agent can fetch through `nifra mcp`.\n * `handler` receives the caller's arguments and returns the rendered messages.\n */\n prompt(name: string, config: {\n readonly description: string;\n readonly arguments?: readonly PromptArgument[];\n }, handler: McpPromptDescriptor[\"handler\"]): Server<R, Ctx>;\n /** The MCP resources declared via {@link resource} — enumerated by `nifra mcp`. */\n mcpResources(): readonly McpResourceDescriptor[];\n /** The MCP prompts declared via {@link prompt} — enumerated by `nifra mcp`. */\n mcpPrompts(): readonly McpPromptDescriptor[];\n /**\n * Register a **WebSocket** route. The connection upgrades on a `GET` to `path` carrying\n * `Upgrade: websocket`; the optional `handler.upgrade(c)` runs in the request context first and may\n * reject (return a `Response`) or seed per-connection `ws.data`. WebSockets are served by the\n * adapter (`listen()`, `@nifrajs/node`, `@nifrajs/deno`, `toFetchHandler`) — not by bare `app.fetch`, which\n * has no socket (a WS path through `app.fetch` is a normal HTTP response).\n *\n * app.ws(\"/chat\", { open: (ws) => ws.send(\"hi\"), message: (ws, data) => ws.send(data) })\n */\n ws<Data = unknown, Schema extends StandardSchemaV1 | undefined = undefined>(path: string, handler: WebSocketHandler<Data, EnvOf<Ctx>, Schema>): this;\n /**\n * Broadcast `data` to every WebSocket connection subscribed to `topic` (via `ws.subscribe(topic)`).\n * In-process and **single-instance** (see {@link TopicRegistry}) — a multi-instance deploy must bridge\n * an external fan-out (Redis, a Durable Object) to this. A no-op when nobody is subscribed.\n */\n publish(topic: string, data: string | ArrayBufferView | ArrayBuffer): void;\n private route;\n /**\n * Low-level route registration shared by the inline builder and `implement()`.\n * Captures the server's current `derive`/`decorate` chain into the route — this\n * is the \"compiled\", order-scoped per-route chain.\n */\n register(method: Method, path: string, schema: RouteSchema | undefined, handler: (context: never) => unknown): void;\n /**\n * Enumerate the registered routes (method, path, input schemas), in registration\n * order. Powers `toOpenAPI` and other introspection; the router trie itself no\n * longer holds the original patterns.\n */\n routes(): ReadonlyArray<RouteDescriptor>;\n /**\n * Resolve a `Request` to a `Response` — the whole lifecycle, testable without a port. The\n * optional `platform` carries edge inputs (`env`, `waitUntil`); edge adapters pass it, and\n * Bun/Node/Deno omit it (then `c.env` is `undefined` and `c.waitUntil` runs fire-and-forget).\n */\n fetch(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<Response>;\n private fetchSource;\n /**\n * Like {@link fetch}, but renders a plain-data result **without** building a Web `Response` — the\n * `@nifrajs/node` adapter serializes the returned primitives straight to the socket, skipping the undici\n * `Response` build + body drain (the bulk of the Node bridge cost, measured ≈4µs/req). A handler that\n * returns a `Response`, an error/short-circuit, or any registered `onResponse` hook falls back to the\n * full Web path (`{ kind: \"response\" }`), so behavior is identical — only the common JSON-data case is\n * faster. Same lifecycle as {@link fetch} (body cap, validation, hooks all run); only the final\n * render differs.\n */\n resolveNode(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;\n resolveNodeSource(source: RequestSource, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;\n /**\n * Resolve a WebSocket upgrade — the seam every serving adapter uses. Returns `pass` (not a WS\n * upgrade for a registered route → handle as normal HTTP), `reject` (a WS route matched but\n * `upgrade()` rejected, or the path was malformed → return `response`), or `upgrade` (perform the\n * runtime upgrade, then dispatch the native socket's events to `handler`, seeding `ws.data` with\n * `data`). Runs the route's `upgrade(c)` guard in a real request context. Synchronous unless\n * `upgrade()` is async; a throw rejects with a flat 500 (no detail leaked).\n */\n resolveWebSocketUpgrade(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<WebSocketUpgradeOutcome>;\n /** Bun `fetch` when WS routes exist: try a WS upgrade first, else run the normal HTTP lifecycle.\n * `undefined` ⇒ Bun owns the upgraded socket; a `Response` ⇒ a normal reply or a rejected upgrade.\n * (The socket dispatch itself lives in `ws-bun.ts`, loaded via `@nifrajs/core/ws`.) */\n private bunFetchWithWebSocket;\n /**\n * The shared lifecycle, generic over how the final value is rendered: `finalize` turns a handler's\n * result + `set` into the output `T` (`toResponse` → a Web `Response`; `toNodeOutcome` → node-direct\n * primitives), `wrapResponse` lifts an early/error `Response` into that same `T`, and `onTimeout`\n * produces the 503. The Web `fetch` and `resolveNode` are thin callers over this one routing +\n * context + lifecycle implementation — no duplication across the trust boundary.\n */\n private dispatch;\n /**\n * onRequest short-circuit path. Synchronous as long as every hook returns synchronously (the\n * common case — e.g. CORS returning `undefined` for a non-preflight request): an `async` version\n * here put EVERY request of any app with one onRequest hook onto the promise machinery, profiled\n * at ~13% of a realistic request. The first hook that returns a Promise hands the REMAINING\n * hooks to the async continuation; behavior is identical.\n */\n private runWithOnRequest;\n /** Async tail of {@link runWithOnRequest}: applies the first awaited hook's outcome, then runs\n * the remaining hooks (awaiting freely — we're already async here). */\n private continueOnRequest;\n private takeResponseRequest;\n /**\n * Route → build context → run. Synchronous through to the handler for a **bare** route\n * ({@link RouteEntry.bare}), so a sync handler produces its result with zero promise allocations;\n * routes with validation/hooks keep the full async {@link runLifecycle}, unchanged.\n */\n private routeAndRun;\n /** The narrowest bare route: a syntactic `() => ...` handler cannot observe the context argument, so\n * successful requests can skip allocating `RequestContext`. Errors still allocate one for logging. */\n private runContextlessBare;\n private contextlessBareError;\n /**\n * The synchronous fast path for a {@link RouteEntry.bare} route: apply static decorations, call the\n * handler, render the result — **no `await`** unless the handler itself returns a promise. It mirrors\n * the bare slice of {@link runLifecycle} (which a bare route would otherwise no-op through) and shares\n * {@link logRequestError}; a bare route has no `onError` hooks, so error handling is fully synchronous\n * (a thrown `Response` is control flow; anything else is a logged flat 500). This is where nifra skips\n * the per-request async-frame tax — the same win codegen routers get, but without `eval`.\n */\n private runBare;\n /** Bare-route error rendering — identical to {@link runLifecycle}'s catch minus the (absent) onError\n * loop: a thrown `Response` is returned as deliberate control flow; anything else is logged + 500. */\n /**\n * Build a route's fused Web lane (see {@link RouteEntry.fusedWeb}). Composition happens once at\n * registration; the returned closure is what every request to the route runs. Behavior is\n * byte-identical to the generic `runBare`/`runContextlessBare` + `toResponse` pair — same\n * decoration order, same error routing (thrown `Response` = control flow; anything else logs and\n * 500s), same respond semantics (the lifecycle parity suite pins it).\n */\n private buildFusedWeb;\n private bareError;\n private runWithAround;\n private runAround;\n private runBodyOnly;\n /** Validate + run the handler for the bodyOnly path — shared by the inline fast path and the\n * streaming fallback. A method (not per-request closures) so the hot path allocates nothing\n * beyond the one `.then` continuation. */\n private finishBodyOnly;\n private executeHandler;\n private handleValidationErrorRecovery;\n private applyBodyValidation;\n private runQueryOnly;\n /** Validate-result → set `ctx.query` → run handler. A method (not a per-request closure), the\n * query analogue of {@link applyBodyValidation}. */\n private applyQueryValidation;\n /**\n * Thread the response through each global `onResponse` hook. Stays SYNCHRONOUS until a hook\n * actually returns a Promise — an `async` version forced a promise + microtask on EVERY response\n * of any app with an onResponse hook (cors/securityHeaders/etag/timing all use onResponse), the\n * same ~13%/req tax the onRequest walk was de-async'd to avoid. The first async hook hands the\n * rest to {@link continueOnResponse}.\n */\n private applyOnResponse;\n /** Async tail of {@link applyOnResponse}: runs the remaining hooks once one has gone async. */\n private continueOnResponse;\n /**\n * Bound the response time. On timeout we abort `ctx.signal` (so cancellation-aware\n * handlers can bail) and return 503; the in-flight work keeps running but its\n * result is discarded — JS can't forcibly cancel a promise.\n */\n private withTimeout;\n /**\n * The post-match lifecycle: validate → derive → beforeHandle → handler → afterHandle, with onError.\n * Generic over the render: a success value goes through `finalize(result, set)` (a Web `Response`, or\n * node-direct primitives); an early/error `Response` (validation, thrown, 500) through `wrapResponse`.\n */\n private runLifecycle;\n private handleLifecycleError;\n /** Log an unhandled request error to the (redacting) logger — shared by {@link runLifecycle} and the\n * bare fast path ({@link bareError}) so both record the same fields. Never throws; never leaks. */\n private logRequestError;\n private readAndValidateBody;\n /**\n * Read the body as text, capped at `maxBodyBytes`. Rejects (`null`) on a\n * `Content-Length` over the cap *before* buffering, and aborts mid-stream once the\n * running byte count exceeds it — so a lying or absent length can't force us to\n * buffer an oversized payload.\n *\n * Fast path: when a non-chunked request carries a `Content-Length` within the cap,\n * a native `req.json()` is already bounded — under HTTP/1.1 + HTTP/2 framing the\n * runtime delivers at most `Content-Length` bytes — so we skip the manual stream\n * loop and a separate text decode. It trusts the wire\n * *framing*, not the header value: nifra only ever receives framed Requests from the\n * runtime's HTTP server, never a hand-built one with a mismatched length. Chunked or\n * length-less bodies fall through to the streaming byte-cap guard below.\n */\n private readBoundedJson;\n /**\n * Start a `Bun.serve` instance bound to `port` (use `0` for an ephemeral port).\n *\n * `reusePort` sets `SO_REUSEPORT` so **multiple processes can bind the same port** and the kernel\n * load-balances connections across them — the standard way to use every core (Bun is\n * single-threaded per process). Spawn one process per core, each calling\n * `app.listen(PORT, { reusePort: true })`; see `examples/cluster.ts`. Every process must opt in,\n * and all of them must be the same app. Linux balances ~evenly; macOS accepts the flag but may\n * favor one socket (fine for dev, measure on Linux for production numbers).\n */\n listen(port: number, options?: {\n readonly reusePort?: boolean;\n }): RunningServer;\n /**\n * Gracefully stop: wait for in-flight requests to finish (up to `drainMs`), then\n * issue a single terminal stop — graceful if everything drained, forced if\n * stragglers remain. Safe to call when not listening.\n *\n * The Bun semantics: poll `pendingRequests` (awaiting\n * `stop()`'s promise drops in-flight requests), and decide graceful-vs-forced in\n * ONE call (Bun can't escalate an already-graceful `stop()` to a forced close).\n * New connections may be accepted during the drain window; in a real deploy the\n * load balancer has already stopped routing here, and `drainMs` bounds it.\n */\n stop({ drainMs }?: {\n drainMs?: number;\n }): Promise<void>;\n private installSignalHandlers;\n}",
|
|
5116
5490
|
"doc": "/**\n * The inline server. Routes are chainable and fully type-inferred. `derive`/\n * `decorate` extend the handler context (`Ctx`) for routes defined *after* them,\n * with full types; `Ctx` is server-only and never touches the client registry.\n *\n * app.decorate(\"db\", db).derive((c) => ({ user: auth(c) }))\n * .get(\"/me\", (c) => c.user) // c.user + c.db are typed\n */"
|
|
5117
5491
|
},
|
|
5118
5492
|
{
|
|
@@ -5160,7 +5534,7 @@
|
|
|
5160
5534
|
"name": "ServerOptions",
|
|
5161
5535
|
"kind": "interface",
|
|
5162
5536
|
"package": "@nifrajs/core",
|
|
5163
|
-
"signature": "export interface ServerOptions {\n /**\n * Max request body size (bytes), enforced **only when a route declares a body schema** — the cap\n * lives in the schema-validated read path. Default 1_000_000.\n *\n * A route WITHOUT a body schema (raw body, file upload, BYO-validation) that reads `c.req` directly\n * is not auto-bounded — use **`c.boundedBody(maxBytes?)`** / **`c.boundedJson(maxBytes?)`**, which\n * apply this same cap (override per route by passing `maxBytes` — larger for an upload endpoint,\n * smaller to tighten one).\n */\n readonly maxBodyBytes?: number;\n /** Max inbound WebSocket message size (bytes) when `listen()`ing on Bun — frames over this are rejected\n * by the runtime before reaching your handler (so a huge frame can't be JSON-parsed into memory).\n * Default: `maxBodyBytes` (1 MB). */\n readonly wsMaxPayloadBytes?: number;\n /** Per-request timeout (ms): a slower request gets a 503 and `ctx.signal` aborts. 0 disables (default). */\n readonly requestTimeoutMs?: number;\n /** When `listen()`ing, install SIGTERM/SIGINT handlers that gracefully `stop()`. Default false. */\n readonly gracefulSignals?: boolean;\n /** Structured logger for framework events (redacts secrets). Default: JSON to stderr. */\n readonly logger?: Logger;\n}"
|
|
5537
|
+
"signature": "export interface ServerOptions {\n /**\n * Max request body size (bytes), enforced **only when a route declares a body schema** — the cap\n * lives in the schema-validated read path. Default 1_000_000.\n *\n * A route WITHOUT a body schema (raw body, file upload, BYO-validation) that reads `c.req` directly\n * is not auto-bounded — use **`c.boundedBody(maxBytes?)`** / **`c.boundedJson(maxBytes?)`**, which\n * apply this same cap (override per route by passing `maxBytes` — larger for an upload endpoint,\n * smaller to tighten one).\n */\n readonly maxBodyBytes?: number;\n /** Max inbound WebSocket message size (bytes) when `listen()`ing on Bun — frames over this are rejected\n * by the runtime before reaching your handler (so a huge frame can't be JSON-parsed into memory).\n * Default: `maxBodyBytes` (1 MB). */\n readonly wsMaxPayloadBytes?: number;\n /** Per-request timeout (ms): a slower request gets a 503 and `ctx.signal` aborts. 0 disables (default). */\n readonly requestTimeoutMs?: number;\n /** When `listen()`ing, install SIGTERM/SIGINT handlers that gracefully `stop()`. Default false. */\n readonly gracefulSignals?: boolean;\n /** Structured logger for framework events (redacts secrets). Default: JSON to stderr. */\n readonly logger?: Logger;\n /**\n * App-wide fallback fired when a route **without its own `onValidationError`** fails body/query\n * validation. Same contract as the per-route hook (`(issues, ctx, kind) => Response | repaired-value |\n * undefined`): a route's own hook takes precedence, and a route can fall through to the plain `422` by\n * returning `undefined`. Use it for one app-wide error envelope (like tRPC's `errorFormatter` /\n * Fastify's `setErrorHandler`) instead of repeating a formatter per route.\n */\n readonly onValidationError?: RouteSchema[\"onValidationError\"];\n}"
|
|
5164
5538
|
},
|
|
5165
5539
|
{
|
|
5166
5540
|
"name": "ServeStaticOptions",
|
|
@@ -5258,6 +5632,12 @@
|
|
|
5258
5632
|
"signature": "export declare function setMountedRouter(router: ClientRouter | undefined): void;",
|
|
5259
5633
|
"doc": "/** Register (or clear) the router that owns fetchers — called by `mountRouter`. Not for app use. */"
|
|
5260
5634
|
},
|
|
5635
|
+
{
|
|
5636
|
+
"name": "SetOptions",
|
|
5637
|
+
"kind": "interface",
|
|
5638
|
+
"package": "@nifrajs/cache",
|
|
5639
|
+
"signature": "export interface SetOptions {\n /** Time-to-live (ms) before the value goes stale. Default: the cache's `defaultTtlMs`. */\n readonly ttlMs?: number;\n /** Extra ms past TTL during which the stale value is served while a background refresh runs. Default 0. */\n readonly swrMs?: number;\n /** Tags for group invalidation via `invalidateTag`. */\n readonly tags?: readonly string[];\n}"
|
|
5640
|
+
},
|
|
5261
5641
|
{
|
|
5262
5642
|
"name": "setWsRuntime",
|
|
5263
5643
|
"kind": "function",
|
|
@@ -5512,6 +5892,13 @@
|
|
|
5512
5892
|
"package": "@nifrajs/env",
|
|
5513
5893
|
"signature": "export type StandardResult<Output> = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: ReadonlyArray<StandardIssue>;\n};"
|
|
5514
5894
|
},
|
|
5895
|
+
{
|
|
5896
|
+
"name": "StandardResult",
|
|
5897
|
+
"kind": "type",
|
|
5898
|
+
"package": "@nifrajs/jobs",
|
|
5899
|
+
"signature": "export type StandardResult<Output> = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: ReadonlyArray<{\n readonly message: string;\n }>;\n};",
|
|
5900
|
+
"doc": "/** The validate-result half of the Standard Schema spec. */"
|
|
5901
|
+
},
|
|
5515
5902
|
{
|
|
5516
5903
|
"name": "StandardSchemaProps",
|
|
5517
5904
|
"kind": "interface",
|
|
@@ -5531,6 +5918,13 @@
|
|
|
5531
5918
|
"package": "@nifrajs/env",
|
|
5532
5919
|
"signature": "export interface StandardSchemaV1<Output = unknown> {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;\n readonly types?: {\n readonly output: Output;\n };\n };\n}"
|
|
5533
5920
|
},
|
|
5921
|
+
{
|
|
5922
|
+
"name": "StandardSchemaV1",
|
|
5923
|
+
"kind": "interface",
|
|
5924
|
+
"package": "@nifrajs/jobs",
|
|
5925
|
+
"signature": "export interface StandardSchemaV1<Output = unknown> {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;\n readonly types?: {\n readonly input: unknown;\n readonly output: Output;\n };\n };\n}",
|
|
5926
|
+
"doc": "/** A minimal structural view of a Standard Schema validator (v1). `t.object(...)` satisfies it. */"
|
|
5927
|
+
},
|
|
5534
5928
|
{
|
|
5535
5929
|
"name": "StandardSuccess",
|
|
5536
5930
|
"kind": "interface",
|
|
@@ -5577,6 +5971,48 @@
|
|
|
5577
5971
|
"signature": "export interface StaticRoutes {\n /** Concrete prerendered paths — static `prerender` routes + each `getStaticPaths` entry. */\n readonly paths: string[];\n /** Per dynamic route pattern, its `getStaticPaths` `fallback` (`\"ssr\"` default). `createWebApp` uses\n * `\"404\"` to reject an unlisted path under that route at runtime (the path simply doesn't exist). */\n readonly fallbacks: Record<string, \"ssr\" | \"404\">;\n}",
|
|
5578
5972
|
"doc": "/** The static-routing facts a server needs from the route modules: which concrete paths are\n * prerendered, plus each dynamic route's `getStaticPaths` fallback policy. */"
|
|
5579
5973
|
},
|
|
5974
|
+
{
|
|
5975
|
+
"name": "StorageAdapter",
|
|
5976
|
+
"kind": "interface",
|
|
5977
|
+
"package": "@nifrajs/storage",
|
|
5978
|
+
"signature": "export interface StorageAdapter {\n /** Store `data` under `key`, overwriting any existing object. */\n put(key: string, data: StorageData, options?: PutOptions): Promise<void>;\n /** Read the object at `key`, or `null` if it doesn't exist. */\n get(key: string): Promise<StorageObject | null>;\n /** Remove `key`. No-op if it doesn't exist. */\n delete(key: string): Promise<void>;\n /** Whether an object exists at `key`. */\n exists(key: string): Promise<boolean>;\n /** List stored keys (optionally filtered by prefix + capped). */\n list(options?: ListOptions): Promise<string[]>;\n}",
|
|
5979
|
+
"doc": "/**\n * A blob store keyed by string. Keys are POSIX-ish paths (`avatars/u1.png`); every adapter rejects unsafe\n * keys (absolute, `..` traversal, NUL, backslash) so a key valid in one adapter is valid in all. All\n * methods are async.\n */"
|
|
5980
|
+
},
|
|
5981
|
+
{
|
|
5982
|
+
"name": "StorageData",
|
|
5983
|
+
"kind": "type",
|
|
5984
|
+
"package": "@nifrajs/storage",
|
|
5985
|
+
"signature": "export type StorageData = Uint8Array | ArrayBuffer | string;",
|
|
5986
|
+
"doc": "/** Accepted `put` payloads — normalized to bytes by each adapter. */"
|
|
5987
|
+
},
|
|
5988
|
+
{
|
|
5989
|
+
"name": "StorageKeyError",
|
|
5990
|
+
"kind": "class",
|
|
5991
|
+
"package": "@nifrajs/storage",
|
|
5992
|
+
"signature": "export declare class StorageKeyError extends Error {\n readonly name = \"StorageKeyError\";\n}",
|
|
5993
|
+
"doc": "/**\n * Storage-key safety. A key is a POSIX-ish relative path (`avatars/u1.png`); we reject anything that\n * could escape a `FileStorage` root or otherwise misbehave — absolute paths, `..` traversal, NUL bytes,\n * and backslashes (Windows traversal). Enforced by EVERY adapter (not just `FileStorage`) so a key is\n * portable across them, and so the check can't be forgotten on the one adapter where it's a vulnerability.\n */"
|
|
5994
|
+
},
|
|
5995
|
+
{
|
|
5996
|
+
"name": "StorageObject",
|
|
5997
|
+
"kind": "interface",
|
|
5998
|
+
"package": "@nifrajs/storage",
|
|
5999
|
+
"signature": "export interface StorageObject {\n readonly body: Uint8Array;\n readonly size: number;\n readonly contentType?: string;\n readonly metadata?: Readonly<Record<string, string>>;\n}",
|
|
6000
|
+
"doc": "/** An object read back from storage. `body` is buffered (not streamed) — fine for typical uploads. */"
|
|
6001
|
+
},
|
|
6002
|
+
{
|
|
6003
|
+
"name": "StoredEntry",
|
|
6004
|
+
"kind": "interface",
|
|
6005
|
+
"package": "@nifrajs/cache",
|
|
6006
|
+
"signature": "export interface StoredEntry {\n readonly value: unknown;\n /** Epoch-ms after which the entry is gone — a miss. */\n readonly expiresAt: number;\n /** Epoch-ms after which the entry is stale: still served during the SWR window while a refresh runs.\n * Equal to `expiresAt` when there's no stale-while-revalidate window. */\n readonly staleAt: number;\n}",
|
|
6007
|
+
"doc": "/** A cached entry as the store holds it. */"
|
|
6008
|
+
},
|
|
6009
|
+
{
|
|
6010
|
+
"name": "StoredJob",
|
|
6011
|
+
"kind": "interface",
|
|
6012
|
+
"package": "@nifrajs/jobs",
|
|
6013
|
+
"signature": "export interface StoredJob {\n readonly id: string;\n readonly name: string;\n readonly payload: unknown;\n readonly attempt: number;\n readonly maxAttempts: number;\n}",
|
|
6014
|
+
"doc": "/** A job as handed back by {@link JobStore.lease}. `attempt` is the count of PRIOR attempts (0 the first time). */"
|
|
6015
|
+
},
|
|
5580
6016
|
{
|
|
5581
6017
|
"name": "string",
|
|
5582
6018
|
"kind": "function",
|
|
@@ -5656,7 +6092,7 @@
|
|
|
5656
6092
|
"name": "t",
|
|
5657
6093
|
"kind": "const",
|
|
5658
6094
|
"package": "@nifrajs/schema",
|
|
5659
|
-
"signature": "export declare const t: {\n readonly string: (options?: StringOptions) => NifraSchema<import(\"@sinclair/typebox\").TString>;\n readonly number: (options?: NumberOptions) => NifraSchema<import(\"@sinclair/typebox\").TNumber>;\n readonly integer: (options?: IntegerOptions) => NifraSchema<import(\"@sinclair/typebox\").TInteger>;\n readonly boolean: () => NifraSchema<import(\"@sinclair/typebox\").TBoolean>;\n readonly null: () => NifraSchema<import(\"@sinclair/typebox\").TNull>;\n readonly literal: <const L extends TLiteralValue>(value: L) => NifraSchema<import(\"@sinclair/typebox\").TLiteral<L>>;\n readonly object: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n /** Like `t.object` but ACCEPTS (and passes through) unknown fields — the explicit opt-out of the\n * strict default. Prefer `t.object` unless you genuinely need an open object. */\n readonly looseObject: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n readonly array: <T extends TSchema>(item: NifraSchema<T>, options?: ArrayOptions) => NifraSchema<import(\"@sinclair/typebox\").TArray<T>>;\n /** Marks a property optional inside `t.object`; standalone it is `T | undefined`. */\n readonly optional: <T extends TSchema>(schema: NifraSchema<T>) => NifraSchema<T extends import(\"@sinclair/typebox\").TOptional<infer S extends TSchema> ? import(\"@sinclair/typebox\").TOptional<S> : import(\"@sinclair/typebox\").Ensure<import(\"@sinclair/typebox\").TOptional<T>>>;\n readonly union: <const S extends readonly NifraSchema[]>(schemas: S) => NifraSchema<TUnion<{ -readonly [K in keyof S]: S[K][\"jsonSchema\"]; }>>;\n readonly record: <T extends TSchema>(value: NifraSchema<T>, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TRecord<import(\"@sinclair/typebox\").TString, T>>;\n};",
|
|
6095
|
+
"signature": "export declare const t: {\n readonly string: (options?: StringOptions) => NifraSchema<import(\"@sinclair/typebox\").TString>;\n readonly number: (options?: NumberOptions) => NifraSchema<import(\"@sinclair/typebox\").TNumber>;\n readonly integer: (options?: IntegerOptions) => NifraSchema<import(\"@sinclair/typebox\").TInteger>;\n readonly boolean: () => NifraSchema<import(\"@sinclair/typebox\").TBoolean>;\n readonly null: () => NifraSchema<import(\"@sinclair/typebox\").TNull>;\n readonly literal: <const L extends TLiteralValue>(value: L) => NifraSchema<import(\"@sinclair/typebox\").TLiteral<L>>;\n readonly object: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n /** Like `t.object` but ACCEPTS (and passes through) unknown fields — the explicit opt-out of the\n * strict default. Prefer `t.object` unless you genuinely need an open object. */\n readonly looseObject: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n readonly array: <T extends TSchema>(item: NifraSchema<T>, options?: ArrayOptions) => NifraSchema<import(\"@sinclair/typebox\").TArray<T>>;\n /** Marks a property optional inside `t.object`; standalone it is `T | undefined`. */\n readonly optional: <T extends TSchema>(schema: NifraSchema<T>) => NifraSchema<T extends import(\"@sinclair/typebox\").TOptional<infer S extends TSchema> ? import(\"@sinclair/typebox\").TOptional<S> : import(\"@sinclair/typebox\").Ensure<import(\"@sinclair/typebox\").TOptional<T>>>;\n readonly union: <const S extends readonly NifraSchema[]>(schemas: S) => NifraSchema<TUnion<{ -readonly [K in keyof S]: S[K][\"jsonSchema\"]; }>>;\n readonly record: <T extends TSchema>(value: NifraSchema<T>, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TRecord<import(\"@sinclair/typebox\").TString, T>>;\n /** A cursor-pagination response envelope: `{ items: T[]; nextCursor: string | null }` (`null` = last page). */\n readonly paginated: <T extends TSchema>(item: NifraSchema<T>, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{\n items: import(\"@sinclair/typebox\").TArray<T>;\n nextCursor: TUnion<[import(\"@sinclair/typebox\").TString, import(\"@sinclair/typebox\").TNull]>;\n }>>;\n /** A request query schema for cursor pagination: `{ cursor?: string; limit?: number }`. `maxLimit`\n * caps `limit` — a larger value fails validation (a 422), so a client can't request an unbounded page.\n * `coerce` is on because query values arrive as strings (`?limit=20` → `\"20\"`); it's what makes `limit`\n * a real `number` in the handler (`c.query.limit`), not a string. */\n readonly pageQuery: (options?: {\n maxLimit?: number;\n }) => NifraSchema<import(\"@sinclair/typebox\").TObject<{\n cursor: import(\"@sinclair/typebox\").TOptional<import(\"@sinclair/typebox\").TString>;\n limit: import(\"@sinclair/typebox\").TOptional<import(\"@sinclair/typebox\").TInteger>;\n }>>;\n};",
|
|
5660
6096
|
"doc": "/**\n * The built-in schema builder. Each constructor returns a `NifraSchema` — a\n * Standard Schema whose validated output type flows into `c.body`/`c.query`, and\n * whose `jsonSchema` powers `toOpenAPI`. Options (min/max, length, pattern, …)\n * pass straight through to TypeBox and so become JSON Schema constraints.\n *\n * Composite constructors are generic over the *inner* TypeBox schema `T extends\n * TSchema` (not over `NifraSchema`): reading `.jsonSchema` off a value typed only as\n * `NifraSchema` would erase to the `TSchema` constraint and collapse the output type\n * to `unknown`. Capturing `T` keeps `Static<T>` precise (`string[]`, not\n * `unknown[]`).\n */"
|
|
5661
6097
|
},
|
|
5662
6098
|
{
|
|
@@ -5692,6 +6128,25 @@
|
|
|
5692
6128
|
"signature": "export declare const testClient: typeof inProcessClient;",
|
|
5693
6129
|
"doc": "/**\n * The in-process test client — the Fastify-`inject` / supertest equivalent for nifra. Drives the\n * app's own `fetch` directly: no server, no port, no network, the full real lifecycle (validation,\n * middleware, contracts, auth), and end-to-end types from `App`. Calls never throw — branch on\n * `res.ok`. An alias of {@link inProcessClient} with a test-focused name; identical behavior.\n *\n * ```ts\n * import { testClient } from \"@nifrajs/client\"\n * import { app } from \"../src/app\"\n *\n * const api = testClient<typeof app>(app)\n * const res = await api.users({ id: \"42\" }).get()\n * expect(res.ok && res.data.id).toBe(\"42\")\n * ```\n */"
|
|
5694
6130
|
},
|
|
6131
|
+
{
|
|
6132
|
+
"name": "testSession",
|
|
6133
|
+
"kind": "function",
|
|
6134
|
+
"package": "@nifrajs/testing",
|
|
6135
|
+
"signature": "export declare function testSession<App extends AppLike>(app: App, options?: TestSessionOptions): TestSession<App>;",
|
|
6136
|
+
"doc": "/** Create a cookie-persisting in-process test client for `app`. */"
|
|
6137
|
+
},
|
|
6138
|
+
{
|
|
6139
|
+
"name": "TestSession",
|
|
6140
|
+
"kind": "interface",
|
|
6141
|
+
"package": "@nifrajs/testing",
|
|
6142
|
+
"signature": "export interface TestSession<App> {\n /** The end-to-end-typed in-process client — every call carries + captures cookies. */\n readonly client: Treaty<App>;\n /** The jar backing this session — inspect (`cookies.get(\"sid\")`), seed, or `clear()` it. */\n readonly cookies: CookieJar;\n}"
|
|
6143
|
+
},
|
|
6144
|
+
{
|
|
6145
|
+
"name": "TestSessionOptions",
|
|
6146
|
+
"kind": "interface",
|
|
6147
|
+
"package": "@nifrajs/testing",
|
|
6148
|
+
"signature": "export interface TestSessionOptions extends Omit<ClientOptions, \"fetch\"> {\n /** Origin used to resolve relative paths. Default `\"http://nifra.internal\"`. */\n readonly origin?: string;\n /** Reuse an existing jar (e.g. seed a session cookie, or share one across sessions). */\n readonly cookies?: CookieJar;\n}"
|
|
6149
|
+
},
|
|
5695
6150
|
{
|
|
5696
6151
|
"name": "TestSummary",
|
|
5697
6152
|
"kind": "interface",
|
|
@@ -5754,6 +6209,13 @@
|
|
|
5754
6209
|
"package": "@nifrajs/middleware",
|
|
5755
6210
|
"signature": "export declare function timingSafeEqualString(a: string, b: string): Promise<boolean>;"
|
|
5756
6211
|
},
|
|
6212
|
+
{
|
|
6213
|
+
"name": "toBytes",
|
|
6214
|
+
"kind": "function",
|
|
6215
|
+
"package": "@nifrajs/storage",
|
|
6216
|
+
"signature": "export declare function toBytes(data: StorageData): Uint8Array;",
|
|
6217
|
+
"doc": "/** Normalize any accepted payload to bytes. */"
|
|
6218
|
+
},
|
|
5757
6219
|
{
|
|
5758
6220
|
"name": "toFetchHandler",
|
|
5759
6221
|
"kind": "function",
|
|
@@ -5779,6 +6241,13 @@
|
|
|
5779
6241
|
"package": "@nifrajs/cli",
|
|
5780
6242
|
"signature": "export declare function tokenSetHas(tokens: ReadonlySet<string>, group: SearchTermGroup): boolean;"
|
|
5781
6243
|
},
|
|
6244
|
+
{
|
|
6245
|
+
"name": "ToolAnnotations",
|
|
6246
|
+
"kind": "interface",
|
|
6247
|
+
"package": "@nifrajs/core",
|
|
6248
|
+
"signature": "export interface ToolAnnotations {\n /** Human-readable display title for the tool, distinct from the machine `name`. */\n readonly title?: string;\n /** The tool does not modify its environment (a pure read). */\n readonly readOnlyHint?: boolean;\n /** The tool may perform destructive updates — only meaningful when `readOnlyHint` is not `true`. */\n readonly destructiveHint?: boolean;\n /** Repeated calls with the same arguments have no additional effect beyond the first. */\n readonly idempotentHint?: boolean;\n /** The tool interacts with external entities (an \"open world\" beyond this server). */\n readonly openWorldHint?: boolean;\n}",
|
|
6249
|
+
"doc": "/**\n * MCP tool safety hints, surfaced in `tools/list`, that tell an agent how risky a `.tool()` call is — so it\n * can decide whether to auto-invoke or confirm first. All optional; an omitted hint means \"unknown\". Mirrors\n * the MCP spec's tool `annotations`.\n */"
|
|
6250
|
+
},
|
|
5782
6251
|
{
|
|
5783
6252
|
"name": "toOpenAPI",
|
|
5784
6253
|
"kind": "function",
|
|
@@ -6257,8 +6726,8 @@
|
|
|
6257
6726
|
"name": "VERSION",
|
|
6258
6727
|
"kind": "const",
|
|
6259
6728
|
"package": "@nifrajs/core",
|
|
6260
|
-
"signature": "export declare const VERSION: \"
|
|
6261
|
-
"doc": "
|
|
6729
|
+
"signature": "export declare const VERSION: \"1.3.1\";",
|
|
6730
|
+
"doc": "/**\n * Current package version. A hardcoded literal on purpose — core runs on the edge (no fs), so it can't\n * read its own package.json at runtime. `scripts/version.ts` rewrites it on every release bump and\n * `check:publish` asserts it equals `@nifrajs/core`'s package version, so the literal can't go stale\n * (it shipped at \"0.0.0\" through 1.0.0 before those guards existed). Kept narrow (`as const`) so\n * consumers can pin it at the type level — see `test/version.test-d.ts`.\n */"
|
|
6262
6731
|
},
|
|
6263
6732
|
{
|
|
6264
6733
|
"name": "ViteDevServer",
|
|
@@ -6297,8 +6766,7 @@
|
|
|
6297
6766
|
"name": "walkSource",
|
|
6298
6767
|
"kind": "function",
|
|
6299
6768
|
"package": "@nifrajs/cli",
|
|
6300
|
-
"signature": "export declare function walkSource(cwd: string, visit: (rel: string, content: string) => void): Promise<void>;"
|
|
6301
|
-
"doc": "/** Walk the project's `.ts`/`.tsx` source (skipping deps/build/tests), calling `visit` per file.\n * Exported so `nifra doctor` ({@link ./doctor.ts}) scans the same source surface as `nifra check`. */"
|
|
6769
|
+
"signature": "export declare function walkSource(cwd: string, visit: (rel: string, content: string) => void): Promise<void>;"
|
|
6302
6770
|
},
|
|
6303
6771
|
{
|
|
6304
6772
|
"name": "WarmWorker",
|
|
@@ -6395,6 +6863,24 @@
|
|
|
6395
6863
|
"signature": "export declare function withISR(app: ISRApp, options: ISROptions): (req: Request, platform?: ISRPlatform) => Promise<Response>;",
|
|
6396
6864
|
"doc": "/**\n * Wrap a nifra app with **Incremental Static Regeneration**: a cacheable page is served from\n * {@link CacheStore} when fresh, served **stale while a fresh copy regenerates in the background**\n * (`platform.waitUntil` on edge), or rendered + stored on a miss. Framework-agnostic (it caches the\n * rendered bytes). Returns a `fetch(req, platform?)` handler — hand it to `Bun.serve`/the Workers\n * `export default`, etc. Regeneration is single-flight per key (no stampede on a hot stale page).\n *\n * Each route's freshness comes from the `revalidate` header the app sets (per-route\n * `export const revalidate`), falling back to `options.revalidate`. Only full-document `text/html`\n * GET 200s are cached; everything else (assets, data-mode GETs, redirects, errors) passes through.\n */"
|
|
6397
6865
|
},
|
|
6866
|
+
{
|
|
6867
|
+
"name": "Worker",
|
|
6868
|
+
"kind": "interface",
|
|
6869
|
+
"package": "@nifrajs/jobs",
|
|
6870
|
+
"signature": "export interface Worker {\n /** Stop polling and await the in-flight round (graceful). */\n stop(): Promise<void>;\n readonly running: boolean;\n}"
|
|
6871
|
+
},
|
|
6872
|
+
{
|
|
6873
|
+
"name": "WorkerOptions",
|
|
6874
|
+
"kind": "interface",
|
|
6875
|
+
"package": "@nifrajs/jobs",
|
|
6876
|
+
"signature": "export interface WorkerOptions {\n /** Max jobs in flight at once. Default 1. */\n readonly concurrency?: number;\n /** How often to poll the store for due jobs (ms). Default 250. */\n readonly pollIntervalMs?: number;\n /** How long a leased job is hidden before it's considered abandoned and re-leased (ms). Default 30_000. */\n readonly leaseMs?: number;\n}"
|
|
6877
|
+
},
|
|
6878
|
+
{
|
|
6879
|
+
"name": "WrapOptions",
|
|
6880
|
+
"kind": "type",
|
|
6881
|
+
"package": "@nifrajs/cache",
|
|
6882
|
+
"signature": "export type WrapOptions = SetOptions;"
|
|
6883
|
+
},
|
|
6398
6884
|
{
|
|
6399
6885
|
"name": "wrapWebSocketMessageValidation",
|
|
6400
6886
|
"kind": "function",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nifrajs/cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "The nifra CLI — zero-config dev/build/start for a nifra app (`nifra dev`, `nifra build`, `nifra start`).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@nifrajs/client": "1.3.
|
|
45
|
-
"@nifrajs/mcp": "1.3.
|
|
46
|
-
"@nifrajs/runner": "1.3.
|
|
47
|
-
"@nifrajs/schema": "1.3.
|
|
48
|
-
"@nifrajs/web": "1.3.
|
|
49
|
-
"create-nifra": "1.3.
|
|
44
|
+
"@nifrajs/client": "1.3.1",
|
|
45
|
+
"@nifrajs/mcp": "1.3.1",
|
|
46
|
+
"@nifrajs/runner": "1.3.1",
|
|
47
|
+
"@nifrajs/schema": "1.3.1",
|
|
48
|
+
"@nifrajs/web": "1.3.1",
|
|
49
|
+
"create-nifra": "1.3.1"
|
|
50
50
|
},
|
|
51
51
|
"repository": {
|
|
52
52
|
"type": "git",
|
package/src/cli.ts
CHANGED
|
@@ -82,7 +82,7 @@ Port: \`dev\` and \`start\` share the default ${DEFAULT_DEV_PORT}. Override with
|
|
|
82
82
|
\`PORT\` env var (\`--port\` wins over \`PORT\`, which wins over the default).`
|
|
83
83
|
|
|
84
84
|
// Kept in lockstep with packages/cli/package.json by check:publish's version-consistency gate.
|
|
85
|
-
const CLI_VERSION = "1.3.
|
|
85
|
+
const CLI_VERSION = "1.3.1"
|
|
86
86
|
|
|
87
87
|
// A render adapter + nifra server are opaque to the CLI (it just forwards them); cast at the seam.
|
|
88
88
|
const asAdapter = (v: unknown): RenderAdapter => v as RenderAdapter
|
package/src/mcp-http.ts
CHANGED
|
@@ -26,7 +26,7 @@ export { docsTools } from "./mcp-docs-tools.ts"
|
|
|
26
26
|
export type { TypeEntry } from "./types-search.ts"
|
|
27
27
|
|
|
28
28
|
// Kept in lockstep with packages/cli/package.json by check:publish's version-consistency gate.
|
|
29
|
-
const VERSION = "1.3.
|
|
29
|
+
const VERSION = "1.3.1"
|
|
30
30
|
const SERVER_INFO = { name: "nifra-docs", version: VERSION }
|
|
31
31
|
const DOCS_HEALTH =
|
|
32
32
|
"nifra docs MCP — POST JSON-RPC 2.0 here (methods: initialize, tools/list, tools/call). Tools: nifra_docs, nifra_example."
|