/** * A rendering-library integration used by Farm's compiler, server renderer, * and browser hydration runtime. * * Renderer descriptors intentionally contain module identifiers instead of * implementation functions. This keeps farm.config.ts serializable and lets * every module resolve from the application that selected the renderer. */ interface FarmRenderer { /** Stable public identifier used in diagnostics and generated manifests. */ name: string; /** Module exporting the renderer's Vite plugin factory. */ vite: string; /** Module exporting Farm's server-renderer compatibility contract. */ server: string; /** Module exporting Farm's browser-renderer compatibility contract. */ client: string; /** JSX import source written to generated TypeScript configuration. */ jsxImportSource?: string; /** Additional file extensions used for renderer-owned route components. */ componentExtensions?: readonly string[]; /** Packages that must share one module instance in a Farm application. */ dedupe?: readonly string[]; /** Renderer packages seeded into Vite's dependency optimizer. */ optimizeDeps?: readonly string[]; /** * Scheduling policy for the production client and SSR graphs. * * Most renderer plugins are safe to run in parallel. Renderers whose * compiler plugins keep process-global mutable state can opt into serial * builds so one graph cannot invalidate the other's transforms. */ buildConcurrency?: "parallel" | "serial"; /** Runtime features this renderer intentionally supports. */ capabilities?: FarmRendererCapabilitiesInput; /** * Serializable options consumed by the renderer's Vite integration. * * Keeping renderer-owned configuration on the descriptor lets one rendering * library expose multiple compiler modes without teaching Farm's core about * each option. */ options?: Readonly>; } interface FarmRendererStreamingCapabilities { /** Supports Node.js writable streams through renderToPipeableStream(). */ node: boolean; /** Supports WHATWG ReadableStream output through renderToReadableStream(). */ web: boolean; } interface FarmRendererCapabilities { streaming: FarmRendererStreamingCapabilities; /** * Whether re-rendering an existing root diffs the new tree against the live * DOM instead of rebuilding it. * * Virtual-DOM renderers (React, Preact, Vue) compare the incoming tree with * what is mounted, so a client navigation that re-renders a shared layout * keeps the matching DOM nodes, their focus, and their component state. * * Compile-time fine-grained renderers (Solid, Svelte) have no virtual DOM to * diff against. Their updates flow through bindings created when elements * were constructed, so handing them a freshly materialized tree replaces the * nodes. That is a property of those runtimes, not a gap in their adapters, * and callers that need state to survive a re-render must keep it in a root * they do not re-render rather than expect reconciliation here. */ reconcilesRerenders: boolean; } interface FarmRendererCapabilitiesInput { streaming?: Partial; reconcilesRerenders?: boolean; } declare function getFarmRendererCapabilities(renderer?: Pick): FarmRendererCapabilities; declare const FARM_COMPONENT_EXTENSIONS: readonly [".ts", ".tsx", ".js", ".jsx"]; declare function resolveFarmComponentExtensions(extensions?: readonly string[]): string[]; declare function getFarmRendererComponentExtensions(renderer?: Pick): string[]; interface FarmRendererViteModule { createFarmRendererPlugin(options?: { ssr?: boolean; rendererOptions?: Readonly>; }): unknown | readonly unknown[] | Promise; } interface FarmServerRendererRuntime { readonly name: string; readonly Fragment: unknown; readonly Suspense: unknown; createElement(type: unknown, props?: unknown, ...children: unknown[]): unknown; isValidElement(value: unknown): boolean; /** Wraps a route-owned client tree so compiled leaf boundaries stay inside that React root. */ wrapClientGraph?(element: unknown): unknown; /** * Optional: locate where a streamed chunk stops being the static shell. * * Partial prerendering caches everything before the first dynamic boundary * and refreshes the rest on the client, so it has to know where that * boundary is. The markers are renderer-specific (React streams Fizz * boundary ids and `$RC`/`$RS` reveal calls, Solid streams `