scrml.dev v0.7.1
Reference › Elements

<schema>

Declarative database schema. Lowers to SQL DDL at compile time; the schema-differ compares declared shape to live DB shape and emits migrations. SQL- mirror canonical, with additive shared-core vocabulary that lowers to CHECK constraints.

Syntax

<schema>
  tableName {
    columnName: sqlType [native-sql-constraints] [shared-core-validators]
    ...
  }
  ...
</schema>

Each table is a brace block; each column is a typed declaration with optional constraints. Two constraint vocabularies coexist on a column: native SQL constraints (canonical) and shared-core validators (additive). Both are legal; mixing is legal.

Worked example

A users table with both vocabularies in play.

<schema>
  users {
    id:    integer primary key
    email: text not null unique
    name:  text req length(>=2)
    age:   integer min(18) max(120)
    role:  text default('user') oneOf([user, admin])
  }

  posts {
    id:        integer primary key
    user_id:   integer not null references(users.id)
    title:     text req length(>=1) length(<=200)
    body:      text req
    published: integer default(0)
  }
</schema>

The compiler reads the schema, compares to the live DB (via SQLite PRAGMA table_info() or equivalent), and emits migration SQL for the diff. Dev mode applies the migrations on reload; production runs them as a versioned step.

Semantics

  • SQL-mirror canonical (§39.5.9). Native SQL constraints (not null, unique, primary key, references(table.col), default(literal)) are the source-level canonical form. They map 1:1 to emitted DDL.
  • Shared-core additive (§39.5.7). The universal-core validator vocabulary (req, length, pattern, min, max, gt, lt, gte, lte, eq, neq, oneOf, notIn) is admitted on schema columns and lowers to SQL CHECK / NOT NULL constraints per §39.5.8. The same word fires the same constraint in three loci: state-validator, refinement-type, and schema-column.
  • Lowering rules (§39.5.8). req lowers to NOT NULL; length(>=N) lowers to CHECK (length(col) >= N); pattern(re) lowers driver-dependent (Postgres ~, SQLite/MySQL REGEXP); oneOf([a, b, c]) lowers to CHECK (col IN (a, b, c)).
  • SQL passthrough is inviolable. SQL strings sent to the database from ?{} blocks are unchanged in shape. The shared-core vocabulary touches scrml source only; the wire form stays standard SQL.
  • Compile-time cross-check. The schema is the source of truth for column types and names used by ?{} blocks. The compiler validates queries against the schema at compile time; unknown columns / type mismatches fire E-SQL-* errors before runtime.
  • Migration diff. The schema-differ at compiler/src/schema-differ.js (~273 LOC) compares desired (<schema> AST) against actual (PRAGMA table_info() output) and emits migration SQL.

Errors this feature can fire

Edge cases

  • Mixed vocabularies on one column. Legal: email: text not null req length(>=3) pattern(/^.+@.+$/). not null + req together is redundant but not erroneous — both lower to NOT NULL semantics.
  • Driver-dependent lowering. Pattern constraints emit different DDL by driver. Postgres uses ~; SQLite/MySQL use REGEXP. The db= attribute on <program> tells the schema-differ which dialect to emit.
  • Schema lives at file or program scope. A <schema> element is structural; it does not live inside reactive scopes or per-page bodies. Multiple <schema> blocks across files are merged at compile time.
  • Migration safety. The schema-differ emits forward migrations; destructive operations (DROP COLUMN, DROP TABLE) require explicit opt-in. Default behavior is additive-only.

Related features

  • ?{ ... } — SQL context. Queries cross-checked against the schema at compile time.
  • scrml:data stdlib module — runtime validator builders for untrusted-payload parsing at boundaries the schema doesn't cover.
  • refinement types (§53) — same shared-core vocabulary on type annotations. Compile-time + runtime boundary check; complementary layer to the schema's DBMS- enforced constraints.
  • validators on state cells (§55) — same vocabulary again, this time wired to the auto-synthesized validity surface for forms.

Availability

Surface Since Notes
<schema> element v0.2 Pre-D3 SQL-mirror canonical form
Shared-core validators on schema columns D3 (2026-05-04) SPEC §39.5.7 + §39.5.8 lowering rules
Migration diff v0.2 compiler/src/schema-differ.js ~273 LOC
Multi-database lowering SPEC §44 Driver-dependent DDL via <program db=>

Specification

This page summarizes SPEC §39 (Schema and Migrations), with cross-refs to §44 (multi-database adaptation) and §53 (refinement types) for the cross-locus vocabulary unification. The normative text lives at compiler/SPEC.md in the scrmlTS repository.