Migrations¶
surql supports code-first schema migrations with up/down SQL generation, versioning, and multi-environment orchestration.
Migration Structure¶
A migration is an object implementing the Migration interface:
import type { Migration } from 'jsr:@oneiriq/surql'
const migration: Migration = {
version: '20240101000001', // Sortable timestamp string
description: 'create_users',
up: async () => 'DEFINE TABLE users SCHEMAFULL; DEFINE FIELD name ON TABLE users TYPE string;',
down: async () => 'REMOVE TABLE users;',
}
Generating Migrations¶
From Schema Diffs¶
import {
diffSchemas,
generateMigrationFromDiffs,
} from 'jsr:@oneiriq/surql'
const before = { tables: [] }
const after = { tables: [userSchema, postSchema] }
const diffs = diffSchemas(before, after)
const migration = generateMigrationFromDiffs(diffs, 'create_users_posts')
console.log(migration.filename) // e.g. 20240101000001_create_users_posts.surql
console.log(migration.upSql)
console.log(migration.downSql)
Blank Migration¶
import { createBlankMigration } from 'jsr:@oneiriq/surql'
const blank = createBlankMigration('add_index_to_users')
// blank.filename, blank.content (with -- UP / -- DOWN sections)
Initial Migration¶
import { generateInitialMigration } from 'jsr:@oneiriq/surql'
const initial = generateInitialMigration(
'DEFINE TABLE users SCHEMAFULL;',
'initial_schema',
)
Running Migrations¶
MigrationRunner¶
import { MigrationRunner } from 'jsr:@oneiriq/surql'
const runner = new MigrationRunner(client, [migration1, migration2])
// Apply all pending migrations
await runner.up()
// Roll back the last applied migration
await runner.down()
// Check status
const status = await runner.status()
console.log(status) // { applied: string[], pending: string[] }
Applying Specific Versions¶
// Apply up to a specific version
await runner.upTo('20240101000002')
// Roll back to a specific version
await runner.downTo('20240101000001')
Migration Discovery¶
Load migrations from .surql files:
import { loadMigrationsFromDir } from 'jsr:@oneiriq/surql'
const migrations = await loadMigrationsFromDir('./migrations')
const runner = new MigrationRunner(client, migrations)
Versioning¶
Migration versions use a sortable format: YYYYMMDDHHMMSS.
import { generateVersion } from 'jsr:@oneiriq/surql'
const version = generateVersion() // e.g. '20240101120000'
Rollback¶
import { RollbackManager } from 'jsr:@oneiriq/surql'
const manager = new RollbackManager(client, migrations)
// Rollback last N migrations
await manager.rollback(3)
// Rollback to checkpoint
await manager.rollbackTo('20240101000001')
Validation¶
Validate a set of migrations before applying them:
import { validateMigrations } from 'jsr:@oneiriq/surql'
const issues = validateMigrations(migrations)
if (issues.length > 0) {
console.error('Migration validation failed:', issues)
}
Next Steps¶
- Orchestration - Deploy migrations across multiple environments
- Versioning & Rollback - Advanced rollback strategies