import { IncomingMessage } from 'node:http'; import { Writable, Duplex } from 'node:stream'; import { FastifyPluginCallback, FastifyPluginAsync, FastifyInstance } from 'fastify'; import { S as ServiceRegistry, C as CoreTaujsConfig, B as DebugConfig, F as BaseLogger } from './types-Ce1QlQ5E.js'; import { TaujsConfig } from './Config.js'; export { AppError } from './Config.js'; import 'vite'; import './Renderer.js'; type GraphSource = 'boot' | 'build'; type GraphSchemaFlag = { declared: boolean; kind?: 'parse' | 'function'; }; type GraphWarningCode = 'routes.duplicate_path' | 'streaming.missing_meta' | 'render.defaulted' | 'csp.dev_directives' | 'fallthrough.unreachable'; type GraphWarning = { code: GraphWarningCode; severity: 'error' | 'warn' | 'info'; source: 'extract-routes' | 'security' | 'graph'; routeId?: string; message?: string; }; type GraphRouteData = { kind: 'none'; } | { kind: 'dynamic'; } | { kind: 'service'; service: string; method: string; }; type GraphRouteCSP = { declared: false; } | { declared: true; disabled: 'hard' | 'soft'; } | { declared: true; mode: 'merge' | 'replace'; dynamic: boolean; reportOnly: boolean; }; type GraphRoute = { id: string; appId: string; path: string; render: { strategy: 'ssr' | 'streaming'; defaulted: boolean; }; hydrate: { enabled: boolean; defaulted: boolean; }; /** Schema-v1 declaration score retained for deterministic graph ordering; Fastify owns runtime precedence. */ specificity: number; middleware: { auth: { declared: boolean; }; csp: GraphRouteCSP; }; data: GraphRouteData; /** * RFC 0007 (R5): declared `attr.deferred` entries, key-sorted. ABSENT when the route declares * none, per spec 02's additive-optional-fields rule - routes without the declaration keep * byte-identical graph emission and older readers are unaffected. `kind: 'none'` is not valid * here: an entry exists only when declared. */ deferred?: { key: string; data: GraphRouteData; }[]; /** head edge, mirrors data (decisions.md 2026-08-27): present only when `attr.head.data` is declared. */ head?: { data: GraphRouteData; }; }; type GraphUsedBy = { routeId: string; appId: string; path: string; }; type GraphServiceMethod = { name: string; params: GraphSchemaFlag; result: GraphSchemaFlag; usedBy: GraphUsedBy[]; }; type GraphService = { name: string; methods: GraphServiceMethod[]; }; type RequestGraph = { schemaVersion: 2; taujs: { server: string; }; source: GraphSource; emittedAt: string; disclosure: 'conservative'; apps: { appId: string; entryPoint: string; routeCount: number; }[]; routes: GraphRoute[]; services: GraphService[] | null; security: { reporting: boolean; }; fallthrough: { mode: 'spa'; appId: string; assetLike: 404; reachable: boolean; }; warnings: GraphWarning[]; }; type CreateRequestGraphOptions = { source: GraphSource; emittedAt: string; serviceRegistry?: ServiceRegistry; }; declare function createRequestGraph(config: CoreTaujsConfig, options: CreateRequestGraphOptions): RequestGraph; /** * RFC 0007 (decision 14): the accepted INTERNAL host -> renderer transport. A BARE named-promise * record - no scheduler, no lifecycle handle, no per-entry policy. Not a public application API. */ type DeferredDataRegistry = Readonly>>>; type StaticMountEntry = { plugin: FastifyPluginCallback | FastifyPluginAsync; options?: Record; }; type StaticAssetsRegistration = false | StaticMountEntry | StaticMountEntry[]; interface InitialRouteParams extends Record { serviceName?: string; serviceMethod?: string; } /** * Structured, NON-FATAL render-error observation (R1-01). `phase` is the OBSERVED timing (had the * shell committed when the renderer surfaced the error) — descriptive only, never a fatality * signal. `recoverable` is `true` only for `post-shell` errors (the renderer's client runtime completes * the affected boundary) and `'unknown'` for `pre-shell` (outcome resolved by the fatal channels). */ type RenderErrorInfo = { error: unknown; phase: 'pre-shell' | 'post-shell'; recoverable: boolean | 'unknown'; }; type RenderCallbacks = { /** REQUIRED (operationally): commits the head + connects the sink. A throwing `onHead` is fatal. */ onHead?: (headContent: string) => void; /** Advisory (isolated — a throw is logged, not fatal). */ onShellReady?: () => void; /** Advisory. Fires once with the resolved route data. */ onAllReady?: (initialData: T) => void; /** FATAL error channel (shell error / timeout / guard / non-recoverable). */ onError?: (error: unknown) => void; /** * Advisory, NON-FATAL structured render-error channel (R1-01) — fires for render errors that do * not fail the response (notably post-shell boundary errors React recovers client-side). The * server wires this to the request logger. Never a fatality signal. */ onRenderError?: (info: RenderErrorInfo) => void; }; /** * Minimal structural logger the server passes to a renderer's optional `opts.logger`. The * server's rich `Logs` satisfies it (asserted below), and it is in turn assignable to a * framework package's looser logger type — so a renderer's `createRenderer(...)` output is * assignable to `RenderModule` cast-free (V1-05; see docs/vue/04-gate-v1-review §4). * `debug`/`isDebugEnabled` accept `any` category to absorb `Logs`'s `DebugCategory`-typed * overloads; framework packages keep their own richer logger types internally. */ type RendererLogger = { info?: (meta?: unknown, message?: string) => void; warn?: (meta?: unknown, message?: string) => void; error?: (meta?: unknown, message?: string) => void; debug?: (category: any, meta?: unknown, message?: string) => void; isDebugEnabled?: (category: any) => boolean; }; /** * ESC-2 (RFC 0006): the named render-options bag shared by {@link RenderSSR} + {@link RenderStream} - the * single home for per-render metadata, superseding the two identical inline `{ logger, routeContext, * headData }` bags. * * - `cspNonce` is AUTHORITATIVE when present: it replaces the removed positional stream argument (the host * derives the request nonce once and passes it here on the streaming path). * - `shouldHydrate` is the host-RESOLVED hydration policy (`attr.hydrate !== false`). The host keeps its * operative hydration mechanism consistent with it (the stream `bootstrapModules` gate; the SSR bootstrap * tag), so a renderer may treat `shouldHydrate` as the authoritative declaration without a second source * of truth. * * Both fields are optional and additive - a renderer that ignores them behaves exactly as before. */ type RenderOptions = { logger?: RendererLogger; routeContext?: unknown; headData?: Record; cspNonce?: string; shouldHydrate?: boolean; /** * RFC 0007 (decision 14): the request-local registry of declared `attr.deferred` entries - * present ONLY when a streaming route declares them, and conditionally spread exactly like * `headData`. This is the accepted INTERNAL host-to-renderer transport, NOT a public application * API: every promise is already started and already pre-observed by the host, a resolved entry * is the host's settlement snapshot (parsed JSON, no identity relationship to the loader's * object), and a value that could not be snapshotted arrives as a detail-free rejection. The * renderer projects each named promise onto its native Suspense/resource primitive and starts * nothing. */ deferredData?: DeferredDataRegistry; }; type RenderSSR = (initialDataResolved: Record, location: string, meta?: Record, signal?: AbortSignal, opts?: RenderOptions) => Promise<{ headContent: string; appHtml: string; }>; /** * The lifecycle handle a renderer's `renderStream` returns (R0-01). * * - `abort()` requests a benign cancel of an in-flight stream. * - `done` resolves on normal completion or benign cancel, and REJECTS on a fatal stream error. * * The rejection is pre-observed inside the renderer: a no-op handler is attached to the same * promise at creation (see each framework's `createStreamController`), so an unobserved `done` * can never raise `unhandledRejection` — which Node's default mode turns into a * process-terminating `uncaughtException`. Consumers who `await done` still receive the fatal * error on their own handler; consumers who ignore `done` are safe. The server observes `done` * as acknowledgement (fatal errors are already handled via the `onError` callback) and as * defence in depth against a third-party renderer that omits the pre-attached handler. */ type RenderStreamHandle = { abort(): void; done: Promise; }; type RenderStream = (sink: Writable, callbacks: RenderCallbacks, initialData: Record | Promise> | (() => Promise>), location: string, bootstrapModules?: string, meta?: Record, signal?: AbortSignal, opts?: RenderOptions) => RenderStreamHandle; type RenderModule = { renderSSR: RenderSSR; renderStream: RenderStream; }; type NetResolved = { host: string; port: number; hmrPort: number; }; type CreateServerOptions = { config: TaujsConfig; serviceRegistry?: ServiceRegistry; clientRoot?: string; alias?: Record; /** * Project root for relative declarative alias normalisation (RFC 0005 §3). Pass the SAME * directory `taujsBuild({ projectRoot })` receives (the scaffold uses `process.cwd()` for * both) so a relative `config.alias` resolves identically in dev and build. Defaults to * `process.cwd()`. */ projectRoot?: string; fastify?: FastifyInstance; debug?: DebugConfig; logger?: BaseLogger; /** * Static assets in production: omit for the default `@fastify/static` registration, pass a * custom registration, or pass `false` to install no static plugin at all (CDN-owned assets). */ staticAssets?: StaticAssetsRegistration; /** * Port reported as `net.port` for the caller's `app.listen()`. Overrides `config.server.port`; * `PORT` / `FASTIFY_PORT` and `--port` still take precedence over it. `0` requests an ephemeral * port - read the bound port from `app.server.address()` after listening. */ port?: number; }; type CreateServerResult = { app?: FastifyInstance; net: NetResolved; dev: { hmr: { /** * `true`: this upgrade is τjs's HMR channel and has been handed to it - do nothing more * with the socket. `false`: not τjs's - the application decides. Never throws. */ tryHandleUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer): boolean; }; }; }; declare const createServer: (opts: CreateServerOptions) => Promise; interface MessageMetaLogger { debug?: (message?: string, meta?: Record) => unknown; info?: (message?: string, meta?: Record) => unknown; warn?: (message?: string, meta?: Record) => unknown; error?: (message?: string, meta?: Record) => unknown; child?: (bindings: Record) => MessageMetaLogger | undefined; } declare function winstonAdapter(winston: MessageMetaLogger): BaseLogger; export { BaseLogger, type CreateRequestGraphOptions, type GraphWarning, type InitialRouteParams, type RenderCallbacks, type RenderModule, type RenderOptions, type RenderSSR, type RenderStream, type RenderStreamHandle, type RendererLogger, type RequestGraph, createRequestGraph, createServer, winstonAdapter };