Migrations API reference

Current emitted signatures and options for @db3.ai/app/db/migrations.

On this pageSource-backed Markdown

Imports and examples

Import supported APIs from @db3.ai/app/db/migrations. These signatures come from the staged package used by consumers. Relative filenames in declarations describe type dependencies; they are not extra supported deep imports.

Use the guide for setup, executable examples, failure handling and ownership. A signature is not proof that every deployment or provider has been exercised.

Migration manager

Migration manager
ts
import type { DatabaseCheckResult, DatabaseMigrationManagerOptions, DatabaseMigrationStatus, DatabaseSyncResult, MakeMigrationOptions, MakeMigrationResult, MigrateOptions, MigrateResult } from './contracts/index.js';
/**
 * Reusable application-configured model migration service.
 *
 * CLI commands, development HTTP actions, and deployment scripts should call
 * this service rather than duplicating model collection or Knex execution.
 */
export declare class DatabaseMigrationManager {
    #private;
    /**
     * Creates a migration manager with app-owned models, paths, and ledger name.
     *
     * @param options - Database connection, model registry, and absolute source paths.
     */
    constructor(options: DatabaseMigrationManagerOptions);
    /**
     * Returns model, snapshot, live database, and Knex migration status without
     * creating the Knex migration ledger.
     *
     * @returns Structured status suitable for CLI or development UI rendering.
     */
    status(): Promise<DatabaseMigrationStatus>;
    /**
     * Checks the live model-owned database subset against current models.
     *
     * Extra columns and tables are ignored to preserve additive blue/green
     * compatibility, while missing or incompatible requirements are reported.
     *
     * @returns Structured database compatibility result.
     */
    check(): Promise<DatabaseCheckResult>;
    /**
     * Generates a frozen migration and advances the committed snapshot when
     * current models contain only supported changes.
     *
     * @param options - Optional human-readable migration name.
     * @returns Generation result including blocked changes or written file path.
     */
    makeMigration(options?: MakeMigrationOptions): Promise<MakeMigrationResult>;
    /**
     * Applies pending committed migrations through Knex's ledger and lock.
     *
     * @param options - Optional matching-database baseline policy.
     * @returns Applied migration names, batch, and optional baselined filenames.
     */
    migrate(options?: MigrateOptions): Promise<MigrateResult>;
    /**
     * Runs the development convenience flow under one generation lock.
     *
     * A blocked model diff returns immediately without applying migrations. A
     * successful flow always finishes with a live database compatibility check.
     *
     * @param options - Optional human-readable generated migration name.
     * @returns Structured make, migrate, and check results.
     */
    sync(options?: MakeMigrationOptions): Promise<DatabaseSyncResult>;
}

Options and workflow results

Options and workflow results
ts
import type { Knex } from 'knex';
import type { ActiveRecordClass } from '../../ActiveRecord.js';
import type { DatabaseDialect } from '../../dialects/index.js';
import type { SchemaMigrationPlan } from './SchemaChange.js';
/**
 * Application-owned paths and runtime policy for database migration tooling.
 */
export interface DatabaseMigrationManagerOptions {
    /** Knex connection used for migration execution and database inspection. */
    db: Knex;
    /** Complete set of ActiveRecord models owned by the application. */
    models: readonly ActiveRecordClass[];
    /** Dialect used to collect field schema metadata. MariaDB is supported first. */
    dialect: DatabaseDialect;
    /** Absolute directory containing permanent Knex migration files. */
    migrationsDirectory: string;
    /** Absolute path of the committed desired-schema snapshot. */
    snapshotFile: string;
    /** Knex migration ledger table. Its lock table follows Knex naming. */
    migrationTableName?: string;
    /** Optional database schema containing the Knex migration ledger. */
    migrationSchemaName?: string;
    /** Migration file extensions Knex may load. */
    loadExtensions?: readonly string[];
    /** Current application environment. Source generation is refused in production. */
    environment?: string;
    /** Absolute cross-process lock path used while generating source files. */
    generationLockFile?: string;
    /** Injectable clock used for deterministic migration filenames in tests. */
    now?: () => Date;
}
/**
 * Persisted and pending Knex migration names without mutating the ledger.
 */
