@nifrajs/cli 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/dist/mcp-http.js +1 -1
- package/docs/llms-full.txt +234 -1
- package/docs/types.json +476 -17
- package/package.json +7 -7
- package/src/cli.ts +1 -1
- package/src/mcp-http.ts +1 -1
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,11 +592,24 @@
|
|
|
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
|
-
"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 /** Response header for cache status. Default `\"x-nifra-cache\"`; set `false` to disable. */\n readonly cacheStatusHeader?: string | false;\n}"
|
|
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}"
|
|
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 */"
|
|
573
613
|
},
|
|
574
614
|
{
|
|
575
615
|
"name": "CacheStore",
|
|
@@ -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",
|
|
@@ -1414,8 +1489,8 @@
|
|
|
1414
1489
|
"name": "docsTools",
|
|
1415
1490
|
"kind": "function",
|
|
1416
1491
|
"package": "@nifrajs/cli",
|
|
1417
|
-
"signature": "export declare function docsTools(loadDocs: () => Promise<string | undefined>, loadExamples: () => Promise<Example[] | undefined>): McpTool[];",
|
|
1418
|
-
"doc": "/** Build `nifra_docs` + `nifra_example` over injected corpus loaders. */"
|
|
1492
|
+
"signature": "export declare function docsTools(loadDocs: () => Promise<string | undefined>, loadExamples: () => Promise<Example[] | undefined>, loadTypes: () => Promise<TypeEntry[] | undefined>): McpTool[];",
|
|
1493
|
+
"doc": "/** Build `nifra_docs` + `nifra_example` + `nifra_types` over injected corpus loaders. */"
|
|
1419
1494
|
},
|
|
1420
1495
|
{
|
|
1421
1496
|
"name": "DoctorAppliedFix",
|
|
@@ -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,19 @@
|
|
|
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
|
+
},
|
|
1630
1731
|
{
|
|
1631
1732
|
"name": "FEATURE_IDS",
|
|
1632
1733
|
"kind": "const",
|
|
@@ -1724,6 +1825,20 @@
|
|
|
1724
1825
|
"signature": "export type FetchRouteData = (path: string, match: RouteMatch, signal?: AbortSignal) => Promise<unknown>;",
|
|
1725
1826
|
"doc": "/** How a router fetches a route's loader data on navigation. `signal` aborts a superseded fetch\n * (and its deferred stream). */"
|
|
1726
1827
|
},
|
|
1828
|
+
{
|
|
1829
|
+
"name": "FieldKey",
|
|
1830
|
+
"kind": "type",
|
|
1831
|
+
"package": "@nifrajs/web",
|
|
1832
|
+
"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;",
|
|
1833
|
+
"doc": "/** The valid field names for that route's body — the schema's keys as a string union. */"
|
|
1834
|
+
},
|
|
1835
|
+
{
|
|
1836
|
+
"name": "FieldProps",
|
|
1837
|
+
"kind": "type",
|
|
1838
|
+
"package": "@nifrajs/web",
|
|
1839
|
+
"signature": "export type FieldProps = Record<string, unknown>;",
|
|
1840
|
+
"doc": "/** Extra attributes merged into the returned input props (id, type, defaultValue, placeholder, …). */"
|
|
1841
|
+
},
|
|
1727
1842
|
{
|
|
1728
1843
|
"name": "filePathToPattern",
|
|
1729
1844
|
"kind": "function",
|
|
@@ -1738,6 +1853,12 @@
|
|
|
1738
1853
|
"signature": "export declare function filePathToPatterns(file: string): string[];",
|
|
1739
1854
|
"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
1855
|
},
|
|
1856
|
+
{
|
|
1857
|
+
"name": "FileStorage",
|
|
1858
|
+
"kind": "class",
|
|
1859
|
+
"package": "@nifrajs/storage",
|
|
1860
|
+
"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}"
|
|
1861
|
+
},
|
|
1741
1862
|
{
|
|
1742
1863
|
"name": "FileType",
|
|
1743
1864
|
"kind": "interface",
|
|
@@ -1752,6 +1873,13 @@
|
|
|
1752
1873
|
"signature": "export declare function fillRoutePattern(pattern: string, params: Record<string, string>): {\n path: string;\n missing: string[];\n};",
|
|
1753
1874
|
"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
1875
|
},
|
|
1876
|
+
{
|
|
1877
|
+
"name": "fixedBackoff",
|
|
1878
|
+
"kind": "const",
|
|
1879
|
+
"package": "@nifrajs/jobs",
|
|
1880
|
+
"signature": "export declare const fixedBackoff: (ms: number) => Backoff;",
|
|
1881
|
+
"doc": "/** Fixed delay before every retry. */"
|
|
1882
|
+
},
|
|
1755
1883
|
{
|
|
1756
1884
|
"name": "Flags",
|
|
1757
1885
|
"kind": "interface",
|
|
@@ -1831,6 +1959,19 @@
|
|
|
1831
1959
|
"signature": "export declare function formatTraceparent(traceId: string, spanId: string, sampled: boolean): string;",
|
|
1832
1960
|
"doc": "/** Format a `traceparent` header value (version `00`). */"
|
|
1833
1961
|
},
|
|
1962
|
+
{
|
|
1963
|
+
"name": "formFor",
|
|
1964
|
+
"kind": "function",
|
|
1965
|
+
"package": "@nifrajs/web",
|
|
1966
|
+
"signature": "export declare function formFor<App, Path extends RoutePaths<App>, Method extends string = \"post\">(): FormHandle<App, Path, Method>;",
|
|
1967
|
+
"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 */"
|
|
1968
|
+
},
|
|
1969
|
+
{
|
|
1970
|
+
"name": "FormHandle",
|
|
1971
|
+
"kind": "interface",
|
|
1972
|
+
"package": "@nifrajs/web",
|
|
1973
|
+
"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}"
|
|
1974
|
+
},
|
|
1834
1975
|
{
|
|
1835
1976
|
"name": "Framework",
|
|
1836
1977
|
"kind": "type",
|
|
@@ -1875,8 +2016,8 @@
|
|
|
1875
2016
|
"name": "fromTypeBox",
|
|
1876
2017
|
"kind": "function",
|
|
1877
2018
|
"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 */"
|
|
2019
|
+
"signature": "export declare function fromTypeBox<T extends TSchema>(schema: T, options?: {\n readonly coerce?: boolean;\n}): NifraSchema<T>;",
|
|
2020
|
+
"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
2021
|
},
|
|
1881
2022
|
{
|
|
1882
2023
|
"name": "generateClientEntry",
|
|
@@ -2168,8 +2309,7 @@
|
|
|
2168
2309
|
"name": "idempotency",
|
|
2169
2310
|
"kind": "function",
|
|
2170
2311
|
"package": "@nifrajs/middleware",
|
|
2171
|
-
"signature": "export declare function idempotency(options: IdempotencyOptions): Middleware;"
|
|
2172
|
-
"doc": "/**\n * Idempotency-key middleware. Apply with `app.use(idempotency({ store }))`.\n *\n * **`Set-Cookie` is intentionally not cached or replayed** — a cookie set on the first request is\n * session-specific, so replaying it to a different caller (key collision or abuse) would leak/fixate a\n * session. Cache the body + status + the rest of the headers; let auth cookies re-issue per request.\n *\n * Caching buffers the response body, so apply this to JSON/API routes, not streaming SSR responses.\n */"
|
|
2312
|
+
"signature": "export declare function idempotency(options: IdempotencyOptions): Middleware;"
|
|
2173
2313
|
},
|
|
2174
2314
|
{
|
|
2175
2315
|
"name": "IdempotencyClaim",
|
|
@@ -2181,7 +2321,7 @@
|
|
|
2181
2321
|
"name": "IdempotencyOptions",
|
|
2182
2322
|
"kind": "interface",
|
|
2183
2323
|
"package": "@nifrajs/middleware",
|
|
2184
|
-
"signature": "export interface IdempotencyOptions {\n /** Where claims + cached responses live. `MemoryIdempotencyStore` for dev; a shared store in production. */\n readonly store: IdempotencyStore;\n /** Header carrying the key. Default `\"idempotency-key\"`. */\n readonly header?: string;\n /** Methods the guard applies to. Default `[\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]` (unsafe methods). */\n readonly methods?: readonly string[];\n /** How long a completed response is replayable, in ms. Default 24h. */\n readonly ttlMs?: number;\n /** How long the in-flight lock survives a crashed handler, in ms. Default 60s. */\n readonly lockTtlMs?: number;\n /** Max response bytes to cache. A larger response is returned but **not** stored. Default 1 MiB. */\n readonly maxBytes?: number;\n /** Whether a response should be cached for replay. Default: status `< 500` (don't replay transient 5xx). */\n readonly shouldCache?: (response: Response) => boolean;\n}"
|
|
2324
|
+
"signature": "export interface IdempotencyOptions {\n /** Where claims + cached responses live. `MemoryIdempotencyStore` for dev; a shared store in production. */\n readonly store: IdempotencyStore;\n /** Header carrying the key. Default `\"idempotency-key\"`. */\n readonly header?: string;\n /** Methods the guard applies to. Default `[\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]` (unsafe methods). */\n readonly methods?: readonly string[];\n /** How long a completed response is replayable, in ms. Default 24h. */\n readonly ttlMs?: number;\n /** How long the in-flight lock survives a crashed handler, in ms. Default 60s. */\n readonly lockTtlMs?: number;\n /** Max response bytes to cache. A larger response is returned but **not** stored. Default 1 MiB. */\n readonly maxBytes?: number;\n /** Whether a response should be cached for replay. Default: status `< 500` (don't replay transient 5xx). */\n readonly shouldCache?: (response: Response) => boolean;\n /**\n * Derive the store key from the request. Default: the `header` value **scoped by method + path**, so the\n * same key on a different endpoint can't collide. Return a **principal-scoped** key (e.g.\n * `` `${userId}:${req.headers.get(\"idempotency-key\")}` ``) so one user can't replay another's stored\n * response on a shared key. Return `null`/`\"\"` to skip dedupe for this request.\n */\n readonly key?: (req: Request, header: string) => string | null;\n}"
|
|
2185
2325
|
},
|
|
2186
2326
|
{
|
|
2187
2327
|
"name": "IdempotencyRecord",
|
|
@@ -2582,6 +2722,61 @@
|
|
|
2582
2722
|
"signature": "export declare const issue: (message: string) => {\n readonly issues: ReadonlyArray<StandardIssue>;\n};",
|
|
2583
2723
|
"doc": "/** A single issue. Messages NEVER include the variable's value — it may be a secret. */"
|
|
2584
2724
|
},
|
|
2725
|
+
{
|
|
2726
|
+
"name": "JobContext",
|
|
2727
|
+
"kind": "interface",
|
|
2728
|
+
"package": "@nifrajs/jobs",
|
|
2729
|
+
"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}",
|
|
2730
|
+
"doc": "/** What a handler receives alongside the payload: identity + which attempt this is (1-based). */"
|
|
2731
|
+
},
|
|
2732
|
+
{
|
|
2733
|
+
"name": "JobCounts",
|
|
2734
|
+
"kind": "interface",
|
|
2735
|
+
"package": "@nifrajs/jobs",
|
|
2736
|
+
"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}"
|
|
2737
|
+
},
|
|
2738
|
+
{
|
|
2739
|
+
"name": "JobDefinition",
|
|
2740
|
+
"kind": "interface",
|
|
2741
|
+
"package": "@nifrajs/jobs",
|
|
2742
|
+
"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}",
|
|
2743
|
+
"doc": "/** A job definition registered on a queue. */"
|
|
2744
|
+
},
|
|
2745
|
+
{
|
|
2746
|
+
"name": "JobError",
|
|
2747
|
+
"kind": "class",
|
|
2748
|
+
"package": "@nifrajs/jobs",
|
|
2749
|
+
"signature": "export declare class JobError extends Error {\n readonly name = \"JobError\";\n}",
|
|
2750
|
+
"doc": "/** Thrown for a misuse of the queue API (duplicate/unknown job name). */"
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
"name": "JobHandle",
|
|
2754
|
+
"kind": "interface",
|
|
2755
|
+
"package": "@nifrajs/jobs",
|
|
2756
|
+
"signature": "export interface JobHandle<Payload> {\n readonly name: string;\n enqueue(payload: Payload, options?: EnqueueOptions): Promise<string>;\n}",
|
|
2757
|
+
"doc": "/** A typed handle to enqueue a defined job. */"
|
|
2758
|
+
},
|
|
2759
|
+
{
|
|
2760
|
+
"name": "JobHandler",
|
|
2761
|
+
"kind": "type",
|
|
2762
|
+
"package": "@nifrajs/jobs",
|
|
2763
|
+
"signature": "export type JobHandler<Payload> = (payload: Payload, ctx: JobContext) => void | Promise<void>;",
|
|
2764
|
+
"doc": "/** A job processor. A throw/rejection routes to `onError` and triggers retry/dead-letter — never crashes the worker. */"
|
|
2765
|
+
},
|
|
2766
|
+
{
|
|
2767
|
+
"name": "JobStore",
|
|
2768
|
+
"kind": "interface",
|
|
2769
|
+
"package": "@nifrajs/jobs",
|
|
2770
|
+
"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}",
|
|
2771
|
+
"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 */"
|
|
2772
|
+
},
|
|
2773
|
+
{
|
|
2774
|
+
"name": "JobValidationError",
|
|
2775
|
+
"kind": "class",
|
|
2776
|
+
"package": "@nifrajs/jobs",
|
|
2777
|
+
"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}",
|
|
2778
|
+
"doc": "/** Thrown by `enqueue` when the payload fails the job's `input` schema (validation at the trust boundary). */"
|
|
2779
|
+
},
|
|
2585
2780
|
{
|
|
2586
2781
|
"name": "jsonError",
|
|
2587
2782
|
"kind": "function",
|
|
@@ -2766,6 +2961,12 @@
|
|
|
2766
2961
|
"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}",
|
|
2767
2962
|
"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 */"
|
|
2768
2963
|
},
|
|
2964
|
+
{
|
|
2965
|
+
"name": "ListOptions",
|
|
2966
|
+
"kind": "interface",
|
|
2967
|
+
"package": "@nifrajs/storage",
|
|
2968
|
+
"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}"
|
|
2969
|
+
},
|
|
2769
2970
|
{
|
|
2770
2971
|
"name": "load",
|
|
2771
2972
|
"kind": "function",
|
|
@@ -2873,6 +3074,13 @@
|
|
|
2873
3074
|
"signature": "export declare function loadReactDomServer(resolve?: ResolveSync | undefined): Promise<ReactDomServer>;",
|
|
2874
3075
|
"doc": "/**\n * Load `react-dom/server`, preferring the app-root-resolved copy under the Bun runtime. Exported for unit\n * tests: `resolve` defaults to the ambient `Bun.resolveSync` (undefined on non-Bun hosts), and a test can\n * inject a stub that succeeds (re-root branch) or throws (fallback branch) to cover both deterministically\n * without depending on the machine's node_modules layout.\n */"
|
|
2875
3076
|
},
|
|
3077
|
+
{
|
|
3078
|
+
"name": "loadTypesCorpus",
|
|
3079
|
+
"kind": "function",
|
|
3080
|
+
"package": "@nifrajs/cli",
|
|
3081
|
+
"signature": "export declare function loadTypesCorpus(): Promise<TypeEntry[] | undefined>;",
|
|
3082
|
+
"doc": "/** Load the bundled type corpus (`docs/types.json`), resolved relative to this module so it works from\n * `src/` (dev) and `dist/` (published) alike. */"
|
|
3083
|
+
},
|
|
2876
3084
|
{
|
|
2877
3085
|
"name": "Locale",
|
|
2878
3086
|
"kind": "type",
|
|
@@ -2906,6 +3114,13 @@
|
|
|
2906
3114
|
"package": "@nifrajs/middleware",
|
|
2907
3115
|
"signature": "export interface LoggerOptions {\n /** Sink for each line. Default: `console.log(JSON.stringify(fields))`. Route to your own logger here. */\n readonly log?: (fields: RequestLogFields) => void;\n}"
|
|
2908
3116
|
},
|
|
3117
|
+
{
|
|
3118
|
+
"name": "lookupType",
|
|
3119
|
+
"kind": "function",
|
|
3120
|
+
"package": "@nifrajs/cli",
|
|
3121
|
+
"signature": "export declare function lookupType(types: readonly TypeEntry[], name: string): TypeEntry[];",
|
|
3122
|
+
"doc": "/** Exact (case-insensitive) name lookup — returns every declaration with that name (a name can exist in\n * more than one package). */"
|
|
3123
|
+
},
|
|
2909
3124
|
{
|
|
2910
3125
|
"name": "Manifest",
|
|
2911
3126
|
"kind": "interface",
|
|
@@ -2950,8 +3165,8 @@
|
|
|
2950
3165
|
"name": "MCP_CLI_VERSION",
|
|
2951
3166
|
"kind": "const",
|
|
2952
3167
|
"package": "create-nifra",
|
|
2953
|
-
"signature": "export declare const MCP_CLI_VERSION:
|
|
2954
|
-
"doc": "/**\n * The `@nifrajs/cli` version the launch command pins to.
|
|
3168
|
+
"signature": "export declare const MCP_CLI_VERSION: string;",
|
|
3169
|
+
"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 */"
|
|
2955
3170
|
},
|
|
2956
3171
|
{
|
|
2957
3172
|
"name": "MCP_CONFIG",
|
|
@@ -2971,7 +3186,7 @@
|
|
|
2971
3186
|
"name": "MCP_SERVER_ARGS",
|
|
2972
3187
|
"kind": "const",
|
|
2973
3188
|
"package": "create-nifra",
|
|
2974
|
-
"signature": "export declare const MCP_SERVER_ARGS: readonly [
|
|
3189
|
+
"signature": "export declare const MCP_SERVER_ARGS: readonly [`@nifrajs/cli@${string}`, \"mcp\"];"
|
|
2975
3190
|
},
|
|
2976
3191
|
{
|
|
2977
3192
|
"name": "MCP_SERVER_COMMAND",
|
|
@@ -3104,6 +3319,18 @@
|
|
|
3104
3319
|
"signature": "export interface McpWidget {\n readonly uri: string;\n readonly resource: McpResource;\n readonly meta: Record<string, unknown>;\n}",
|
|
3105
3320
|
"doc": "/** A widget: the resource to register on the server, its `ui://` URI, and the `_meta` link for its tool. */"
|
|
3106
3321
|
},
|
|
3322
|
+
{
|
|
3323
|
+
"name": "MemoryCache",
|
|
3324
|
+
"kind": "class",
|
|
3325
|
+
"package": "@nifrajs/cache",
|
|
3326
|
+
"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}"
|
|
3327
|
+
},
|
|
3328
|
+
{
|
|
3329
|
+
"name": "MemoryCacheOptions",
|
|
3330
|
+
"kind": "interface",
|
|
3331
|
+
"package": "@nifrajs/cache",
|
|
3332
|
+
"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}"
|
|
3333
|
+
},
|
|
3107
3334
|
{
|
|
3108
3335
|
"name": "MemoryCacheStore",
|
|
3109
3336
|
"kind": "class",
|
|
@@ -3130,6 +3357,13 @@
|
|
|
3130
3357
|
"package": "@nifrajs/middleware",
|
|
3131
3358
|
"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}"
|
|
3132
3359
|
},
|
|
3360
|
+
{
|
|
3361
|
+
"name": "MemoryJobStore",
|
|
3362
|
+
"kind": "class",
|
|
3363
|
+
"package": "@nifrajs/jobs",
|
|
3364
|
+
"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}",
|
|
3365
|
+
"doc": "/** Construct an in-memory job store. `idFor` is injectable for deterministic tests. */"
|
|
3366
|
+
},
|
|
3133
3367
|
{
|
|
3134
3368
|
"name": "MemoryResponseCache",
|
|
3135
3369
|
"kind": "class",
|
|
@@ -3155,6 +3389,12 @@
|
|
|
3155
3389
|
"package": "@nifrajs/auth",
|
|
3156
3390
|
"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}"
|
|
3157
3391
|
},
|
|
3392
|
+
{
|
|
3393
|
+
"name": "MemoryStorage",
|
|
3394
|
+
"kind": "class",
|
|
3395
|
+
"package": "@nifrajs/storage",
|
|
3396
|
+
"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}"
|
|
3397
|
+
},
|
|
3158
3398
|
{
|
|
3159
3399
|
"name": "MemoryStore",
|
|
3160
3400
|
"kind": "class",
|
|
@@ -3389,6 +3629,13 @@
|
|
|
3389
3629
|
"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}",
|
|
3390
3630
|
"doc": "/** The portable socket handed to WS lifecycle callbacks. Each adapter wraps its native socket. */"
|
|
3391
3631
|
},
|
|
3632
|
+
{
|
|
3633
|
+
"name": "noBackoff",
|
|
3634
|
+
"kind": "const",
|
|
3635
|
+
"package": "@nifrajs/jobs",
|
|
3636
|
+
"signature": "export declare const noBackoff: Backoff;",
|
|
3637
|
+
"doc": "/** No delay — retry immediately. */"
|
|
3638
|
+
},
|
|
3392
3639
|
{
|
|
3393
3640
|
"name": "NodeBuiltinFinding",
|
|
3394
3641
|
"kind": "interface",
|
|
@@ -3547,6 +3794,13 @@
|
|
|
3547
3794
|
"signature": "export declare function packageOf(spec: string): string | undefined;",
|
|
3548
3795
|
"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 */"
|
|
3549
3796
|
},
|
|
3797
|
+
{
|
|
3798
|
+
"name": "Page",
|
|
3799
|
+
"kind": "interface",
|
|
3800
|
+
"package": "@nifrajs/schema",
|
|
3801
|
+
"signature": "export interface Page<Item> {\n readonly items: Item[];\n readonly nextCursor: string | null;\n}",
|
|
3802
|
+
"doc": "/** A cursor-pagination page — matches the shape of `t.paginated(item)`. */"
|
|
3803
|
+
},
|
|
3550
3804
|
{
|
|
3551
3805
|
"name": "PageRouteInput",
|
|
3552
3806
|
"kind": "interface",
|
|
@@ -3561,6 +3815,13 @@
|
|
|
3561
3815
|
"signature": "export declare function pageRoutesSection(manifest: Manifest | undefined): string;",
|
|
3562
3816
|
"doc": "/** Markdown section listing the file-routed pages (URL pattern → source file). */"
|
|
3563
3817
|
},
|
|
3818
|
+
{
|
|
3819
|
+
"name": "paginate",
|
|
3820
|
+
"kind": "function",
|
|
3821
|
+
"package": "@nifrajs/schema",
|
|
3822
|
+
"signature": "export declare function paginate<Row>(rows: readonly Row[], limit: number, cursorOf: (row: Row) => unknown): Page<Row>;",
|
|
3823
|
+
"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 */"
|
|
3824
|
+
},
|
|
3564
3825
|
{
|
|
3565
3826
|
"name": "Params",
|
|
3566
3827
|
"kind": "type",
|
|
@@ -3917,6 +4178,12 @@
|
|
|
3917
4178
|
"signature": "export declare function publicEnvDefines(prefix: string, env: Readonly<Record<string, string | undefined>>): Record<string, string>;",
|
|
3918
4179
|
"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 */"
|
|
3919
4180
|
},
|
|
4181
|
+
{
|
|
4182
|
+
"name": "PutOptions",
|
|
4183
|
+
"kind": "interface",
|
|
4184
|
+
"package": "@nifrajs/storage",
|
|
4185
|
+
"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}"
|
|
4186
|
+
},
|
|
3920
4187
|
{
|
|
3921
4188
|
"name": "QueryClient",
|
|
3922
4189
|
"kind": "interface",
|
|
@@ -3977,12 +4244,44 @@
|
|
|
3977
4244
|
"signature": "export type QueryValue = string | string[];",
|
|
3978
4245
|
"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). */"
|
|
3979
4246
|
},
|
|
4247
|
+
{
|
|
4248
|
+
"name": "Queue",
|
|
4249
|
+
"kind": "interface",
|
|
4250
|
+
"package": "@nifrajs/jobs",
|
|
4251
|
+
"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}"
|
|
4252
|
+
},
|
|
4253
|
+
{
|
|
4254
|
+
"name": "QueueOptions",
|
|
4255
|
+
"kind": "interface",
|
|
4256
|
+
"package": "@nifrajs/jobs",
|
|
4257
|
+
"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}"
|
|
4258
|
+
},
|
|
3980
4259
|
{
|
|
3981
4260
|
"name": "quotedHeaderValue",
|
|
3982
4261
|
"kind": "function",
|
|
3983
4262
|
"package": "@nifrajs/middleware",
|
|
3984
4263
|
"signature": "export declare function quotedHeaderValue(value: string): string;"
|
|
3985
4264
|
},
|
|
4265
|
+
{
|
|
4266
|
+
"name": "R2BucketLike",
|
|
4267
|
+
"kind": "interface",
|
|
4268
|
+
"package": "@nifrajs/storage",
|
|
4269
|
+
"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}",
|
|
4270
|
+
"doc": "/** The slice of the R2 bucket binding this adapter calls. `env.<BUCKET>` satisfies it. */"
|
|
4271
|
+
},
|
|
4272
|
+
{
|
|
4273
|
+
"name": "R2ObjectLike",
|
|
4274
|
+
"kind": "interface",
|
|
4275
|
+
"package": "@nifrajs/storage",
|
|
4276
|
+
"signature": "export interface R2ObjectLike {\n readonly size: number;\n readonly httpMetadata?: {\n readonly contentType?: string;\n };\n readonly customMetadata?: Record<string, string>;\n}",
|
|
4277
|
+
"doc": "/** The slice of R2's object metadata this adapter reads. */"
|
|
4278
|
+
},
|
|
4279
|
+
{
|
|
4280
|
+
"name": "R2Storage",
|
|
4281
|
+
"kind": "class",
|
|
4282
|
+
"package": "@nifrajs/storage",
|
|
4283
|
+
"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}"
|
|
4284
|
+
},
|
|
3986
4285
|
{
|
|
3987
4286
|
"name": "rateLimit",
|
|
3988
4287
|
"kind": "function",
|
|
@@ -4262,6 +4561,13 @@
|
|
|
4262
4561
|
"signature": "export declare function renderSizeReport(report: SizeReport): string;",
|
|
4263
4562
|
"doc": "/**\n * Render a {@link SizeReport} as a terse aligned table (biggest first) with a totals row — the text\n * `nifra build --report` prints. Pure (string in, string out) so the formatting is unit-testable.\n */"
|
|
4264
4563
|
},
|
|
4564
|
+
{
|
|
4565
|
+
"name": "renderTypesResult",
|
|
4566
|
+
"kind": "function",
|
|
4567
|
+
"package": "@nifrajs/cli",
|
|
4568
|
+
"signature": "export declare function renderTypesResult(types: readonly TypeEntry[], name: string | undefined, query: string | undefined, limit: number): string;",
|
|
4569
|
+
"doc": "/**\n * Render the tool result. `name` → the exact declaration(s); else `query` → the top matches; else a\n * per-package index of type names. The signatures are authoritative (generated from the built `.d.ts`),\n * so this is the complete answer — there is no need to read a `.d.ts` file.\n */"
|
|
4570
|
+
},
|
|
4265
4571
|
{
|
|
4266
4572
|
"name": "reproduciblePath",
|
|
4267
4573
|
"kind": "function",
|
|
@@ -4463,6 +4769,12 @@
|
|
|
4463
4769
|
"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: null;\n readonly error: ApiError;\n};",
|
|
4464
4770
|
"doc": "/**\n * The outcome of a client call. The client never throws — inspect `ok` (or\n * `error`) to branch. On success `data` is the (JSON-shaped) response body; on\n * failure `error` carries the server's structured error or a transport error.\n */"
|
|
4465
4771
|
},
|
|
4772
|
+
{
|
|
4773
|
+
"name": "RetryPolicy",
|
|
4774
|
+
"kind": "interface",
|
|
4775
|
+
"package": "@nifrajs/jobs",
|
|
4776
|
+
"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}"
|
|
4777
|
+
},
|
|
4466
4778
|
{
|
|
4467
4779
|
"name": "revalidate",
|
|
4468
4780
|
"kind": "function",
|
|
@@ -4523,6 +4835,13 @@
|
|
|
4523
4835
|
"signature": "export declare const ROUTE_GLOBAL = \"__NIFRA_ROUTE__\";",
|
|
4524
4836
|
"doc": "/** Global the server writes the matched route id into; the client uses it to pick the chain. */"
|
|
4525
4837
|
},
|
|
4838
|
+
{
|
|
4839
|
+
"name": "RouteBody",
|
|
4840
|
+
"kind": "type",
|
|
4841
|
+
"package": "@nifrajs/web",
|
|
4842
|
+
"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;",
|
|
4843
|
+
"doc": "/** The body object type of `App`'s `Method Path` route (`never` when the route declares no body). */"
|
|
4844
|
+
},
|
|
4526
4845
|
{
|
|
4527
4846
|
"name": "RouteConfigError",
|
|
4528
4847
|
"kind": "class",
|
|
@@ -4607,6 +4926,13 @@
|
|
|
4607
4926
|
"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}",
|
|
4608
4927
|
"doc": "/** A route module — the default component + optional loader / action / meta. */"
|
|
4609
4928
|
},
|
|
4929
|
+
{
|
|
4930
|
+
"name": "RoutePaths",
|
|
4931
|
+
"kind": "type",
|
|
4932
|
+
"package": "@nifrajs/web",
|
|
4933
|
+
"signature": "export type RoutePaths<App> = keyof RegistryOf<App> & string;",
|
|
4934
|
+
"doc": "/** Every route path the app declares — constrains `Path`, so a wrong path is itself a type error. */"
|
|
4935
|
+
},
|
|
4610
4936
|
{
|
|
4611
4937
|
"name": "routePathToFile",
|
|
4612
4938
|
"kind": "function",
|
|
@@ -4948,6 +5274,12 @@
|
|
|
4948
5274
|
"package": "@nifrajs/cli",
|
|
4949
5275
|
"signature": "export interface ScoredSection extends DocSection {\n readonly score: number;\n}"
|
|
4950
5276
|
},
|
|
5277
|
+
{
|
|
5278
|
+
"name": "ScoredType",
|
|
5279
|
+
"kind": "interface",
|
|
5280
|
+
"package": "@nifrajs/cli",
|
|
5281
|
+
"signature": "export interface ScoredType extends TypeEntry {\n readonly score: number;\n}"
|
|
5282
|
+
},
|
|
4951
5283
|
{
|
|
4952
5284
|
"name": "ScriptDescriptor",
|
|
4953
5285
|
"kind": "interface",
|
|
@@ -4995,6 +5327,13 @@
|
|
|
4995
5327
|
"signature": "export interface SearchTermGroup {\n readonly term: string;\n readonly variants: readonly string[];\n}",
|
|
4996
5328
|
"doc": "/**\n * Tiny deterministic query expansion for the agent-facing docs/example search tools.\n *\n * This is intentionally not \"semantic search\": the corpora are small, curated, and bundled with the\n * package. A few framework-specific aliases plus safe prefix matching cover the common human/agent\n * wording drift (\"authentication\" vs \"auth\", \"ws\" vs \"websocket\") without adding dependencies,\n * model calls, or nondeterministic ranking.\n */"
|
|
4997
5329
|
},
|
|
5330
|
+
{
|
|
5331
|
+
"name": "searchTypes",
|
|
5332
|
+
"kind": "function",
|
|
5333
|
+
"package": "@nifrajs/cli",
|
|
5334
|
+
"signature": "export declare function searchTypes(types: readonly TypeEntry[], query: string, limit: number): ScoredType[];",
|
|
5335
|
+
"doc": "/** Keyword-score types: a term in the name is worth far more than one in the signature/doc body. */"
|
|
5336
|
+
},
|
|
4998
5337
|
{
|
|
4999
5338
|
"name": "secretBytes",
|
|
5000
5339
|
"kind": "function",
|
|
@@ -5079,7 +5418,7 @@
|
|
|
5079
5418
|
"name": "Server",
|
|
5080
5419
|
"kind": "class",
|
|
5081
5420
|
"package": "@nifrajs/core",
|
|
5082
|
-
"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 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}",
|
|
5421
|
+
"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}",
|
|
5083
5422
|
"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 */"
|
|
5084
5423
|
},
|
|
5085
5424
|
{
|
|
@@ -5127,7 +5466,7 @@
|
|
|
5127
5466
|
"name": "ServerOptions",
|
|
5128
5467
|
"kind": "interface",
|
|
5129
5468
|
"package": "@nifrajs/core",
|
|
5130
|
-
"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 /** 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}"
|
|
5469
|
+
"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}"
|
|
5131
5470
|
},
|
|
5132
5471
|
{
|
|
5133
5472
|
"name": "ServeStaticOptions",
|
|
@@ -5225,6 +5564,12 @@
|
|
|
5225
5564
|
"signature": "export declare function setMountedRouter(router: ClientRouter | undefined): void;",
|
|
5226
5565
|
"doc": "/** Register (or clear) the router that owns fetchers — called by `mountRouter`. Not for app use. */"
|
|
5227
5566
|
},
|
|
5567
|
+
{
|
|
5568
|
+
"name": "SetOptions",
|
|
5569
|
+
"kind": "interface",
|
|
5570
|
+
"package": "@nifrajs/cache",
|
|
5571
|
+
"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}"
|
|
5572
|
+
},
|
|
5228
5573
|
{
|
|
5229
5574
|
"name": "setWsRuntime",
|
|
5230
5575
|
"kind": "function",
|
|
@@ -5479,6 +5824,13 @@
|
|
|
5479
5824
|
"package": "@nifrajs/env",
|
|
5480
5825
|
"signature": "export type StandardResult<Output> = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: ReadonlyArray<StandardIssue>;\n};"
|
|
5481
5826
|
},
|
|
5827
|
+
{
|
|
5828
|
+
"name": "StandardResult",
|
|
5829
|
+
"kind": "type",
|
|
5830
|
+
"package": "@nifrajs/jobs",
|
|
5831
|
+
"signature": "export type StandardResult<Output> = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: ReadonlyArray<{\n readonly message: string;\n }>;\n};",
|
|
5832
|
+
"doc": "/** The validate-result half of the Standard Schema spec. */"
|
|
5833
|
+
},
|
|
5482
5834
|
{
|
|
5483
5835
|
"name": "StandardSchemaProps",
|
|
5484
5836
|
"kind": "interface",
|
|
@@ -5498,6 +5850,13 @@
|
|
|
5498
5850
|
"package": "@nifrajs/env",
|
|
5499
5851
|
"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}"
|
|
5500
5852
|
},
|
|
5853
|
+
{
|
|
5854
|
+
"name": "StandardSchemaV1",
|
|
5855
|
+
"kind": "interface",
|
|
5856
|
+
"package": "@nifrajs/jobs",
|
|
5857
|
+
"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}",
|
|
5858
|
+
"doc": "/** A minimal structural view of a Standard Schema validator (v1). `t.object(...)` satisfies it. */"
|
|
5859
|
+
},
|
|
5501
5860
|
{
|
|
5502
5861
|
"name": "StandardSuccess",
|
|
5503
5862
|
"kind": "interface",
|
|
@@ -5544,6 +5903,48 @@
|
|
|
5544
5903
|
"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}",
|
|
5545
5904
|
"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. */"
|
|
5546
5905
|
},
|
|
5906
|
+
{
|
|
5907
|
+
"name": "StorageAdapter",
|
|
5908
|
+
"kind": "interface",
|
|
5909
|
+
"package": "@nifrajs/storage",
|
|
5910
|
+
"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}",
|
|
5911
|
+
"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 */"
|
|
5912
|
+
},
|
|
5913
|
+
{
|
|
5914
|
+
"name": "StorageData",
|
|
5915
|
+
"kind": "type",
|
|
5916
|
+
"package": "@nifrajs/storage",
|
|
5917
|
+
"signature": "export type StorageData = Uint8Array | ArrayBuffer | string;",
|
|
5918
|
+
"doc": "/** Accepted `put` payloads — normalized to bytes by each adapter. */"
|
|
5919
|
+
},
|
|
5920
|
+
{
|
|
5921
|
+
"name": "StorageKeyError",
|
|
5922
|
+
"kind": "class",
|
|
5923
|
+
"package": "@nifrajs/storage",
|
|
5924
|
+
"signature": "export declare class StorageKeyError extends Error {\n readonly name = \"StorageKeyError\";\n}",
|
|
5925
|
+
"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 */"
|
|
5926
|
+
},
|
|
5927
|
+
{
|
|
5928
|
+
"name": "StorageObject",
|
|
5929
|
+
"kind": "interface",
|
|
5930
|
+
"package": "@nifrajs/storage",
|
|
5931
|
+
"signature": "export interface StorageObject {\n readonly body: Uint8Array;\n readonly size: number;\n readonly contentType?: string;\n readonly metadata?: Readonly<Record<string, string>>;\n}",
|
|
5932
|
+
"doc": "/** An object read back from storage. `body` is buffered (not streamed) — fine for typical uploads. */"
|
|
5933
|
+
},
|
|
5934
|
+
{
|
|
5935
|
+
"name": "StoredEntry",
|
|
5936
|
+
"kind": "interface",
|
|
5937
|
+
"package": "@nifrajs/cache",
|
|
5938
|
+
"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}",
|
|
5939
|
+
"doc": "/** A cached entry as the store holds it. */"
|
|
5940
|
+
},
|
|
5941
|
+
{
|
|
5942
|
+
"name": "StoredJob",
|
|
5943
|
+
"kind": "interface",
|
|
5944
|
+
"package": "@nifrajs/jobs",
|
|
5945
|
+
"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}",
|
|
5946
|
+
"doc": "/** A job as handed back by {@link JobStore.lease}. `attempt` is the count of PRIOR attempts (0 the first time). */"
|
|
5947
|
+
},
|
|
5547
5948
|
{
|
|
5548
5949
|
"name": "string",
|
|
5549
5950
|
"kind": "function",
|
|
@@ -5623,7 +6024,7 @@
|
|
|
5623
6024
|
"name": "t",
|
|
5624
6025
|
"kind": "const",
|
|
5625
6026
|
"package": "@nifrajs/schema",
|
|
5626
|
-
"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};",
|
|
6027
|
+
"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 400), 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};",
|
|
5627
6028
|
"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 */"
|
|
5628
6029
|
},
|
|
5629
6030
|
{
|
|
@@ -5659,6 +6060,25 @@
|
|
|
5659
6060
|
"signature": "export declare const testClient: typeof inProcessClient;",
|
|
5660
6061
|
"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 */"
|
|
5661
6062
|
},
|
|
6063
|
+
{
|
|
6064
|
+
"name": "testSession",
|
|
6065
|
+
"kind": "function",
|
|
6066
|
+
"package": "@nifrajs/testing",
|
|
6067
|
+
"signature": "export declare function testSession<App extends AppLike>(app: App, options?: TestSessionOptions): TestSession<App>;",
|
|
6068
|
+
"doc": "/** Create a cookie-persisting in-process test client for `app`. */"
|
|
6069
|
+
},
|
|
6070
|
+
{
|
|
6071
|
+
"name": "TestSession",
|
|
6072
|
+
"kind": "interface",
|
|
6073
|
+
"package": "@nifrajs/testing",
|
|
6074
|
+
"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}"
|
|
6075
|
+
},
|
|
6076
|
+
{
|
|
6077
|
+
"name": "TestSessionOptions",
|
|
6078
|
+
"kind": "interface",
|
|
6079
|
+
"package": "@nifrajs/testing",
|
|
6080
|
+
"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}"
|
|
6081
|
+
},
|
|
5662
6082
|
{
|
|
5663
6083
|
"name": "TestSummary",
|
|
5664
6084
|
"kind": "interface",
|
|
@@ -5721,6 +6141,13 @@
|
|
|
5721
6141
|
"package": "@nifrajs/middleware",
|
|
5722
6142
|
"signature": "export declare function timingSafeEqualString(a: string, b: string): Promise<boolean>;"
|
|
5723
6143
|
},
|
|
6144
|
+
{
|
|
6145
|
+
"name": "toBytes",
|
|
6146
|
+
"kind": "function",
|
|
6147
|
+
"package": "@nifrajs/storage",
|
|
6148
|
+
"signature": "export declare function toBytes(data: StorageData): Uint8Array;",
|
|
6149
|
+
"doc": "/** Normalize any accepted payload to bytes. */"
|
|
6150
|
+
},
|
|
5724
6151
|
{
|
|
5725
6152
|
"name": "toFetchHandler",
|
|
5726
6153
|
"kind": "function",
|
|
@@ -5854,6 +6281,13 @@
|
|
|
5854
6281
|
"signature": "export declare function tsTypeOf(schema: unknown, depth?: number): string;",
|
|
5855
6282
|
"doc": "/**\n * Render a JSON Schema as a compact TypeScript-like type (`{ id: string, name?: string }`) — the\n * shape agents already think in, at a fraction of the raw JSON Schema's tokens (~70-80% smaller).\n * Anything the renderer doesn't model falls back to the raw JSON for that subtree, so the output\n * is always faithful, just not always minimal.\n */"
|
|
5856
6283
|
},
|
|
6284
|
+
{
|
|
6285
|
+
"name": "TypeEntry",
|
|
6286
|
+
"kind": "interface",
|
|
6287
|
+
"package": "@nifrajs/cli",
|
|
6288
|
+
"signature": "export interface TypeEntry {\n readonly name: string;\n readonly kind: \"interface\" | \"type\" | \"class\" | \"function\" | \"enum\" | \"const\";\n readonly package: string;\n /** The literal declaration text from the `.d.ts` — a clean signature, no implementation. */\n readonly signature: string;\n /** The declaration's JSDoc block, if any. */\n readonly doc?: string;\n}",
|
|
6289
|
+
"doc": "/**\n * `nifra_types` — the EXACT TypeScript of every exported `@nifrajs/*` symbol. The corpus is `types.json`\n * (written into this package by `bun run gen:llms`): each entry's `signature` is the literal declaration\n * parsed from the package's BUILT `.d.ts` with the TS compiler — a clean signature, never prose, never\n * truncated. So an agent that needs the precise shape of a type (`RateLimitStore`, `RouteSchema`, a\n * function signature) gets the authoritative source here and never has to read a `.d.ts` file.\n *\n * Lookup by `name` is exact (case-insensitive); `query` keyword-scores over the name (heavy) + the\n * signature/doc body; no args → a per-package index of the available type names.\n */"
|
|
6290
|
+
},
|
|
5857
6291
|
{
|
|
5858
6292
|
"name": "UI_EXTENSION_KEY",
|
|
5859
6293
|
"kind": "const",
|
|
@@ -6217,8 +6651,8 @@
|
|
|
6217
6651
|
"name": "VERSION",
|
|
6218
6652
|
"kind": "const",
|
|
6219
6653
|
"package": "@nifrajs/core",
|
|
6220
|
-
"signature": "export declare const VERSION: \"
|
|
6221
|
-
"doc": "
|
|
6654
|
+
"signature": "export declare const VERSION: \"1.1.0\";",
|
|
6655
|
+
"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 */"
|
|
6222
6656
|
},
|
|
6223
6657
|
{
|
|
6224
6658
|
"name": "ViteDevServer",
|
|
@@ -6260,6 +6694,13 @@
|
|
|
6260
6694
|
"signature": "export declare function walkSource(cwd: string, visit: (rel: string, content: string) => void): Promise<void>;",
|
|
6261
6695
|
"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`. */"
|
|
6262
6696
|
},
|
|
6697
|
+
{
|
|
6698
|
+
"name": "WarmWorker",
|
|
6699
|
+
"kind": "class",
|
|
6700
|
+
"package": "@nifrajs/cli",
|
|
6701
|
+
"signature": "export declare class WarmWorker {\n readonly fingerprint: string;\n private readonly label;\n private readonly proc;\n private readonly pending;\n private stdoutBuffer;\n private stderrBuffer;\n private nextId;\n private closed;\n constructor(child: \"mcp-run\" | \"mcp-render\", cwd: string, fingerprint: string, label: string);\n stop(): void;\n request(input: unknown, signal?: AbortSignal): Promise<string>;\n private readStdout;\n private readStderr;\n private handleLine;\n}",
|
|
6702
|
+
"doc": "/** A persistent `mcp-run`/`mcp-render` `--worker` subprocess: the backend/web app is loaded ONCE and\n * reused across newline-delimited `{ id, input }` requests, replying `{ id, output }`. The same machinery\n * powers both `nifra_run warm` and `nifra_render warm` — `child` selects which engine, `label` shapes the\n * cancellation message. The owning handler ({@link createWarmHandler}) fingerprints the source tree and\n * replaces the worker when a file changes, so warm reuse never serves a stale result. Exported for the\n * concurrency test that proves a single per-request cancel doesn't tear down the shared worker. */"
|
|
6703
|
+
},
|
|
6263
6704
|
{
|
|
6264
6705
|
"name": "wasmImageBackend",
|
|
6265
6706
|
"kind": "function",
|
|
@@ -6311,7 +6752,7 @@
|
|
|
6311
6752
|
"name": "WebSocketHandler",
|
|
6312
6753
|
"kind": "interface",
|
|
6313
6754
|
"package": "@nifrajs/core",
|
|
6314
|
-
"signature": "export interface WebSocketHandler<Data = unknown, Env = unknown, Schema extends StandardSchemaV1 | undefined = undefined> {\n /**\n * Cross-site WebSocket hijacking (CSWSH) guard — checked BEFORE `upgrade()`. A browser does not\n * apply CORS to WebSocket handshakes and DOES send the page's cookies, so without an Origin check\n * any site can open an authenticated socket to your app. Set this to lock the route to known\n * origins: a string allow-list (exact `Origin` header match) or a predicate. A request whose\n * `Origin` doesn't match (or is absent, for the allow-list form) is rejected with `403` before any\n * per-connection work
|
|
6755
|
+
"signature": "export interface WebSocketHandler<Data = unknown, Env = unknown, Schema extends StandardSchemaV1 | undefined = undefined> {\n /**\n * Cross-site WebSocket hijacking (CSWSH) guard — checked BEFORE `upgrade()`. A browser does not\n * apply CORS to WebSocket handshakes and DOES send the page's cookies, so without an Origin check\n * any site can open an authenticated socket to your app. Set this to lock the route to known\n * origins: a string allow-list (exact `Origin` header match) or a predicate. A request whose\n * `Origin` doesn't match (or is absent, for the allow-list form) is rejected with `403` before any\n * per-connection work.\n *\n * **When omitted, the default is same-origin:** a cross-origin BROWSER handshake (an `Origin` header\n * whose host differs from the request's) is rejected with `403`. Non-browser clients (no `Origin`) and\n * same-origin browsers pass. Set this to allow specific cross-origin clients, or `() => true` for a\n * genuinely public socket. Non-browser clients can spoof `Origin`, so this is a browser-CSWSH defense,\n * not authentication — pair it with auth in `upgrade()`.\n */\n allowedOrigins?: ReadonlyArray<string> | ((origin: string | null) => boolean);\n /**\n * Runs in the HTTP request context **before** the upgrade (and after {@link allowedOrigins}) — the\n * place to authenticate or rate-limit. Return the initial per-connection `data` (→ `ws.data`), or a\n * `Response` to **reject** the upgrade (the client never connects). Omit to accept with\n * `data: undefined`. A thrown error rejects with a flat 500.\n */\n upgrade?(c: WebSocketContext<Env>): MaybePromise<Data | Response>;\n /**\n * Contract-first messages: a Standard Schema (`t`, zod, valibot, …) validating each **inbound** frame.\n * Text frames are parsed as JSON first. When set, `message` receives the validated, typed value; a\n * non-JSON or schema-invalid frame is routed to `onInvalidMessage` (or dropped if that's omitted).\n */\n messageSchema?: Schema;\n open?(ws: NifraWebSocket<Data>): MaybePromise<void>;\n message?(ws: NifraWebSocket<Data>, data: WsMessageInput<Schema>): MaybePromise<void>;\n /** Inbound frame that failed JSON parse or `messageSchema` validation (only fires when a schema is\n * set). `raw` is the original frame; `issues` are the Standard Schema issues (one synthetic issue for\n * a JSON parse failure). Omit to silently drop invalid frames. */\n onInvalidMessage?(ws: NifraWebSocket<Data>, issues: ReadonlyArray<StandardIssue>, raw: WebSocketData): MaybePromise<void>;\n close?(ws: NifraWebSocket<Data>, code: number, reason: string): MaybePromise<void>;\n error?(ws: NifraWebSocket<Data>, error: unknown): MaybePromise<void>;\n}",
|
|
6315
6756
|
"doc": "/** A WebSocket route's lifecycle. All callbacks optional; only `message` is needed for an echo. */"
|
|
6316
6757
|
},
|
|
6317
6758
|
{
|
|
@@ -6348,6 +6789,24 @@
|
|
|
6348
6789
|
"signature": "export declare function withISR(app: ISRApp, options: ISROptions): (req: Request, platform?: ISRPlatform) => Promise<Response>;",
|
|
6349
6790
|
"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 */"
|
|
6350
6791
|
},
|
|
6792
|
+
{
|
|
6793
|
+
"name": "Worker",
|
|
6794
|
+
"kind": "interface",
|
|
6795
|
+
"package": "@nifrajs/jobs",
|
|
6796
|
+
"signature": "export interface Worker {\n /** Stop polling and await the in-flight round (graceful). */\n stop(): Promise<void>;\n readonly running: boolean;\n}"
|
|
6797
|
+
},
|
|
6798
|
+
{
|
|
6799
|
+
"name": "WorkerOptions",
|
|
6800
|
+
"kind": "interface",
|
|
6801
|
+
"package": "@nifrajs/jobs",
|
|
6802
|
+
"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}"
|
|
6803
|
+
},
|
|
6804
|
+
{
|
|
6805
|
+
"name": "WrapOptions",
|
|
6806
|
+
"kind": "type",
|
|
6807
|
+
"package": "@nifrajs/cache",
|
|
6808
|
+
"signature": "export type WrapOptions = SetOptions;"
|
|
6809
|
+
},
|
|
6351
6810
|
{
|
|
6352
6811
|
"name": "wrapWebSocketMessageValidation",
|
|
6353
6812
|
"kind": "function",
|