Menu

API Reference

@kovojs/server

Generated from 9 public subpaths — 279 exports, 163 documented. Do not edit by hand.

@kovojs/server#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/index.ts

Functions#

createApp#

Assemble the app aggregate: the routes, queries, mutations, endpoints, document options, and session provider that make up a Kovo application. The returned KovoApp is the single object request dispatch starts from; pass it to createRequestHandler or a platform adapter like toNodeHandler (SPEC §9.5).

Parameter Type Description
options CreateAppOptions<SessionValue, DbValue, RawRequest, AppRequest> Routes, queries, mutations, endpoints, document, CSRF, and session config.
(returns) KovoApp<SessionValue, DbValue, RawRequest, AppRequest> A KovoApp aggregate with defaults filled in.
ts
function createApp<
  SessionValue = never,
  DbValue = never,
  RawRequest extends globalThis.Request = globalThis.Request,
  AppRequest = AppLifecycleRequest<RawRequest, SessionValue, DbValue>,
>(
  options: CreateAppOptions<SessionValue, DbValue, RawRequest, AppRequest> = {},
): KovoApp<SessionValue, DbValue, RawRequest, AppRequest>;

Example

ts
import { createApp, createRequestHandler, route } from '@kovojs/server';

const app = createApp({
  routes: [route('/', { page: () => '<h1>Home</h1>' })],
});

export const handler = createRequestHandler(app);

createRequestHandler#

Turn a KovoApp into a (request: Request) => Response handler that dispatches to routes, queries, mutations, and endpoints. Requires an app built by createApp (SPEC §9.5).

Parameter Type Description
app KovoApp An app aggregate from createApp.
(returns) RequestHandler A request handler suitable for the platform's server.
ts
function createRequestHandler(app: KovoApp): RequestHandler;

isKovoApp#

Return whether a dynamically loaded value is a closed Kovo app aggregate.

App-owned dev and export scripts use this SPEC.md §9.5 guard after loading an app module, before replaying it through the public Request -> Response shell.

ts
function isKovoApp(value: unknown): value is KovoApp;

createMemoryVersionedClientModuleRegistry#

Create an in-memory registry of versioned client modules — the default store createApp uses to serve hashed island/handler bundles to the browser.

Parameter Type Description
options MemoryVersionedClientModuleRegistryOptions Optional registry configuration.
(returns) VersionedClientModuleRegistry A VersionedClientModuleRegistry.
ts
function createMemoryVersionedClientModuleRegistry(
  options: MemoryVersionedClientModuleRegistryOptions = {},
): VersionedClientModuleRegistry;

toNodeHandler#

Adapt a Web-standard RequestHandler (from createRequestHandler) to a Node http/https (req, res) listener, translating between Node and Web request/response objects.

Parameter Type Description
handler RequestHandler The Web request handler to adapt.
options NodeHandlerOptions Node adapter options (e.g. base URL resolution).
(returns) NodeRequestHandler A Node request listener.
ts
function toNodeHandler(
  handler: RequestHandler,
  options: NodeHandlerOptions = {},
): NodeRequestHandler;

exportStaticApp#

Pre-render an app's static routes to files on disk for static hosting, verifying the app aggregate and compile diagnostics before emitting (SPEC §9.5).

Parameter Type Description
app KovoApp An app aggregate from createApp.
options StaticExportOptions Output directory and static-export options.
(returns) Promise<StaticExportResult> A StaticExportResult describing the emitted files.
ts
async function exportStaticApp(
  app: KovoApp,
  options: StaticExportOptions = {},
): Promise<StaticExportResult>;

createKovoAppShellViteDevIntegration#

Create the app-facing dev integration for Kovo's Vite stack. App code can pass integration.onModuleDiagnostics to the compiler plugin and integration.plugin to Vite, while the request shell owns the diagnostic ledger and rendering behavior (SPEC.md §9.5.1).

ts
function createKovoAppShellViteDevIntegration(
  options: KovoAppShellViteDevPluginOptions = {},
): KovoAppShellViteDevIntegration;

kovoAppShellViteDevPlugin#

Vite dev-server plugin for a Kovo app shell. App authors add it to the plugins array in their vite.config.ts so the dev server serves the app through the same Request -> Response shell that SPEC.md §9.5 uses for build/export replay. The plugin's configureServer hook mounts middleware that ssrLoadModule-loads the app and dispatches matching requests to it.

ts
function kovoAppShellViteDevPlugin(
  options: KovoAppShellViteDevPluginOptions = {},
): KovoAppShellViteDevPlugin;

csrfField#

Render a hidden <input> carrying a CSRF token, ready to drop inside a form. Forms emitted by the framework include this automatically; use it for hand-written forms (SPEC §6.6).

Parameter Type Description
request Request The request to derive the session from.
options CsrfOptions<Request> & { field?: string } CSRF options plus an optional field name (defaults to kovo-csrf).
(returns) string The hidden-input HTML string.
ts
function csrfField<Request>(
  request: Request,
  options: CsrfOptions<Request> & { field?: string },
): string;

csrfToken#

Mint a session-bound CSRF synchronizer token for a request (SPEC §6.6).

Parameter Type Description
request Request The request to derive the session from.
options CsrfOptions<Request> The CSRF secret and sessionId extractor.
(returns) string The CSRF token string.
ts
function csrfToken<Request>(request: Request, options: CsrfOptions<Request>): string;

Example

ts
import { csrfToken } from '@kovojs/server';

interface Req { session: { id: string } }
const token: string = csrfToken({ session: { id: 's1' } } as Req, {
  secret: 'shop-secret',
  sessionId: (request: Req) => request.session.id,
});

domain#

Declare an invalidation domain — the currency the framework uses to connect writes to reads. A query's reads and a mutation's touches are lists of domains; touching a domain reruns every query that reads it (SPEC §10.1).

Parameter Type Description
key Key The domain's stable name.
(returns) Domain<Key> A Domain keyed by key.
ts
function domain<const Key extends string>(key: Key): Domain<Key>;

Example

ts
import { domain } from '@kovojs/server';

export const cart = domain('cart');
export const product = domain('product');

tag#

Declare an invalidation tag — a Domain by another name, used for narrower, row-level invalidation keys alongside coarse domains (SPEC §10.1).

Parameter Type Description
key Key The tag's stable name.
(returns) Tag<Key> A Tag keyed by key.
ts
function tag<const Key extends string>(key: Key): Tag<Key>;

Example

ts
import { tag } from '@kovojs/server';

export const cartItem = tag('cart-item');

errorBoundary#

Attach an error-boundary renderer to a fragment renderer, so a fragment that throws while rendering degrades to boundary HTML instead of failing the whole mutation response (SPEC §9.1).

Parameter Type Description
renderer Renderer The fragment renderer to wrap.
boundary ErrorBoundaryRenderer The renderer invoked when renderer throws.
(returns) Renderer & { errorBoundary: ErrorBoundaryRenderer } The fragment renderer with an errorBoundary attached.
ts
function errorBoundary<Renderer extends FragmentRenderer>(
  renderer: Renderer,
  boundary: ErrorBoundaryRenderer,
): Renderer & { errorBoundary: ErrorBoundaryRenderer };

invalidate#

Build a change record that marks a domain (optionally scoped to row keys) as touched. Returned from mutation handlers via context.invalidate, or used directly to declare manual invalidation; every query reading the domain reruns (SPEC §10.3).

Parameter Type Description
domain Domain<DomainKey> The domain to invalidate.
options InvalidateOptions<Input> Optional row keys, an input echo, and a reason.
(returns) ChangeRecord<DomainKey, Input> A ChangeRecord for the touched domain.
ts
function invalidate<const DomainKey extends string, Input = unknown>(
  domain: Domain<DomainKey>,
  options: InvalidateOptions<Input> = {},
): ChangeRecord<DomainKey, Input>;

Example

ts
import { domain, invalidate } from '@kovojs/server';

const cart = domain('cart');
const change = invalidate(cart, { reason: 'item added' });

mutation#

Declare a typed write. A mutation couples a stable key, an input Schema, a handler that performs the write, optional typed errors, an optional guard, an optional static defaultRedirectTo, and an optional transaction wrapper. The input schema doubles as FormData coercion; context.fail(code, payload) returns a typed failure; context.invalidate(domain) records what the write touched so dependent queries rerun (SPEC §10.3). CSRF is default-on — supply csrf or set it to false with justification.

Parameter Type Description
key Key The mutation's stable registry key.
definition Omit< MutationDefinition<Key, InputSchema, Errors, Request, Value, GuardedRequest>, 'key' > Input schema, handler, and optional errors/guard/transaction/csrf.
(returns) MutationDefinition<Key, InputSchema, Errors, Request, Value, GuardedRequest> & { key: Key } A MutationDefinition carrying key.
ts
function mutation<
  const Key extends string,
  InputSchema extends Schema<unknown>,
  Errors extends Record<string, Schema<unknown>> = Record<string, Schema<unknown>>,
  Request = unknown,
  Value = unknown,
  GuardedRequest extends Request = Request,
>(
  key: Key,
  definition: Omit<
    MutationDefinition<Key, InputSchema, Errors, Request, Value, GuardedRequest>,
    'key'
  >,
): MutationDefinition<Key, InputSchema, Errors, Request, Value, GuardedRequest> & { key: Key };

Example

ts
import { mutation, s } from '@kovojs/server';

interface CartRequest {
  db: { add(productId: string, quantity: number): void };
}

export const addToCart = mutation('cart/add', {
  csrf: false,
  input: s.object({
    productId: s.string(),
    quantity: s.number().int().min(1).default(1),
  }),
  errors: {
    OUT_OF_STOCK: s.object({ available: s.number().int().min(0) }),
  },
  handler(input, request: CartRequest, context) {
    if (input.quantity > 10) return context.fail('OUT_OF_STOCK', { available: 10 });
    request.db.add(input.productId, input.quantity);
    return { productId: input.productId };
  },
});

write#

Declare a reusable write: a named operation plus the exact domains it touches. Composing mutations from writes makes the touched-domain set explicit and auditable instead of inferred (SPEC §10.3).

Parameter Type Description
definition WriteDefinition<Key, Touches, Args, Value> The write's key, touches domains, and run body.
(returns) WriteDefinition<Key, Touches, Args, Value> The same WriteDefinition, typed.
ts
function write<
  const Key extends string,
  const Touches extends readonly Domain[],
  Args extends readonly unknown[],
  Value,
>(
  definition: WriteDefinition<Key, Touches, Args, Value>,
): WriteDefinition<Key, Touches, Args, Value>;

Example

ts
import { domain, write } from '@kovojs/server';

const cart = domain('cart');

export const addItem = write({
  key: 'cart/add-item',
  touches: [cart],
  run: (productId: string, quantity: number) => ({ productId, quantity }),
});

mutationFormAttributes#

