@xemahq/app-schema-ddl
v0.1.1
Published
Layer 1 SDK: the SINGLE trusted server-side compiler that turns a typed, discriminated `SchemaChangePlan` into Postgres DDL statements. No SQL string ever crosses a wire — callers send a plan, this package emits the SQL. `PgTypeToken` is a closed enum (no
Readme
@xemahq/app-schema-ddl
This package belongs to Layer 1 — a pure SDK that depends only on zod. It
is owned by the xema-kernel-sdk carved repo, so both Layer 2 (xema-base,
e.g. org-database-pool-api, which executes the SQL) and Layer 3
(xema-cultivars, e.g. app-forge, which builds the plan) may depend on it
without crossing the release DAG.
What it is
The single trusted compiler that turns a typed, discriminated
SchemaChangePlan into Postgres DDL. No SQL string ever crosses a wire —
a caller sends a plan, this package emits the statements. It is the sole SQL
emitter for user-app entity schemas; there is exactly one function pair to
audit.
Safety invariants
PgTypeTokenis a closed enum (TEXT | DOUBLE PRECISION | NUMERIC(38,9) | BOOLEAN | DATE | TIMESTAMPTZ | JSONB). A column carries a token, never a free-text type, so nothing outside this set can be emitted.- Every identifier is re-validated against
KEY_PATTERN(^[a-z][a-z0-9-]*$) inside the emitter viaquoteIdent, not only at the DTO. A caller cannot smuggle an unsafe identifier past it. The pattern forbids the"character, so a double-quoted identifier is injection-proof. - The additive path cannot emit a
DROP.compileAdditivePlanaccepts onlyAddEntity | AddField | WidenField | AddReferenceFkand throws on any destructive kind; its module contains noDROP/RENAMEverb.compileDestructivePlanis the separate, gated path forRenameField | NarrowField | DropField | DropEntity. - No free-text SQL member exists on any
SchemaChangevariant (they are zodstrictObjects; a type-level test asserts it).
Exports
| Export | Purpose |
| --- | --- |
| PgTypeToken, pgType | Closed Postgres type set + re-validating accessor |
| AppSchemaChangeKind | Closed set of the 8 schema mutations |
| SchemaChangeSchema, SchemaChange | Discriminated union (zod + type) |
| SchemaChangePlanSchema, SchemaChangePlan | { schemaName, changes[] } |
| ColumnSpecSchema, ColumnSpec | One entity column |
| compileAdditivePlan(plan) | Emit additive DDL; throws on destructive kinds |
| compileDestructivePlan(plan) | Emit destructive DDL; throws on additive kinds |
| KEY_PATTERN, quoteIdent, assertIdent | Identifier validation |
| AppSchemaDdlError | The single typed error this package throws |
Usage
import {
AppSchemaChangeKind,
PgTypeToken,
compileAdditivePlan,
} from '@xemahq/app-schema-ddl';
const statements = compileAdditivePlan({
schemaName: 'shop',
changes: [
{
kind: AppSchemaChangeKind.AddEntity,
entityKey: 'order',
columns: [{ key: 'total', type: PgTypeToken.DoublePrecision, notNull: true }],
},
],
});
// → ['CREATE TABLE IF NOT EXISTS "shop"."order" ( … );']Learn more at xema.dev.
