Generating TypeScript types — @cratebase/schema-codegen
@cratebase/schema-codegen is a
standalone build-time CLI, versioned independently of the server, that turns a
schema-as-code JSON document into a single .d.ts file with
one TypeScript interface per non-system collection. It has no dependency on the server or admin
dashboard — run it from your own project’s build pipeline wherever a PostsRecord-shaped type is
more useful than hand-written ones.
npx @cratebase/schema-codegen ./schema.json -o src/cratebase-types.d.tsThe input is exactly what GET /api/collections returns (an { items: [...] } page), what
PUT /api/collections/import and POST /api/schema/apply accept ({ collections: [...] }), a
bare array of collection objects, or a live server URL to fetch that page from directly:
npx @cratebase/schema-codegen https://api.example.com --token <superuser-jwt> -o types.d.tsGiven this schema (a base collection plus a select and a relation field):
{ "items": [ { "name": "posts", "type": "base", "fields": [ { "name": "title", "type": "text", "required": true }, { "name": "tags", "type": "select", "maxSelect": 5 }, { "name": "author", "type": "relation", "maxSelect": 1 } ] } ]}npx @cratebase/schema-codegen ./schema.json -o cratebase-types.d.ts writes:
// Generated by @cratebase/schema-codegen. Do not edit by hand;// re-run the codegen script instead./** `posts` (base). Generated by @cratebase/schema-codegen — do not edit by hand. */export interface PostsRecord { title: string; tags?: string[]; author?: string;}Field types follow FieldKind’s variants in crates/core/src/field.rs one-for-one: select,
file and relation fields become an array when their maxSelect is greater than 1 and a bare
string otherwise, and every other kind maps straight to its TypeScript scalar (number →
number, bool → boolean, json → unknown, geoPoint →
{ lon: number; lat: number }, …). System collections (_superusers, _admins, and the like)
are skipped, since a project’s own code has no business constructing rows in those directly.
A CI pipeline typically checks the generated .d.ts into the repo alongside the checked-in
schema.json from Schema as code, regenerating both whenever
the schema changes so pb.collection("posts").getOne<PostsRecord>(id) stays in sync with what the
server actually serves.