Render the no-JS/enhanced form attributes for a typed mutation value (SPEC §6.3). Component-authored <form mutation={...}> is still compiler lowered when submitted-form targets are needed; this helper keeps direct server-rendered templates from hard-coding /_m/* URLs.

ts
function mutationFormAttributes<const Key extends string, Request = unknown>(
  definition: MutationFormDefinition<Key, Request>,
): MutationFormAttributes<Key, Request>;

renderMutationFormAttributes#

Render SPEC §6.3 no-JS/enhanced form attributes for string templates.

Use this when a direct server-rendered helper returns an HTML string rather than JSX, so the mutation endpoint URL and data-mutation value still derive from the typed mutation definition.

ts
function renderMutationFormAttributes<const Key extends string>(
  definition: Pick<MutationDefinition<Key>, 'key'>,
): string;

query#

Declare a typed read. A query couples a stable key, a load function, and the domains it reads. The read set is the entire invalidation declaration — nothing else registers anywhere; when a mutation touches a domain in reads, this query reruns (SPEC §10.2). Optional args validate inputs, output validates results, and version/instanceKey control caching identity.

Parameter Type Description
key Key The query's stable registry key.
definition Definition load, reads, and optional args/output/guard/version.
(returns) QueryWithArgsBinding<Definition, Input> & { key: Key } A query definition carrying key.
ts
function query<
  const Key extends string,
  Input,
  Request,
  Value,
  const Definition extends Omit<QueryArgsDeclarationDefinition<Key, Value, Input, Request>, 'key'>,
>(key: Key, definition: Definition): QueryWithArgsBinding<Definition, Input> & { key: Key };
function query<
  const Key extends string,
  const Definition extends Omit<RegisteredQueryDefinition, 'key'>,
>(
  key: Key,
  definition: Definition,
): Definition extends { args: Schema<infer Input> }
  ? QueryWithArgsBinding<Definition, Input> & { key: Key }
  : Definition & { key: Key };

Example

ts
import { domain, query } from '@kovojs/server';

const product = domain('product');

export const productsQuery = query('products', {
  load: () => ({ items: [] as { id: string }[] }),
  reads: [product],
});

createMemoryMutationReplayStore#

Undocumented.

ts
function createMemoryMutationReplayStore<
  Response extends MutationReplayResponse = MutationReplayResponse,
>(options: MutationReplayStoreOptions = {}): MutationReplayStore<Response>;

renderComponentMutationFailure#

Render a component failure target with SPEC §6.3/§9.2 mutation form state injected.

Enhanced mutation failures rerender the submitted form target through the same component render function; this helper prepares the forms.<mutation>.failure slot value that app-authored TSX reads during that render.

ts
function renderComponentMutationFailure<
  const Definition extends ComponentDefinitionInput,
  Queries,
  State extends JsonValue = JsonValue,
>(
  component: Component<Definition>,
  queries: Queries,
  failure: MutationFail,
  options: ComponentMutationFailureRenderOptions<State>,
): string;

componentMutationFailureSlots#

Build component render slots with one typed mutation-form failure state.

This lower-level helper is useful when a component render helper needs to merge a mutation failure with existing slots before calling renderComponent(...) or definition.render(...) directly.

ts
function componentMutationFailureSlots(
  formName: string,
  failure: MutationFail,
  slots: ComponentRenderSlots = {},
): ComponentRenderSlots;

stylesheet#

Declare a local or external stylesheet for route/page hints.

Local paths derive /assets/<file> unless options.href overrides it; external and root-relative hrefs are preserved.

ts
function stylesheet(source: string, options?: StylesheetDeclarationOptions): StylesheetAsset;
function stylesheet(options: StylesheetDeclarationOptions): StylesheetAsset;

stylesheetsForTargets#

Undocumented.

ts
function stylesheetsForTargets(
  manifest: readonly StylesheetManifestEntry[],
  targets?: readonly string[],
): StylesheetAsset[];

i18n#

Declare a typed message catalog for one locale. Look messages up with t, which type-checks keys against this catalog. i18n stays server-rendered (plans/open-design-areas.md).

Parameter Type Description
locale string The catalog's locale tag (e.g. 'en').
messages Messages A map of message keys to template strings ({name} placeholders).
(returns) I18nCatalog<Messages> An I18nCatalog.
ts
function i18n<const Messages extends Record<string, string>>(
  locale: string,
  messages: Messages,
): I18nCatalog<Messages>;

Example

ts
import { i18n, t } from '@kovojs/server';

const en = i18n('en', { greeting: 'Hello, {name}!' });
const text: string = t(en, 'greeting', { name: 'Sam' });

meta#

Declare static document metadata (title, description, image) for a route's head. Pass the result as a route's meta (SPEC §6.4).

Parameter Type Description
definition Meta The route metadata fields.
(returns) Meta The same RouteMeta, typed.
ts
function meta<const Meta extends RouteMeta>(definition: Meta): Meta;

Example

ts
import { meta } from '@kovojs/server';

export const homeMeta = meta({
  title: 'Kovo Shop',
  description: 'Fresh coffee gear.',
});

metaFromQuery#

Derive route metadata from a query's loaded value, so the document head reflects the same data the page rendered. Returns a deferred meta factory when given just a derive function, or resolved meta when given the value directly (SPEC §6.4).

Parameter Type Description
queryDefinition Query The query whose result drives the metadata.
derive (value: QueryResult<Query>) => Meta Maps the query's value to RouteMeta.
(returns) RouteMetaFactory A RouteMetaFactory (deferred) or resolved RouteMeta.
ts
function metaFromQuery<const Query extends QueryDefinition, const Meta extends RouteMeta>(
  queryDefinition: Query,
  derive: (value: QueryResult<Query>) => Meta,
): RouteMetaFactory;
function metaFromQuery<
  const Query extends { load?: (input: never) => unknown },
  const Meta extends RouteMeta,
>(_query: Query, value: QueryResult<Query>, derive: (value: QueryResult<Query>) => Meta): Meta;

t#

Resolve a message from an i18n catalog, substituting {name} placeholders. The key is type-checked against the catalog's messages (plans/open-design-areas.md).

Parameter Type Description
catalog I18nCatalog<Messages> The catalog to read from.
key Key A message key present in the catalog.
values Record<string, string | number> Placeholder substitutions.
(returns) string The resolved, substituted message string.
ts
function t<
  Messages extends Record<string, string>,
  Key extends Extract<keyof Messages, string>,
>(catalog: I18nCatalog<Messages>, key: Key, values: Record<string, string | number> = {}): string;

Build a typed link descriptor ({ href }) for a registered route. Same typing as href, returned as an object you can spread onto an anchor (SPEC §6.4).

Parameter Type Description
path Path A registered route path.
options RouteHrefOptions<RouteFor<Path>> params for the path segments and optional search.
(returns) LinkDescriptor A LinkDescriptor carrying the resolved href.
ts
function Link<const Path extends RegistryKey<RouteRegistry>>(
  path: Path,
  options: RouteHrefOptions<RouteFor<Path>>,
): LinkDescriptor;

Example

ts
import { Link } from '@kovojs/core';

const link = Link('/products/:id', { params: { id: 'p1' } });
const anchor = `<a href="${link.href}">View</a>`;

href#

Build a URL string for a registered route, substituting :param segments and appending typed search values. Params for the path are required and type-checked against the route's declared shape (SPEC §6.4).

Parameter Type Description
path Path A registered route path.
options RouteHrefOptions<RouteFor<Path>> params for the path segments and optional search.
(returns) string The encoded URL string.
ts
function href<const Path extends RegistryKey<RouteRegistry>>(
  path: Path,
  options: RouteHrefOptions<RouteFor<Path>>,
): string;

Example

ts
import { href } from '@kovojs/core';

const url: string = href('/products/:id', { params: { id: 'p1' } });

redirect#

Build a 303 redirect to a registered route. Return it from a route page or mutation handler to send the browser to a typed destination (SPEC §6.4).

Parameter Type Description
path Path A registered route path.
options RouteHrefOptions<RouteFor<Path>> params for the path segments and optional search.
(returns) Redirect A Redirect with status: 303 and the resolved location.
ts
function redirect<const Path extends RegistryKey<RouteRegistry>>(
  path: Path,
  options: RouteHrefOptions<RouteFor<Path>>,
): Redirect;

Example

ts
import { redirect } from '@kovojs/core';

const toProduct = redirect('/products/:id', { params: { id: 'p1' } });
// toProduct.status === 303

endpoint#

Declare a raw HTTP endpoint: a handler taking a Request and returning a Response, mounted at an exact path or a path prefix. Endpoints are the escape hatch for machine traffic (webhooks, APIs) that bypasses the page/query pipeline. CSRF is default-on — opt out with csrf: false plus a justification (SPEC §6.6).

Parameter Type Description
path Path The path the endpoint mounts at.
definition EndpointDefinition<Method, Mount> The handler, plus optional method, mount, auth, and CSRF opt-out.
(returns) EndpointDeclaration<Path, Method, Mount> An EndpointDeclaration.
ts
function endpoint<
  const Path extends string,
  const Method extends EndpointMethod = EndpointMethod,
  const Mount extends EndpointMount = 'exact',
>(
  path: Path,
  definition: EndpointDefinition<Method, Mount>,
): EndpointDeclaration<Path, Method, Mount>;

Example

ts
import { endpoint } from '@kovojs/server';

export const health = endpoint('/healthz', {
  method: 'GET',
  csrf: false,
  csrfJustification: 'read-only health probe',
  handler: () => new Response('ok'),
});

session#

Declare the session schema for the app: how to parse the raw session into a typed value, and how to wire a provider that resolves the session from a request. The parsed type flows into guards and request types (SPEC §6.5).

Parameter Type Description
schema Schema<Value> A Schema describing the session shape.
(returns) SessionDefinition<Value> A SessionDefinition with parse, provider, and the schema.
ts
function session<Value>(schema: Schema<Value>): SessionDefinition<Value>;

Example

ts
import { s, session } from '@kovojs/server';

export const appSession = session(
  s.object({ userId: s.string() }),
);

isHeaderSource#

Type guard for anything readHeader accepts: a Headers, an entries iterable, or a plain header record.

Parameter Type Description
value unknown The value to test.
(returns) value is HeaderSource true when value is a usable header source.
ts
function isHeaderSource(value: unknown): value is HeaderSource;

layout#

Declare a reusable nested layout segment. Layouts compose page chrome around a route page; parent layouts wrap child layouts, guards run before the route page, and layout queries load from the same request lifecycle context as route/component queries (SPEC §4.5/§9.5).

ts
function layout<
  Request = unknown,
  const Queries extends LayoutQueryMap<Request> = LayoutQueryMap<Request>,
  Page = unknown,
>(definition: LayoutDefinition<Request, Queries, Page>): LayoutDeclaration<Request, Queries, Page>;

notFound#

Return a 404 not-found outcome from a route page handler.

Parameter Type Description
(returns) NotFound A NotFound marker ({ notFound: true, status: 404 }).
ts
function notFound(): NotFound;

Example

ts
import { notFound } from '@kovojs/server';

const missing = notFound();
// missing.status === 404

route#

Declare a server route with a page handler. The path's :params and any search schema are parsed and passed to page as a typed context; page returns the page value (rendered by renderRoutePageResponse), notFound(), or a response outcome. Optional guard/onUnauthenticated gate access, and meta/hint fields control the document head (SPEC §6.4). Pages are complete server-rendered documents — there is no client router.

Parameter Type Description
path Path URL pattern; :name segments become typed params.
definition RouteDefinition<Path, ParamsSchema, SearchSchema, Request, Page, GuardedRequest> The page handler plus optional params/search schemas, guards, and meta.
(returns) RouteDeclaration<Path, ParamsSchema, SearchSchema, Request, Page, GuardedRequest> A RouteDeclaration carrying path.
ts
function route<
  const Path extends string,
  const ParamsSchema extends MaybeSchema<Record<string, string>> = undefined,
  const SearchSchema extends MaybeSchema<Record<string, JsonValue>> = undefined,
  Request = unknown,
  Page = unknown,
  GuardedRequest extends Request = Request,
>(
  path: Path,
  definition: RouteDefinition<Path, ParamsSchema, SearchSchema, Request, Page, GuardedRequest> = {},
): RouteDeclaration<Path, ParamsSchema, SearchSchema, Request, Page, GuardedRequest>;

Example

ts
import { notFound, route, s } from '@kovojs/server';

const catalog = new Map<string, { name: string }>();

export const productRoute = route('/products/:id', {
  params: s.object({ id: s.string() }),
  page({ params }) {
    const product = catalog.get(params.id);
    if (!product) return notFound();
    return `<h1>${product.name}</h1>`;
  },
});

webhook#

Declare a webhook endpoint: a named POST receiver that verifies the raw payload signature before parsing input, then runs a handler that can record domain changes and is idempotent by construction. Pass a WebhookVerifier built from generic helpers such as hmacSignature, or verify: 'none' with a justification (SPEC §9.1).

Parameter Type Description
name Name The webhook's identifier.
definition WebhookDefinition<InputSchema, Value, Tx> & { path: Path } The path, verify, input schema, and handler (plus optional idempotency/transaction).
(returns) WebhookDeclaration<Name, Path, InputSchema, Value, Tx> A WebhookDeclaration (a verified EndpointDeclaration).
ts
function webhook<
  const Name extends string,
  const Path extends string,
  InputSchema extends Schema<unknown>,
  Value = unknown,
  Tx = unknown,
>(
  name: Name,
  definition: WebhookDefinition<InputSchema, Value, Tx> & { path: Path },
): WebhookDeclaration<Name, Path, InputSchema, Value, Tx>;

Example

ts
import { domain, webhook, s } from '@kovojs/server';

const order = domain('order');

export const orderPaid = webhook('order-paid', {
  path: '/webhooks/order-paid',
  verify: 'none',
  verifyJustification: 'internal test fixture',
  input: s.object({ orderId: s.string() }),
  handler(input, context) {
    return { changes: [context.recordChange(order, { keys: [input.orderId] })] };
  },
});

Types & interfaces#

StaticExportError#

Error thrown when static export is configured to fail on non-exportable routes.

ts
class StaticExportError extends Error {
  readonly code: DiagnosticCode | 'KV229';
  readonly diagnostics: readonly StaticExportDiagnostic[];

  constructor(diagnostics: readonly StaticExportDiagnostic[]) {
    super(
      diagnostics.length === 1
        ? diagnostics[0]?.message
        : `KV229 static export found ${diagnostics.length} non-exportable routes.`,
    );
    this.name = 'StaticExportError';
    this.code = diagnostics[0]?.code ?? 'KV229';
    this.diagnostics = diagnostics;
  }
}

AppDiagnostic#

A compile/route-table diagnostic surfaced on a KovoApp (the diagnostics array returned by createApp). Carries the diagnostic code, message, source file, and optional severity/position so app tooling can report it (SPEC §9.5).

ts
interface AppDiagnostic {
  code: DiagnosticCode;
  fileName: string;
  help?: string;
  length?: number;
  message: string;
  severity?: DiagnosticSeverity;
  start?: { column: number; line: number };
}

AppDocumentOptions#

Document-level options applied by createApp() when rendering route documents.

ts
interface AppDocumentOptions {
  lang?: string;
  template?: DocumentTemplate;
}

AppErrorShellOptions#

Optional shell renderers for framework-owned error pages in the request shell (SPEC §9.5).

ts
interface AppErrorShellOptions {
  forbidden?: ErrorShellRenderer;
  notFound?: ErrorShellRenderer;
  serverError?: ErrorShellRenderer;
}

AppMutationResponseContext#

Runtime context passed to mutation response resolvers when the request shell builds redirect, fragment, or failure responses (SPEC §9.5).

ts
interface AppMutationResponseContext {
  currentUrl: string;
  key: string;
  mutation: AppMutationDeclaration;
  rawInput: unknown;
  request: Request;
  url: URL;
}

AppMutationResponseOptions#

Per-mutation response policy used by the request shell after a mutation handler succeeds or fails (SPEC §9.5).

ts
interface AppMutationResponseOptions {
  csrf?: CsrfValidationOptions<Request>;
  failureTarget?: string;
  failureStylesheets?: readonly (string | StylesheetAsset)[];
  fragmentRenderers?: readonly FragmentRenderer[];
  redirectTo?: string | ((result: MutationSuccess<unknown>) => string);
  renderFailureFragment?: (failure: MutationFail, rawInput: unknown) => string | Promise<string>;
  renderFailurePage?: (failure: MutationFail) => string | Promise<string>;
}

AppMutationResponseResolver#

Resolve mutation response policy from the current mutation request instead of declaring static options up front (SPEC §9.5).

ts
type AppMutationResponseResolver = (
  context: AppMutationResponseContext,
) => AppMutationResponseOptions | Promise<AppMutationResponseOptions | undefined> | undefined;

AppRouteRenderContext#

Request-shell context passed to a custom renderRoute hook (SPEC §9.5).

ts
interface AppRouteRenderContext<Route extends AnyRouteDeclaration = AnyRouteDeclaration> {
  params: Record<string, string>;
  request: Request;
  route: Route;
  search: Record<string, string | string[]>;
}

CreateAppOptions#

Options for createApp: the routes, queries, mutations, endpoints, document, CSRF, and request providers.

ts
interface CreateAppOptions<
  SessionValue = never,
  DbValue = never,
  RawRequest extends globalThis.Request = globalThis.Request,
  AppRequest = AppLifecycleRequest<RawRequest, SessionValue, DbValue>,
> {
  clientModules?: VersionedClientModuleRegistry;
  csrf?: CsrfValidationOptions<AppRequest>;
  db?: DbProvider<RawRequest, DbValue, SessionValue>;
  document?: AppDocumentOptions;
  endpoints?: readonly EndpointDeclaration<string, EndpointMethod, EndpointMount>[];
  errorShells?: AppErrorShellOptions;
  liveTargetRenderers?: readonly LiveTargetRenderer<AppRequest>[];
  mutationResponses?: AppMutationResponses;
  mutations?: AppAuthoringDeclarations<AppMutationDeclaration<AppRequest>, AppRequest>;
  mutationReplayStore?: MutationReplayStore;
  onError?: ServerErrorHandler;
  queries?: AppAuthoringDeclarations<AppQueryDeclaration<AppRequest>, AppRequest>;
  renderRoute?: (value: unknown, context: AppRouteRenderContext) => Promise<string> | string;
  routes?: AppAuthoringDeclarations<AppRouteDeclaration<AppRequest>, AppRequest>;
  sessionProvider?: SessionProvider<RawRequest, SessionValue>;
  /** App-wide stylesheets inherited by route documents (SPEC §13.1). */
  stylesheets?: readonly (string | StylesheetAsset)[];
}

