Skip to content

Code Generation

codegen turns a schema shape into types. By default it compiles the current Declarative Schema through the Shadow Database and generates from that, so the types always match the schema you have committed — no live database needed.

Terminal window
shki codegen --output src/schema rust
shki codegen --output src/schema typescript
shki codegen --output proto protobuf

Language subcommands accept aliases: rs, ts, proto.

Use --source to generate from a specific Snapshot JSON file, SQL Declarative Schema file, or Directory Schema instead of compiling the current one:

Terminal window
shki codegen --source migrations/_meta/0000_create_users.snapshot.json --output src/schema rust

--preview prints the result without writing files.

--format / [codegen] format:

ModeLayout
fileOne file with every struct and enum, e.g. out/models.rs. Default. Always overwritten.
moduleOne module directory, one file per type plus a generated mod.rs. Always overwritten.
modulesOne directory per type: _def.rs holds the generated definition, mod.rs mounts it and is yours to edit.

modules is the mode to pick when you want hand-written impl blocks next to generated types: _def.rs is always regenerated, mod.rs is only created when missing, so anything you add there survives regeneration.

Name resolution order is: explicit rename, default casing, then pattern. Struct defaults singularize table names and use PascalCase, so users becomes User. Enum defaults use PascalCase, so user_status becomes UserStatus. A pattern then wraps that base name — {}Row turns User into UserRow.

Everything below lives in [codegen] in shki.toml. CLI flags override it.

[codegen]
output = "src/schema"
format = "module"
serde = true
sqlx = true
struct_pattern = "{}Row"
enum_pattern = "Db{}"
include_tables = ["users", "orders"]
exclude_tables = ["audit_log"]
struct_derives = ["Debug", "Clone"]
struct_attributes = ["#[allow(dead_code)]"]
enum_derives = ["Debug", "Clone", "PartialEq"]
enum_attributes = ['#[serde(rename_all = "snake_case")]']
[codegen.struct_renames]
users = "Account"
[codegen.enum_renames]
user_status = "AccountStatus"
[codegen.type_overrides]
jsonb = "serde_json::Value"
"public.money" = "rust_decimal::Decimal"
OptionDefaultPurpose
outputDefault output path when --output is not provided. Relative paths resolve from root.
formatfileOutput layout: file, module, or modules.
serdefalseInjects serde::Serialize/Deserialize derives and #[serde(rename)] attributes. Kept out of the derive lists so it can be toggled.
sqlxtrueInjects sqlx::FromRow (structs) / sqlx::Type (enums) derives and #[sqlx(...)] attributes. Set false for plain types with no sqlx coupling.
struct_derives["Debug", "Clone"]Replaces the default derives attached to generated structs.
struct_attributesExtra raw attributes added above generated structs.
enum_derives["Debug", "Clone", "PartialEq"]Replaces the default derives attached to generated enums.
enum_attributesExtra raw attributes added above generated enums.
struct_renamesExact table-name to generated struct-name overrides. Applied before struct_pattern.
struct_patternPattern for generated struct names; {} is the resolved base name. For table users the base is User, so {}Row produces UserRow.
enum_renamesExact enum-name to generated enum-name overrides. Applied before enum_pattern.
enum_patternPattern for generated enum names; {} is the resolved base name. For enum user_status the base is UserStatus, so Db{} produces DbUserStatus.
type_overridesSQL type to generated type overrides. Built-in types use lowercase keys like jsonb; custom PostgreSQL types may use schema-qualified keys like public.money.
include_tablesallIf non-empty, only listed table names are generated.
exclude_tablesListed table names are skipped. Applied after include_tables.

The same type mapping and naming config is reused by typed queries, so generated query functions return the structs and enums defined here rather than parallel copies.