export interface DatabaseMigrationState {
    completed: string[];
    pending: string[];
    missingFiles: string[];
}
/**
 * Combined model, snapshot, database, and Knex status for CLI or development UI.
 */
export interface DatabaseMigrationStatus {
    snapshotExists: boolean;
    modelsMatchSnapshot: boolean;
    databaseMatchesModels: boolean;
    generationPlan: SchemaMigrationPlan;
    databasePlan: SchemaMigrationPlan;
    migrations: DatabaseMigrationState;
}
/**
 * Result returned after checking the live database against current models.
 */
export interface DatabaseCheckResult {
    /** Whether the live model-owned schema satisfies current models. */
    schemaMatches: boolean;
    /** Whether current models have a corresponding committed snapshot. */
    modelsMatchSnapshot: boolean;
    /** Overall readiness including snapshot and Knex migration state. */
    matches: boolean;
    /** Differences between the live model-owned schema and current models. */
    plan: SchemaMigrationPlan;
    /** Differences between the committed snapshot and current models. */
    snapshotPlan: SchemaMigrationPlan;
    /** Completed, pending, and corrupt Knex migration history. */
    migrations: DatabaseMigrationState;
}
/**
 * Options accepted when generating one permanent migration file.
 */
export interface MakeMigrationOptions {
    /** Human-readable migration name. A deterministic name is inferred when omitted. */
    name?: string;
    /**
     * When true, generate drop DDL for blocked column/index/foreign-key/table
     * removals after warning. Other blocked operations still refuse generation.
     */
    allowDestructive?: boolean;
}
/**
 * Result of comparing models with the committed snapshot and optionally writing
 * a new migration.
 */
export interface MakeMigrationResult {
    generated: boolean;
    blocked: boolean;
    file: string | null;
    plan: SchemaMigrationPlan;
}
/**
 * Options used when applying permanent Knex migrations.
 */
/**
 * Optional controls for applying committed migrations.
 */
export interface MigrateOptions {
    /**
     * Adopt all pending migrations without DDL when an existing untracked
     * database already matches the committed schema snapshot.
     */
    baselineIfMatching?: boolean;
}
/**
 * Result of applying pending Knex migrations.
 */
export interface MigrateResult {
    applied: string[];
    batch: number | null;
    baselined: string[] | null;
}
/**
 * Result of the development `make -> migrate -> check` convenience operation.
 */
export interface DatabaseSyncResult {
    make: MakeMigrationResult;
    migrate: MigrateResult | null;
    check: DatabaseCheckResult | null;
}

Schema change plans

Schema change plans
ts
import type { SchemaColumn, SchemaForeignKey, SchemaIndex, SchemaTable } from './SchemaSnapshot.js';
/**
 * Schema operation that the first migration generator can apply safely.
 */
export type SafeSchemaChange = {
    kind: 'create_table';
    table: SchemaTable;
    description: string;
} | {
    kind: 'add_column';
    tableName: string;
    column: SchemaColumn;
    description: string;
} | {
    kind: 'add_index';
    tableName: string;
    index: SchemaIndex;
    description: string;
} | {
    kind: 'add_foreign_key';
    tableName: string;
    foreignKey: SchemaForeignKey;
    description: string;
} | {
    kind: 'alter_column';
    tableName: string;
    column: SchemaColumn;
    alterType: boolean;
    alterNullable: boolean;
    alterComment: boolean;
    /** Whether the generated alteration changes or removes the database default. */
    alterDefault: boolean;
    description: string;
} | {
    kind: 'alter_table_comment';
    tableName: string;
    comment: string | null;
    description: string;
} | {
    kind: 'drop_column';
    tableName: string;
    columnName: string;
    description: string;
} | {
    kind: 'drop_index';
    tableName: string;
    indexName: string;
    description: string;
} | {
    kind: 'drop_foreign_key';
    tableName: string;
    foreignKeyName: string;
    description: string;
} | {
    kind: 'drop_table';
    tableName: string;
    description: string;
};
/**
 * Potentially destructive or ambiguous operation requiring a reviewed manual
 * migration before the snapshot can advance.
 */