ErrorShellRenderer#

Render an app-provided 403, 404, or 500 shell response for request-shell errors (SPEC §9.5).

ts
type ErrorShellRenderer = (context: {
  request: Request;
  status: 403 | 404 | 500;
}) => RoutePageResponse | Promise<RoutePageResponse>;

KovoApp#

The assembled app aggregate returned by createApp; request dispatch starts here.

ts
interface KovoApp<
  _SessionValue = unknown,
  _DbValue = unknown,
  _RawRequest extends globalThis.Request = globalThis.Request,
  _AppRequest = any,
> {
  clientModules: VersionedClientModuleRegistry;
  csrf?: CsrfValidationOptions<any>;
  db?: DbProvider<any, any, any>;
  diagnostics: readonly AppDiagnostic[];
  document: AppDocumentOptions;
  endpoints: readonly EndpointDeclaration<string, EndpointMethod, EndpointMount>[];
  errorShells: AppErrorShellOptions;
  liveTargetRenderers: readonly LiveTargetRenderer<any>[];
  mutationResponses: AppMutationResponses;
  mutations: readonly AppMutationDeclaration<any>[];
  mutationReplayStore?: MutationReplayStore;
  onError?: ServerErrorHandler;
  queries: readonly AppQueryDeclaration<any>[];
  renderRoute?: (value: unknown, context: AppRouteRenderContext) => Promise<string> | string;
  routes: readonly AppRouteDeclaration<any>[];
  sessionProvider?: SessionProvider<any, any>;
  /** App-wide stylesheets inherited by route documents (SPEC §13.1). */
  stylesheets: readonly (string | StylesheetAsset)[];
}

RequestHandler#

Web-standard request handler returned by createRequestHandler() (SPEC §9.5).

ts
type RequestHandler = (request: Request) => Promise<Response>;

MemoryVersionedClientModuleRegistryOptions#

Options for the in-memory versioned client-module registry.

ts
interface MemoryVersionedClientModuleRegistryOptions {
  maxVersionsPerPath?: number;
}

VersionedClientModuleInput#

Source module registered into the request-shell client-module registry for versioned browser delivery (SPEC §9.5).

ts
interface VersionedClientModuleInput {
  contentType?: string;
  path: string;
  source: string;
  version: string;
}

VersionedClientModuleRegistry#

Registry used by the server request shell to publish immutable versioned client modules and resolve browser requests for them (SPEC §9.5).

ts
interface VersionedClientModuleRegistry {
  /**
   * A deterministic build-global token derived from the set of registered
   * client module versions. Identical within one build, changes on redeploy.
   * Used for `Kovo-Build` response header and `<meta name="kovo-build">` page
   * stamping so the client can detect deploy skew (SPEC §5.1, §9.1.1).
   * Returns an empty string when no modules are registered.
   */
  buildToken(): string;
  /**
   * Return the registered immutable modules for build/static artifact emission.
   * Entries are normalized to same-origin `/c/` paths and sorted
   * deterministically by path + version.
   */
  entries(): readonly VersionedClientModuleInput[];
  put(module: VersionedClientModuleInput): string;
  resolve(href: string): ServerResponseBase<string, Record<string, string>, 200 | 404>;
}

NodeHandlerOptions#

Options for adapting a Web RequestHandler to a Node http listener.

ts
interface NodeHandlerOptions {
  earlyHints?: boolean;
  origin?: string | ((request: IncomingMessage) => string);
}

NodeRequestHandler#

Node http/https listener shape returned by toNodeHandler().

ts
type NodeRequestHandler = (
  request: IncomingMessage,
  response: ServerResponse,
) => Promise<void> | void;

StaticExportCompileDiagnostic#

Undocumented.

ts
interface StaticExportCompileDiagnostic {
  code: DiagnosticCode;
  fileName: string;
  help?: string;
  message: string;
  start?: { column: number; line: number };
}

StaticExportDiagnostic#

Route-level diagnostic emitted when a request-shell route cannot be represented by static export output (SPEC §11.3).

ts
interface StaticExportDiagnostic {
  code: DiagnosticCode | 'KV229';
  message: string;
  routePath: string;
}

StaticExportDiagnosticSeverity#

Severity label used when formatting static-export diagnostics.

ts
type StaticExportDiagnosticSeverity = 'ERROR' | 'WARN';

StaticExportOptions#

Options for exporting a KovoApp request shell to static route documents.

ts
interface StaticExportOptions {
  assets?: readonly StaticExportAssetInput[];
  diagnostics?: readonly import('./static-export-diagnostics.js').StaticExportCompileDiagnostic[];
  onNonExportable?: StaticExportNonExportablePolicy;
  origin?: string;
  outDir?: string | URL;
}

StaticExportResult#

Static export output produced by exportStaticApp().

ts
interface StaticExportResult {
  artifacts: readonly StaticExportArtifact[];
  assets: readonly StaticExportAssetArtifact[];
  clientModules: readonly StaticExportClientModuleArtifact[];
  diagnostics: readonly import('./static-export-diagnostics.js').StaticExportDiagnostic[];
}

KovoAppShellViteCompilerModuleDiagnosticReport#

Compiler-compatible module diagnostic report accepted by the app-shell dev integration. It is structural on purpose so @kovojs/server does not depend on @kovojs/compiler.

ts
interface KovoAppShellViteCompilerModuleDiagnosticReport {
  diagnostics: readonly DiagnosticDocumentDiagnostic[];
  fileName: string;
  source: string;
}

KovoAppShellViteDevIntegration#

Combined app-shell dev plugin plus compiler-diagnostic callback for Vite dev.

ts
interface KovoAppShellViteDevIntegration {
  diagnostics: KovoAppShellDevDiagnosticLedger;
  onModuleDiagnostics(report: KovoAppShellViteCompilerModuleDiagnosticReport): void;
  plugin: KovoAppShellViteDevPlugin;
}

KovoAppShellViteDevPlugin#

The Vite dev-server plugin object returned by kovoAppShellViteDevPlugin, ready to be placed in a vite.config.ts plugins array. It wires the app shell into the dev server for the SPEC.md §9.5 dev/build/export replay path.

ts
interface KovoAppShellViteDevPlugin {
  configureServer(server: KovoAppShellViteDevModuleServer): void | (() => void);
  handleHotUpdate?(context: KovoAppShellViteHotUpdateContext): Promise<readonly unknown[]>;
  name: string;
}

KovoAppShellViteDevPluginOptions#

Options for kovoAppShellViteDevPlugin. Control how the dev-server middleware loads and serves the app shell during SPEC.md §9.5 Vite dev/build/export replay, including which module/export to load, request filtering, and Early Hints relay.

ts
interface KovoAppShellViteDevPluginOptions {
  appExportName?: string;
  /**
   * Dev diagnostic ledger shared with the compiler Vite plugin. When present,
   * requests depending on failed component modules render the same teaching
   * diagnostic document as direct dev diagnostic requests (SPEC.md §9.5.1).
   */
  devDiagnostics?: KovoAppShellDevDiagnosticLedger;
  /**
   * Defaults to true. Set to false when a dev middleware stack cannot safely
   * relay 103 Early Hints but should still keep the final Link header.
   */
  earlyHints?: boolean;
  moduleId?: string;
  name?: string;
  /**
   * When omitted, dev serving adapts the loaded app through the same
   * Request -> Response shell that SPEC §9.5 uses for build/export replay.
   */
  nodeHandlerExportName?: string;
  order?: 'pre' | 'post';
  shouldHandleRequest?: (request: IncomingMessage, app: KovoApp) => boolean;
}

CsrfOptions#

CSRF config: a secret and a sessionId extractor that binds the token to a session.

ts
interface CsrfOptions<Request> {
  secret: string;
  sessionId: (request: Request) => string | undefined;
}

CsrfValidationOptions#

CsrfOptions plus the optional form field name to validate against.

ts
interface CsrfValidationOptions<Request> extends CsrfOptions<Request> {
  field?: string;
}

Domain#

An invalidation domain: a named unit of cache currency that queries read and mutations touch.

ts
interface Domain<Key extends string = string> {
  key: Key;
}

Tag#

Alias of Domain; tag produces this for finer-grained, row-scoped invalidation keys.

ts
type Tag<Key extends string = string> = Domain<Key>;

ChangeRecord#

A record of one domain a mutation touched, optionally scoped to specific keys.

ts
interface ChangeRecord<DomainKey extends string = string, Input = unknown> {
  domain: DomainKey;
  keys?: readonly string[];
  input?: Input;
  manual?: true;
  reason?: string;
}

