@momentumcms/migrations 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "@momentumcms/migrations",
3
+ "version": "0.3.0",
4
+ "description": "Database migration system for Momentum CMS",
5
+ "license": "MIT",
6
+ "main": "./index.cjs",
7
+ "types": "./src/index.d.ts",
8
+ "peerDependencies": {
9
+ "@momentumcms/core": ">=0.0.1",
10
+ "pg": "^8.0.0"
11
+ },
12
+ "module": "./index.js"
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import type { ResolvedMomentumConfig, DatabaseAdapter } from '@momentumcms/core';
2
+ import type { DatabaseDialect } from '../lib/schema/column-type-map';
3
+ import type { TrackerQueryFn } from '../lib/tracking/migration-tracker';
4
+ import type { MigrationContext } from '../lib/migration.types';
5
+ import type { PushRunnerDb } from '../lib/runner/push-runner';
6
+ import type { CloneCapableDb } from '../lib/runner/clone-test-apply';
7
+ import type { DatabaseSchemaSnapshot } from '../lib/schema/schema-snapshot';
8
+ /**
9
+ * Load a MomentumConfig from a file path using dynamic import.
10
+ */
11
+ export declare function loadMomentumConfig(configPath: string): Promise<ResolvedMomentumConfig>;
12
+ /**
13
+ * Resolve the database dialect from an adapter.
14
+ * Throws if the adapter doesn't declare its dialect.
15
+ */
16
+ export declare function resolveDialect(adapter: DatabaseAdapter): DatabaseDialect;
17
+ /**
18
+ * Bridge a DatabaseAdapter to TrackerQueryFn.
19
+ */
20
+ export declare function buildTrackerFromAdapter(adapter: DatabaseAdapter): TrackerQueryFn;
21
+ /**
22
+ * Bridge a DatabaseAdapter to MigrationContext.
23
+ */
24
+ export declare function buildContextFromAdapter(adapter: DatabaseAdapter, dialect: DatabaseDialect): MigrationContext;
25
+ /**
26
+ * Bridge a DatabaseAdapter to PushRunnerDb.
27
+ */
28
+ export declare function buildPushDbFromAdapter(adapter: DatabaseAdapter): PushRunnerDb;
29
+ /**
30
+ * Bridge a DatabaseAdapter to CloneCapableDb.
31
+ */
32
+ export declare function buildCloneDbFromAdapter(adapter: DatabaseAdapter): CloneCapableDb;
33
+ /**
34
+ * Build an introspection function from a DatabaseAdapter.
35
+ */
36
+ export declare function buildIntrospector(adapter: DatabaseAdapter, dialect: DatabaseDialect): () => Promise<DatabaseSchemaSnapshot>;
37
+ /**
38
+ * Parsed CLI arguments for migration commands.
39
+ */
40
+ export interface MigrationCliArgs {
41
+ /** Path to momentum.config.ts */
42
+ configPath: string;
43
+ /** Migration name (for generate) */
44
+ name?: string;
45
+ /** Dry run — show changes without writing files */
46
+ dryRun?: boolean;
47
+ /** Test only — run clone test but don't apply to real DB */
48
+ testOnly?: boolean;
49
+ /** Skip clone test safety pipeline */
50
+ skipCloneTest?: boolean;
51
+ }
52
+ /**
53
+ * Parse CLI arguments for migration commands.
54
+ *
55
+ * Usage: npx tsx <command>.ts <configPath> [--name <name>] [--dry-run] [--test-only] [--skip-clone-test]
56
+ */
57
+ export declare function parseMigrationArgs(args: string[]): MigrationCliArgs;
@@ -0,0 +1 @@
1
+ export {};
package/src/index.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @momentumcms/migrations
3
+ *
4
+ * Database migration system for Momentum CMS.
5
+ * Provides schema introspection, diffing, generation, and execution.
6
+ */
7
+ export * from './lib/schema/schema-snapshot';
8
+ export * from './lib/schema/column-type-map';
9
+ export { introspectPostgres } from './lib/schema/introspect-postgres';
10
+ export type { QueryFunction } from './lib/schema/introspect-postgres';
11
+ export { introspectSqlite } from './lib/schema/introspect-sqlite';
12
+ export type { SqliteQueryFunction } from './lib/schema/introspect-sqlite';
13
+ export { collectionToTableSnapshot, collectionsToSchema } from './lib/schema/collections-to-schema';
14
+ export { diffSchemas } from './lib/schema/schema-diff';
15
+ export type { SchemaDiffOptions, SchemaDiffResult } from './lib/schema/schema-diff';
16
+ export * from './lib/operations/operation.types';
17
+ export { operationToSql, operationToReverseSql, operationsToUpSql, operationsToDownSql, } from './lib/generator/sql-generator';
18
+ export { generateMigrationName, generateMigrationFileContent, } from './lib/generator/migration-file-generator';
19
+ export type { GenerateMigrationOptions } from './lib/generator/migration-file-generator';
20
+ export { ensureTrackingTable, getAppliedMigrations, getNextBatchNumber, recordMigration, removeMigrationRecord, getMigrationsByBatch, getLatestBatchNumber, isMigrationApplied, } from './lib/tracking/migration-tracker';
21
+ export type { TrackerQueryFn } from './lib/tracking/migration-tracker';
22
+ export { detectDangers } from './lib/danger/danger-detector';
23
+ export type { DangerSeverity, DangerWarning, DangerDetectionResult, } from './lib/danger/danger-detector';
24
+ export { runPush } from './lib/runner/push-runner';
25
+ export type { PushRunnerDb, PushRunnerOptions, PushResult } from './lib/runner/push-runner';
26
+ export { runMigrations, rollbackBatch, getMigrationStatus } from './lib/runner/migrate-runner';
27
+ export type { LoadedMigration, MigrationRunResult, MigrateResult, MigrateRunnerOptions, MigrationStatusEntry, } from './lib/runner/migrate-runner';
28
+ export { cloneTestApply } from './lib/runner/clone-test-apply';
29
+ export type { CloneCapableDb, CloneTestApplyOptions, CloneTestApplyResult, } from './lib/runner/clone-test-apply';
30
+ export { createDataHelpers } from './lib/helpers/data-helpers';
31
+ export type { DataHelperDb } from './lib/helpers/data-helpers';
32
+ export { loadMigrationsFromDisk } from './lib/loader/migration-loader';
33
+ export { readSnapshot, writeSnapshot, getSnapshotPath } from './lib/loader/snapshot-manager';
34
+ export { resolveDialect, buildTrackerFromAdapter, buildContextFromAdapter, buildPushDbFromAdapter, buildCloneDbFromAdapter, buildIntrospector, parseMigrationArgs, } from './cli/shared';
35
+ export type { MigrationCliArgs } from './cli/shared';
36
+ export * from './lib/migration.types';
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Dangerous Operation Detection
3
+ *
4
+ * Inspired by Rails' strong_migrations, analyzes migration operations
5
+ * for patterns that could cause data loss, downtime, or failures.
6
+ *
7
+ * Each danger has a severity, a human-readable message, and a suggested fix.
8
+ */
9
+ import type { MigrationOperation } from '../operations/operation.types';
10
+ import type { DatabaseDialect } from '../schema/column-type-map';
11
+ /**
12
+ * Severity levels for dangerous operations.
13
+ */
14
+ export type DangerSeverity = 'error' | 'warning' | 'info';
15
+ /**
16
+ * A detected dangerous operation.
17
+ */
18
+ export interface DangerWarning {
19
+ /** Severity of the issue */
20
+ severity: DangerSeverity;
21
+ /** Which operation triggered this warning */
22
+ operation: MigrationOperation;
23
+ /** The index of the operation in the operations array */
24
+ operationIndex: number;
25
+ /** Human-readable description of the danger */
26
+ message: string;
27
+ /** Suggested alternative or fix */
28
+ suggestion: string;
29
+ }
30
+ /**
31
+ * Result of danger detection.
32
+ */
33
+ export interface DangerDetectionResult {
34
+ /** All detected warnings, ordered by severity (errors first) */
35
+ warnings: DangerWarning[];
36
+ /** Whether any errors were found (should block migration) */
37
+ hasErrors: boolean;
38
+ /** Whether any warnings were found */
39
+ hasWarnings: boolean;
40
+ }
41
+ /**
42
+ * Analyze migration operations for dangerous patterns.
43
+ */
44
+ export declare function detectDangers(operations: MigrationOperation[], dialect: DatabaseDialect): DangerDetectionResult;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Migration File Generator
3
+ *
4
+ * Produces TypeScript migration file content from a SchemaDiffResult.
5
+ * These files implement the MigrationFile interface (meta, up, down).
6
+ */
7
+ import type { SchemaDiffResult } from '../schema/schema-diff';
8
+ import type { DatabaseDialect } from '../schema/column-type-map';
9
+ /**
10
+ * Options for generating a migration file.
11
+ */
12
+ export interface GenerateMigrationOptions {
13
+ /** Migration name (used as filename and in meta) */
14
+ name: string;
15
+ /** Human-readable description */
16
+ description?: string;
17
+ /** Database dialect for SQL generation */
18
+ dialect: DatabaseDialect;
19
+ }
20
+ /**
21
+ * Generate a timestamp-prefixed migration name.
22
+ * Format: YYYYMMDDHHMMSS_name
23
+ */
24
+ export declare function generateMigrationName(name: string, timestamp?: Date): string;
25
+ /**
26
+ * Generate the TypeScript content for a migration file.
27
+ */
28
+ export declare function generateMigrationFileContent(diff: SchemaDiffResult, options: GenerateMigrationOptions): string;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * SQL Generator
3
+ *
4
+ * Converts MigrationOperations into raw SQL strings for a given dialect.
5
+ * Used by both the migration file generator and the push-mode runner.
6
+ */
7
+ import type { MigrationOperation } from '../operations/operation.types';
8
+ import type { DatabaseDialect } from '../schema/column-type-map';
9
+ /**
10
+ * Generate SQL for a single migration operation.
11
+ */
12
+ export declare function operationToSql(op: MigrationOperation, dialect: DatabaseDialect): string;
13
+ /**
14
+ * Generate SQL for the reverse (down) of an operation.
15
+ */
16
+ export declare function operationToReverseSql(op: MigrationOperation, dialect: DatabaseDialect): string | null;
17
+ /**
18
+ * Generate all up SQL statements for a set of operations.
19
+ */
20
+ export declare function operationsToUpSql(operations: MigrationOperation[], dialect: DatabaseDialect): string[];
21
+ /**
22
+ * Generate all down SQL statements for a set of operations (in reverse order).
23
+ */
24
+ export declare function operationsToDownSql(operations: MigrationOperation[], dialect: DatabaseDialect): string[];
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Data Migration Helpers
3
+ *
4
+ * Provides batched, safe data transformation operations for use
5
+ * within migration up/down functions via MigrationContext.data.
6
+ */
7
+ import type { DataMigrationHelpers } from '../migration.types';
8
+ import type { DatabaseDialect } from '../schema/column-type-map';
9
+ /**
10
+ * Database interface needed by data helpers.
11
+ */
12
+ export interface DataHelperDb {
13
+ execute(sql: string, params?: unknown[]): Promise<number>;
14
+ query<T extends Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
15
+ }
16
+ /**
17
+ * Create a DataMigrationHelpers instance bound to a database.
18
+ */
19
+ export declare function createDataHelpers(db: DataHelperDb, dialect: DatabaseDialect): DataMigrationHelpers;
@@ -0,0 +1,11 @@
1
+ import type { LoadedMigration } from '../runner/migrate-runner';
2
+ /**
3
+ * Load all migration files from a directory.
4
+ *
5
+ * Scans for `.ts` files matching the YYYYMMDDHHMMSS_name.ts pattern,
6
+ * dynamically imports each one, validates the exports, and returns
7
+ * them sorted by filename (timestamp prefix ensures correct order).
8
+ *
9
+ * @returns Sorted array of loaded migrations (empty if directory is missing/empty)
10
+ */
11
+ export declare function loadMigrationsFromDisk(directory: string): Promise<LoadedMigration[]>;
@@ -0,0 +1,15 @@
1
+ import type { DatabaseSchemaSnapshot } from '../schema/schema-snapshot';
2
+ /**
3
+ * Read the schema snapshot from the migrations directory.
4
+ * Returns null if no snapshot file exists.
5
+ */
6
+ export declare function readSnapshot(directory: string): DatabaseSchemaSnapshot | null;
7
+ /**
8
+ * Write a schema snapshot to the migrations directory.
9
+ * Creates the directory if it doesn't exist.
10
+ */
11
+ export declare function writeSnapshot(directory: string, snapshot: DatabaseSchemaSnapshot): void;
12
+ /**
13
+ * Get the full path to the snapshot file.
14
+ */
15
+ export declare function getSnapshotPath(directory: string): string;
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Migration System Core Types
3
+ *
4
+ * Defines the migration file interface, context, and tracking types.
5
+ */
6
+ import type { DatabaseDialect } from './schema/column-type-map';
7
+ /**
8
+ * Helpers for data transformations within migrations.
9
+ */
10
+ export interface DataMigrationHelpers {
11
+ /**
12
+ * Backfill a column with a static value.
13
+ * Uses batched updates to avoid long-running transactions.
14
+ */
15
+ backfill(table: string, column: string, value: unknown, options?: {
16
+ where?: string;
17
+ batchSize?: number;
18
+ }): Promise<number>;
19
+ /**
20
+ * Transform values in a column using a SQL expression.
21
+ * @example transform('posts', 'slug', "LOWER(REPLACE(title, ' ', '-'))")
22
+ */
23
+ transform(table: string, column: string, sqlExpression: string, options?: {
24
+ where?: string;
25
+ batchSize?: number;
26
+ }): Promise<number>;
27
+ /**
28
+ * Safe column rename: add new column, copy data, drop old column.
29
+ * Safer than ALTER TABLE RENAME COLUMN for production.
30
+ */
31
+ renameColumn(table: string, from: string, to: string, columnType: string): Promise<void>;
32
+ /**
33
+ * Split a column into multiple columns via SQL expressions.
34
+ */
35
+ splitColumn(table: string, sourceColumn: string, targets: Array<{
36
+ name: string;
37
+ type: string;
38
+ expression: string;
39
+ }>): Promise<void>;
40
+ /**
41
+ * Merge multiple columns into one.
42
+ */
43
+ mergeColumns(table: string, sourceColumns: string[], targetColumn: string, targetType: string, mergeExpression: string): Promise<void>;
44
+ /**
45
+ * Copy data between tables with optional transformation.
46
+ */
47
+ copyData(sourceTable: string, targetTable: string, columnMapping: Record<string, string | {
48
+ expression: string;
49
+ }>, options?: {
50
+ where?: string;
51
+ batchSize?: number;
52
+ }): Promise<number>;
53
+ /**
54
+ * Move a flat column's data into a JSONB field.
55
+ */
56
+ columnToJson(table: string, sourceColumn: string, jsonColumn: string, jsonKey: string): Promise<void>;
57
+ /**
58
+ * Extract a key from a JSONB column into a new flat column.
59
+ */
60
+ jsonToColumn(table: string, jsonColumn: string, jsonKey: string, targetColumn: string, targetType: string): Promise<void>;
61
+ /**
62
+ * Deduplicate rows before adding a unique constraint.
63
+ * Keeps the row based on the chosen strategy.
64
+ * @returns Number of rows deleted
65
+ */
66
+ dedup(table: string, columns: string[], keepStrategy?: 'latest' | 'earliest' | 'first'): Promise<number>;
67
+ }
68
+ /**
69
+ * Context passed to migration up/down functions.
70
+ */
71
+ export interface MigrationContext {
72
+ /** Execute raw SQL (DDL or DML) */
73
+ sql(query: string, params?: unknown[]): Promise<void>;
74
+ /** Query raw SQL and return rows */
75
+ query<T extends Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
76
+ /** Data migration helpers */
77
+ data: DataMigrationHelpers;
78
+ /** Current database dialect */
79
+ dialect: DatabaseDialect;
80
+ /** Logger */
81
+ log: {
82
+ info(message: string): void;
83
+ warn(message: string): void;
84
+ };
85
+ }
86
+ /**
87
+ * Metadata for a migration file.
88
+ */
89
+ export interface MigrationMeta {
90
+ /** Migration name (filename without extension) */
91
+ name: string;
92
+ /** Human-readable description */
93
+ description: string;
94
+ /** Operations this migration will apply (for danger detection) */
95
+ operations?: ReadonlyArray<{
96
+ type: string;
97
+ [key: string]: unknown;
98
+ }>;
99
+ }
100
+ /**
101
+ * A migration file's exports.
102
+ */
103
+ export interface MigrationFile {
104
+ /** Migration metadata */
105
+ meta: MigrationMeta;
106
+ /** Apply the migration */
107
+ up(ctx: MigrationContext): Promise<void>;
108
+ /** Revert the migration */
109
+ down(ctx: MigrationContext): Promise<void>;
110
+ }
111
+ /**
112
+ * Internal tracking record for an applied migration.
113
+ * Stored in the _momentum_migrations table.
114
+ */
115
+ export interface MigrationTrackingRecord {
116
+ /** Auto-generated UUID primary key */
117
+ id: string;
118
+ /** Migration name (matches filename without extension) */
119
+ name: string;
120
+ /** Batch number (migrations applied together share a batch) */
121
+ batch: number;
122
+ /** SHA-256 checksum of the migration file content */
123
+ checksum: string;
124
+ /** When the migration was applied (ISO string) */
125
+ appliedAt: string;
126
+ /** Execution time in milliseconds */
127
+ executionMs: number;
128
+ }
129
+ /**
130
+ * Slug for the internal migration tracking table.
131
+ */
132
+ export declare const MIGRATION_TRACKING_TABLE = "_momentum_migrations";
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Migration Operation Types
3
+ *
4
+ * Represents all possible schema change operations.
5
+ * Generated by the diff engine, consumed by migration file generator and runner.
6
+ */
7
+ export interface CreateTableOperation {
8
+ readonly type: 'createTable';
9
+ readonly table: string;
10
+ readonly columns: ReadonlyArray<{
11
+ name: string;
12
+ type: string;
13
+ nullable: boolean;
14
+ defaultValue?: string;
15
+ primaryKey?: boolean;
16
+ }>;
17
+ }
18
+ export interface DropTableOperation {
19
+ readonly type: 'dropTable';
20
+ readonly table: string;
21
+ }
22
+ export interface RenameTableOperation {
23
+ readonly type: 'renameTable';
24
+ readonly from: string;
25
+ readonly to: string;
26
+ }
27
+ export interface AddColumnOperation {
28
+ readonly type: 'addColumn';
29
+ readonly table: string;
30
+ readonly column: string;
31
+ readonly columnType: string;
32
+ readonly nullable: boolean;
33
+ readonly defaultValue?: string;
34
+ }
35
+ export interface DropColumnOperation {
36
+ readonly type: 'dropColumn';
37
+ readonly table: string;
38
+ readonly column: string;
39
+ /** Previous type, for generating down() */
40
+ readonly previousType?: string;
41
+ readonly previousNullable?: boolean;
42
+ }
43
+ export interface AlterColumnTypeOperation {
44
+ readonly type: 'alterColumnType';
45
+ readonly table: string;
46
+ readonly column: string;
47
+ readonly fromType: string;
48
+ readonly toType: string;
49
+ /** Optional USING clause for PostgreSQL type casts */
50
+ readonly castExpression?: string;
51
+ }
52
+ export interface AlterColumnNullableOperation {
53
+ readonly type: 'alterColumnNullable';
54
+ readonly table: string;
55
+ readonly column: string;
56
+ readonly nullable: boolean;
57
+ }
58
+ export interface AlterColumnDefaultOperation {
59
+ readonly type: 'alterColumnDefault';
60
+ readonly table: string;
61
+ readonly column: string;
62
+ readonly defaultValue: string | null;
63
+ readonly previousDefault: string | null;
64
+ }
65
+ export interface RenameColumnOperation {
66
+ readonly type: 'renameColumn';
67
+ readonly table: string;
68
+ readonly from: string;
69
+ readonly to: string;
70
+ }
71
+ export interface AddForeignKeyOperation {
72
+ readonly type: 'addForeignKey';
73
+ readonly table: string;
74
+ readonly constraintName: string;
75
+ readonly column: string;
76
+ readonly referencedTable: string;
77
+ readonly referencedColumn: string;
78
+ readonly onDelete: string;
79
+ }
80
+ export interface DropForeignKeyOperation {
81
+ readonly type: 'dropForeignKey';
82
+ readonly table: string;
83
+ readonly constraintName: string;
84
+ }
85
+ export interface CreateIndexOperation {
86
+ readonly type: 'createIndex';
87
+ readonly table: string;
88
+ readonly indexName: string;
89
+ readonly columns: readonly string[];
90
+ readonly unique: boolean;
91
+ }
92
+ export interface DropIndexOperation {
93
+ readonly type: 'dropIndex';
94
+ readonly table: string;
95
+ readonly indexName: string;
96
+ }
97
+ export interface RawSqlOperation {
98
+ readonly type: 'rawSql';
99
+ readonly upSql: string;
100
+ readonly downSql: string;
101
+ readonly description: string;
102
+ }
103
+ /**
104
+ * All possible migration operations.
105
+ */
106
+ export type MigrationOperation = CreateTableOperation | DropTableOperation | RenameTableOperation | AddColumnOperation | DropColumnOperation | AlterColumnTypeOperation | AlterColumnNullableOperation | AlterColumnDefaultOperation | RenameColumnOperation | AddForeignKeyOperation | DropForeignKeyOperation | CreateIndexOperation | DropIndexOperation | RawSqlOperation;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Clone-Test-Apply Pipeline
3
+ *
4
+ * The crown jewel of the migration system. This pipeline:
5
+ * 1. Clones the database
6
+ * 2. Runs migrations on the clone
7
+ * 3. Detects errors and generates fix suggestions
8
+ * 4. If clone succeeds, applies to real database
9
+ * 5. Cleans up the clone
10
+ *
11
+ * This ensures migrations are safe before touching production data.
12
+ */
13
+ import type { MigrationContext } from '../migration.types';
14
+ import type { DatabaseDialect } from '../schema/column-type-map';
15
+ import type { TrackerQueryFn } from '../tracking/migration-tracker';
16
+ import type { LoadedMigration, MigrateResult } from './migrate-runner';
17
+ import type { DangerDetectionResult } from '../danger/danger-detector';
18
+ /**
19
+ * Database interface needed for clone operations.
20
+ */
21
+ export interface CloneCapableDb {
22
+ /** Clone the database to a new instance */
23
+ cloneDatabase(targetName: string): Promise<string>;
24
+ /** Drop a cloned database */
25
+ dropClone(targetName: string): Promise<void>;
26
+ }
27
+ /**
28
+ * Options for the clone-test-apply pipeline.
29
+ */
30
+ export interface CloneTestApplyOptions {
31
+ /** All loaded migrations, in order */
32
+ migrations: LoadedMigration[];
33
+ /** Database dialect */
34
+ dialect: DatabaseDialect;
35
+ /** Tracker for the real database */
36
+ tracker: TrackerQueryFn;
37
+ /** Build a MigrationContext for the real database */
38
+ buildContext: () => MigrationContext;
39
+ /** Clone-capable database interface */
40
+ db: CloneCapableDb;
41
+ /** Build a TrackerQueryFn for the cloned database */
42
+ buildCloneTracker: (cloneName: string) => TrackerQueryFn;
43
+ /** Build a MigrationContext for the cloned database */
44
+ buildCloneContext: (cloneName: string) => MigrationContext;
45
+ /** If true, skip applying to real DB after clone test */
46
+ testOnly?: boolean;
47
+ /** If true, skip danger detection */
48
+ skipDangerDetection?: boolean;
49
+ /** Logger */
50
+ log?: {
51
+ info(msg: string): void;
52
+ warn(msg: string): void;
53
+ };
54
+ }
55
+ /**
56
+ * Result of the clone-test-apply pipeline.
57
+ */
58
+ export interface CloneTestApplyResult {
59
+ /** Phase that was reached */
60
+ phase: 'clone' | 'test' | 'apply' | 'complete' | 'skipped';
61
+ /** Result from running migrations on the clone */
62
+ cloneResult: MigrateResult | null;
63
+ /** Result from running migrations on the real database */
64
+ applyResult: MigrateResult | null;
65
+ /** Danger detection result */
66
+ dangers: DangerDetectionResult | null;
67
+ /** Whether the clone was cleaned up */
68
+ cloneCleanedUp: boolean;
69
+ /** Name of the clone database (for debugging) */
70
+ cloneName: string;
71
+ /** Error that caused the pipeline to stop */
72
+ error?: string;
73
+ /** Suggested fixes if the clone test failed */
74
+ suggestions: string[];
75
+ }
76
+ /**
77
+ * Run the clone-test-apply pipeline.
78
+ */
79
+ export declare function cloneTestApply(options: CloneTestApplyOptions): Promise<CloneTestApplyResult>;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Migrate Mode Runner
3
+ *
4
+ * Runs migration files in order, tracking which have been applied.
5
+ * Supports forward migration, rollback by batch, and status checking.
6
+ */
7
+ import type { MigrationFile, MigrationContext } from '../migration.types';
8
+ import type { DatabaseDialect } from '../schema/column-type-map';
9
+ import type { TrackerQueryFn } from '../tracking/migration-tracker';
10
+ import type { DangerDetectionResult } from '../danger/danger-detector';
11
+ /**
12
+ * A loaded migration with its file content.
13
+ */
14
+ export interface LoadedMigration {
15
+ /** Migration name (filename without extension) */
16
+ name: string;
17
+ /** The migration file exports */
18
+ file: MigrationFile;
19
+ }
20
+ /**
21
+ * Result of running a single migration.
22
+ */
23
+ export interface MigrationRunResult {
24
+ name: string;
25
+ success: boolean;
26
+ executionMs: number;
27
+ error?: string;
28
+ /** SQLSTATE error code from the database driver (e.g., '23505' for unique_violation) */
29
+ errorCode?: string;
30
+ }
31
+ /**
32
+ * Result of running all pending migrations.
33
+ */
34
+ export interface MigrateResult {
35
+ /** Batch number assigned to these migrations */
36
+ batch: number;
37
+ /** Results for each migration that was run */
38
+ results: MigrationRunResult[];
39
+ /** Number of successful migrations */
40
+ successCount: number;
41
+ /** Number of failed migrations */
42
+ failCount: number;
43
+ /** Danger detection result (null if skipped) */
44
+ dangers: DangerDetectionResult | null;
45
+ }
46
+ /**
47
+ * Options for the migrate runner.
48
+ */
49
+ export interface MigrateRunnerOptions {
50
+ /** All loaded migrations, in order */
51
+ migrations: LoadedMigration[];
52
+ /** Database dialect */
53
+ dialect: DatabaseDialect;
54
+ /** Tracker DB interface */
55
+ tracker: TrackerQueryFn;
56
+ /** Build a MigrationContext for executing migrations */
57
+ buildContext: () => MigrationContext;
58
+ /** If true, skip danger detection */
59
+ skipDangerDetection?: boolean;
60
+ /** Logger */
61
+ log?: {
62
+ info(msg: string): void;
63
+ warn(msg: string): void;
64
+ };
65
+ }
66
+ /**
67
+ * Run all pending migrations forward.
68
+ */
69
+ export declare function runMigrations(options: MigrateRunnerOptions): Promise<MigrateResult>;
70
+ /**
71
+ * Rollback the latest batch of migrations.
72
+ */
73
+ export declare function rollbackBatch(options: MigrateRunnerOptions): Promise<MigrateResult>;
74
+ /**
75
+ * Get migration status: which are applied, which are pending.
76
+ */
77
+ export interface MigrationStatusEntry {
78
+ name: string;
79
+ status: 'applied' | 'pending';
80
+ batch?: number;
81
+ appliedAt?: string;
82
+ }
83
+ export declare function getMigrationStatus(migrations: LoadedMigration[], tracker: TrackerQueryFn, dialect: DatabaseDialect): Promise<MigrationStatusEntry[]>;