@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/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/index.cjs +2515 -0
- package/index.js +2449 -0
- package/package.json +13 -0
- package/src/cli/generate.d.ts +1 -0
- package/src/cli/rollback.d.ts +1 -0
- package/src/cli/run.d.ts +1 -0
- package/src/cli/shared.d.ts +57 -0
- package/src/cli/status.d.ts +1 -0
- package/src/index.d.ts +36 -0
- package/src/lib/danger/danger-detector.d.ts +44 -0
- package/src/lib/generator/migration-file-generator.d.ts +28 -0
- package/src/lib/generator/sql-generator.d.ts +24 -0
- package/src/lib/helpers/data-helpers.d.ts +19 -0
- package/src/lib/loader/migration-loader.d.ts +11 -0
- package/src/lib/loader/snapshot-manager.d.ts +15 -0
- package/src/lib/migration.types.d.ts +132 -0
- package/src/lib/operations/operation.types.d.ts +106 -0
- package/src/lib/runner/clone-test-apply.d.ts +79 -0
- package/src/lib/runner/migrate-runner.d.ts +83 -0
- package/src/lib/runner/push-runner.d.ts +70 -0
- package/src/lib/schema/collections-to-schema.d.ts +19 -0
- package/src/lib/schema/column-type-map.d.ts +33 -0
- package/src/lib/schema/introspect-postgres.d.ts +19 -0
- package/src/lib/schema/introspect-sqlite.d.ts +18 -0
- package/src/lib/schema/schema-diff.d.ts +56 -0
- package/src/lib/schema/schema-snapshot.d.ts +89 -0
- package/src/lib/tracking/migration-tracker.d.ts +42 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push Mode Runner
|
|
3
|
+
*
|
|
4
|
+
* Applies schema changes directly to the database without generating
|
|
5
|
+
* migration files. Used in development for rapid iteration.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Build desired schema from collections
|
|
9
|
+
* 2. Introspect actual schema from database
|
|
10
|
+
* 3. Diff them
|
|
11
|
+
* 4. Run danger detection
|
|
12
|
+
* 5. Generate and execute SQL statements
|
|
13
|
+
*/
|
|
14
|
+
import type { CollectionConfig } from '@momentumcms/core';
|
|
15
|
+
import type { DatabaseDialect } from '../schema/column-type-map';
|
|
16
|
+
import type { DatabaseSchemaSnapshot } from '../schema/schema-snapshot';
|
|
17
|
+
import type { SchemaDiffResult } from '../schema/schema-diff';
|
|
18
|
+
import type { DangerDetectionResult } from '../danger/danger-detector';
|
|
19
|
+
/**
|
|
20
|
+
* Query interface needed by the push runner.
|
|
21
|
+
*/
|
|
22
|
+
export interface PushRunnerDb {
|
|
23
|
+
executeRaw(sql: string): Promise<number>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Options for the push runner.
|
|
27
|
+
*/
|
|
28
|
+
export interface PushRunnerOptions {
|
|
29
|
+
/** Collections to sync */
|
|
30
|
+
collections: CollectionConfig[];
|
|
31
|
+
/** Database dialect */
|
|
32
|
+
dialect: DatabaseDialect;
|
|
33
|
+
/** Database query interface */
|
|
34
|
+
db: PushRunnerDb;
|
|
35
|
+
/** Function to introspect the current DB schema */
|
|
36
|
+
introspect: () => Promise<DatabaseSchemaSnapshot>;
|
|
37
|
+
/** If true, only report what would change without executing */
|
|
38
|
+
dryRun?: boolean;
|
|
39
|
+
/** If true, skip danger detection */
|
|
40
|
+
skipDangerDetection?: boolean;
|
|
41
|
+
/** Logger */
|
|
42
|
+
log?: {
|
|
43
|
+
info(msg: string): void;
|
|
44
|
+
warn(msg: string): void;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Result of a push operation.
|
|
49
|
+
*/
|
|
50
|
+
export interface PushResult {
|
|
51
|
+
/** Whether any changes were applied */
|
|
52
|
+
applied: boolean;
|
|
53
|
+
/** The diff result */
|
|
54
|
+
diff: SchemaDiffResult;
|
|
55
|
+
/** Danger detection result (null if skipped) */
|
|
56
|
+
dangers: DangerDetectionResult | null;
|
|
57
|
+
/** SQL statements that were executed (or would be in dry-run) */
|
|
58
|
+
sqlStatements: string[];
|
|
59
|
+
/** Number of successful statements */
|
|
60
|
+
successCount: number;
|
|
61
|
+
/** Errors encountered during execution */
|
|
62
|
+
errors: Array<{
|
|
63
|
+
sql: string;
|
|
64
|
+
error: string;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Run push mode: directly apply schema changes to the database.
|
|
69
|
+
*/
|
|
70
|
+
export declare function runPush(options: PushRunnerOptions): Promise<PushResult>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collections-to-Schema Mapper
|
|
3
|
+
*
|
|
4
|
+
* Converts Momentum CMS collection configs into a DatabaseSchemaSnapshot.
|
|
5
|
+
* This represents the "desired" state that the diff engine compares
|
|
6
|
+
* against the "actual" state from introspection.
|
|
7
|
+
*/
|
|
8
|
+
import type { CollectionConfig } from '@momentumcms/core';
|
|
9
|
+
import type { TableSnapshot, DatabaseSchemaSnapshot } from './schema-snapshot';
|
|
10
|
+
import type { DatabaseDialect } from './column-type-map';
|
|
11
|
+
/**
|
|
12
|
+
* Convert a single collection config to a TableSnapshot.
|
|
13
|
+
*/
|
|
14
|
+
export declare function collectionToTableSnapshot(collection: CollectionConfig, dialect: DatabaseDialect): TableSnapshot;
|
|
15
|
+
/**
|
|
16
|
+
* Convert an array of collection configs to a full DatabaseSchemaSnapshot.
|
|
17
|
+
* This is the "desired" schema that the diff engine compares against.
|
|
18
|
+
*/
|
|
19
|
+
export declare function collectionsToSchema(collections: CollectionConfig[], dialect: DatabaseDialect): DatabaseSchemaSnapshot;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Column Type Mapping
|
|
3
|
+
*
|
|
4
|
+
* Maps Momentum CMS field types to database column types.
|
|
5
|
+
* Shared between the migration system and database adapters.
|
|
6
|
+
*/
|
|
7
|
+
import type { Field } from '@momentumcms/core';
|
|
8
|
+
/**
|
|
9
|
+
* Supported database dialects for column type mapping.
|
|
10
|
+
*/
|
|
11
|
+
export type DatabaseDialect = 'postgresql' | 'sqlite';
|
|
12
|
+
/**
|
|
13
|
+
* Map a Momentum field type to a PostgreSQL column type.
|
|
14
|
+
*/
|
|
15
|
+
export declare function fieldToPostgresType(field: Field): string;
|
|
16
|
+
/**
|
|
17
|
+
* Map a Momentum field type to a SQLite column type.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fieldToSqliteType(field: Field): string;
|
|
20
|
+
/**
|
|
21
|
+
* Map a Momentum field type to a database column type for the given dialect.
|
|
22
|
+
*/
|
|
23
|
+
export declare function fieldToColumnType(field: Field, dialect: DatabaseDialect): string;
|
|
24
|
+
/**
|
|
25
|
+
* Normalize a raw database type string for reliable comparison.
|
|
26
|
+
* Handles variations like "character varying(255)" vs "VARCHAR(255)".
|
|
27
|
+
*/
|
|
28
|
+
export declare function normalizeColumnType(rawType: string, dialect: DatabaseDialect): string;
|
|
29
|
+
/**
|
|
30
|
+
* Check if two column types are compatible (same effective storage).
|
|
31
|
+
* Used to avoid flagging non-breaking type "changes" as diffs.
|
|
32
|
+
*/
|
|
33
|
+
export declare function areTypesCompatible(typeA: string, typeB: string, dialect: DatabaseDialect): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Schema Introspection
|
|
3
|
+
*
|
|
4
|
+
* Reads the current database schema from PostgreSQL system catalogs.
|
|
5
|
+
* Returns a DatabaseSchemaSnapshot for diffing against collection config.
|
|
6
|
+
*/
|
|
7
|
+
import { type DatabaseSchemaSnapshot } from './schema-snapshot';
|
|
8
|
+
/**
|
|
9
|
+
* Query function signature — abstracts away the specific database driver.
|
|
10
|
+
*/
|
|
11
|
+
export type QueryFunction = <T extends Record<string, unknown>>(sql: string, params?: unknown[]) => Promise<T[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Introspect the PostgreSQL database schema.
|
|
14
|
+
* Queries information_schema and pg_catalog to build a complete snapshot.
|
|
15
|
+
*
|
|
16
|
+
* @param queryFn - Function to execute SQL queries (from adapter.queryRaw)
|
|
17
|
+
* @param schema - PostgreSQL schema name to introspect (default: 'public')
|
|
18
|
+
*/
|
|
19
|
+
export declare function introspectPostgres(queryFn: QueryFunction, schema?: string): Promise<DatabaseSchemaSnapshot>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Schema Introspection
|
|
3
|
+
*
|
|
4
|
+
* Reads the current database schema from SQLite system tables.
|
|
5
|
+
* Returns a DatabaseSchemaSnapshot for diffing against collection config.
|
|
6
|
+
*/
|
|
7
|
+
import { type DatabaseSchemaSnapshot } from './schema-snapshot';
|
|
8
|
+
/**
|
|
9
|
+
* Query function for SQLite — all return values must use consistent interface.
|
|
10
|
+
* SQLite drivers return results synchronously but we use async for adapter compat.
|
|
11
|
+
*/
|
|
12
|
+
export type SqliteQueryFunction = <T extends Record<string, unknown>>(sql: string, params?: unknown[]) => Promise<T[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Introspect the SQLite database schema.
|
|
15
|
+
*
|
|
16
|
+
* @param queryFn - Function to execute SQL queries
|
|
17
|
+
*/
|
|
18
|
+
export declare function introspectSqlite(queryFn: SqliteQueryFunction): Promise<DatabaseSchemaSnapshot>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Diff Engine
|
|
3
|
+
*
|
|
4
|
+
* Compares two DatabaseSchemaSnapshots (desired vs actual) and produces
|
|
5
|
+
* an ordered list of MigrationOperations to reconcile the differences.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Table create/drop detection
|
|
9
|
+
* - Column add/drop/alter detection
|
|
10
|
+
* - Type change detection with normalization
|
|
11
|
+
* - Nullable and default value change detection
|
|
12
|
+
* - Foreign key add/drop detection
|
|
13
|
+
* - Index create/drop detection
|
|
14
|
+
* - Heuristic rename detection (column disappears + new one with compatible type)
|
|
15
|
+
*/
|
|
16
|
+
import type { DatabaseSchemaSnapshot } from './schema-snapshot';
|
|
17
|
+
import type { MigrationOperation } from '../operations/operation.types';
|
|
18
|
+
import type { DatabaseDialect } from './column-type-map';
|
|
19
|
+
/**
|
|
20
|
+
* Options for the diff engine.
|
|
21
|
+
*/
|
|
22
|
+
export interface SchemaDiffOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Enable heuristic rename detection.
|
|
25
|
+
* When a column disappears and a new one appears with the same type,
|
|
26
|
+
* suggest a rename instead of drop+add.
|
|
27
|
+
* @default true
|
|
28
|
+
*/
|
|
29
|
+
detectRenames?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Similarity threshold for rename detection (0-1).
|
|
32
|
+
* Currently unused but reserved for fuzzy name matching.
|
|
33
|
+
* @default 0.6
|
|
34
|
+
*/
|
|
35
|
+
renameSimilarityThreshold?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Result of a schema diff operation.
|
|
39
|
+
*/
|
|
40
|
+
export interface SchemaDiffResult {
|
|
41
|
+
/** Whether the schemas are identical */
|
|
42
|
+
hasChanges: boolean;
|
|
43
|
+
/** Ordered list of operations to apply */
|
|
44
|
+
operations: MigrationOperation[];
|
|
45
|
+
/** Summary of changes for human-readable output */
|
|
46
|
+
summary: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Diff two schema snapshots and produce migration operations.
|
|
50
|
+
*
|
|
51
|
+
* @param desired - The schema we want (from collection configs)
|
|
52
|
+
* @param actual - The schema we have (from database introspection)
|
|
53
|
+
* @param dialect - The database dialect for type normalization
|
|
54
|
+
* @param options - Diff options
|
|
55
|
+
*/
|
|
56
|
+
export declare function diffSchemas(desired: DatabaseSchemaSnapshot, actual: DatabaseSchemaSnapshot, dialect: DatabaseDialect, options?: SchemaDiffOptions): SchemaDiffResult;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot of a single database column.
|
|
3
|
+
*/
|
|
4
|
+
export interface ColumnSnapshot {
|
|
5
|
+
/** Column name */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Raw database type (e.g., VARCHAR(36), TEXT, JSONB) */
|
|
8
|
+
type: string;
|
|
9
|
+
/** Whether the column accepts NULL */
|
|
10
|
+
nullable: boolean;
|
|
11
|
+
/** Default value expression, or null */
|
|
12
|
+
defaultValue: string | null;
|
|
13
|
+
/** Whether this column is the primary key */
|
|
14
|
+
isPrimaryKey: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Snapshot of a foreign key constraint.
|
|
18
|
+
*/
|
|
19
|
+
export interface ForeignKeySnapshot {
|
|
20
|
+
/** Constraint name */
|
|
21
|
+
constraintName: string;
|
|
22
|
+
/** Column in the source table */
|
|
23
|
+
column: string;
|
|
24
|
+
/** Referenced table */
|
|
25
|
+
referencedTable: string;
|
|
26
|
+
/** Referenced column */
|
|
27
|
+
referencedColumn: string;
|
|
28
|
+
/** ON DELETE action (CASCADE, SET NULL, RESTRICT, NO ACTION) */
|
|
29
|
+
onDelete: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Snapshot of a database index.
|
|
33
|
+
*/
|
|
34
|
+
export interface IndexSnapshot {
|
|
35
|
+
/** Index name */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Columns included in the index */
|
|
38
|
+
columns: string[];
|
|
39
|
+
/** Whether the index enforces uniqueness */
|
|
40
|
+
unique: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Snapshot of a single database table.
|
|
44
|
+
*/
|
|
45
|
+
export interface TableSnapshot {
|
|
46
|
+
/** Table name */
|
|
47
|
+
name: string;
|
|
48
|
+
/** All columns in the table */
|
|
49
|
+
columns: ColumnSnapshot[];
|
|
50
|
+
/** Foreign key constraints */
|
|
51
|
+
foreignKeys: ForeignKeySnapshot[];
|
|
52
|
+
/** Indexes (excluding the primary key index) */
|
|
53
|
+
indexes: IndexSnapshot[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Complete snapshot of a database schema.
|
|
57
|
+
*/
|
|
58
|
+
export interface DatabaseSchemaSnapshot {
|
|
59
|
+
/** Database dialect */
|
|
60
|
+
dialect: 'postgresql' | 'sqlite';
|
|
61
|
+
/** All tables in the schema */
|
|
62
|
+
tables: TableSnapshot[];
|
|
63
|
+
/** When this snapshot was captured (ISO string) */
|
|
64
|
+
capturedAt: string;
|
|
65
|
+
/** SHA-256 checksum of the canonical JSON (for drift detection) */
|
|
66
|
+
checksum: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Internal tables that should be excluded from schema snapshots.
|
|
70
|
+
*/
|
|
71
|
+
export declare const INTERNAL_TABLES: Set<string>;
|
|
72
|
+
/**
|
|
73
|
+
* Compute a deterministic SHA-256 checksum for a schema snapshot.
|
|
74
|
+
* The checksum is computed over the sorted, canonical JSON of tables only
|
|
75
|
+
* (excluding capturedAt and checksum fields).
|
|
76
|
+
*/
|
|
77
|
+
export declare function computeSchemaChecksum(tables: TableSnapshot[]): string;
|
|
78
|
+
/**
|
|
79
|
+
* Create a DatabaseSchemaSnapshot from a list of tables.
|
|
80
|
+
*/
|
|
81
|
+
export declare function createSchemaSnapshot(dialect: 'postgresql' | 'sqlite', tables: TableSnapshot[]): DatabaseSchemaSnapshot;
|
|
82
|
+
/**
|
|
83
|
+
* Serialize a snapshot to JSON string (for .snapshot.json files).
|
|
84
|
+
*/
|
|
85
|
+
export declare function serializeSnapshot(snapshot: DatabaseSchemaSnapshot): string;
|
|
86
|
+
/**
|
|
87
|
+
* Deserialize a snapshot from a JSON string.
|
|
88
|
+
*/
|
|
89
|
+
export declare function deserializeSnapshot(json: string): DatabaseSchemaSnapshot;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { MigrationTrackingRecord } from '../migration.types';
|
|
2
|
+
import type { DatabaseDialect } from '../schema/column-type-map';
|
|
3
|
+
/**
|
|
4
|
+
* Database query function type.
|
|
5
|
+
* Abstracts the adapter's queryRaw / executeRaw methods.
|
|
6
|
+
*/
|
|
7
|
+
export interface TrackerQueryFn {
|
|
8
|
+
query<T extends Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
9
|
+
execute(sql: string, params?: unknown[]): Promise<number>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ensure the migration tracking table exists.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ensureTrackingTable(db: TrackerQueryFn, dialect: DatabaseDialect): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Get all applied migrations, ordered by batch and name.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getAppliedMigrations(db: TrackerQueryFn): Promise<MigrationTrackingRecord[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the next batch number.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getNextBatchNumber(db: TrackerQueryFn): Promise<number>;
|
|
23
|
+
/**
|
|
24
|
+
* Record a migration as applied.
|
|
25
|
+
*/
|
|
26
|
+
export declare function recordMigration(db: TrackerQueryFn, record: Omit<MigrationTrackingRecord, 'id'>, dialect: DatabaseDialect): Promise<MigrationTrackingRecord>;
|
|
27
|
+
/**
|
|
28
|
+
* Remove a migration record (for rollbacks).
|
|
29
|
+
*/
|
|
30
|
+
export declare function removeMigrationRecord(db: TrackerQueryFn, name: string, dialect: DatabaseDialect): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Get migrations from a specific batch (for rollback).
|
|
33
|
+
*/
|
|
34
|
+
export declare function getMigrationsByBatch(db: TrackerQueryFn, batch: number, dialect: DatabaseDialect): Promise<MigrationTrackingRecord[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Get the latest batch number.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getLatestBatchNumber(db: TrackerQueryFn): Promise<number>;
|
|
39
|
+
/**
|
|
40
|
+
* Check if a specific migration has been applied.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isMigrationApplied(db: TrackerQueryFn, name: string, dialect: DatabaseDialect): Promise<boolean>;
|