InvalidateOptions#

Options for invalidate/context.invalidate: row keys, input echo, and a reason.

ts
interface InvalidateOptions<Input = unknown> {
  input?: Input;
  keys?: readonly string[];
  reason?: string;
}

MutationContext#

Undocumented.

ts
interface MutationContext<Errors extends Record<string, Schema<unknown>>> {
  fail<const Code extends Extract<keyof Errors, string>>(
    code: Code,
    payload: InferSchema<Errors[Code]>,
  ): MutationFail<Code, InferSchema<Errors[Code]>>;
  invalidate<const DomainKey extends string, Input = unknown>(
    domain: Domain<DomainKey>,
    options?: InvalidateOptions<Input>,
  ): ChangeRecord<DomainKey, Input>;
  setCookie?: {
    (rawSetCookie: string): void;
    (name: string, value: string, options?: CookieOptions): void;
  };
}

MutationDefinition#

Undocumented.

ts
interface MutationDefinition<
  Key extends string = string,
  InputSchema extends Schema<unknown> = Schema<unknown>,
  Errors extends Record<string, Schema<unknown>> = Record<string, Schema<unknown>>,
  Request = unknown,
  Value = unknown,
  GuardedRequest extends Request = Request,
> {
  csrf?: CsrfValidationOptions<Request> | false;
  /** Static/common POST-redirect-GET target for successful no-JS submissions (SPEC §9.1). */
  defaultRedirectTo?: string;
  errors?: Errors;
  guard?: Guard<Request, GuardedRequest>;
  handler: (
    input: InferSchema<InputSchema>,
    request: GuardedRequest,
    context: MutationContext<Errors>,
  ) => Promise<Value | MutationFail> | Value | MutationFail;
  input: InputSchema;
  key: Key;
  /** Mutation-local success redirect policy for dynamic POST-redirect-GET targets. */
  redirectTo?: string | ((result: MutationSuccess<Value, InferSchema<InputSchema>>) => string);
  registry?: MutationRegistry;
  transaction?: <Result>(
    request: Request,
    run: (transactionRequest: GuardedRequest) => Promise<Result>,
  ) => Promise<Result>;
}

MutationFail#

Undocumented.

ts
interface MutationFail<Code extends string = string, Payload = unknown> {
  error: {
    code: Code;
    payload: Payload;
  };
  ok: false;
  retryAfter?: number;
  status: 422 | 429;
}

MutationFormDefinition#

Undocumented.

ts
interface MutationFormDefinition<Key extends string = string, Request = unknown> {
  csrf?: CsrfValidationOptions<Request> | false;
  key: Key;
}

MutationRegistry#

Undocumented.

ts
interface MutationRegistry {
  inferredTouches?: readonly MutationTouchSite[];
  queries?: readonly RegisteredQueryDefinition[];
  touches?: readonly Domain[];
}

MutationResult#

Undocumented.

ts
type MutationResult<Value, Input = unknown> = MutationFail | MutationSuccess<Value, Input>;

MutationSuccess#

Undocumented.

ts
interface MutationSuccess<Value, Input = unknown> {
  changes: ChangeRecord[];
  input: Input;
  rerunQueryInstances?: QueryRerun[];
  rerunQueries: string[];
  ok: true;
  responseHeaders?: MutationResponseHeaders;
  value: Value;
}

MutationTouchSite#

A statically inferred touch site on a mutation: a domain and an optional key expression.

ts
interface MutationTouchSite {
  domain: string;
  keys: null | string;
}

QueryRerun#

Undocumented.

ts
interface QueryRerun {
  instanceKey?: string;
  key: string;
}

RunMutationOptions#

Undocumented.

ts
interface RunMutationOptions<
  Request,
  SessionValue = unknown,
  DbValue = unknown,
> extends RequestLifecycleOptions<Request, SessionValue, DbValue> {
  csrf?: CsrfValidationOptions<Request>;
}

WriteDefinition#

Undocumented.

ts
interface WriteDefinition<
  Key extends string,
  Touches extends readonly Domain[],
  Args extends readonly unknown[],
  Value,
> {
  key: Key;
  run: (...args: Args) => Promise<Value> | Value;
  touches: Touches;
}

MutationFormAttributes#

Attributes emitted for a SPEC §6.3 enhanced mutation form.

ts
interface MutationFormAttributes<Key extends string = string, Request = unknown> {
  /** No-JS mutation endpoint path derived from the typed mutation key. */
  action: `/_m/${Key}`;
  /** Stable mutation key metadata used by enhanced submit/runtime tooling. */
  'data-mutation': Key;
  /** Enables the SPEC §9.1 enhanced fragment submit path. */
  enhance: true;
  /** Mutation forms post by default. */
  method: 'post';
  /** Typed mutation value retained for server JSX runtime CSRF injection. */
  mutation: MutationFormDefinition<Key, Request>;
}

QueryDefinition#

The shape of a query: its key, load, reads domains, and optional args/output/guard/version.

ts
interface QueryDefinition<
  Key extends string = string,
  Value = unknown,
  Input = unknown,
  Request = unknown,
> {
  args?: Schema<Input>;
  /**
   * Delta-eligible collections for this query. When present, the server can
   * emit a change-record-scoped delta (SPEC §9.1.1) instead of the full value
   * when the delta is smaller. The compiler populates this; framework/test code
   * may set it directly.
   */
  delta?: readonly QueryDeltaListMeta[];
  guard?: Guard<Request>;
  instanceKey?: ((input: unknown) => string | undefined) | string;
  load?(input: Input, context?: QueryLoadContext<Request>): Promise<Value> | Value;
  key: Key;
  output?: Schema<Value>;
  reads: readonly Domain[];
  version?: ((input: Input, value: Value) => number | string | undefined) | number | string;
}

QueryEndpointFailure#

Undocumented.

ts
interface QueryEndpointFailure {
  auth?: ResolvedGuardFailure['auth'];
  error: {
    code: 'KV410' | 'RATE_LIMITED' | 'UNAUTHORIZED' | 'VALIDATION';
    payload: Record<string, unknown> | ValidationFailurePayload;
  };
  ok: false;
  retryAfter?: number;
  status: 422 | 429 | 500;
}

QueryEndpointRegistry#

Undocumented.

ts
interface QueryEndpointRegistry<Request = unknown> {
  queries: readonly QueryDefinition<string, unknown, unknown, Request>[];
}

QueryEndpointRequest#

Undocumented.

ts
interface QueryEndpointRequest<
  Request = unknown,
  SessionValue = unknown,
> extends GuardFailureResponseOptions<Request, SessionValue> {
  request: Request;
  search?: QuerySearchInput;
}

QueryEndpointResponse#

Undocumented.

ts
interface QueryEndpointResponse extends ServerResponseBase<
  string,
  Record<string, string>,
  200 | 303 | 403 | 404 | 422 | 429 | 500
> {}

QueryEndpointResult#

Undocumented.

ts
type QueryEndpointResult<Value, Input = unknown> =
  | QueryEndpointSuccess<Value, Input>
  | QueryEndpointFailure;

QueryEndpointSuccess#

Undocumented.

ts
interface QueryEndpointSuccess<Value, Input = unknown> {
  input: Input;
  ok: true;
  value: Value;
}

QueryLoadContext#

The context a query's load receives: the current request value.

ts
interface QueryLoadContext<Request = unknown> {
  request: Request;
}

QueryResult#

Extract the resolved value type a query's load produces.

ts
type QueryResult<Query> = Query extends { load: (...args: never[]) => infer Value }
  ? Awaited<Value>
  : unknown;

QuerySearchInput#

Undocumented.

ts
type QuerySearchInput =
  | URLSearchParams
  | Iterable<readonly [string, string]>
  | Record<string, readonly string[] | string | undefined>;

RegisteredQueryDefinition#

Undocumented.

ts
interface RegisteredQueryDefinition {
  args?: Schema<unknown>;
  /**
   * Delta-eligible collections for this query (SPEC §9.1.1). The compiler
   * populates this; framework/test code may set it directly.
   */
  delta?: readonly QueryDeltaListMeta[];
  guard?: BivariantQueryGuard;
  instanceKey?: ((input: unknown) => string | undefined) | string;
  key: string;
  load?: BivariantQueryLoad;
  output?: Schema<unknown>;
  reads: readonly Domain[];
  version?: BivariantQueryVersion | number | string;
}

MutationReplayReservation#

Undocumented.

ts
interface MutationReplayReservation<
  Response extends MutationReplayResponse = MutationReplayResponse,
> {
  /**
   * Abandon the reservation without committing a result, releasing the pending
   * record so a corrected retry can run (e.g. after a non-replayable validation
   * failure). Optional for backward compatibility with stores predating
   * security finding M4; callers must tolerate its absence.
   */
  abort?(): void;
  commit(response: Response): void;
}

MutationReplayStore#

Undocumented.

ts
interface MutationReplayStore<
  Response extends MutationReplayResponse = MutationReplayResponse,
> {
  get(scope: string, idem: string): Promise<Response> | Response | undefined;
  reserve(scope: string, idem: string): MutationReplayReservation<Response> | undefined;
  set(scope: string, idem: string, response: Response): void;
}

SchemaValidationError#

Thrown by a schema's parse when input is invalid; carries the per-field issues.

ts
class SchemaValidationError extends Error {
  readonly issues: readonly ValidationIssue[];

  constructor(issues: readonly ValidationIssue[]) {
    super(issues[0]?.message ?? 'Invalid input');
    this.name = 'SchemaValidationError';
    this.issues = issues;
  }
}

FileLike#

Undocumented.

ts
interface FileLike {
  arrayBuffer(): Promise<ArrayBuffer>;
  name: string;
  size: number;
  type: string;
}

FileSchema#

Undocumented.

ts
interface FileSchema extends Schema<FileLike> {
  maxBytes(value: number): FileSchema;
  mime(types: readonly string[]): FileSchema;
  store(options: StoredFileSchemaOptions): StoredFileSchema;
}

FileSchemaOptions#

Undocumented.

ts
interface FileSchemaOptions {
  maxBytes?: number;
  mime?: readonly string[];
}

InferSchema#

Extract the parsed value type of a Schema.

ts
type InferSchema<T> = T extends Schema<infer Value> ? Value : never;

MaybePromise#

Undocumented.

ts
type MaybePromise<Value> = Promise<Value> | Value;

NumberSchema#

Undocumented.

ts
interface NumberSchema extends Schema<number> {
  default(value: number): NumberSchema;
  int(): NumberSchema;
  min(value: number): NumberSchema;
}

Schema#

A validator that parses unknown input into a typed value (throwing SchemaValidationError on failure).

ts
interface Schema<T> {
  parse(input: unknown): T;
}

StoredFileSchema#

Undocumented.

ts
interface StoredFileSchema extends AsyncSchema<StoredFileUpload> {}

StoredFileSchemaOptions#

Undocumented.

ts
interface StoredFileSchemaOptions {
  key: string | ((file: FileLike) => MaybePromise<string>);
  metadata?: (file: FileLike) => Readonly<Record<string, string>>;
  storage: StorageCapability;
}

StoredFileUpload#

Undocumented.

ts
interface StoredFileUpload {
  file: FileLike;
  key: string;
  storage: StorageObjectInfo;
}

ValidationFailurePayload#

Undocumented.

ts
interface ValidationFailurePayload {
  issues: readonly ValidationIssue[];
}

ValidationIssue#

Undocumented.

ts
interface ValidationIssue {
  message: string;
  path: readonly string[];
}

ContentSecurityPolicyOptions#

Options for assembling a Content-Security-Policy header from Kovo document metadata.

ts
interface ContentSecurityPolicyOptions {
  connectSrc?: readonly string[];
  defaultSrc?: readonly string[];
  imgSrc?: readonly string[];
  scriptSrc?: readonly string[];
  styleSrc?: readonly string[];
}

CspInlineMetadata#

CSP hash metadata for inline scripts/styles generated during document assembly.

ts
interface CspInlineMetadata {
  /** Stable CSP hashes for generated inline `<script>` bodies in document order. */
  scripts: readonly string[];
  /** Stable CSP hashes for generated inline `<style>` bodies in document order. */
  styles: readonly string[];
}

ComponentRenderOptions#

Runtime inputs for rendering a component outside the full document pipeline.

This mirrors the SPEC §4.5 composition call shape: callers may provide compiler-hoisted slots and a serializable component state value, while query data stays the explicit second argument to renderComponent(...).

ts
interface ComponentRenderOptions<State extends JsonValue = JsonValue> {
  /** Named slot renderers hoisted from fragment-target children. */
  slots?: ComponentRenderSlots;
  /** Serializable component state for stateful server component renders. */
  state?: State;
}

ComponentMutationFailureRenderOptions#

