Each generated contract file in domains/<domain>/shared/contracts/ owns two
runtime schemas:
- input schema
- result schema
TypeScript input and result types are inferred from those schemas. A separate handwritten interface is not generated.
The initial generator emits Zod schemas. boundra remains provider
agnostic by requiring only this structural shape:
export type BoundraSchema<Output> = {
parse(value: unknown): Output;
};Another schema provider may be used when its schema implements the same parse contract. Provider-specific features are not part of the Boundra runtime API.
import { defineQuery, type InferSchema } from "boundra";
import { z } from "zod";
export const getOrderInputSchema = z.object({});
export const getOrderResultSchema = z.object({});
export type GetOrderQueryInput = InferSchema<typeof getOrderInputSchema>;
export type GetOrderQueryResult = InferSchema<typeof getOrderResultSchema>;
export const getOrderQuery = defineQuery({
name: "get-order",
input: getOrderInputSchema,
result: getOrderResultSchema,
});The generated empty objects are safe scaffolds. Feature work replaces their fields with real domain schemas; generated files are application-owned after creation and are never overwritten.
- client query/mutation calls parse input before transport
- transport results are parsed before returning to application code
- client calls may pass an
AbortSignal; the signal is forwarded to custom and HTTP transports - intentional cancellation is rethrown unchanged instead of being reported as
a
RUNTIME-003transport failure - server route execution parses input before the handler and parses the handler result before returning
- missing handlers and schema parse failures surface typed runtime errors
- schema parse failures expose provider-neutral field issues through
BoundraRuntimeError.issues - serialized runtime errors omit the original input and internal
cause
Generation appends an idempotent export to shared/public.ts:
export * from "./contracts/get-order";The direct contract path remains in domain.json publicApi.shared for
compatibility with current manifests. Consumers should prefer the stable
shared/public entrypoint.
- generator owns initial file creation
- application code owns schema fields and handler implementation afterward
- repeated generation must fail rather than overwrite application changes