export interface BlockedSchemaChange {
    kind: 'blocked_change';
    operation: 'add_required_column' | 'add_unique_column' | 'add_index_to_existing_columns' | 'add_foreign_key_to_existing_column' | 'remove_table' | 'remove_column' | 'remove_index' | 'remove_foreign_key' | 'alter_column_type' | 'tighten_column_nullability' | 'alter_column_primary' | 'alter_column_unique' | 'alter_index' | 'alter_foreign_key';
    tableName: string;
    columnName?: string;
    objectName?: string;
    description: string;
}
/**
 * Pure result of comparing a previous snapshot with a desired snapshot.
 */
export interface SchemaMigrationPlan {
    /** Stable hash of the previous schema snapshot. */
    fromHash: string;
    /** Stable hash of the desired schema snapshot. */
    toHash: string;
    /** Automatically renderable additive or widening changes. */
    safeChanges: SafeSchemaChange[];
    /** Changes that must stop automatic generation. */
    blockedChanges: BlockedSchemaChange[];
}

Schema snapshots

Schema snapshots
ts
import type { DatabaseDialectName } from '../../dialects/index.js';
/**
 * JSON-safe value that can be frozen into a schema snapshot and migration.
 */
export type SchemaValue = null | string | number | boolean | SchemaValue[] | {
    [key: string]: SchemaValue;
};
/**
 * Normalized database column owned by an ActiveRecord model.
 */
export interface SchemaColumn {
    /** Physical database column name. */
    name: string;
    /** Dialect-specific SQL column type. */
    type: string;
    /** Whether the database column accepts null values. */
    nullable: boolean;
    /** Whether the database column is the table primary key. */
    primary: boolean;
    /** Whether the database column has a single-column unique constraint. */
    unique: boolean;
    /** Static database default, when the model declares one. */
    default?: SchemaValue;
    /** Normalized database-native column comment. */
    comment: string | null;
}
/**
 * One ordered column in a normalized database index.
 */
export interface SchemaIndexColumn {
    /** Physical database column name. */
    name: string;
    /** Optional explicit index ordering. */
    order?: 'asc' | 'desc';
}
/**
 * Named database index owned by an ActiveRecord model.
 */
export interface SchemaIndex {
    /** Stable database index name. */
    name: string;
    /** Ordered columns included in the index. */
    columns: SchemaIndexColumn[];
    /** Whether values must be unique across the index columns. */
    unique: boolean;
    /** Database index implementation. */
    type: 'normal' | 'vector';
}
/**
 * Named foreign-key constraint owned by an ActiveRecord model.
 */
export interface SchemaForeignKey {
    /** Stable database constraint name. */
    name: string;
    /** Local physical database column. */
    column: string;
    /** Referenced physical database table. */
    referencesTable: string;
    /** Referenced physical database column. */
    referencesColumn: string;
    /** Optional action applied when a referenced row is deleted. */
    onDelete?: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'NO ACTION';
    /** Optional action applied when a referenced key changes. */
    onUpdate?: 'CASCADE' | 'RESTRICT' | 'SET NULL' | 'NO ACTION';
}
/**
 * Normalized database table owned by one ActiveRecord model.
 */
export interface SchemaTable {
    /** Physical database table name. */
    name: string;
    /** Normalized database-native table comment. */
    comment: string | null;
    /** Columns sorted by physical name for deterministic serialization. */
    columns: SchemaColumn[];
    /** Indexes sorted by stable database name. */
    indexes: SchemaIndex[];
    /** Foreign keys sorted by stable database name. */
    foreignKeys: SchemaForeignKey[];
}
/**
 * Serializable desired database state collected from ActiveRecord models.
 *
 * Snapshots deliberately contain no model imports or executable values so an
 * old migration remains reproducible after application models change.
 */
export interface SchemaSnapshot {
    /** Snapshot format used to support future schema-tool upgrades. */
    formatVersion: 1;
    /** Database dialect used to resolve model field types. */
    dialect: DatabaseDialectName;
    /** Model-owned tables sorted by physical database name. */
    tables: SchemaTable[];
}