Options for rendering a component with one SPEC §6.3 mutation form failure injected into its forms.<name>.failure slot.

ts
interface ComponentMutationFailureRenderOptions<
  State extends JsonValue = JsonValue,
> extends ComponentRenderOptions<State> {
  /** Component-local key from `mutations: { ... }`, e.g. `addToCart`. */
  formName: string;
}

DeferredFragmentChunk#

Undocumented.

ts
interface DeferredFragmentChunk {
  html: string;
  mode?: 'append' | 'replace';
  priority?: DeferredPriority;
  stylesheets?: readonly (string | StylesheetAsset)[];
  target: string;
}

DeferredPriority#

Undocumented.

ts
type DeferredPriority = 'high' | 'normal' | 'low' | number;

DeferredQueryChunk#

Undocumented.

ts
interface DeferredQueryChunk {
  key?: string;
  name: string;
  value: unknown;
}

DeferredStreamChunk#

Undocumented.

ts
interface DeferredStreamChunk {
  fragments: readonly DeferredFragmentChunk[];
  priority?: DeferredPriority;
  queries?: readonly DeferredQueryChunk[];
}

DeferredStreamOptions#

Undocumented.

ts
interface DeferredStreamOptions {
  boundary?: string;
  chunks: readonly DeferredStreamChunk[];
  closeHtml?: string;
  shell: string;
}

DeferredStreamResponse#

Undocumented.

ts
interface DeferredStreamResponse extends ServerResponseBase<
  string,
  Record<string, string>,
  200
> {}

DeferredDocumentAssemblyOptions#

Undocumented.

ts
interface DeferredDocumentAssemblyOptions extends Omit<DocumentAssemblyOptions, 'template'> {
  boundary?: string;
  chunks: readonly DeferredStreamChunk[];
  template?: DeferredDocumentTemplate;
}

DeferredDocumentFrame#

Undocumented.

ts
interface DeferredDocumentFrame {
  closeHtml: string;
  shell: string;
}

DeferredDocumentRenderResult#

Undocumented.

ts
interface DeferredDocumentRenderResult extends ServerResponseBase<
  string,
  Record<string, string>,
  200
> {
  csp: CspInlineMetadata;
}

DeferredDocumentTemplate#

Undocumented.

ts
type DeferredDocumentTemplate = (
  context: DeferredDocumentTemplateContext,
) => DeferredDocumentFrame;

DeferredDocumentTemplateContext#

Undocumented.

ts
interface DeferredDocumentTemplateContext {
  csp: CspInlineMetadata;
  parts: DocumentParts;
}

DocumentAssemblyOptions#

Undocumented.

ts
interface DocumentAssemblyOptions {
  /**
   * Build-global render-plan version token (SPEC §5.1, §9.1.1). When present and
   * non-empty, stamped as `<meta name="kovo-build" content="<token>">` in the
   * document `<head>` so the client can detect deploy skew.
   */
  buildToken?: string;
  body: string;
  hints?: PageHintOptions;
  lang?: string;
  queries?: readonly QueryScriptRenderOptions[];
  template?: DocumentTemplate;
}

DocumentParts#

Undocumented.

ts
interface DocumentParts {
  body: string;
  head: string;
  lang: string;
  queryScripts: readonly string[];
}

DocumentRenderResult#

Undocumented.

ts
interface DocumentRenderResult {
  csp: CspInlineMetadata;
  earlyHints: PageHints['earlyHints'];
  html: string;
}

DocumentResponseOptions#

Undocumented.

ts
interface DocumentResponseOptions extends Omit<DocumentAssemblyOptions, 'body'> {}

DocumentRoutePageResponse#

Undocumented.

ts
interface DocumentRoutePageResponse extends DocumentRouteResponseBase {}

DocumentTemplate#

Undocumented.

ts
type DocumentTemplate = (context: DocumentTemplateContext) => string;

DocumentTemplateContext#

Undocumented.

ts
interface DocumentTemplateContext {
  csp: CspInlineMetadata;
  parts: DocumentParts;
}

ErrorDocumentOptions#

Undocumented.

ts
interface ErrorDocumentOptions {
  hints?: PageHintOptions;
  lang?: string;
  message?: string;
  status: 403 | 404 | 500;
  template?: DocumentTemplate;
  title?: string;
}

DocumentQueryScriptRenderOptions#

Options for renderQueryScript: the query name, its value, and optional instance key.

ts
interface QueryScriptRenderOptions {
  key?: string | undefined;
  name: string;
  value: unknown;
}

DiagnosticDocumentDiagnostic#

Undocumented.

ts
interface DiagnosticDocumentDiagnostic {
  code: DiagnosticCode;
  fileName?: string;
  help?: string;
  length?: number;
  message: string;
  severity?: DiagnosticSeverity;
  start?: {
    column: number;
    line: number;
  };
}

DiagnosticDocumentOptions#

Undocumented.

ts
interface DiagnosticDocumentOptions {
  diagnostics: readonly DiagnosticDocumentDiagnostic[];
  lang?: string;
  source?: DiagnosticDocumentSource | string;
  template?: DocumentTemplate;
}

DiagnosticDocumentSource#

Undocumented.

ts
interface DiagnosticDocumentSource {
  fileName?: string;
  source: string;
}

I18nCatalog#

Undocumented.

ts
interface I18nCatalog<Messages extends Record<string, string> = Record<string, string>> {
  locale: string;
  messages: Messages;
}

PageHintOptions#

Undocumented.

ts
interface PageHintOptions {
  bootstrapScript?: string;
  i18n?: I18nCatalog | readonly I18nCatalog[];
  meta?: RouteMetaSource | readonly RouteMetaSource[];
  modulepreloads?: readonly string[];
  prefetch?: RoutePrefetch;
  prerenderUrls?: readonly string[];
  stylesheets?: readonly (string | StylesheetAsset)[];
}

PageHintRenderContext#

Undocumented.

ts
interface PageHintRenderContext {
  queries?: Record<string, unknown>;
}

PageHints#

Undocumented.

ts
interface PageHints {
  csp?: CspInlineMetadata;
  earlyHints: Record<string, string>;
  html: string;
}

RouteMeta#

Undocumented.

ts
interface RouteMeta {
  description?: string;
  image?: string;
  title?: string;
}

RouteMetaFactory#

Undocumented.

ts
interface RouteMetaFactory {
  queries: readonly string[];
  resolve(values: Record<string, unknown>): RouteMeta;
}

RouteMetaSource#

Undocumented.

ts
type RouteMetaSource = RouteMeta | RouteMetaFactory;

RoutePrefetch#

Undocumented.

ts
type RoutePrefetch = 'conservative' | 'moderate' | false;

StylesheetAsset#

Undocumented.

ts
interface StylesheetAsset {
  criticalCss?: string;
  cspHash?: string;
  href: string;
  preload?: boolean;
}

StylesheetDeclarationOptions#

Options for declaring an authored stylesheet asset (SPEC.md §13.1).

ts
interface StylesheetDeclarationOptions {
  /** Critical CSS to inline before the linked stylesheet identity. */
  criticalCss?: string | readonly string[];
  /** Optional CSP hash for the inlined critical CSS. */
  cspHash?: string;
  /** Public stylesheet href; local sources derive `/assets/<file>` when omitted. */
  href?: string;
  /** Whether Early Hints should preload the linked stylesheet. */
  preload?: boolean;
  /** Theme CSS to prepend to `criticalCss`. */
  theme?: StylesheetTheme;
}

StylesheetManifestEntry#

Undocumented.

ts
interface StylesheetManifestEntry extends StylesheetAsset {
  fragmentTargets?: readonly string[];
  sourceFileName?: string;
}

StylesheetTheme#

Theme CSS accepted by {@link stylesheet}; usually a Kovo theme object from @kovojs/style.

ts
type StylesheetTheme = string | { readonly css: string };

QueryScriptRenderOptions#

Options for renderQueryScript: the query name, its value, and optional instance key.

ts
interface QueryScriptRenderOptions {
  key?: string | undefined;
  name: string;
  value: unknown;
}

DiagnosticCode#

The string-literal union of every KV### diagnostic code the framework can emit.

ts
type DiagnosticCode =
  | 'KV201'
  | 'KV210'
  | 'KV211'
  | 'KV212'
  | 'KV220'
  | 'KV221'
  | 'KV222'
  | 'KV223'
  | 'KV224'
  | 'KV225'
  | 'KV226'
  | 'KV227'
  | 'KV228'
  | 'KV230'
  | 'KV231'
  | 'KV232'
  | 'KV233'
  | 'KV234'
  | 'KV235'
  | 'KV236'
  | 'KV237'
  | 'KV238'
  | 'KV239'
  | 'KV240'
  | 'KV241'
  | 'KV242'
  | 'KV301'
  | 'KV302'
  | 'KV303'
  | 'KV304'
  | 'KV310'
  | 'KV311'
  | 'KV320'
  | 'KV330'
  | 'KV402'
  | 'KV403'
  | 'KV404'
  | 'KV405'
  | 'KV406'
// … truncated (5 more lines); see the package source for the full declaration.

JsonValue#

Any value that survives a JSON round-trip; the boundary type for island state and wire payloads (SPEC §4.1).

ts
type JsonValue =
  | null
  | boolean
  | number
  | string
  | JsonValue[]
  | { [key: string]: JsonValue };

LinkDescriptor#

Result of Link(): a resolved href string ready to spread onto an anchor.

ts
interface LinkDescriptor {
  href: string;
}

Redirect#

A 303 redirect outcome returned by redirect().

ts
interface Redirect {
  location: string;
  status: 303;
}

Route#

A route descriptor: typed path, param/search shapes, and prefetch policy.

ts
interface Route<
  Path extends string,
  Params extends Record<string, string> = PathParams<Path>,
  Search extends Record<string, JsonValue> = Record<string, JsonValue>,
> {
  path: Path;
  params?: Params;
  prefetch?: 'conservative' | 'moderate' | false;
  search?: Search;
}

ServerErrorDiagnosticContext#

Undocumented.

ts
interface ServerErrorDiagnosticContext {
  mutationKey?: string;
  operation:
    | 'app-request'
    | 'client-module'
    | 'error-shell'
    | 'mutation-handler'
    | 'mutation-render'
    | 'no-js-mutation-handler'
    | 'query-endpoint'
    | 'route-page'
    | 'route-render';
  queryKey?: string;
  request?: unknown;
  routePath?: string;
  status?: 403 | 404 | 500;
  targets?: readonly string[];
  url?: string;
}

ServerErrorHandler#

Undocumented.

ts
type ServerErrorHandler = (
  error: unknown,
  context: ServerErrorDiagnosticContext,
) => Promise<void> | void;

Endpoint#

A raw HTTP endpoint descriptor: path, method, mount mode, and auth/CSRF declarations.

ts
interface Endpoint<
  Path extends string,
  Method extends EndpointMethod = EndpointMethod,
  Mount extends EndpointMount = 'exact',
> {
  auth?: EndpointAuthDeclaration;
  csrf?: EndpointCsrfExemption;
  method?: Method;
  mount: Mount;
  path: Path;
}

EndpointAuthDeclaration#

How an endpoint authenticates: a named verifier, a named custom scheme, or a justified none.

ts
type EndpointAuthDeclaration =
  | { kind: 'custom'; name: string }
  | { kind: 'none'; justification: string }
  | { kind: 'verifier'; name: string };

EndpointCsrfExemption#

Records an explicit, justified opt-out of default-on CSRF for an endpoint (SPEC §6.6).

ts
interface EndpointCsrfExemption {
  exempt: true;
  justification: string;
}

EndpointDeclaration#

An endpoint with its path attached, as returned by endpoint().

ts
interface EndpointDeclaration<
  Path extends string = string,
  Method extends EndpointMethod = EndpointMethod,
  Mount extends EndpointMount = EndpointMount,
> extends Endpoint<Path, Method, Mount> {
  handler: EndpointHandler;
}

EndpointDefinition#

The body passed to endpoint(): handler, method/mount, and the CSRF default-or-exempt choice.

ts
type EndpointDefinition<
  Method extends EndpointMethod = EndpointMethod,
  Mount extends EndpointMount = 'exact',
> = EndpointDefinitionBase<Method, Mount> & (EndpointCsrfDefault | EndpointCsrfExempt);

EndpointHandler#

An endpoint handler: maps a session-free Request to a Response.

ts
type EndpointHandler = (request: EndpointRequest) => Promise<Response> | Response;

EndpointMethod#

HTTP method for an endpoint; arbitrary strings are allowed for custom verbs.

ts
type EndpointMethod = 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT' | (string & {});

EndpointMount#

Whether an endpoint matches an exact path or a path prefix.

ts
type EndpointMount = 'exact' | 'prefix';

