linkgress-orm 0.2.16 → 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.
Files changed (32) hide show
  1. package/README.md +2 -0
  2. package/dist/entity/db-context.d.ts +22 -2
  3. package/dist/entity/db-context.d.ts.map +1 -1
  4. package/dist/entity/db-context.js +67 -14
  5. package/dist/entity/db-context.js.map +1 -1
  6. package/dist/index.d.ts +6 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +9 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/migration/db-schema-manager.d.ts +2 -2
  11. package/dist/migration/db-schema-manager.d.ts.map +1 -1
  12. package/dist/migration/migration-journal.d.ts +52 -0
  13. package/dist/migration/migration-journal.d.ts.map +1 -0
  14. package/dist/migration/migration-journal.js +84 -0
  15. package/dist/migration/migration-journal.js.map +1 -0
  16. package/dist/migration/migration-loader.d.ts +70 -0
  17. package/dist/migration/migration-loader.d.ts.map +1 -0
  18. package/dist/migration/migration-loader.js +199 -0
  19. package/dist/migration/migration-loader.js.map +1 -0
  20. package/dist/migration/migration-runner.d.ts +84 -0
  21. package/dist/migration/migration-runner.d.ts.map +1 -0
  22. package/dist/migration/migration-runner.js +197 -0
  23. package/dist/migration/migration-runner.js.map +1 -0
  24. package/dist/migration/migration-scaffold.d.ts +100 -0
  25. package/dist/migration/migration-scaffold.d.ts.map +1 -0
  26. package/dist/migration/migration-scaffold.js +434 -0
  27. package/dist/migration/migration-scaffold.js.map +1 -0
  28. package/dist/migration/migration.interface.d.ts +108 -0
  29. package/dist/migration/migration.interface.d.ts.map +1 -0
  30. package/dist/migration/migration.interface.js +3 -0
  31. package/dist/migration/migration.interface.js.map +1 -0
  32. package/package.json +1 -1
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MigrationJournal = void 0;
4
+ /**
5
+ * Manages the migration journal table that tracks which migrations have been applied.
6
+ *
7
+ * The journal table stores a record for each successfully applied migration,
8
+ * allowing the system to know which migrations to skip on subsequent runs.
9
+ */
10
+ class MigrationJournal {
11
+ constructor(client, config) {
12
+ this.client = client;
13
+ this.tableName = config?.journalTable || '__migrations';
14
+ this.schemaName = config?.journalSchema || 'public';
15
+ this.qualifiedName = `"${this.schemaName}"."${this.tableName}"`;
16
+ }
17
+ /**
18
+ * Ensure the journal table exists in the database.
19
+ * Creates it if it doesn't exist.
20
+ */
21
+ async ensureTable() {
22
+ // First ensure the schema exists
23
+ if (this.schemaName !== 'public') {
24
+ await this.client.query(`CREATE SCHEMA IF NOT EXISTS "${this.schemaName}"`);
25
+ }
26
+ const sql = `
27
+ CREATE TABLE IF NOT EXISTS ${this.qualifiedName} (
28
+ id SERIAL PRIMARY KEY,
29
+ filename VARCHAR(255) NOT NULL UNIQUE,
30
+ applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
31
+ )
32
+ `;
33
+ await this.client.query(sql);
34
+ }
35
+ /**
36
+ * Get all applied migrations ordered by filename (chronologically).
37
+ */
38
+ async getApplied() {
39
+ const result = await this.client.query(`SELECT id, filename, applied_at FROM ${this.qualifiedName} ORDER BY filename ASC`);
40
+ return result.rows;
41
+ }
42
+ /**
43
+ * Check if a specific migration has been applied.
44
+ * @param filename - The migration filename to check
45
+ */
46
+ async isApplied(filename) {
47
+ const result = await this.client.query(`SELECT 1 FROM ${this.qualifiedName} WHERE filename = $1`, [filename]);
48
+ return result.rows.length > 0;
49
+ }
50
+ /**
51
+ * Record a migration as successfully applied.
52
+ * @param filename - The migration filename
53
+ */
54
+ async recordApplied(filename) {
55
+ await this.client.query(`INSERT INTO ${this.qualifiedName} (filename) VALUES ($1)`, [filename]);
56
+ }
57
+ /**
58
+ * Remove a migration record (used when rolling back).
59
+ * @param filename - The migration filename to remove
60
+ */
61
+ async recordReverted(filename) {
62
+ await this.client.query(`DELETE FROM ${this.qualifiedName} WHERE filename = $1`, [filename]);
63
+ }
64
+ /**
65
+ * Get the qualified table name (schema.table).
66
+ */
67
+ getQualifiedName() {
68
+ return this.qualifiedName;
69
+ }
70
+ /**
71
+ * Get the table name without schema.
72
+ */
73
+ getTableName() {
74
+ return this.tableName;
75
+ }
76
+ /**
77
+ * Get the schema name.
78
+ */
79
+ getSchemaName() {
80
+ return this.schemaName;
81
+ }
82
+ }
83
+ exports.MigrationJournal = MigrationJournal;
84
+ //# sourceMappingURL=migration-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-journal.js","sourceRoot":"","sources":["../../src/migration/migration-journal.ts"],"names":[],"mappings":";;;AAGA;;;;;GAKG;AACH,MAAa,gBAAgB;IAK3B,YACU,MAAsB,EAC9B,MAAgE;QADxD,WAAM,GAAN,MAAM,CAAgB;QAG9B,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,YAAY,IAAI,cAAc,CAAC;QACxD,IAAI,CAAC,UAAU,GAAG,MAAM,EAAE,aAAa,IAAI,QAAQ,CAAC;QACpD,IAAI,CAAC,aAAa,GAAG,IAAI,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC,SAAS,GAAG,CAAC;IAClE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,iCAAiC;QACjC,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACrB,gCAAgC,IAAI,CAAC,UAAU,GAAG,CACnD,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG;mCACmB,IAAI,CAAC,aAAa;;;;;KAKhD,CAAC;QACF,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACpC,wCAAwC,IAAI,CAAC,aAAa,wBAAwB,CACnF,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB;QAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACpC,iBAAiB,IAAI,CAAC,aAAa,sBAAsB,EACzD,CAAC,QAAQ,CAAC,CACX,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,QAAgB;QAClC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACrB,eAAe,IAAI,CAAC,aAAa,yBAAyB,EAC1D,CAAC,QAAQ,CAAC,CACX,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACrB,eAAe,IAAI,CAAC,aAAa,sBAAsB,EACvD,CAAC,QAAQ,CAAC,CACX,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF;AApGD,4CAoGC"}
@@ -0,0 +1,70 @@
1
+ import { LoadedMigration } from './migration.interface';
2
+ /**
3
+ * Loads migration files from the filesystem.
4
+ *
5
+ * Migration files must:
6
+ * - Be TypeScript files with .ts extension
7
+ * - Export a default class/object implementing the Migration interface (up/down methods)
8
+ *
9
+ * Naming conventions (all supported):
10
+ * - YYYYMMDD-HHMMSS.ts (recommended, generated by scaffold)
11
+ * - 001_initial.ts, 002_add_users.ts (numbered)
12
+ * - create_users.ts, add_posts.ts (descriptive)
13
+ *
14
+ * Files are sorted lexicographically, so use consistent naming for proper order.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const loader = new MigrationLoader('./migrations');
19
+ * const migrations = await loader.loadAllMigrations();
20
+ * ```
21
+ */
22
+ export declare class MigrationLoader {
23
+ private migrationsDirectory;
24
+ constructor(migrationsDirectory: string);
25
+ /**
26
+ * Extract a sort key from the filename.
27
+ * For timestamp patterns, extracts the timestamp.
28
+ * For other patterns, uses the filename without extension.
29
+ */
30
+ private extractSortKey;
31
+ /**
32
+ * Get all migration files in the directory, sorted lexicographically.
33
+ * Includes all .ts files in the directory.
34
+ */
35
+ getMigrationFiles(): Promise<string[]>;
36
+ /**
37
+ * Load a single migration file.
38
+ *
39
+ * Uses require() to load the TypeScript file, which works when running
40
+ * with ts-node, tsx, or other TypeScript loaders.
41
+ *
42
+ * @param filename - The migration filename to load
43
+ * @returns The loaded migration with metadata
44
+ * @throws Error if the file doesn't exist or doesn't implement Migration
45
+ */
46
+ loadMigration(filename: string): Promise<LoadedMigration>;
47
+ /**
48
+ * Load all migrations from the directory, sorted lexicographically.
49
+ * @returns Array of loaded migrations in order
50
+ */
51
+ loadAllMigrations(): Promise<LoadedMigration[]>;
52
+ /**
53
+ * Generate a new migration filename with the current timestamp.
54
+ * Format: YYYYMMDD-HHMMSS.ts (recommended naming convention)
55
+ *
56
+ * @returns A new unique migration filename
57
+ */
58
+ generateFilename(): string;
59
+ /**
60
+ * Get the absolute path to the migrations directory.
61
+ * Resolves relative paths against process.cwd().
62
+ */
63
+ getAbsoluteDirectory(): string;
64
+ /**
65
+ * Ensure the migrations directory exists.
66
+ * Creates it (including parent directories) if it doesn't exist.
67
+ */
68
+ ensureDirectory(): void;
69
+ }
70
+ //# sourceMappingURL=migration-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-loader.d.ts","sourceRoot":"","sources":["../../src/migration/migration-loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQnE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,mBAAmB;gBAAnB,mBAAmB,EAAE,MAAM;IAE/C;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAStB;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAa5C;;;;;;;;;OASG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAyD/D;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAYrD;;;;;OAKG;IACH,gBAAgB,IAAI,MAAM;IAe1B;;;OAGG;IACH,oBAAoB,IAAI,MAAM;IAM9B;;;OAGG;IACH,eAAe,IAAI,IAAI;CAMxB"}
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MigrationLoader = void 0;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs"));
39
+ /**
40
+ * Pattern for timestamp-based migration filenames: YYYYMMDD-HHMMSS.ts
41
+ * This is the recommended format used by scaffold, but not required.
42
+ */
43
+ const TIMESTAMP_PATTERN = /^(\d{8}-\d{6})\.ts$/;
44
+ /**
45
+ * Loads migration files from the filesystem.
46
+ *
47
+ * Migration files must:
48
+ * - Be TypeScript files with .ts extension
49
+ * - Export a default class/object implementing the Migration interface (up/down methods)
50
+ *
51
+ * Naming conventions (all supported):
52
+ * - YYYYMMDD-HHMMSS.ts (recommended, generated by scaffold)
53
+ * - 001_initial.ts, 002_add_users.ts (numbered)
54
+ * - create_users.ts, add_posts.ts (descriptive)
55
+ *
56
+ * Files are sorted lexicographically, so use consistent naming for proper order.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const loader = new MigrationLoader('./migrations');
61
+ * const migrations = await loader.loadAllMigrations();
62
+ * ```
63
+ */
64
+ class MigrationLoader {
65
+ constructor(migrationsDirectory) {
66
+ this.migrationsDirectory = migrationsDirectory;
67
+ }
68
+ /**
69
+ * Extract a sort key from the filename.
70
+ * For timestamp patterns, extracts the timestamp.
71
+ * For other patterns, uses the filename without extension.
72
+ */
73
+ extractSortKey(filename) {
74
+ const timestampMatch = filename.match(TIMESTAMP_PATTERN);
75
+ if (timestampMatch) {
76
+ return timestampMatch[1];
77
+ }
78
+ // Remove .ts extension for sorting
79
+ return filename.replace(/\.ts$/, '');
80
+ }
81
+ /**
82
+ * Get all migration files in the directory, sorted lexicographically.
83
+ * Includes all .ts files in the directory.
84
+ */
85
+ async getMigrationFiles() {
86
+ const absoluteDir = this.getAbsoluteDirectory();
87
+ if (!fs.existsSync(absoluteDir)) {
88
+ return [];
89
+ }
90
+ const files = fs.readdirSync(absoluteDir);
91
+ return files
92
+ .filter(f => f.endsWith('.ts') && !f.endsWith('.d.ts'))
93
+ .sort((a, b) => this.extractSortKey(a).localeCompare(this.extractSortKey(b)));
94
+ }
95
+ /**
96
+ * Load a single migration file.
97
+ *
98
+ * Uses require() to load the TypeScript file, which works when running
99
+ * with ts-node, tsx, or other TypeScript loaders.
100
+ *
101
+ * @param filename - The migration filename to load
102
+ * @returns The loaded migration with metadata
103
+ * @throws Error if the file doesn't exist or doesn't implement Migration
104
+ */
105
+ async loadMigration(filename) {
106
+ const absoluteDir = this.getAbsoluteDirectory();
107
+ const filePath = path.join(absoluteDir, filename);
108
+ if (!filename.endsWith('.ts')) {
109
+ throw new Error(`Invalid migration filename: ${filename}. Must be a .ts file`);
110
+ }
111
+ if (!fs.existsSync(filePath)) {
112
+ throw new Error(`Migration file not found: ${filePath}`);
113
+ }
114
+ // Clear require cache to ensure fresh load (useful during development)
115
+ delete require.cache[require.resolve(filePath)];
116
+ // Dynamically require the migration file
117
+ // This works with ts-node/tsx at runtime
118
+ const module = require(filePath);
119
+ const MigrationClass = module.default || module;
120
+ // Instantiate if it's a class, otherwise use as-is (for object exports)
121
+ let migration;
122
+ try {
123
+ migration = typeof MigrationClass === 'function'
124
+ ? new MigrationClass()
125
+ : MigrationClass;
126
+ }
127
+ catch (err) {
128
+ throw new Error(`Failed to instantiate migration ${filename}: ${err.message}`);
129
+ }
130
+ // Validate migration has required methods
131
+ if (typeof migration.up !== 'function') {
132
+ throw new Error(`Migration ${filename} must export a class/object with an 'up' method`);
133
+ }
134
+ if (typeof migration.down !== 'function') {
135
+ throw new Error(`Migration ${filename} must export a class/object with a 'down' method`);
136
+ }
137
+ // Extract timestamp if present, otherwise use sort key
138
+ const sortKey = this.extractSortKey(filename);
139
+ return {
140
+ filename,
141
+ timestamp: sortKey,
142
+ migration,
143
+ filePath,
144
+ };
145
+ }
146
+ /**
147
+ * Load all migrations from the directory, sorted lexicographically.
148
+ * @returns Array of loaded migrations in order
149
+ */
150
+ async loadAllMigrations() {
151
+ const files = await this.getMigrationFiles();
152
+ const migrations = [];
153
+ for (const file of files) {
154
+ const loaded = await this.loadMigration(file);
155
+ migrations.push(loaded);
156
+ }
157
+ return migrations;
158
+ }
159
+ /**
160
+ * Generate a new migration filename with the current timestamp.
161
+ * Format: YYYYMMDD-HHMMSS.ts (recommended naming convention)
162
+ *
163
+ * @returns A new unique migration filename
164
+ */
165
+ generateFilename() {
166
+ const now = new Date();
167
+ const timestamp = [
168
+ now.getFullYear().toString(),
169
+ (now.getMonth() + 1).toString().padStart(2, '0'),
170
+ now.getDate().toString().padStart(2, '0'),
171
+ '-',
172
+ now.getHours().toString().padStart(2, '0'),
173
+ now.getMinutes().toString().padStart(2, '0'),
174
+ now.getSeconds().toString().padStart(2, '0'),
175
+ ].join('');
176
+ return `${timestamp}.ts`;
177
+ }
178
+ /**
179
+ * Get the absolute path to the migrations directory.
180
+ * Resolves relative paths against process.cwd().
181
+ */
182
+ getAbsoluteDirectory() {
183
+ return path.isAbsolute(this.migrationsDirectory)
184
+ ? this.migrationsDirectory
185
+ : path.resolve(process.cwd(), this.migrationsDirectory);
186
+ }
187
+ /**
188
+ * Ensure the migrations directory exists.
189
+ * Creates it (including parent directories) if it doesn't exist.
190
+ */
191
+ ensureDirectory() {
192
+ const absoluteDir = this.getAbsoluteDirectory();
193
+ if (!fs.existsSync(absoluteDir)) {
194
+ fs.mkdirSync(absoluteDir, { recursive: true });
195
+ }
196
+ }
197
+ }
198
+ exports.MigrationLoader = MigrationLoader;
199
+ //# sourceMappingURL=migration-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-loader.js","sourceRoot":"","sources":["../../src/migration/migration-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { DatabaseContext } from '../entity/db-context';
2
+ import { MigrationConfig, MigrationRunResult, LoadedMigration } from './migration.interface';
3
+ import { MigrationJournal } from './migration-journal';
4
+ import { MigrationLoader } from './migration-loader';
5
+ /**
6
+ * Executes migrations against the database.
7
+ *
8
+ * The runner:
9
+ * - Loads migration files from the configured directory
10
+ * - Tracks applied migrations in a journal table
11
+ * - Executes pending migrations in chronological order
12
+ * - Supports rolling back migrations
13
+ * - Runs each migration within a transaction for atomicity
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const runner = new MigrationRunner(db, {
18
+ * migrationsDirectory: './migrations',
19
+ * verbose: true,
20
+ * });
21
+ *
22
+ * // Run all pending migrations
23
+ * const result = await runner.up();
24
+ * console.log(`Applied ${result.applied.length} migrations`);
25
+ *
26
+ * // Rollback last migration
27
+ * await runner.down(1);
28
+ * ```
29
+ */
30
+ export declare class MigrationRunner {
31
+ private db;
32
+ private config;
33
+ private journal;
34
+ private loader;
35
+ private verbose;
36
+ private logger;
37
+ constructor(db: DatabaseContext, config: MigrationConfig);
38
+ private log;
39
+ /**
40
+ * Run all pending migrations in chronological order.
41
+ *
42
+ * Each migration is executed within a transaction. If a migration fails,
43
+ * the transaction is rolled back and execution stops.
44
+ *
45
+ * @returns Result containing applied, skipped, and failed migrations
46
+ */
47
+ up(): Promise<MigrationRunResult>;
48
+ /**
49
+ * Revert the last N migrations in reverse chronological order.
50
+ *
51
+ * Each migration's down() method is executed within a transaction.
52
+ *
53
+ * @param count - Number of migrations to revert (default: 1)
54
+ * @returns Result containing reverted migrations
55
+ */
56
+ down(count?: number): Promise<MigrationRunResult>;
57
+ /**
58
+ * Get all pending migrations (not yet applied).
59
+ */
60
+ getPending(): Promise<LoadedMigration[]>;
61
+ /**
62
+ * Get all applied migrations.
63
+ */
64
+ getApplied(): Promise<LoadedMigration[]>;
65
+ /**
66
+ * Get the status of all migrations.
67
+ *
68
+ * @returns Array of migration status objects
69
+ */
70
+ status(): Promise<{
71
+ filename: string;
72
+ applied: boolean;
73
+ appliedAt?: Date;
74
+ }[]>;
75
+ /**
76
+ * Get the migration loader (for generating filenames, etc.)
77
+ */
78
+ getLoader(): MigrationLoader;
79
+ /**
80
+ * Get the migration journal (for advanced operations)
81
+ */
82
+ getJournal(): MigrationJournal;
83
+ }
84
+ //# sourceMappingURL=migration-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-runner.d.ts","sourceRoot":"","sources":["../../src/migration/migration-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,eAAe;IAOxB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAA4B;gBAGhC,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,eAAe;IAQjC,OAAO,CAAC,GAAG;IAMX;;;;;;;OAOG;IACG,EAAE,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAmDvC;;;;;;;OAOG;IACG,IAAI,CAAC,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAwD1D;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAU9C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAU9C;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,IAAI,CAAA;KAAE,EAAE,CAAC;IAcnF;;OAEG;IACH,SAAS,IAAI,eAAe;IAI5B;;OAEG;IACH,UAAU,IAAI,gBAAgB;CAG/B"}
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MigrationRunner = void 0;
4
+ const migration_journal_1 = require("./migration-journal");
5
+ const migration_loader_1 = require("./migration-loader");
6
+ /**
7
+ * Executes migrations against the database.
8
+ *
9
+ * The runner:
10
+ * - Loads migration files from the configured directory
11
+ * - Tracks applied migrations in a journal table
12
+ * - Executes pending migrations in chronological order
13
+ * - Supports rolling back migrations
14
+ * - Runs each migration within a transaction for atomicity
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const runner = new MigrationRunner(db, {
19
+ * migrationsDirectory: './migrations',
20
+ * verbose: true,
21
+ * });
22
+ *
23
+ * // Run all pending migrations
24
+ * const result = await runner.up();
25
+ * console.log(`Applied ${result.applied.length} migrations`);
26
+ *
27
+ * // Rollback last migration
28
+ * await runner.down(1);
29
+ * ```
30
+ */
31
+ class MigrationRunner {
32
+ constructor(db, config) {
33
+ this.db = db;
34
+ this.config = config;
35
+ this.journal = new migration_journal_1.MigrationJournal(db.getClient(), config);
36
+ this.loader = new migration_loader_1.MigrationLoader(config.migrationsDirectory);
37
+ this.verbose = config.verbose ?? false;
38
+ this.logger = config.logger ?? console.log;
39
+ }
40
+ log(message) {
41
+ if (this.verbose) {
42
+ this.logger(message);
43
+ }
44
+ }
45
+ /**
46
+ * Run all pending migrations in chronological order.
47
+ *
48
+ * Each migration is executed within a transaction. If a migration fails,
49
+ * the transaction is rolled back and execution stops.
50
+ *
51
+ * @returns Result containing applied, skipped, and failed migrations
52
+ */
53
+ async up() {
54
+ await this.journal.ensureTable();
55
+ const allMigrations = await this.loader.loadAllMigrations();
56
+ const applied = await this.journal.getApplied();
57
+ const appliedSet = new Set(applied.map(a => a.filename));
58
+ const pending = allMigrations.filter(m => !appliedSet.has(m.filename));
59
+ const result = {
60
+ applied: [],
61
+ skipped: allMigrations
62
+ .filter(m => appliedSet.has(m.filename))
63
+ .map(m => m.filename),
64
+ };
65
+ this.log(`Found ${pending.length} pending migration(s)`);
66
+ for (const migration of pending) {
67
+ try {
68
+ this.log(`Applying: ${migration.filename}`);
69
+ // Execute migration within a transaction
70
+ await this.db.transaction(async (txDb) => {
71
+ await migration.migration.up(txDb);
72
+ });
73
+ // Record only after successful commit
74
+ await this.journal.recordApplied(migration.filename);
75
+ result.applied.push(migration.filename);
76
+ this.log(` Applied: ${migration.filename}`);
77
+ }
78
+ catch (error) {
79
+ result.failed = {
80
+ filename: migration.filename,
81
+ error: error,
82
+ };
83
+ this.logger(` FAILED: ${migration.filename} - ${error.message}`);
84
+ break; // Stop on first failure
85
+ }
86
+ }
87
+ if (result.applied.length > 0) {
88
+ this.log(`\nCompleted: ${result.applied.length} migration(s) applied`);
89
+ }
90
+ else if (!result.failed) {
91
+ this.log('No pending migrations');
92
+ }
93
+ return result;
94
+ }
95
+ /**
96
+ * Revert the last N migrations in reverse chronological order.
97
+ *
98
+ * Each migration's down() method is executed within a transaction.
99
+ *
100
+ * @param count - Number of migrations to revert (default: 1)
101
+ * @returns Result containing reverted migrations
102
+ */
103
+ async down(count = 1) {
104
+ await this.journal.ensureTable();
105
+ const applied = await this.journal.getApplied();
106
+ const allMigrations = await this.loader.loadAllMigrations();
107
+ // Get migrations to revert (most recent first)
108
+ const toRevert = applied.slice(-count).reverse();
109
+ const result = {
110
+ applied: [],
111
+ skipped: [],
112
+ };
113
+ this.log(`Reverting ${toRevert.length} migration(s)`);
114
+ for (const entry of toRevert) {
115
+ const migration = allMigrations.find(m => m.filename === entry.filename);
116
+ if (!migration) {
117
+ this.logger(` WARNING: Migration file not found for ${entry.filename}, removing from journal`);
118
+ await this.journal.recordReverted(entry.filename);
119
+ result.applied.push(entry.filename);
120
+ continue;
121
+ }
122
+ try {
123
+ this.log(`Reverting: ${migration.filename}`);
124
+ // Execute down migration within a transaction
125
+ await this.db.transaction(async (txDb) => {
126
+ await migration.migration.down(txDb);
127
+ });
128
+ // Remove from journal only after successful rollback
129
+ await this.journal.recordReverted(migration.filename);
130
+ result.applied.push(migration.filename);
131
+ this.log(` Reverted: ${migration.filename}`);
132
+ }
133
+ catch (error) {
134
+ result.failed = {
135
+ filename: migration.filename,
136
+ error: error,
137
+ };
138
+ this.logger(` FAILED: ${migration.filename} - ${error.message}`);
139
+ break;
140
+ }
141
+ }
142
+ if (result.applied.length > 0) {
143
+ this.log(`\nCompleted: ${result.applied.length} migration(s) reverted`);
144
+ }
145
+ return result;
146
+ }
147
+ /**
148
+ * Get all pending migrations (not yet applied).
149
+ */
150
+ async getPending() {
151
+ await this.journal.ensureTable();
152
+ const allMigrations = await this.loader.loadAllMigrations();
153
+ const applied = await this.journal.getApplied();
154
+ const appliedSet = new Set(applied.map(a => a.filename));
155
+ return allMigrations.filter(m => !appliedSet.has(m.filename));
156
+ }
157
+ /**
158
+ * Get all applied migrations.
159
+ */
160
+ async getApplied() {
161
+ await this.journal.ensureTable();
162
+ const allMigrations = await this.loader.loadAllMigrations();
163
+ const applied = await this.journal.getApplied();
164
+ const appliedSet = new Set(applied.map(a => a.filename));
165
+ return allMigrations.filter(m => appliedSet.has(m.filename));
166
+ }
167
+ /**
168
+ * Get the status of all migrations.
169
+ *
170
+ * @returns Array of migration status objects
171
+ */
172
+ async status() {
173
+ await this.journal.ensureTable();
174
+ const allMigrations = await this.loader.loadAllMigrations();
175
+ const applied = await this.journal.getApplied();
176
+ const appliedMap = new Map(applied.map(a => [a.filename, a]));
177
+ return allMigrations.map(m => ({
178
+ filename: m.filename,
179
+ applied: appliedMap.has(m.filename),
180
+ appliedAt: appliedMap.get(m.filename)?.applied_at,
181
+ }));
182
+ }
183
+ /**
184
+ * Get the migration loader (for generating filenames, etc.)
185
+ */
186
+ getLoader() {
187
+ return this.loader;
188
+ }
189
+ /**
190
+ * Get the migration journal (for advanced operations)
191
+ */
192
+ getJournal() {
193
+ return this.journal;
194
+ }
195
+ }
196
+ exports.MigrationRunner = MigrationRunner;
197
+ //# sourceMappingURL=migration-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-runner.js","sourceRoot":"","sources":["../../src/migration/migration-runner.ts"],"names":[],"mappings":";;;AAMA,2DAAuD;AACvD,yDAAqD;AAErD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAa,eAAe;IAM1B,YACU,EAAmB,EACnB,MAAuB;QADvB,OAAE,GAAF,EAAE,CAAiB;QACnB,WAAM,GAAN,MAAM,CAAiB;QAE/B,IAAI,CAAC,OAAO,GAAG,IAAI,oCAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,GAAG,IAAI,kCAAe,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC9D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC;IAC7C,CAAC;IAEO,GAAG,CAAC,OAAe;QACzB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE;QACN,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAEjC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEzD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEvE,MAAM,MAAM,GAAuB;YACjC,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,aAAa;iBACnB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;iBACvC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;SACxB,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,SAAS,OAAO,CAAC,MAAM,uBAAuB,CAAC,CAAC;QAEzD,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,aAAa,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAE5C,yCAAyC;gBACzC,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;oBACvC,MAAM,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBACrC,CAAC,CAAC,CAAC;gBAEH,sCAAsC;gBACtC,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBACrD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBAExC,IAAI,CAAC,GAAG,CAAC,cAAc,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,MAAM,GAAG;oBACd,QAAQ,EAAE,SAAS,CAAC,QAAQ;oBAC5B,KAAK,EAAE,KAAc;iBACtB,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,aAAa,SAAS,CAAC,QAAQ,MAAO,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC7E,MAAM,CAAC,wBAAwB;YACjC,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,OAAO,CAAC,MAAM,uBAAuB,CAAC,CAAC;QACzE,CAAC;aAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,IAAI,CAAC,QAAgB,CAAC;QAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAEjC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAE5D,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QAEjD,MAAM,MAAM,GAAuB;YACjC,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,EAAE;SACZ,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,aAAa,QAAQ,CAAC,MAAM,eAAe,CAAC,CAAC;QAEtD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC;YAEzE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,2CAA2C,KAAK,CAAC,QAAQ,yBAAyB,CAAC,CAAC;gBAChG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAClD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACpC,SAAS;YACX,CAAC;YAED,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,cAAc,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAE7C,8CAA8C;gBAC9C,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;oBACvC,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvC,CAAC,CAAC,CAAC;gBAEH,qDAAqD;gBACrD,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBACtD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBAExC,IAAI,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,MAAM,GAAG;oBACd,QAAQ,EAAE,SAAS,CAAC,QAAQ;oBAC5B,KAAK,EAAE,KAAc;iBACtB,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,aAAa,SAAS,CAAC,QAAQ,MAAO,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC7E,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,OAAO,CAAC,MAAM,wBAAwB,CAAC,CAAC;QAC1E,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAEjC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEzD,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAEjC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEzD,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAEjC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9D,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;YACnC,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,UAAU;SAClD,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AA3MD,0CA2MC"}