Migration errors

Migration errors
ts
import type { SchemaMigrationPlan } from './contracts/index.js';
/**
 * Error raised when another process already owns the source-generation lock.
 */
export declare class DatabaseMigrationLockError extends Error {
    readonly lockFile: string;
    /**
     * Creates a generation-lock contention error.
     *
     * @param lockFile - Absolute lock file currently owned by another process.
     */
    constructor(lockFile: string);
}
/**
 * Error raised when an existing untracked database cannot safely adopt the
 * sole initial migration without executing its DDL.
 */
export declare class DatabaseMigrationBaselineError extends Error {
    readonly plan: SchemaMigrationPlan;
    /**
     * Creates a baseline mismatch error with its structured schema differences.
     *
     * @param plan - Differences between the existing database and initial snapshot.
     */
    constructor(plan: SchemaMigrationPlan);
}
/**
 * Error raised when a source-writing operation is attempted in production.
 */
export declare class DatabaseMigrationSourceGenerationError extends Error {
    /**
     * Creates a production source-generation policy error.
     */
    constructor();
}

Collect model schema

Collect model schema
ts
import type { ActiveRecordClass } from '../ActiveRecord.js';
import type { DatabaseDialect } from '../dialects/index.js';
import type { SchemaSnapshot, SchemaValue } from './contracts/index.js';
/**
 * Collects a deterministic serializable schema snapshot from ActiveRecord
 * model metadata.
 *
 * @param models - Complete model registry owned by the application.
 * @param dialect - Database dialect used by fields to resolve physical types.
 * @returns Normalized desired database state sorted by physical names.
 */
export declare function collectModelSchema(models: readonly ActiveRecordClass[], dialect: DatabaseDialect): SchemaSnapshot;
/**
 * Canonicalizes dialect type strings so snapshots do not change because of
 * harmless whitespace, case, or MariaDB integer display widths.
 *
 * @param input - Dialect-provided or database-inspected SQL type.
 * @returns Stable lower-case SQL type.
 */
export declare function normalizeSchemaColumnType(input: string): string;
/**
 * Converts a static field default to the JSON-safe representation permitted in
 * committed snapshots and generated migration source.
 *
 * @param input - Static database default produced by a field.
 * @param path - Human-readable location used in validation errors.
 * @returns Deterministically ordered JSON-safe value.
 */
export declare function normalizeSchemaValue(input: unknown, path: string): SchemaValue;

Inspect live schema

Inspect live schema
ts
import type { Knex } from 'knex';
import type { DatabaseDialect } from '../dialects/index.js';
import type { SchemaSnapshot } from './contracts/index.js';
/**
 * Reads the model-owned subset of a live MariaDB database into the same
 * normalized representation used by model snapshots.
 *
 * Extra database objects are intentionally ignored. This lets an older
 * blue/green application release accept additive objects introduced by a newer
 * release while still detecting missing or incompatible requirements. Database
 * comments are treated as non-runtime metadata: committed snapshots retain
 * them, while compatibility checks ignore live comment drift.
 *
 * @param db - Knex connection used for information-schema reads.
 * @param desired - Current model snapshot defining objects that must be checked.
 * @param dialect - MariaDB dialect metadata and index inspection functions.
 * @returns Live model-owned database state.
 */
export declare function inspectDatabaseSchema(db: Knex, desired: SchemaSnapshot, dialect: DatabaseDialect): Promise<SchemaSnapshot>;

Compare snapshots

Compare snapshots
ts
import type { SchemaMigrationPlan, SchemaSnapshot } from './contracts/index.js';
/**
 * Computes a pure deterministic migration plan between two normalized schema
 * snapshots.
 *
 * The automatic policy is intentionally conservative. Any blocked change
 * prevents the manager from emitting a partially correct migration.
 *
 * @param from - Previously committed or currently installed model-owned state.
 * @param to - New desired model-owned state.
 * @returns Safe renderable changes and blocked reviewed changes.
 */