EndpointRequest#

A Request guaranteed to carry no session, as endpoint handlers receive.

ts
type EndpointRequest = Request & { readonly session?: never };

AuthenticatedRequest#

A request narrowed to one with a present session user, produced by guards.authed.

ts
type AuthenticatedRequest<Request extends SessionRequestLike> = Request & {
  session: NonNullable<Request['session']> & {
    user: NonNullable<NonNullable<Request['session']>['user']>;
  };
};

ForbiddenContext#

Undocumented.

ts
interface ForbiddenContext<Request> {
  request: Request;
}

ForbiddenDenial#

The caller is authenticated but not permitted. SPEC §6.5: the framework renders the app's 403 shell with status 403.

ts
interface ForbiddenDenial {
  kind: 'forbidden';
  payload?: Record<string, unknown>;
}

ForbiddenRenderer#

Undocumented.

ts
type ForbiddenRenderer<Request> = (
  context: ForbiddenContext<Request>,
) => string | Promise<string>;

Guard#

An access guard over a request; may refine the request type when it passes.

ts
interface Guard<Request, RefinedRequest extends Request = Request> {
  (request: Request): GuardResult | Promise<GuardResult>;
  readonly refines?: (request: Request) => request is RefinedRequest;
}

GuardDenial#

A guard denial that expresses the user-facing intent of a rejection, leaving the HTTP status to the framework. SPEC §6.5 fixes the three outcomes: an unauthenticated caller is sent through the app's onUnauthenticated handler (default: a 303 redirect to the login route with the original URL as next); an authenticated-but-unauthorized caller renders the app's 403 shell; a rate-limited caller gets a 429 carrying retryAfter seconds. The wire status is derived from kind inside the framework (renderHttpGuardFailureResponse), so an author reads the intent, not a transport detail. Return true to allow.

ts
type GuardDenial = UnauthenticatedDenial | ForbiddenDenial | RateLimitedDenial;

GuardFailure#

Back-compat alias for {@link GuardDenial}: the type a guard returns to reject a request (SPEC §6.5).

@deprecated Use {@link GuardDenial}. Retained as a documented alias so external code that imported the previous denial type keeps compiling; the intent-based kind discriminant (SPEC §6.5) replaces the old code/status fields, which advertised an internal sentinel status (422) the browser never received on the documented auth paths.

ts
type GuardFailure = GuardDenial;

GuardFailureResponseOptions#

Undocumented.

ts
interface GuardFailureResponseOptions<
  Request,
  SessionValue = unknown,
  DbValue = unknown,
> extends RequestLifecycleOptions<Request, SessionValue, DbValue> {
  currentUrl?: string;
  loginPath?: string;
  onUnauthenticated?: UnauthenticatedHandler<Request>;
  renderForbidden?: ForbiddenRenderer<Request>;
}

GuardResult#

What a guard returns: true to allow, or a {@link GuardDenial} to reject (SPEC §6.5).

ts
type GuardResult = boolean | GuardDenial;

RateLimitedDenial#

The caller exceeded a rate limit. SPEC §6.5: the framework answers 429 and surfaces retryAfter (seconds) as a Retry-After header.

ts
interface RateLimitedDenial {
  kind: 'rateLimited';
  payload?: Record<string, unknown>;
  retryAfter?: number;
}

RateLimitOptions#

Options for guards.rateLimit: window size, max requests, scope, and key function.

ts
interface RateLimitOptions<Request> {
  key?: (request: Request) => string;
  max: number;
  maxKeys?: number;
  per?: 'global' | 'session';
  windowMs?: number;
}

RequestLifecycleOptions#

Per-request options shared across the lifecycle: error hook plus session/db providers.

ts
interface RequestLifecycleOptions<RawRequest, SessionValue = unknown, DbValue = unknown> {
  db?: DbProvider<RawRequest, DbValue, SessionValue>;
  onError?: ServerErrorHandler;
  sessionProvider?: SessionProvider<RawRequest, SessionValue>;
}

SessionDefinition#

The app's session declaration returned by session(): parse, provider, and schema.

ts
interface SessionDefinition<Value> {
  parse(request: { session?: unknown }): Value;
  provider<RawRequest>(
    provider: SessionProvider<RawRequest, Value>,
  ): SessionProvider<RawRequest, Value>;
  schema: Schema<Value>;
}

SessionProvider#

A function that resolves the session value from a raw request (or null).

ts
type SessionProvider<RawRequest, SessionValue> = (
  request: RawRequest,
) => Promise<SessionValue | null | undefined> | SessionValue | null | undefined;

SessionRequestLike#

A request carrying an optional session; the constraint for built-in guards.

ts
interface SessionRequestLike {
  session?: {
    id?: string;
    user?: SessionUserLike | null;
  } | null;
}

SessionUserLike#

The minimal authenticated-user shape guards inspect: id and roles.

ts
interface SessionUserLike {
  id?: string;
  roles?: readonly string[];
}

UnauthenticatedContext#

Undocumented.

ts
interface UnauthenticatedContext<Request> {
  next: string;
  request: Request;
}

UnauthenticatedDenial#

The caller is not authenticated. SPEC §6.5: the framework runs the app's onUnauthenticated handler, whose default is a 303 redirect to the login route with the original URL available as next.

ts
interface UnauthenticatedDenial {
  kind: 'unauthenticated';
  payload?: Record<string, unknown>;
}

UnauthenticatedHandler#

Undocumented.

ts
type UnauthenticatedHandler<Request> = (
  context: UnauthenticatedContext<Request>,
) => CoreRedirect | Promise<CoreRedirect>;

MutationResponseHeaderValue#

A single mutation-response header value (alias of ResponseHeaderValue).

ts
type MutationResponseHeaderValue = ResponseHeaderValue;

MutationResponseHeaders#

A mutation-response header bag (alias of ResponseHeaders).

ts
type MutationResponseHeaders = ResponseHeaders;

NotFound#

The 404 marker returned by notFound().

ts
interface NotFound {
  notFound: true;
  status: 404;
}

ResponseHeaderValue#

A single header value: one string or a list of strings.

ts
type ResponseHeaderValue = string | string[];

ResponseHeaders#

A header bag mapping header names to values.

ts
type ResponseHeaders = Record<string, ResponseHeaderValue>;

RouteFileOptions#

Options for respond.file: content type and optional filename/etag/headers.

ts
interface RouteFileOptions {
  contentType: string;
  etag?: string;
  filename?: string;
  headers?: Record<string, string>;
}

RoutePageResponse#

A fully rendered route HTTP response (status, headers, body).

ts
interface RoutePageResponse extends ServerResponseBase<
  RouteResponseBody,
  Record<string, string>,
  RouteResponseStatus
> {}

RouteResponseBody#

A renderable route body: a string, bytes, an ArrayBuffer, or a byte stream.

ts
type RouteResponseBody = ArrayBuffer | ReadableStream<Uint8Array> | Uint8Array | string;

RouteResponseOutcome#

A non-document route outcome (file/stream) produced by respond.

ts
interface RouteResponseOutcome {
  body: RouteResponseBody;
  contentDisposition: string;
  contentType: string;
  etag?: string;
  headers?: Record<string, string>;
  routeResponse: true;
}

RouteStreamOptions#

Options for respond.stream: RouteFileOptions plus inline/attachment disposition.

ts
interface RouteStreamOptions extends RouteFileOptions {
  disposition?: 'attachment' | 'inline';
}

ServerResponseBase#

The common shape of every server response: body, headers, and status.

ts
interface ServerResponseBase<
  Body,
  Headers extends ResponseHeaders = ResponseHeaders,
  Status extends number = number,
> {
  body: Body;
  headers: Headers;
  status: Status;
}

LayoutDeclaration#

A first-class page-chrome segment, as returned by layout().

ts
interface LayoutDeclaration<
  Request = unknown,
  Queries extends LayoutQueryMap<Request> = LayoutQueryMap<Request>,
  Page = unknown,
> extends LayoutDefinition<Request, Queries, Page> {}

LayoutDefinition#

The body passed to layout(): optional parent, guard, queries, and chrome render function.

ts
interface LayoutDefinition<
  Request = unknown,
  Queries extends LayoutQueryMap<Request> = LayoutQueryMap<Request>,
  Page = unknown,
> extends PageHintOptions {
  boundaries?: RouteBoundaries<Request, Page>;
  guard?: Guard<Request>;
  parent?: LayoutDeclaration<Request, any, unknown>;
  queries?: Queries;
  render?: (
    queries: LayoutQueryResults<Queries>,
    state: undefined,
    slots: LayoutRenderSlots<Request>,
  ) => Page | Promise<Page>;
}

LayoutFactory#

App-scoped layout factory whose guards and render slots see the configured request shape.

ts
interface LayoutFactory<Request = unknown> {
  <const Queries extends LayoutQueryMap<Request> = LayoutQueryMap<Request>, Page = unknown>(
    definition: LayoutDefinition<Request, Queries, Page>,
  ): LayoutDeclaration<Request, Queries, Page>;
}

LayoutQueryResults#

Resolved layout query values passed to a layout().render function (SPEC §4.5/§9.5).

ts
type LayoutQueryResults<Queries> = {
  [Name in keyof Queries]: Queries[Name] extends QueryDefinition<string, infer Value, any, any>
    ? Awaited<Value>
    : unknown;
};

LayoutRenderSlots#

Slots passed to a layout().render function: child page/layout HTML plus the lifecycle request.

ts
interface LayoutRenderSlots<Request> {
  /** The child layout or route page output this layout wraps. */
  children: unknown;
  /** The request after configured app lifecycle providers have run. */
  request: Request;
}

RouteBoundaries#

Per-segment boundaries that override app-level error shells for matching route failures.

ts
interface RouteBoundaries<Request = unknown, Page = unknown> {
  error?: RouteBoundaryRenderer<Request, Page>;
  notFound?: RouteBoundaryRenderer<Request, Page>;
  unauthorized?: RouteBoundaryRenderer<Request, Page>;
}

RouteBoundaryContext#

Context passed to route/layout segment boundary renderers.

ts
interface RouteBoundaryContext<Request> {
  error?: unknown;
  request: Request;
  status: 403 | 404 | 500;
}

RouteBoundaryRenderer#

Render a route/layout segment boundary for expected route failures or errors.

ts
type RouteBoundaryRenderer<Request, Page = unknown> = (
  context: RouteBoundaryContext<Request>,
) => Page | Promise<Page>;

RouteDeclaration#

A RouteDefinition with its path attached, as returned by route().

ts
interface RouteDeclaration<
  Path extends string,
  ParamsSchema extends MaybeSchema<Record<string, string>> = undefined,
  SearchSchema extends MaybeSchema<Record<string, JsonValue>> = undefined,
  Request = unknown,
  Page = unknown,
  GuardedRequest extends Request = Request,
> extends RouteDefinition<Path, ParamsSchema, SearchSchema, Request, Page, GuardedRequest> {
  path: Path;
}

RouteDefinition#

The body of a route passed to route(): page, param/search schemas, guards, and meta/hints.

ts
interface RouteDefinition<
  Path extends string,
  ParamsSchema extends MaybeSchema<Record<string, string>> = undefined,
  SearchSchema extends MaybeSchema<Record<string, JsonValue>> = undefined,
  Request = unknown,
  Page = unknown,
  GuardedRequest extends Request = Request,
> extends PageHintOptions {
  boundaries?: RouteBoundaries<Request, Page>;
  guard?: Guard<Request, GuardedRequest>;
  layout?: LayoutDeclaration<any, any, any>;
  onUnauthenticated?: UnauthenticatedHandler<Request>;
  page?: (
    context: RouteRequest<Path, ParamsSchema, SearchSchema>,
    request: GuardedRequest,
  ) => Page | NotFound | RouteResponseOutcome | Promise<Page | NotFound | RouteResponseOutcome>;
  params?: ParamsSchema;
  search?: SearchSchema;
  staticPaths?: readonly string[];
}

RoutePageFailure#

Undocumented.

ts
interface RoutePageFailure {
  auth?: ResolvedGuardFailure['auth'];
  error?: {
    code: 'RATE_LIMITED' | 'RENDER_ERROR' | 'UNAUTHORIZED';
    payload: Record<string, unknown>;
  };
  ok: false;
  retryAfter?: number;
  status: 404 | 422 | 429 | 500;
}

RoutePageOutcomeSuccess#

Undocumented.

ts
interface RoutePageOutcomeSuccess {
  ok: true;
  outcome: RouteResponseOutcome;
}

RoutePageRenderSuccess#

Undocumented.

ts
interface RoutePageRenderSuccess<Page> {
  ok: true;
  value: Page;
}

RoutePageResult#

Undocumented.

