JS API Reference
All exports from @retrofit-ui/builder-zod. The package produces spec JSON; your server emits it on whatever routes you register (matched to the apiBase in /retrofit.json — the default is /api/ui) and serves the SPA bundle.
Serving the SPA
The builders only produce specs. To serve the UI, serve the pre-built bundle from @retrofit-ui/spa-solid-shoelace as static files and expose a /retrofit.json config endpoint:
import { distPath } from '@retrofit-ui/spa-solid-shoelace';
app.get('/retrofit.json', (_req, res) =>
res.json({ apiBase: '/api/ui', theme }), // theme is optional
);
app.use(express.static(distPath));The SPA fetches /retrofit.json on startup to learn its apiBase and apply the optional theme (see RetrofitTheme). Hash-based routing means no catch-all route is needed. Any server in any language can serve the bundle the same way.
TableView / TableViewBuilder
TableView is an alias for TableViewBuilder.
class TableViewBuilder<S extends ZodRawShape> {
static schema<S>(schema: ZodObject<S>): TableViewBuilder<S>
updateSchema(schema: ZodObject<ZodRawShape>): this
columnOverride(key: string, override: Partial<Column>): this
visibleColumns(keys: string[]): this
rowAction(action: RowAction): this
list(directive: EndpointDirective): this
find(directive: EndpointDirective): this
create(directive: EndpointDirective): this
update(directive: EndpointDirective): this
delete(directive: EndpointDirective): this
build(): TableSpec
}formSpec / FormSpecBuilder
function formSpec<S extends ZodRawShape>(
schema: ZodObject<S>,
updateSchema?: ZodObject<ZodRawShape>,
): FormSpecBuilder<S>
class FormSpecBuilder<S extends ZodRawShape> {
fieldOverride(key: string, override: Partial<Field>): this
find(directive: EndpointDirective): this
create(directive: EndpointDirective): this
update(directive: EndpointDirective): this
delete(directive: EndpointDirective): this
build(): FormSpec
}TableFormWorkflowBundle / WorkflowBundleBuilder
TableFormWorkflowBundle is an alias for WorkflowBundleBuilder.
class WorkflowBundleBuilder<S extends ZodRawShape> {
static schema<S>(schema: ZodObject<S>): WorkflowBundleBuilder<S>
updateSchema(schema: ZodObject<ZodRawShape>): this
table(customizer: (t: TableCustomizer) => TableCustomizer): this
form(customizer: (f: FormCustomizer) => FormCustomizer): this
list(directive: EndpointDirective): this
find(directive: EndpointDirective): this
create(directive: EndpointDirective): this
update(directive: EndpointDirective): this
delete(directive: EndpointDirective): this
build(): WorkflowBundle
}
class WorkflowBundle {
tableSpec: TableSpec
formSpec: FormSpec
}
class TableCustomizer {
columnOverride(key: string, override: Partial<Column>): this
visibleColumns(keys: string[]): this
rowAction(action: RowAction): this
}
class FormCustomizer {
fieldOverride(key: string, override: Partial<Field>): this
}build() returns a plain WorkflowBundle holding the two specs. Serve them on a collection route and an item route — see Workflow Bundle.
Types
EndpointDirective
interface EndpointDirective {
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
url: string; // may contain {id} placeholder
}TableSpec
interface TableSpec {
columns: Column[];
endpoints: {
list?: EndpointDirective;
find?: EndpointDirective;
create?: EndpointDirective;
update?: EndpointDirective;
delete?: EndpointDirective;
};
rowActions?: RowAction[];
metadata?: { title?: string };
}FormSpec
interface FormSpec {
fields: Field[];
endpoints: {
find?: EndpointDirective;
create?: EndpointDirective;
update?: EndpointDirective;
delete?: EndpointDirective;
};
metadata?: { title?: string };
}MarkdownViewSpec
interface MarkdownViewSpec {
entityEndpoint: EndpointDirective;
field: string;
metadata?: { title?: string };
}Column
interface Column {
key: string;
label: string;
type: 'string' | 'number' | 'date' | 'boolean' | 'enum' | 'custom';
sortable?: boolean;
filterable?: boolean;
editable?: boolean;
width?: string;
alignment?: 'left' | 'center' | 'right';
options?: FieldOption[];
}Field
interface Field {
name: string;
label: string;
type: 'text' | 'email' | 'password' | 'number' | 'date' | 'select'
| 'multiselect' | 'checkbox' | 'radio' | 'textarea' | 'markdown' | 'file';
required?: boolean;
readOnly?: boolean;
placeholder?: string;
helpText?: string;
validation?: { required?: boolean; min?: number; max?: number; pattern?: string };
options?: FieldOption[];
}FieldOption
interface FieldOption {
label: string;
value: string | number;
}RowAction
interface RowAction {
label: string;
routePattern: string; // e.g. '/{id}/render'
}RetrofitTheme
interface RetrofitTheme {
cssVariables?: Record<string, string>;
extraCss?: string;
}The SPA applies the theme client-side from /retrofit.json: cssVariables are set on :root and extraCss is injected as a <style> tag.