L10 - Migrations
Synchronize your TypeScript schema with the database through diffing and DDL generation
Location: src/migrations/
Why This Layer Exists
Your TypeScript schema is the source of truth:
const user = s.model({
id: s.string().id().ulid(),
email: s.string().unique(),
name: s.string().nullable(), // ← Add this field
});The migrations layer detects this change and generates:
ALTER TABLE "user" ADD COLUMN "name" VARCHAR NULL;How It Works
1. Schema Snapshot
First, the current TypeScript schema is serialized into a database-agnostic snapshot:
{
tables: [{
name: "user",
columns: [{
name: "email",
type: "varchar",
nullable: false,
unique: true
}],
indexes: [...],
foreignKeys: [...]
}]
}2. Database Introspection
The current database state is read through the driver:
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'user';3. Diffing
The differ compares snapshots and produces operations:
[
{ type: "addColumn", table: "user", column: { name: "name", ... } },
{ type: "dropIndex", table: "user", indexName: "email_idx" }
]4. DDL Generation
Each operation becomes database-specific DDL via the adapter:
adapter.addColumn(operation) // → ALTER TABLE ... ADD COLUMN ...Operation Types
| Operation | Description |
|---|---|
createTable | New table |
dropTable | Remove table |
addColumn | Add column to table |
dropColumn | Remove column |
alterColumn | Change column type/constraints |
createIndex | Add index |
dropIndex | Remove index |
addForeignKey | Add foreign key constraint |
dropForeignKey | Remove foreign key constraint |
Ambiguous Changes
Some changes can't be automatically resolved:
// Did you rename "name" to "fullName"?
// Or delete "name" and create "fullName"?The CLI prompts for clarification:
? Column "name" was removed and "fullName" was added.
○ Rename "name" to "fullName" (preserves data)
○ Drop "name" and create "fullName" (loses data)Push vs Migrate
VibORM offers two approaches:
viborm push
Direct sync - applies changes immediately:
viborm push
# Compares schema → database
# Shows diff
# Applies changesBest for: Development, prototyping
Migration Files (Planned)
Generate SQL files for review:
viborm migrate generate
# Creates: migrations/20240115_add_name.sql
viborm migrate apply
# Executes pending migrationsBest for: Production, team workflows
Connection to Other Layers
- L2 (Fields): Field state determines column definitions
- L4 (Relations): Relations determine foreign key constraints
- L7 (Adapters): Adapters generate database-specific DDL
- L8 (Drivers): Drivers execute DDL and introspect schema