/** * @evjs/shared/manifest * * Shared contracts for the evjs control plane: semantic CoreGraph, concrete * BuildPlan, linked BuildOutput, and their runtime and deployment projections. * Core serializes DeploymentMetadata; client and framework runtimes consume * their dedicated projections rather than the complete BuildOutput. */ import { type StaticJsonObject } from "../serialization/static-json.js"; import { type PageMetadata } from "./page/metadata.js"; /** JavaScript and CSS assets emitted for a manifest entry. */ export interface AssetGroup { /** JavaScript bundle paths. */ js: string[]; /** CSS bundle paths. */ css: string[]; } export type PageScope = { kind: "module"; file: string; } | { kind: "directory"; root: string; }; export interface PprConfig { delivery?: PprDeliveryMode; revalidate?: number | false; regions?: Record; } export interface PprRegionConfig { component: string; fallback?: string; cache?: PprCachePolicy; } export type PprCachePolicy = "no-store" | { revalidate: number; }; export type PprDeliveryMode = "merge" | "stream"; export type AppRouteTarget = { kind: "page"; pageId: string; } | { kind: "group"; } | { kind: "redirect"; to: AppRouteLocation; }; export type AppRouteLocation = { kind: "path"; path: string; } | { kind: "url"; href: string; }; export interface ServerFunctionNode { id: string; module: string; exportName: string; } export interface ServerRouteNode { id: string; module: string; path: string; methods: string[]; } export interface ClientReferenceNode { id: string; module: string; exportName?: string; } export interface ServerReferenceNode { id: string; module: string; exportName?: string; } export type RenderMode = "csr" | "ssr" | "ssg"; export type ComponentModel = "client" | "rsc"; export type PrerenderConfig = true | { partial?: boolean; delivery?: PprDeliveryMode; revalidate?: number | false; }; export type HydrationMode = "none" | "load"; export type BuildEnvironment = "client" | "server"; export type ServerRuntime = "node" | "edge"; export type PublicPathOutput = string; /** * Concrete compilation and materialization units derived from resolved config * and CoreGraph. Semantic ownership remains in CoreGraph; bundler adapters * consume this plan and return build facts for linking. */ export interface BuildPlan { version: 1; buildId: string; mode: "development" | "production"; distDir: string; output: { clientDir: string; serverDir: string; }; resolve?: ResolvePlan; generated?: GeneratedFrameworkPlan; entries: BuildEntry[]; html: HtmlPlan[]; server: ServerBuildPlan; runtime: RuntimePlan; dev: DevBuildPlan; rsc?: RscBuildPlan; } export interface DevBuildPlan { clientRoutes: DevClientRoutePlan[]; /** Canonical request Route patterns handled by server file routes. */ serverRequestRoutePaths: string[]; /** Canonical Page route patterns whose rendering requires the dev server. */ serverRenderedPagePaths: string[]; hasPpr: boolean; } export interface DevClientRoutePlan { path: string; target: { kind: "app"; appId: string; } | { kind: "page"; pageId: string; }; } export interface RscBuildPlan { clientReferenceModules: string[]; } export interface ResolvePlan { alias?: Record; external?: Record; } export interface ResolveExternalPlan { source?: string; runtime?: "client" | "server" | "all"; } export interface BuildEntry { name: string; import: string; environment: BuildEnvironment; runtime?: "browser" | ServerRuntime; phase?: BuildEntryPhase; kind: "app-client" | "page-client" | "page-server" | "rsc-page" | "ppr-shell" | "ppr-region" | "server-runtime" | "runtime"; owner?: BuildEntryOwner; metadata?: BuildEntryMetadata; } export type BuildEntryPhase = "runtime" | "build"; export interface BuildEntryOwner { appId?: string; pageId?: string; routeId?: string; regionId?: string; } export type BuildEntryMetadata = ReactComponentPageEntryMetadata | ReactServerPageEntryMetadata | PagesAppEntryMetadata | ServerAppEntryMetadata; export interface ReactComponentPageEntryMetadata { type: "react-component-page"; component: string; /** Outer-to-inner Page composition for an independent MPA Page. */ layers?: ReactPageLayer[]; mount: string; /** * Effective browser activation policy. `"load"` mounts a CSR Page, but * hydrates a Page whose initial HTML came from SSR or SSG. */ hydrate: HydrationMode; render: RenderMode; route?: { id: string; path: string; }; } export interface ReactServerPageEntryMetadata { type: "react-server-page"; component: string; /** Outer-to-inner route composition shared with the client Page tree. */ layers?: ReactPageLayer[]; } export interface ReactPageLayer { kind: "layout" | "wrapper"; module: string; } export interface PagesAppEntryMetadata { type: "pages-app"; /** Browser route prefix applied by the generated SPA router. */ basepath?: string; routes: PagesAppRouteNode[]; mount: string; rootModule?: string; /** Application-root React wrappers, ordered outer-to-inner. */ wrappers?: string[]; } /** Route input consumed only by the generated framework SPA bootstrap. */ export interface PagesAppRouteNode { id: string; path: string; parentId?: string; kind?: PageRouteKind; module?: string; target?: AppRouteTarget; wrappers?: string[]; /** Bypass the Application/root layout while this route branch matches. */ layout?: false; errorModule?: string; notFoundModule?: string; /** Page-owned metadata projected into the generated SPA route runtime. */ metadata?: PageMetadata; } export interface ServerMiddlewareNode { id: string; module: string; scope: "global" | "route"; scopeSegments?: string[]; } export interface ServerAppRouteNode extends ServerRouteNode { middlewares?: ServerMiddlewareNode[]; } export interface ServerAppEntryMetadata { type: "server-app"; routes: ServerAppRouteNode[]; middlewares?: ServerMiddlewareNode[]; serverFunctions?: ServerFunctionNode[]; } export interface PageRouteNode { id: string; path: string; module: string; /** Page source boundary; explicit route input may retain module scope. */ scope?: PageScope; html?: string; parentId?: string; kind?: PageRouteKind; errorModule?: string; notFoundModule?: string; } export type PageRouteKind = "page" | "layout"; export interface HtmlPlan { id: string; template: string; fileName: string; /** Additional static paths containing the same transformed HTML Document. */ aliases?: string[]; owner: { appId?: string; pageId?: string; }; /** Page-owned metadata projected onto this concrete HTML document. */ metadata?: PageMetadata; } export interface ServerBuildPlan { entry?: string; renderers?: ServerRenderPlan[]; /** Module resolution overrides applied only to server build entries. */ resolve?: ServerResolvePlan; /** External modules applied only to server build entries. */ externals?: Record; /** * HTML templates compiled into request-time document shells for Pages that * are rendered by the deployment server. * * These are build inputs, not emitted static documents. Keeping them on the * server plan makes template ownership explicit and avoids reconstructing * document semantics from the CoreGraph in the runtime emission phase. */ documents?: ServerDocumentPlan[]; } export type ServerResolvePlan = Pick; export interface ServerDocumentPlan { /** Page whose request-time HTML is inserted into this document. */ pageId: string; /** Core Document identity exposed to HTML plugin hooks. */ documentId: string; /** Application identity exposed to application-scoped HTML contributions. */ applicationId: string; /** Source HTML template path. */ template: string; /** Logical document filename exposed to HTML plugin hooks; not emitted. */ fileName: string; /** Mount selector whose contents are replaced by the server-rendered Page. */ mount: string; /** Page-owned metadata applied before HTML plugin hooks run. */ metadata?: PageMetadata; } /** * Serialized request-time document template split around values produced while * rendering a Page request. */ export interface ServerDocumentShell { /** Document bytes before the server-rendered Page HTML. */ beforeContent: string; /** Document bytes between Page HTML and request-specific bootstrap data. */ betweenContentAndData: string; /** Document bytes after request-specific bootstrap data. */ afterData: string; } export interface ServerRenderPlan { name: string; import: string; phase?: BuildEntryPhase; kind: "page-server" | "rsc-page" | "ppr-shell" | "ppr-region"; owner?: BuildEntryOwner; metadata?: ReactServerPageEntryMetadata; } export interface RuntimePlan { publicPath: PublicPathOutput; server: RuntimeServerOutput; transport?: TransportOutput; } export interface BuildPlanUpdate { reason: "config" | "route-declaration" | "server-declaration" | "plugin"; previous: BuildPlan; next: BuildPlan; entries: { added: BuildEntry[]; removed: BuildEntry[]; changed: BuildEntry[]; }; html: { added: HtmlPlan[]; removed: HtmlPlan[]; changed: HtmlPlan[]; }; /** Generated IR or CoreGraph semantics changed without changing entry identity. */ generatedChanged: boolean; /** Bundler resolution inputs changed and require adapter reconfiguration. */ resolveChanged: boolean; /** Runtime endpoints, public paths, or transport settings changed. */ runtimeChanged: boolean; /** Config changed and framework-owned delivery artifacts must be re-emitted. */ deliveryChanged: boolean; /** Server compiler output, renderers, or RSC compilation inputs changed. */ serverCompilationChanged: boolean; /** Request-time server Document inputs changed and must be re-emitted. */ serverDocumentsChanged: boolean; /** Development routing or proxy topology changed. */ devRoutingChanged: boolean; } /** * Complete in-memory link of CoreGraph ownership, BuildPlan units, and bundler * asset facts. Plugins, runtime projection, and deployment projection consume * this contract; it is not serialized wholesale as the deployment artifact. */ export interface BuildOutput { version: 1; buildId: string; paths: BuildOutputPaths; publicPath: PublicPathOutput; runtime: RuntimeOutput; assets: Record; apps: Record; pages: Record; routes: RouteOutput[]; server: ServerOutput; rsc?: RscOutput; deployment?: StaticJsonObject; } export interface BuildOutputPaths { rootDir: string; publicDir: string; serverDir: string; } export interface RuntimeOutput { server: RuntimeServerOutput; transport?: TransportOutput; } export interface RuntimeServerOutput { basepath: string; fn: string; ppr?: string; rsc?: string; } export interface TransportOutput { baseUrl?: string; credentials?: "omit" | "same-origin" | "include"; headers?: Record; } export interface AppOutput { assets: AssetGroup; /** Browser route prefix for a framework-owned SPA Application. */ basepath?: string; document?: HtmlDocumentOutput; mount?: string; module?: RuntimeModuleOutput; } export interface PageOutput { assets: AssetGroup; document?: HtmlDocumentOutput; render: RenderMode; rendering: PageRenderingOutput; path?: string; routeId?: string; componentModel?: ComponentModel; /** Effective browser activation; CSR `"load"` means mount, not hydration. */ hydrate?: HydrationMode; mount?: string; prerender?: PrerenderConfig; module?: RuntimeModuleOutput; ppr?: PprPageOutput; metadata?: PageMetadata; } export interface HtmlDocumentOutput { fileName: string; aliases?: string[]; } export interface PageRenderingOutput { /** React execution model used by the page module. */ component: "client" | "server" | "rsc"; /** HTML delivery strategy for the initial document. */ html: "client" | "server" | "static" | "partial"; /** Static generation shape, when any part of the page is precomputed. */ prerender?: "full" | "partial"; /** Whether the page can stream server-rendered content after shell start. */ streaming: boolean; /** * Effective browser activation policy. CSR `"load"` means mount; with * server- or build-rendered HTML it means hydrate. */ hydrate: HydrationMode; } export interface PprPageOutput { delivery: PprDeliveryMode; shell: AssetGroup; regions: Record; } export interface PprRegionOutput { id: string; assets: AssetGroup; cache?: PprCachePolicy; } export interface RuntimeModuleOutput { type: "entry" | "lifecycle" | "react-component"; href?: string; } export interface RouteOutput { id: string; path: string; parentId?: string; kind?: PageRouteKind; appId?: string; pageId?: string; } /** * Canonical serializable deployment projection of public assets, Documents, * request routes, the server entry, and plugin-owned deployment metadata. */ export interface DeploymentMetadata { version: 1; buildId: string; paths: BuildOutputPaths; publicPath: PublicPathOutput; assets?: Record; documents: DeploymentDocumentOutput[]; routes: DeploymentRouteOutput[]; server: DeploymentServerOutput; metadata?: StaticJsonObject; } export type DeploymentDocumentOutput = { kind: "app"; id: string; fileName: string; aliases?: string[]; fallback?: string; assets?: AssetGroup; } | { kind: "page"; id: string; fileName: string; aliases?: string[]; assets?: AssetGroup; }; export type DeploymentPageRenderOutput = RenderMode; export type DeploymentServerPageRenderOutput = Extract; export type DeploymentRouteOutput = { kind: "static-page"; path: string; pageId: string; documentId: string; render: Extract; methods: ["GET", "HEAD"]; } | { kind: "server-page"; path: string; pageId: string; render: DeploymentServerPageRenderOutput; prerender?: "full" | "partial"; rsc?: true; methods: ["GET", "HEAD"]; } | { kind: "server-function"; path: string; methods: ["POST"]; } | { kind: "ppr-endpoint"; path: string; methods: ["GET", "HEAD"]; } | { kind: "rsc-endpoint"; path: string; methods: ["GET", "HEAD"]; } | { kind: "api-route"; path: string; methods: string[]; }; export interface DeploymentServerOutput { entry?: string; } export interface ServerOutput { entry?: string; assets: AssetGroup; renderers?: Record; functions: Record; routes: ServerRouteOutput[]; } export interface ServerRendererOutput { kind: ServerRenderPlan["kind"]; phase?: BuildEntryPhase; owner?: BuildEntryOwner; assets: AssetGroup; } export interface ServerFunctionOutput { assets: AssetGroup; exportName: string; } export interface ServerRouteOutput { path: string; methods: string[]; assets: AssetGroup; } export interface RscOutput { pages?: Record; } export interface RscPageOutput { renderer: string; assets: AssetGroup; routeId?: string; } export declare function assertFrameworkManifestShape(value: unknown, source: string): asserts value is BuildOutput; export type GeneratedScope = { kind: "application"; } | { kind: "page"; pageId: string; } | { kind: "server"; }; export type FrameworkSlotName = "client.entry" | "server.entry" | "application.wrapper" | "page.wrapper" | "server.request.middleware" | "html.tag" | "resolve.alias" | "resolve.external"; export type EntryContributionPosition = "polyfill" | "before-main-imports" | "after-main-imports" | "before-main" | "after-main"; export type ContributionRuntime = "client" | "server" | "all"; export type ClientContributionRuntime = "client"; export type ContributionTarget = { kind: "application"; applicationId?: string; } | { kind: "page"; pageId: string; }; export interface GeneratedFrameworkPlan { version: 1; rootDir: string; entriesDir: string; frameworkDir: string; pluginsDir: string; frameworkFiles: GeneratedFrameworkFilePlan[]; modules: GeneratedModulePlan[]; slots: FrameworkSlotPlanItem[]; importEdges: GeneratedImportEdgePlan[]; entries: GeneratedEntryPlan[]; /** Stable digest of the CoreGraph snapshot exposed to contribution hooks. */ coreGraphHash?: string; } export interface GeneratedFrameworkFilePlan { id: "core-graph" | "build-plan" | "api-client" | "server-function-transport"; file: string; } export interface GeneratedModulePlan { key: string; id: string; pluginId: string; scope: GeneratedScope; file: string; specifier: string; extension: string; /** Stable digest of the fully resolved generated module source. */ sourceHash: string; } export interface GeneratedEntryPlan { name: string; file: string; originalImport: string; kind: BuildEntry["kind"]; environment: BuildEnvironment; } export interface GeneratedImportEdgePlan { from: string; to: string; kind: "module-import" | "slot-module" | "resolve-alias" | "plugin-import-helper"; specifier: string; } export type FrameworkSlotPlanItem = ClientEntrySlotPlanItem | ServerEntrySlotPlanItem | ApplicationWrapperSlotPlanItem | PageWrapperSlotPlanItem | ServerRequestMiddlewareSlotPlanItem | HtmlTagSlotPlanItem | ResolveAliasSlotPlanItem | ResolveExternalSlotPlanItem; interface FrameworkSlotPlanItemBase { key: string; id: string; pluginId: string; } export interface ClientEntrySlotPlanItem extends FrameworkSlotPlanItemBase { slot: "client.entry"; module: string; position: EntryContributionPosition; runtime: ClientContributionRuntime; mode: "import" | "replace"; target?: ContributionTarget; } export interface ServerEntrySlotPlanItem extends FrameworkSlotPlanItemBase { slot: "server.entry"; module: string; position: EntryContributionPosition; mode: "import" | "replace"; target: { kind: "page"; pageId: string; }; } export interface ApplicationWrapperSlotPlanItem extends FrameworkSlotPlanItemBase { slot: "application.wrapper"; module: string; target?: { kind: "application"; applicationId?: string; }; } export interface PageWrapperSlotPlanItem extends FrameworkSlotPlanItemBase { slot: "page.wrapper"; module: string; runtime: ContributionRuntime; target?: ContributionTarget; } export interface ServerRequestMiddlewareSlotPlanItem extends FrameworkSlotPlanItemBase { slot: "server.request.middleware"; module: string; } export type HtmlTagPlacement = "head-prepend" | "head-append" | "body-prepend" | "body-append"; export type HtmlTagName = "meta" | "link" | "script" | "style"; export interface HtmlTagSlotPlanItem extends FrameworkSlotPlanItemBase { slot: "html.tag"; tag: HtmlTagName; placement: HtmlTagPlacement; attrs?: Record; children?: string; target?: ContributionTarget; } export interface ResolveAliasSlotPlanItem extends FrameworkSlotPlanItemBase { slot: "resolve.alias"; specifier: string; replacement: string; } export interface ResolveExternalSlotPlanItem extends FrameworkSlotPlanItemBase { slot: "resolve.external"; specifier: string; source?: string; runtime: ContributionRuntime; } export {}; //# sourceMappingURL=contracts.d.ts.map