import { BlockDefinition, ComponentRegistryEntry, EvaluatedBlock } from "@ministryofjustice/hmpps-forge/core/components"; import { RENDER_BLOCK_BRAND, ValidationResult, ValidationResult as ValidationResult$1, isRenderBlock } from "@ministryofjustice/hmpps-forge/core"; import { BlockType, ViewConfig } from "@ministryofjustice/hmpps-forge/core/authoring"; //#region forge-core/src/framework/types/adapter.type.d.ts /** * A minimal logger interface compatible with pino, bunyan, console, and most logging libraries. */ interface Logger { info(...args: unknown[]): void; error(...args: unknown[]): void; warn(...args: unknown[]): void; debug(...args: unknown[]): void; } /** * Read-only view of the components an adapter can render, keyed by variant. */ interface ComponentRegistry { get(variant: string): ComponentRegistryEntry | undefined; getAll(): ReadonlyMap>; } //#endregion //#region forge-core/src/framework/types/request.type.d.ts /** * HTTP method for the request */ type HttpMethod = 'GET' | 'POST'; interface RequestLocation { readonly origin: string; readonly href: string; readonly pathname: string; readonly basePath: string; } //#endregion //#region forge-core/src/framework/types/snapshot.type.d.ts /** * A plain, framework-agnostic description of a single request to evaluate. * * The adapter builds this from its native request (Express, Remix, a test * harness, a React store, …) and hands it to {@link Forge.evaluate}. The engine * never sees the native request — everything it needs to evaluate a step lives * here as serialisable data. */ interface RequestSnapshot { /** Identifies which compiled node (step or journey root) to evaluate. Taken from {@link ForgeRoute.nodeId}. */ readonly nodeId: string; /** GET selects the view/enter pipeline; POST selects the submit pipeline. */ readonly method: HttpMethod; /** Origin, pathname and base path used to resolve relative redirect targets. */ readonly location: RequestLocation; readonly params: Record; readonly query: Record; readonly post: Record; readonly headers: Record; readonly cookies: Record; /** Adapter-managed request state (e.g. Express `res.locals`), readable by hooks. */ readonly state: Record; /** * The session object. The engine reads it via `getSession()` and author code * may mutate it in place; the adapter is responsible for persisting it. */ readonly session: unknown; } //#endregion //#region forge-core/src/engine/chassis/contracts/ast/ast.type.d.ts /** * Template literal types for enforcing NodeID structure */ type CompileAstNodeId = `compile_ast:${number}`; type CompiledNodeId = `compiled:${string}`; /** * Union of all valid NodeId formats */ type NodeId = CompileAstNodeId | CompiledNodeId; /** * NodeIds categorized by AST node type */ type AstNodeId = CompileAstNodeId; //#endregion //#region forge-core/src/framework/types/routeTree.type.d.ts type RouteTreeRouteKind = 'journey' | 'step'; interface RouteTreeRoute { kind: RouteTreeRouteKind; nodeId: NodeId; title?: string; description?: string; metadata?: Record; } interface RouteTreeNode { segment: string; path: string; templatePath: string; active: boolean; metadata?: Record; route?: RouteTreeRoute; children: RouteTreeNode[]; } type RouteTree = RouteTreeNode[]; //#endregion //#region forge-core/src/framework/types/rendering.type.d.ts type MaybePromise = T | Promise; interface RenderBlock { readonly id: NodeId; readonly variant: string; readonly blockType: BlockType; readonly properties: Record; } /** * A field validation failure prepared for rendering. `anchor` is the failing * block instance's document anchor (its `idPrefix` or code) for error summary * links; several blocks may share one code, so the code alone cannot identify * the instance. */ interface RenderValidationError extends ValidationResult$1 { anchor?: string; } /** * Journey ancestor in the render context, including its evaluated view configuration. */ interface JourneyAncestor { code: string; path: string; title?: string; view?: ViewConfig; metadata?: Record; [key: string]: unknown; } /** * Render context assembled by the resolve phase (`request.resolve`). * Contains all data needed to render a page */ interface RenderContext { /** Route hierarchy with request params resolved and active state applied. */ routeTree: RouteTree; /** * Current step properties (excluding hooks and blocks). * Contains all step properties like path, title, view, backlink, metadata, * plus any custom properties defined on the step. */ step: { path: string; title?: string; /** Effective view inherited from journey ancestors and completed by the current step. */ view?: ViewConfig; backlink?: string; metadata?: Record; [key: string]: unknown; }; /** Journey ancestors from root to immediate parent. */ ancestors: JourneyAncestor[]; /** Evaluated blocks ready for rendering (data, not HTML) */ blocks: RenderBlock[]; /** Whether to show validation failures on blocks */ showValidationFailures: boolean; /** Failed validation results from field blocks (only populated when showValidationFailures is true) */ fieldValidationErrors: RenderValidationError[]; /** Failed domain validation results from step-level validations (only populated when showValidationFailures is true) */ domainValidationErrors: ValidationResult$1[]; /** Current answers state */ answers: Record; /** Current data state */ data: Record; } interface ForgeRenderer { renderBlock(entry: ComponentRegistryEntry, block: EvaluatedBlock): MaybePromise; /** * Optionally tag a block's rendered output with an out-of-band marker tying it * to its `nodeId`, so devtools can locate the block within the host output — * for an HTML renderer, paired comments bracketing the block. The orchestrator * calls this once per rendered block (nested blocks included) and only while a * request is being traced, so untraced (production) output is never marked. * Renderers whose output can't carry an invisible marker omit this method. */ markBlock?(nodeId: NodeId, output: TOut): TOut; wrapNestedBlock(block: BlockDefinition, output: TOut): MaybePromise; assemblePage(context: RenderContext, renderedBlocks: readonly TOut[], requestState: Record): MaybePromise; } //#endregion //#region forge-core/src/framework/types/outcome.type.d.ts /** * Error returned in a Forge error outcome. Its optional status and statusCode * properties are hints for framework adapters. */ interface ForgeError extends Error { readonly status?: number; readonly statusCode?: number; } type ForgeOutcome = { readonly kind: 'render'; readonly context: RenderContext; readonly output?: TOut; } | { readonly kind: 'navigate'; readonly url: string; } | { readonly kind: 'error'; readonly error: ForgeError; }; //#endregion //#region forge-core/src/framework/types/topology.type.d.ts type RouteMethod = 'GET' | 'POST'; /** * A single registrable route, derived by the engine from the compiled journey. * * Adapters consume these to wire routes into their framework however they like * (Express routers, Remix route modules, a client-side dispatch table, …). The * engine owns route *derivation*; the adapter owns route *registration*. */ interface ForgeRoute { /** Pass this back on the {@link RequestSnapshot} to evaluate this node. */ readonly nodeId: string; readonly kind: 'step' | 'journey'; /** Full path template including base path and `:param` placeholders, e.g. `/forms/order/:id/details`. */ readonly templatePath: string; /** The owning journey's base path template, used to resolve relative redirects. */ readonly basePath: string; /** Steps accept GET (view) and POST (submit); journey roots accept GET (enter). */ readonly methods: RouteMethod[]; } /** The full set of routes a registered set of journeys exposes. */ interface ForgeTopology { readonly routes: ForgeRoute[]; } //#endregion //#region forge-core/src/framework/types/response.type.d.ts interface CookieOptions { maxAge?: number; expires?: Date; httpOnly?: boolean; secure?: boolean; sameSite?: 'strict' | 'lax' | 'none'; path?: string; domain?: string; } interface CookieMutation { value: string; options?: CookieOptions; } //#endregion //#region forge-core/src/framework/types/responseBindings.type.d.ts interface ResponseBindings { setHeader(name: string, value: string): void; setCookie(name: string, value: string, options?: CookieOptions): void; } declare const NO_OP_RESPONSE_BINDINGS: ResponseBindings; //#endregion export { type AstNodeId, type ComponentRegistry, type CookieMutation, type CookieOptions, type ForgeError, type ForgeOutcome, type ForgeRenderer, type ForgeRoute, type ForgeTopology, type HttpMethod, type JourneyAncestor, type Logger, NO_OP_RESPONSE_BINDINGS, type NodeId, RENDER_BLOCK_BRAND, type RenderBlock, type RenderContext, type RequestLocation, type RequestSnapshot, type ResponseBindings, type RouteMethod, type RouteTree, type RouteTreeNode, type RouteTreeRoute, type RouteTreeRouteKind, type ValidationResult, isRenderBlock };