export declare function diffSchemaSnapshots(from: SchemaSnapshot, to: SchemaSnapshot): SchemaMigrationPlan;

Render frozen migrations

Render frozen migrations
ts
import type { SchemaMigrationPlan } from './contracts/index.js';
/**
 * Renders a frozen TypeScript Knex migration from a safe schema plan.
 *
 * Generated source contains literal table, column, index, and foreign-key
 * operations. It never imports current models or field implementations.
 *
 * @param plan - Pure schema plan with no blocked changes.
 * @returns Deterministic TypeScript migration source.
 */
export declare function renderKnexMigration(plan: SchemaMigrationPlan): string;

Serialize snapshots

Serialize snapshots
ts
import type { DatabaseDialectName } from '../dialects/index.js';
import type { SchemaSnapshot } from './contracts/index.js';
/**
 * Creates an empty normalized snapshot for an application with no models.
 *
 * @param dialect - Database dialect represented by the snapshot.
 * @returns Empty schema snapshot suitable as the first diff baseline.
 */
export declare function emptySchemaSnapshot(dialect: DatabaseDialectName): SchemaSnapshot;
/**
 * Serializes a normalized snapshot in the committed human-readable format.
 *
 * @param snapshot - Normalized schema snapshot.
 * @returns Deterministic JSON document ending with one newline.
 */
export declare function serializeSchemaSnapshot(snapshot: SchemaSnapshot): string;
/**
 * Parses and minimally validates a committed schema snapshot.
 *
 * @param input - JSON text read from the application snapshot file.
 * @returns Parsed version-one schema snapshot.
 */
export declare function parseSchemaSnapshot(input: string): SchemaSnapshot;
/**
 * Produces a stable content hash for migration lineage and comparisons.
 *
 * @param snapshot - Normalized schema snapshot.
 * @returns Lower-case SHA-256 digest.
 */
export declare function hashSchemaSnapshot(snapshot: SchemaSnapshot): string;

Schema naming

Schema naming
ts
import type { SchemaIndexColumn } from './contracts/index.js';
/**
 * Builds the stable name used for a model-owned database index.
 *
 * @param tableName - Physical database table name.
 * @param columns - Ordered columns included in the index.
 * @param unique - Whether the index enforces uniqueness.
 * @param type - Normal or vector database index type.
 * @returns MariaDB-safe deterministic index name.
 */
export declare function defaultSchemaIndexName(tableName: string, columns: readonly SchemaIndexColumn[], unique: boolean, type: 'normal' | 'vector'): string;
/**
 * Builds the stable name used for a model-owned foreign-key constraint.
 *
 * @param tableName - Physical database table name.
 * @param columnName - Local physical database column.
 * @returns MariaDB-safe deterministic foreign-key name.
 */
export declare function defaultSchemaForeignKeyName(tableName: string, columnName: string): string;
/**
 * Truncates an identifier with a stable hash while respecting MariaDB's
 * 64-character identifier limit.
 *
 * @param identifier - Preferred human-readable identifier.
 * @returns Original or deterministically shortened identifier.
 */
export declare function fitSchemaIdentifier(identifier: string): string;

Explicit destructive promotion

Explicit destructive promotion
ts
import type { SchemaMigrationPlan } from './contracts/index.js';
/**
 * Promotes reviewed destructive removals into safe renderable changes.
 *
 * Non-destructive blocked operations (type changes, required-column adds, and
 * similar) remain blocked so accidental data-loss still requires a review.
 *
 * @param plan - Diff plan that may contain blocked removals.
 * @returns Plan with promoted drop operations, or the original plan when nothing
 *   could be promoted / remaining blocked changes still exist.
 */
export declare function promoteDestructiveSchemaChanges(plan: SchemaMigrationPlan): SchemaMigrationPlan;
/**
 * Reports whether a plan still contains only promotable destructive removals.
 *
 * @param plan - Diff plan before promotion.
 * @returns True when every blocked change can be turned into a drop.
 */
export declare function planHasOnlyPromotableDestructiveChanges(plan: SchemaMigrationPlan): boolean;