ts
type RoutePageResult<Page> = RoutePageSuccess<Page> | RoutePageFailure;

RoutePageSuccess#

Undocumented.

ts
type RoutePageSuccess<Page> = RoutePageRenderSuccess<Page> | RoutePageOutcomeSuccess;

RouteRequest#

The typed context a route page receives: parsed params, search, and the path.

ts
interface RouteRequest<
  Path extends string,
  ParamsSchema extends MaybeSchema<Record<string, string>> = undefined,
  SearchSchema extends MaybeSchema<Record<string, JsonValue>> = undefined,
> {
  params: RouteParamsFor<Path, ParamsSchema>;
  path: Path;
  search: RouteSearchFor<SearchSchema>;
}

RouteRequestInput#

Raw, unparsed params/search input handed to a route before schema parsing.

ts
interface RouteRequestInput {
  params?: unknown;
  search?: unknown;
}

CookieOptions#

Undocumented.

ts
interface CookieOptions {
  domain?: string;
  expires?: Date | string;
  httpOnly?: boolean;
  maxAge?: number;
  path?: string;
  sameSite?: 'lax' | 'none' | 'strict';
  secure?: boolean;
}

WebhookChangeOptions#

Undocumented.

ts
interface WebhookChangeOptions<Input = unknown> {
  input?: Input;
  keys?: readonly string[];
  reason?: string;
}

WebhookDeclaration#

Undocumented.

ts
interface WebhookDeclaration<
  Name extends string = string,
  Path extends string = string,
  InputSchema extends Schema<unknown> = Schema<unknown>,
  Value = unknown,
  Tx = unknown,
> extends EndpointDeclaration<Path, 'POST', 'exact'> {
  name: Name;
  webhook: true;
  webhookDefinition: WebhookDefinition<InputSchema, Value, Tx>;
}

WebhookDefinition#

Undocumented.

ts
type WebhookDefinition<
  InputSchema extends Schema<unknown> = Schema<unknown>,
  Value = unknown,
  Tx = unknown,
> = WebhookDefinitionBase<InputSchema, Value, Tx> &
  (WebhookVerifiedDefinition | WebhookNoneDefinition);

WebhookFail#

Undocumented.

ts
interface WebhookFail<Code extends string = string, Payload = unknown> {
  error: {
    code: Code;
    payload: Payload;
  };
  ok: false;
  retryAfter?: number;
  status: WebhookFailureStatus;
}

WebhookFailureStatus#

Undocumented.

ts
type WebhookFailureStatus = 400 | 401 | 422 | 429 | 500;

WebhookHandlerContext#

Undocumented.

ts
interface WebhookHandlerContext<Input, Tx = unknown> {
  fail<Code extends string, Payload>(
    code: Code,
    payload: Payload,
    options?: { retryAfter?: number; status?: WebhookFailureStatus },
  ): WebhookFail<Code, Payload>;
  rawBody: Uint8Array;
  recordChange<const DomainKey extends string, ChangeInput = Input>(
    domain: Domain<DomainKey>,
    options?: WebhookChangeOptions<ChangeInput>,
  ): ChangeRecord<DomainKey, ChangeInput | Input>;
  request: EndpointRequest;
  tx: Tx;
}

WebhookReplayReservation#

Undocumented.

ts
interface WebhookReplayReservation {
  commit(response: WebhookWireResponse): void;
}

WebhookReplayStore#

Undocumented.

ts
interface WebhookReplayStore {
  get(scope: string, idem: string): Promise<WebhookWireResponse> | WebhookWireResponse | undefined;
  reserve(scope: string, idem: string): WebhookReplayReservation | undefined;
  set(scope: string, idem: string, response: WebhookWireResponse): void;
}

WebhookResponseStatus#

Undocumented.

ts
type WebhookResponseStatus = WebhookFailureStatus | WebhookSuccessStatus;

WebhookSuccessStatus#

Undocumented.

ts
type WebhookSuccessStatus = 200;

WebhookTransactionContext#

Undocumented.

ts
interface WebhookTransactionContext<Input> {
  input: Input;
  rawBody: Uint8Array;
  request: EndpointRequest;
}

WebhookWireResponse#

Undocumented.

ts
interface WebhookWireResponse extends ServerResponseBase<
  string,
  MutationResponseHeaders,
  WebhookResponseStatus
> {}

Constants#

s#

The schema builder. Compose validators with s.object, s.string, s.number, s.boolean, s.array, and s.file; each returns a Schema whose parse coerces and validates FormData-shaped input, so the same schema validates JSON and form submissions (SPEC §6.3).

ts
const s = {
  array<Item>(item: Schema<Item>): Schema<Item[]> {
    return {
      parse(input: unknown): Item[] {
        const values =
          input === undefined || input === null ? [] : Array.isArray(input) ? input : [input];

        return values.map((value, index) => {
          try {
            return item.parse(value);
          } catch (error) {
            throw validationErrorFrom(error, [String(index)]);
          }
        });
      },
    };
  },
  boolean(): Schema<boolean> {
    return {
      parse(input: unknown): boolean {
        if (typeof input === 'boolean') return input;
        if (input === undefined || input === null || input === '') return false;
        if (typeof input === 'number' && (input === 0 || input === 1)) return Boolean(input);

        if (typeof input === 'string') {
          const value = input.toLowerCase();
          if (['1', 'on', 'true', 'yes'].includes(value)) return true;
          if (['0', 'false', 'no', 'off'].includes(value)) return false;
        }

        throw validationError('Expected boolean');
      },
    };
  },
  file(options: FileSchemaOptions = {}): FileSchema {
    return new FileSchemaImpl(options);
  },
  string(): Schema<string> {
    return {
      parse(input: unknown): string {
// … truncated (46 more lines); see the package source for the full declaration.

Example

ts
import { s } from '@kovojs/server';

const input = s.object({
  productId: s.string(),
  quantity: s.number().int().min(1).default(1),
  tags: s.array(s.string()),
});

const parsed = input.parse({ productId: 'p1', quantity: '2', tags: 'a' });
// parsed.quantity === 2, parsed.tags === ['a']

guards#

Built-in guard factories for routes, queries, and mutations. guards.authed() requires a logged-in session (and refines the request type), guards.role(r) requires a role, guards.rateLimit(opts) throttles, and guards.all(...) composes guards left-to-right. Attach the result as a guard on a route, query, or mutation (SPEC §6.5).

ts
const guards = {
  all<Request, RefinedRequest extends Request = Request>(
    ...items: Guard<Request, RefinedRequest>[]
  ): Guard<Request, RefinedRequest> {
    return async (request: Request) => {
      for (const item of items) {
        const result = await item(request);
        // Propagate the first denial (intent object) or bare `false` as-is so the
        // §6.5 status mapping stays owned by the render path, not flattened here.
        if (result !== true) return result;
      }

      return true;
    };
  },
  authed<Request extends SessionRequestLike>(): Guard<Request, AuthenticatedRequest<Request>> {
    return (request) => (request.session?.user ? true : unauthenticatedGuardFailure());
  },
  rateLimit<Request extends SessionRequestLike>(
    options: RateLimitOptions<Request>,
  ): Guard<Request> {
    const counts = new Map<string, { count: number; resetAt: number }>();

    return (request) => {
      const now = Date.now();
      evictExpiredRateLimits(counts, now);

      const windowMs = options.windowMs ?? defaultRateLimitWindowMs;
      if (options.max <= 0) return rateLimitFailure(now + windowMs, now);

      const key = rateLimitKey(request, options);
      const existing = counts.get(key);

      if (existing && existing.resetAt > now) {
        if (existing.count >= options.max) return rateLimitFailure(existing.resetAt, now);

        existing.count += 1;
        return true;
      }

// … truncated (21 more lines); see the package source for the full declaration.

Example

ts
import { guards, route, type SessionRequestLike } from '@kovojs/server';

interface AppRequest extends SessionRequestLike {}

export const dashboard = route('/dashboard', {
  guard: guards.authed<AppRequest>(),
  page: () => '<h1>Dashboard</h1>',
});

respond#

Build a non-document route response from a route page handler: respond.file for an attachment download, respond.stream for a streamed body. Both set the content type and disposition; return the result instead of a page value (SPEC §6.4).

ts
const respond = {
  file(body: Exclude<RouteResponseBody, ReadableStream<Uint8Array>>, options: RouteFileOptions) {
    return routeResponseOutcome(body, {
      ...options,
      disposition: 'attachment',
    });
  },
  stream(body: RouteResponseBody, options: RouteStreamOptions) {
    return routeResponseOutcome(body, {
      ...options,
      disposition: options.disposition ?? 'attachment',
    });
  },
};

Example

ts
import { respond, route } from '@kovojs/server';

export const exportRoute = route('/export.csv', {
  page: () =>
    respond.file('id,name\n1,Kettle\n', {
      contentType: 'text/csv',
      filename: 'products.csv',
    }),
});

@kovojs/server/app-shell/client-modules#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/api/app-shell/client-modules.ts

No public exports are declared by this subpath.

@kovojs/server/app-shell/core#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/api/app-shell/core.ts

No public exports are declared by this subpath.

@kovojs/server/app-shell/node#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/api/app-shell/node.ts

No public exports are declared by this subpath.

@kovojs/server/app-shell/static-export#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/api/app-shell/static-export.ts

Types & interfaces#

StaticExportArtifact#

Undocumented.

ts
interface StaticExportArtifact extends StaticExportResponseSnapshot {
  path: string;
}

StaticExportAssetArtifact#

Undocumented.

ts
interface StaticExportAssetArtifact {
  headers: Record<string, string>;
  path: string;
  source: string;
  status: number;
}

StaticExportAssetInput#

Undocumented.

ts
interface StaticExportAssetInput {
  contentType?: string;
  headers?: HeadersInit;
  path: string;
  source: string | URL;
}

StaticExportClientModuleArtifact#

Undocumented.

ts
interface StaticExportClientModuleArtifact extends StaticExportResponseSnapshot {
  href: string;
  path: string;
}

StaticExportInventoryItem#

Undocumented.

ts
type StaticExportInventoryItem =
  | {
      headers: Record<string, string>;
      kind: 'route-document';
      path: string;
      status: number;
    }
  | {
      headers: Record<string, string>;
      href: string;
      kind: 'client-module';
      path: string;
      status: number;
    }
  | {
      headers: Record<string, string>;
      kind: 'static-asset';
      path: string;
      source: string;
      status: number;
    };

StaticExportManifest#

Undocumented.

ts
interface StaticExportManifest {
  assets: readonly StaticExportManifestAsset[];
  clientModules: readonly StaticExportManifestClientModule[];
  files: readonly StaticExportInventoryItem[];
  routeDocuments: readonly StaticExportManifestRouteDocument[];
}

StaticExportManifestAsset#

Undocumented.

ts
interface StaticExportManifestAsset {
  headers: Record<string, string>;
  path: string;
  source: string;
  status: number;
}

StaticExportManifestClientModule#

Undocumented.

ts
interface StaticExportManifestClientModule {
  headers: Record<string, string>;
  href: string;
  path: string;
  status: number;
}

StaticExportManifestRouteDocument#

Undocumented.

ts
interface StaticExportManifestRouteDocument {
  headers: Record<string, string>;
  path: string;
  status: number;
}

StaticExportNonExportablePolicy#

Undocumented.

ts
type StaticExportNonExportablePolicy = 'error' | 'skip';

@kovojs/server/build#

Build-time deployment presets and neutral artifact helpers for kovo build.

Source: packages/server/src/build.ts

Functions#

defineConfig#

Type helper for authoring kovo.config.ts without changing runtime behavior.

ts
function defineConfig(config: KovoConfig): KovoConfig;

node#

Create the built-in Node/VPS preset descriptor.

The emitted output wraps the neutral server/handler.mjs Request-to-Response contract in a Node http server and serves immutable /c/* and /assets/* client files without Vite at request time.

ts
function node(options: NodePresetOptions = {}): NodePreset;

vercel#

Create the built-in Vercel preset descriptor.

The emitted output follows Vercel Build Output API v3: static client files land under .vercel/output/static, and the request handler is wrapped as a Node.js Vercel Function under .vercel/output/functions/kovo.func.

ts
function vercel(options: VercelPresetOptions = {}): VercelPreset;

cloudflare#

Create the built-in Cloudflare Workers preset descriptor.

The emitted output is a Wrangler project with a module Worker, static assets binding, and nodejs_compat enabled for the current Node-first request path.

ts
function cloudflare(options: CloudflarePresetOptions = {}): CloudflarePreset;

writeKovoNeutralBuild#

Write Kovo's platform-neutral deployment artifact.

This Phase 0 API reuses the existing app-shell Vite manifest/client-module pipeline and creates the dist/.kovo-style metadata layout. The server bundle step is still supplied by callers as serverHandlerSource until kovo build owns bundling.

ts
async function writeKovoNeutralBuild(
  options: WriteKovoNeutralBuildOptions,
): Promise<KovoNeutralBuild>;

Types & interfaces#

KovoPreset#

Build-time preset descriptor consumed by kovo build and deployment tooling.

ts
interface KovoPreset {
  /** Emit platform-native output from an already-written neutral build. */
  emit?(build: KovoNeutralBuild, context: PresetContext): Promise<void> | void;
  /** Return target-specific diagnostics before output is emitted. */
  inspect?(
    build: KovoNeutralBuild,
    context: PresetInspectContext,
  ): Promise<readonly PresetDiagnostic[]> | readonly PresetDiagnostic[];
  /** Stable preset name, such as `node`, `vercel`, or `cloudflare`. */
  name: string;
}

PresetInspectContext#

Context passed to a preset while it validates target-specific constraints.

ts
interface PresetInspectContext {
  /** Environment variables the app declares or the build inferred, such as `DATABASE_URL`. */
  declaredEnv: readonly string[];
  /** Read the bundled request handler source when a preset needs target-specific inspection. */
  readServerHandlerSource?(): Promise<string | undefined> | string | undefined;
}

PresetContext#

Context passed to a preset while it transforms the neutral build output.

ts
interface PresetContext extends PresetInspectContext {
  /** Build log sink supplied by the CLI or host integration. */
  log(message: string): void;
  /** Platform output directory for the preset. */
  outDir: string;
  /** Read the neutral build facts the preset is transforming. */
  readNeutral(): KovoNeutralBuild;
}

PresetDiagnostic#

A preset validation diagnostic reported before platform output is emitted.

ts
interface PresetDiagnostic {
  /** Stable diagnostic code owned by the preset. */
  code: string;
  /** Human-readable diagnostic message. */
  message: string;
  /** Whether the diagnostic blocks the build. */
  severity: 'error' | 'warning';
}

NodePresetOptions#

Options for the built-in Node/VPS preset.

ts
interface NodePresetOptions {
  /** Whether the node preset emits a minimal Dockerfile next to `server.mjs`; defaults to true. */
  dockerfile?: boolean;
}

NodePreset#

Built-in Node/VPS preset descriptor returned by node().

ts
interface NodePreset extends KovoPreset {
  /** Emit a standalone Node output from Kovo's neutral build artifact. */
  emit(build: KovoNeutralBuild, context: PresetContext): Promise<void>;
  /** Return blocking diagnostics when the neutral build lacks a request handler. */
  inspect(build: KovoNeutralBuild, context: PresetInspectContext): readonly PresetDiagnostic[];
  /** Options captured by `node()`. */
  options: NodePresetOptions;
}

VercelPresetOptions#

Options for the built-in Vercel preset.

ts
interface VercelPresetOptions {
  /** Maximum Vercel Function duration in seconds. */
  maxDuration?: number;
  /** Vercel Function memory in MB. */
  memory?: number;
  /** Vercel regions for the Node function. */
  regions?: readonly string[];
}

VercelPreset#

Built-in Vercel Build Output API v3 preset descriptor returned by vercel().

ts
interface VercelPreset extends KovoPreset {
  /** Emit `.vercel/output` from Kovo's neutral build artifact. */
  emit(build: KovoNeutralBuild, context: PresetContext): Promise<void>;
  /** Return blocking diagnostics when the neutral build lacks a request handler. */
  inspect(build: KovoNeutralBuild, context: PresetInspectContext): readonly PresetDiagnostic[];
  /** Options captured by `vercel()`. */
  options: VercelPresetOptions;
}

CloudflarePresetOptions#

Options for the built-in Cloudflare Workers preset.

ts
interface CloudflarePresetOptions {
  /** Worker compatibility date; defaults to the first date that supports `nodejs_compat` v2. */
  compatibilityDate?: string;
  /** Generated Worker name in `wrangler.toml`; defaults to `kovo-app`. */
  name?: string;
}

CloudflarePreset#

Built-in Cloudflare Workers preset descriptor returned by cloudflare().

ts
interface CloudflarePreset extends KovoPreset {
  /** Emit a Wrangler project from Kovo's neutral build artifact. */
  emit(build: KovoNeutralBuild, context: PresetContext): Promise<void>;
  /** Return diagnostics for Cloudflare Worker runtime constraints. */
  inspect(
    build: KovoNeutralBuild,
    context: PresetInspectContext,
  ): Promise<readonly PresetDiagnostic[]>;
  /** Options captured by `cloudflare()`. */
  options: CloudflarePresetOptions;
}

KovoConfig#

Build-time project configuration loaded from kovo.config.ts.

ts
interface KovoConfig {
  /** Platform preset used by `kovo build` when CLI/env overrides are absent. */
  preset?: KovoPreset;
}

WriteKovoNeutralBuildOptions#

Inputs for writing Kovo's platform-neutral deployment artifact.

ts
interface WriteKovoNeutralBuildOptions {
  /** App aggregate produced by `createApp()`. */
  app: KovoApp;
  /** Optional public base path used to resolve manifest asset hrefs. */
  base?: string;
  /**
   * Build-owned CSS fragments to materialize into declared stylesheet assets, such as
   * first-party package component CSS extracted by `kovo build` (SPEC.md §13.1).
   */
  buildStylesheetCss?: readonly {
    /** CSS text to merge into the stylesheet asset. */
    css: string;
    /** Public stylesheet href that receives this CSS. */
    href: string;
  }[];
  /** Compiler-produced client modules that should be emitted under `client/c/`. */
  clientModules?: readonly KovoAppShellCompiledClientModule[];
  /** Vite manifest file used to derive asset inventory and per-route hints. */
  manifestFile?: string | URL;
  /** Target neutral artifact directory, conventionally `dist/.kovo`. */
  outDir: string | URL;
  /** Route path to Vite entry mapping used for route hints. */
  routeEntryMap?: KovoAppShellRouteEntryMap;
  /** Optional pre-bundled handler source to write to `server/handler.mjs`. */
  serverHandlerSource?: string;
}

KovoNeutralBuild#

Facts returned after writing the platform-neutral deployment artifact.

ts
interface KovoNeutralBuild {
  /** Absolute path to the neutral client directory. */
  clientDir: string;
  /** Versioned client modules emitted under `client/c/`. */
  clientModules: readonly KovoAppShellBuiltClientModule[];
  /** Absolute path to the neutral manifest JSON file. */
  manifestPath: string;
  /** Absolute path to the neutral meta JSON file. */
  metaPath: string;
  /** Absolute path to the neutral build root. */
  outDir: string;
  /** Per-route Vite hints merged into the built app shell. */
  routeHints: readonly KovoAppShellRouteBuildHints[];
  /** Absolute path to the neutral routes JSON file. */
  routesPath: string;
  /** Absolute path to the neutral server directory. */
  serverDir: string;
  /** Absolute path to `server/handler.mjs` when a handler source was supplied. */
  serverHandlerPath?: string;
  /** Static assets discovered from the Vite manifest. */
  staticAssets: readonly {
    file: string;
    href: string;
    path: string;
  }[];
  /** Fully static output when every route was proven exportable. */
  staticOutput?: {
    /** Absolute path to the neutral static export directory. */
    dir: string;
    /** Whether every route was exported without route-level diagnostics. */
    complete: boolean;
    /** Route-level diagnostics produced while exporting the static subtree. */
    diagnostics: readonly StaticExportDiagnostic[];
    /** Absolute path to the static export manifest JSON file. */
    manifestPath: string;
    /** Concrete route documents written into the static subtree. */
    routeDocuments: readonly StaticExportRouteTarget[];
  };
  /** Whether this build can be deployed without a server/function fallback. */
  staticOnly: boolean;
// … truncated (3 more lines); see the package source for the full declaration.

@kovojs/server/jsx-runtime#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/jsx-runtime.ts

Functions#

Fragment#

Undocumented.

ts
function Fragment(props: JsxProps): MaybePromise<string>;

jsx#

Undocumented.

ts
function jsx(
  type: JsxComponent | KovoJsxComponent | string,
  props: JsxProps,
  key?: unknown,
): MaybePromise<string>;

jsxDEV#

Undocumented.

ts
function jsxDEV(
  type: JsxComponent | KovoJsxComponent | string,
  props: JsxProps,
  key?: unknown,
): MaybePromise<string>;

Types & interfaces#

JsxNode#

Undocumented.

ts
type JsxNode = JsxNode[] | boolean | null | number | Promise<JsxNode> | string | undefined;

JsxProps#

Undocumented.

ts
interface JsxProps {
  children?: JsxNode;
  [attribute: string]: unknown;
}

JsxComponent#

Undocumented.

ts
type JsxComponent = (props: any) => any;

Constants#

jsxs#

Undocumented.

ts
const jsxs = jsx;

JSX#

Undocumented.

ts
namespace JSX {
  type Element = any;
  type ElementType = JsxComponent | KovoJsxComponent | string;
  interface ElementChildrenAttribute {
    children: unknown;
  }
  interface IntrinsicElements {
    [tag: string]: Record<string, unknown>;
  }
}

@kovojs/server/jsx-dev-runtime#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/jsx-runtime.ts

Functions#

Fragment#

Undocumented.

ts
function Fragment(props: JsxProps): MaybePromise<string>;

jsx#

Undocumented.

ts
function jsx(
  type: JsxComponent | KovoJsxComponent | string,
  props: JsxProps,
  key?: unknown,
): MaybePromise<string>;

jsxDEV#

Undocumented.

ts
function jsxDEV(
  type: JsxComponent | KovoJsxComponent | string,
  props: JsxProps,
  key?: unknown,
): MaybePromise<string>;

Types & interfaces#

JsxNode#

Undocumented.

ts
type JsxNode = JsxNode[] | boolean | null | number | Promise<JsxNode> | string | undefined;

JsxProps#

Undocumented.

ts
interface JsxProps {
  children?: JsxNode;
  [attribute: string]: unknown;
}

JsxComponent#

Undocumented.

ts
type JsxComponent = (props: any) => any;

Constants#

jsxs#

Undocumented.

ts
const jsxs = jsx;

JSX#

Undocumented.

ts
namespace JSX {
  type Element = any;
  type ElementType = JsxComponent | KovoJsxComponent | string;
  interface ElementChildrenAttribute {
    children: unknown;
  }
  interface IntrinsicElements {
    [tag: string]: Record<string, unknown>;
  }
}

@kovojs/server/vite#

Schemas and validation, guards and sessions, the request lifecycle, route matching, rendering, and streaming.

Source: packages/server/src/vite.ts

Functions#

kovo#

Public Vite integration for authored Kovo apps (SPEC.md §9.5). The app entry must default-export a KovoApp; generated route artifacts stay compiler-owned.

ts
function kovo(options: KovoVitePluginOptions): KovoVitePlugin;

createKovoViteIntegration#

Create the public Vite integration without adding options beyond the authored app entry.

ts
function createKovoViteIntegration(options: KovoVitePluginOptions): KovoViteIntegration;

Types & interfaces#

KovoVitePluginOptions#

Options for the public Kovo Vite plugin (SPEC.md §9.5).

ts
interface KovoVitePluginOptions {
  /** Authored app module id to load in Vite dev; it must default-export a KovoApp. */
  app: string;
}

KovoViteDevServer#

Minimal Vite dev-server surface used by the Kovo plugin adapter.

ts
interface KovoViteDevServer {
  /** Connect-compatible middleware stack owned by Vite. */
  middlewares: {
    use(handler: KovoViteMiddleware): void;
  };
  /** Load an SSR module through Vite's transform pipeline. */
  ssrLoadModule(id: string): Promise<Record<string, unknown>>;
}

KovoViteMiddleware#

Connect-compatible middleware installed by the Kovo Vite plugin.

ts
type KovoViteMiddleware = (
  request: IncomingMessage,
  response: ServerResponse,
  next: (error?: unknown) => void,
) => void;

KovoVitePostHook#

Optional post-configuration hook returned by a Vite plugin.

ts
type KovoVitePostHook = () => void | Promise<void>;

KovoVitePlugin#

Vite plugin object returned by {@link kovo}.

ts
interface KovoVitePlugin {
  /** Install the Kovo request-shell middleware into the Vite dev server. */
  configureServer(server: KovoViteDevServer): Promise<void | KovoVitePostHook>;
  /** Stable plugin name used by Vite diagnostics. */
  name: 'kovo';
}

KovoViteIntegration#

Public Kovo Vite integration bundle.

ts
interface KovoViteIntegration {
  /** Vite plugin that serves the authored app during local development. */
  plugin: KovoVitePlugin;
}