@studiosonrai/nestjs-migrations 1.0.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/dist/bin/cli.d.ts +2 -0
- package/dist/bin/cli.js +242 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +16 -0
- package/dist/src/migration-core.d.ts +49 -0
- package/dist/src/migration-core.js +184 -0
- package/dist/src/migration.module.d.ts +37 -0
- package/dist/src/migration.module.js +108 -0
- package/dist/src/migration.service.d.ts +32 -0
- package/dist/src/migration.service.js +77 -0
- package/dist/src/types.d.ts +83 -0
- package/dist/src/types.js +5 -0
- package/package.json +49 -0
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const typeorm_1 = require("typeorm");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const migration_core_1 = require("../src/migration-core");
|
|
7
|
+
function printUsage() {
|
|
8
|
+
console.log(`
|
|
9
|
+
@studiosonrai/nestjs-migrations CLI
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
nestjs-migrations run [options]
|
|
13
|
+
nestjs-migrations status [options]
|
|
14
|
+
|
|
15
|
+
Commands:
|
|
16
|
+
run Run all pending migrations
|
|
17
|
+
status Show migration status
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--migrations-dir, -d Path to migrations directory (required)
|
|
21
|
+
--host, -h Database host (default: localhost)
|
|
22
|
+
--port, -p Database port (default: 1433)
|
|
23
|
+
--database, -D Database name (required)
|
|
24
|
+
--username, -u Database username
|
|
25
|
+
--password, -P Database password
|
|
26
|
+
--encrypt Enable encryption (default: false)
|
|
27
|
+
--trust-cert Trust server certificate (default: false)
|
|
28
|
+
--dry-run Show pending migrations without applying
|
|
29
|
+
--verbose, -v Verbose output (default: true)
|
|
30
|
+
--help Show this help message
|
|
31
|
+
|
|
32
|
+
Environment variables:
|
|
33
|
+
DB_HOST Database host
|
|
34
|
+
DB_PORT Database port
|
|
35
|
+
DB_DATABASE Database name
|
|
36
|
+
DB_USERNAME Database username
|
|
37
|
+
DB_PASSWORD Database password
|
|
38
|
+
DB_ENCRYPT Enable encryption
|
|
39
|
+
MIGRATIONS_DIR Path to migrations directory
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
nestjs-migrations run -d ./migrations -D mydb -u sa -P password
|
|
43
|
+
nestjs-migrations status --migrations-dir ./migrations --database mydb
|
|
44
|
+
nestjs-migrations run --dry-run -d ./migrations -D mydb
|
|
45
|
+
`);
|
|
46
|
+
}
|
|
47
|
+
function parseArgs(args) {
|
|
48
|
+
const options = {
|
|
49
|
+
verbose: true,
|
|
50
|
+
};
|
|
51
|
+
let command = '';
|
|
52
|
+
for (let i = 0; i < args.length; i++) {
|
|
53
|
+
const arg = args[i];
|
|
54
|
+
const nextArg = args[i + 1];
|
|
55
|
+
switch (arg) {
|
|
56
|
+
case 'run':
|
|
57
|
+
case 'status':
|
|
58
|
+
command = arg;
|
|
59
|
+
break;
|
|
60
|
+
case '--migrations-dir':
|
|
61
|
+
case '-d':
|
|
62
|
+
options.migrationsDir = nextArg;
|
|
63
|
+
i++;
|
|
64
|
+
break;
|
|
65
|
+
case '--host':
|
|
66
|
+
case '-h':
|
|
67
|
+
options.host = nextArg;
|
|
68
|
+
i++;
|
|
69
|
+
break;
|
|
70
|
+
case '--port':
|
|
71
|
+
case '-p':
|
|
72
|
+
options.port = parseInt(nextArg, 10);
|
|
73
|
+
i++;
|
|
74
|
+
break;
|
|
75
|
+
case '--database':
|
|
76
|
+
case '-D':
|
|
77
|
+
options.database = nextArg;
|
|
78
|
+
i++;
|
|
79
|
+
break;
|
|
80
|
+
case '--username':
|
|
81
|
+
case '-u':
|
|
82
|
+
options.username = nextArg;
|
|
83
|
+
i++;
|
|
84
|
+
break;
|
|
85
|
+
case '--password':
|
|
86
|
+
case '-P':
|
|
87
|
+
options.password = nextArg;
|
|
88
|
+
i++;
|
|
89
|
+
break;
|
|
90
|
+
case '--encrypt':
|
|
91
|
+
options.encrypt = true;
|
|
92
|
+
break;
|
|
93
|
+
case '--trust-cert':
|
|
94
|
+
options.trustServerCertificate = true;
|
|
95
|
+
break;
|
|
96
|
+
case '--dry-run':
|
|
97
|
+
options.dryRun = true;
|
|
98
|
+
break;
|
|
99
|
+
case '--verbose':
|
|
100
|
+
case '-v':
|
|
101
|
+
options.verbose = true;
|
|
102
|
+
break;
|
|
103
|
+
case '--help':
|
|
104
|
+
printUsage();
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { command, options };
|
|
109
|
+
}
|
|
110
|
+
function resolveOptions(cliOptions) {
|
|
111
|
+
// Load environment variables
|
|
112
|
+
const dotenv = require('dotenv');
|
|
113
|
+
dotenv.config();
|
|
114
|
+
const options = {
|
|
115
|
+
migrationsDir: cliOptions.migrationsDir || process.env.MIGRATIONS_DIR || '',
|
|
116
|
+
host: cliOptions.host || process.env.DB_HOST || 'localhost',
|
|
117
|
+
port: cliOptions.port || parseInt(process.env.DB_PORT || '1433', 10),
|
|
118
|
+
database: cliOptions.database || process.env.DB_DATABASE || '',
|
|
119
|
+
username: cliOptions.username || process.env.DB_USERNAME,
|
|
120
|
+
password: cliOptions.password || process.env.DB_PASSWORD,
|
|
121
|
+
encrypt: cliOptions.encrypt || process.env.DB_ENCRYPT === 'true',
|
|
122
|
+
trustServerCertificate: cliOptions.trustServerCertificate || false,
|
|
123
|
+
dryRun: cliOptions.dryRun || false,
|
|
124
|
+
verbose: cliOptions.verbose ?? true,
|
|
125
|
+
};
|
|
126
|
+
// Resolve relative paths
|
|
127
|
+
if (options.migrationsDir && !path.isAbsolute(options.migrationsDir)) {
|
|
128
|
+
options.migrationsDir = path.resolve(process.cwd(), options.migrationsDir);
|
|
129
|
+
}
|
|
130
|
+
return options;
|
|
131
|
+
}
|
|
132
|
+
function validateOptions(options) {
|
|
133
|
+
if (!options.migrationsDir) {
|
|
134
|
+
console.error('Error: --migrations-dir is required');
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
if (!options.database) {
|
|
138
|
+
console.error('Error: --database is required');
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function createDataSource(options) {
|
|
143
|
+
const dataSource = new typeorm_1.DataSource({
|
|
144
|
+
type: 'mssql',
|
|
145
|
+
host: options.host,
|
|
146
|
+
port: options.port,
|
|
147
|
+
database: options.database,
|
|
148
|
+
username: options.username,
|
|
149
|
+
password: options.password,
|
|
150
|
+
options: {
|
|
151
|
+
encrypt: options.encrypt || false,
|
|
152
|
+
trustServerCertificate: options.trustServerCertificate || false,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
await dataSource.initialize();
|
|
156
|
+
return dataSource;
|
|
157
|
+
}
|
|
158
|
+
async function runCommand(options) {
|
|
159
|
+
console.log('Starting migration runner...');
|
|
160
|
+
console.log(`Migrations directory: ${options.migrationsDir}`);
|
|
161
|
+
console.log(`Database: ${options.database}`);
|
|
162
|
+
console.log(`Host: ${options.host}:${options.port}`);
|
|
163
|
+
console.log('');
|
|
164
|
+
const dataSource = await createDataSource(options);
|
|
165
|
+
console.log('Database connection established');
|
|
166
|
+
try {
|
|
167
|
+
const migrationCore = new migration_core_1.MigrationCore(dataSource, {
|
|
168
|
+
migrationsDir: options.migrationsDir,
|
|
169
|
+
});
|
|
170
|
+
const result = await migrationCore.runMigrations({
|
|
171
|
+
dryRun: options.dryRun,
|
|
172
|
+
verbose: options.verbose,
|
|
173
|
+
});
|
|
174
|
+
if (result.success) {
|
|
175
|
+
console.log('');
|
|
176
|
+
console.log('Migration completed successfully!');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
await dataSource.destroy();
|
|
181
|
+
console.log('Database connection closed');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async function statusCommand(options) {
|
|
185
|
+
console.log('Checking migration status...');
|
|
186
|
+
console.log(`Migrations directory: ${options.migrationsDir}`);
|
|
187
|
+
console.log(`Database: ${options.database}`);
|
|
188
|
+
console.log('');
|
|
189
|
+
const dataSource = await createDataSource(options);
|
|
190
|
+
try {
|
|
191
|
+
const migrationCore = new migration_core_1.MigrationCore(dataSource, {
|
|
192
|
+
migrationsDir: options.migrationsDir,
|
|
193
|
+
});
|
|
194
|
+
const status = await migrationCore.getStatus();
|
|
195
|
+
console.log(`Total migrations: ${status.total}`);
|
|
196
|
+
console.log(`Applied: ${status.applied}`);
|
|
197
|
+
console.log(`Pending: ${status.pending}`);
|
|
198
|
+
if (status.pendingFiles.length > 0) {
|
|
199
|
+
console.log('');
|
|
200
|
+
console.log('Pending migrations:');
|
|
201
|
+
status.pendingFiles.forEach((file) => console.log(` - ${file}`));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
await dataSource.destroy();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async function main() {
|
|
209
|
+
const args = process.argv.slice(2);
|
|
210
|
+
if (args.length === 0 || args.includes('--help')) {
|
|
211
|
+
printUsage();
|
|
212
|
+
process.exit(0);
|
|
213
|
+
}
|
|
214
|
+
const { command, options: cliOptions } = parseArgs(args);
|
|
215
|
+
const options = resolveOptions(cliOptions);
|
|
216
|
+
if (!command) {
|
|
217
|
+
console.error('Error: No command specified. Use "run" or "status".');
|
|
218
|
+
printUsage();
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
validateOptions(options);
|
|
222
|
+
try {
|
|
223
|
+
switch (command) {
|
|
224
|
+
case 'run':
|
|
225
|
+
await runCommand(options);
|
|
226
|
+
break;
|
|
227
|
+
case 'status':
|
|
228
|
+
await statusCommand(options);
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
console.error(`Unknown command: ${command}`);
|
|
232
|
+
printUsage();
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
console.error('Migration failed:', error);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
main();
|
|
242
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vYmluL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxxQ0FBcUM7QUFDckMsNkJBQTZCO0FBQzdCLDBEQUFzRDtBQWV0RCxTQUFTLFVBQVU7SUFDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXFDYixDQUFDLENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsSUFBYztJQUMvQixNQUFNLE9BQU8sR0FBd0I7UUFDbkMsT0FBTyxFQUFFLElBQUk7S0FDZCxDQUFDO0lBQ0YsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO0lBRWpCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDckMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFNUIsUUFBUSxHQUFHLEVBQUUsQ0FBQztZQUNaLEtBQUssS0FBSyxDQUFDO1lBQ1gsS0FBSyxRQUFRO2dCQUNYLE9BQU8sR0FBRyxHQUFHLENBQUM7Z0JBQ2QsTUFBTTtZQUNSLEtBQUssa0JBQWtCLENBQUM7WUFDeEIsS0FBSyxJQUFJO2dCQUNQLE9BQU8sQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDO2dCQUNoQyxDQUFDLEVBQUUsQ0FBQztnQkFDSixNQUFNO1lBQ1IsS0FBSyxRQUFRLENBQUM7WUFDZCxLQUFLLElBQUk7Z0JBQ1AsT0FBTyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUM7Z0JBQ3ZCLENBQUMsRUFBRSxDQUFDO2dCQUNKLE1BQU07WUFDUixLQUFLLFFBQVEsQ0FBQztZQUNkLEtBQUssSUFBSTtnQkFDUCxPQUFPLENBQUMs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LENBQUM7SUFDbEIsQ0FBQztBQUNILENBQUM7QUFFRCxJQUFJLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIiMhL3Vzci9iaW4vZW52IG5vZGVcblxuaW1wb3J0IHsgRGF0YVNvdXJjZSB9IGZyb20gJ3R5cGVvcm0nO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IE1pZ3JhdGlvbkNvcmUgfSBmcm9tICcuLi9zcmMvbWlncmF0aW9uLWNvcmUnO1xuXG5pbnRlcmZhY2UgQ2xpT3B0aW9ucyB7XG4gIG1pZ3JhdGlvbnNEaXI6IHN0cmluZztcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBudW1iZXI7XG4gIGRhdGFiYXNlOiBzdHJpbmc7XG4gIHVzZXJuYW1lPzogc3RyaW5nO1xuICBwYXNzd29yZD86IHN0cmluZztcbiAgZW5jcnlwdD86IGJvb2xlYW47XG4gIHRydXN0U2VydmVyQ2VydGlmaWNhdGU/OiBib29sZWFuO1xuICBkcnlSdW4/OiBib29sZWFuO1xuICB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gcHJpbnRVc2FnZSgpOiB2b2lkIHtcbiAgY29uc29sZS5sb2coYFxuQHN0dWRpb3NvbnJhaS9uZXN0anMtbWlncmF0aW9ucyBDTElcblxuVXNhZ2U6XG4gIG5lc3Rqcy1taWdyYXRpb25zIHJ1biBbb3B0aW9uc11cbiAgbmVzdGpzLW1pZ3JhdGlvbnMgc3RhdHVzIFtvcHRpb25zXVxuXG5Db21tYW5kczpcbiAgcnVuICAgICAgIFJ1biBhbGwgcGVuZGluZyBtaWdyYXRpb25zXG4gIHN0YXR1cyAgICBTaG93IG1pZ3JhdGlvbiBzdGF0dXNcblxuT3B0aW9uczpcbiAgLS1taWdyYXRpb25zLWRpciwgLWQgICAgUGF0aCB0byBtaWdyYXRpb25zIGRpcmVjdG9yeSAocmVxdWlyZWQpXG4gIC0taG9zdCwgLWggICAgICAgICAgICAgIERhdGFiYXNlIGhvc3QgKGRlZmF1bHQ6IGxvY2FsaG9zdClcbiAgLS1wb3J0LCAtcCAgICAgICAgICAgICAgRGF0YWJhc2UgcG9ydCAoZGVmYXVsdDogMTQzMylcbiAgLS1kYXRhYmFzZSwgLUQgICAgICAgICAgRGF0YWJhc2UgbmFtZSAocmVxdWlyZWQpXG4gIC0tdXNlcm5hbWUsIC11ICAgICAgICAgIERhdGFiYXNlIHVzZXJuYW1lXG4gIC0tcGFzc3dvcmQsIC1QICAgICAgICAgIERhdGFiYXNlIHBhc3N3b3JkXG4gIC0tZW5jcnlwdCAgICAgICAgICAgICAgIEVuYWJsZSBlbmNyeXB0aW9uIChkZWZhdWx0OiBmYWxzZSlcbiAgLS10cnVzdC1jZXJ0ICAgICAgICAgICAgVHJ1c3Qgc2VydmVyIGNlcnRpZmljYXRlIChkZWZhdWx0OiBmYWxzZSlcbiAgLS1kcnktcnVuICAgICAgICAgICAgICAgU2hvdyBwZW5kaW5nIG1pZ3JhdGlvbnMgd2l0aG91dCBhcHBseWluZ1xuICAtLXZlcmJvc2UsIC12ICAgICAgICAgICBWZXJib3NlIG91dHB1dCAoZGVmYXVsdDogdHJ1ZSlcbiAgLS1oZWxwICAgICAgICAgICAgICAgICAgU2hvdyB0aGlzIGhlbHAgbWVzc2FnZVxuXG5FbnZpcm9ubWVudCB2YXJpYWJsZXM6XG4gIERCX0hPU1QgICAgICAgICAgICAgICAgIERhdGFiYXNlIGhvc3RcbiAgREJfUE9SVCAgICAgICAgICAgICAgICAgRGF0YWJhc2UgcG9ydFxuICBEQl9EQVRBQkFTRSAgICAgICAgICAgICBEYXRhYmFzZSBuYW1lXG4gIERCX1VTRVJOQU1FICAgICAgICAgICAgIERhdGFiYXNlIHVzZXJuYW1lXG4gIERCX1BBU1NXT1JEICAgICAgICAgICAgIERhdGFiYXNlIHBhc3N3b3JkXG4gIERCX0VOQ1JZUFQgICAgICAgICAgICAgIEVuYWJsZSBlbmNyeXB0aW9uXG4gIE1JR1JBVElPTlNfRElSICAgICAgICAgIFBhdGggdG8gbWlncmF0aW9ucyBkaXJlY3RvcnlcblxuRXhhbXBsZXM6XG4gIG5lc3Rqcy1taWdyYXRpb25zIHJ1biAtZCAuL21pZ3JhdGlvbnMgLUQgbXlkYiAtdSBzYSAtUCBwYXNzd29yZFxuICBuZXN0anMtbWlncmF0aW9ucyBzdGF0dXMgLS1taWdyYXRpb25zLWRpciAuL21pZ3JhdGlvbnMgLS1kYXRhYmFzZSBteWRiXG4gIG5lc3Rqcy1taWdyYXRpb25zIHJ1biAtLWRyeS1ydW4gLWQgLi9taWdyYXRpb25zIC1EIG15ZGJcbmApO1xufVxuXG5mdW5jdGlvbiBwYXJzZUFyZ3MoYXJnczogc3RyaW5nW10pOiB7IGNvbW1hbmQ6IHN0cmluZzsgb3B0aW9uczogUGFydGlhbDxDbGlPcHRpb25zPiB9IHtcbiAgY29uc3Qgb3B0aW9uczogUGFydGlhbDxDbGlPcHRpb25zPiA9IHtcbiAgICB2ZXJib3NlOiB0cnVlLFxuICB9O1xuICBsZXQgY29tbWFuZCA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGFyZyA9IGFyZ3NbaV07XG4gICAgY29uc3QgbmV4dEFyZyA9IGFyZ3NbaSArIDFdO1xuXG4gICAgc3dpdGNoIChhcmcpIHtcbiAgICAgIGNhc2UgJ3J1bic6XG4gICAgICBjYXNlICdzdGF0dXMnOlxuICAgICAgICBjb21tYW5kID0gYXJnO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJy0tbWlncmF0aW9ucy1kaXInOlxuICAgICAgY2FzZSAnLWQnOlxuICAgICAgICBvcHRpb25zLm1pZ3JhdGlvbnNEaXIgPSBuZXh0QXJnO1xuICAgICAgICBpKys7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnLS1ob3N0JzpcbiAgICAgIGNhc2UgJy1oJzpcbiAgICAgICAgb3B0aW9ucy5ob3N0ID0gbmV4dEFyZztcbiAgICAgICAgaSsrO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJy0tcG9ydCc6XG4gICAgICBjYXNlICctcCc6XG4gICAgICAgIG9wdGlvbnMucG9ydCA9IHBhcnNlSW50KG5leHRBcmcsIDEwKTtcbiAgICAgICAgaSsrO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJy0tZGF0YWJhc2UnOlxuICAgICAgY2FzZSAnLUQnOlxuICAgICAgICBvcHRpb25zLmRhdGFiYXNlID0gbmV4dEFyZztcbiAgICAgICAgaSsrO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJy0tdXNlcm5hbWUnOlxuICAgICAgY2FzZSAnLXUnOlxuICAgICAgICBvcHRpb25zLnVzZXJuYW1lID0gbmV4dEFyZztcbiAgICAgICAgaSsrO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJy0tcGFzc3dvcmQnOlxuICAgICAgY2FzZSAnLVAnOlxuICAgICAgICBvcHRpb25zLnBhc3N3b3JkID0gbmV4dEFyZztcbiAgICAgICAgaSsrO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJy0tZW5jcnlwdCc6XG4gICAgICAgIG9wdGlvbnMuZW5jcnlwdCA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnLS10cnVzdC1jZXJ0JzpcbiAgICAgICAgb3B0aW9ucy50cnVzdFNlcnZlckNlcnRpZmljYXRlID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICctLWRyeS1ydW4nOlxuICAgICAgICBvcHRpb25zLmRyeVJ1biA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnLS12ZXJib3NlJzpcbiAgICAgIGNhc2UgJy12JzpcbiAgICAgICAgb3B0aW9ucy52ZXJib3NlID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICctLWhlbHAnOlxuICAgICAgICBwcmludFVzYWdlKCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBjb21tYW5kLCBvcHRpb25zIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPcHRpb25zKGNsaU9wdGlvbnM6IFBhcnRpYWw8Q2xpT3B0aW9ucz4pOiBDbGlPcHRpb25zIHtcbiAgLy8gTG9hZCBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgY29uc3QgZG90ZW52ID0gcmVxdWlyZSgnZG90ZW52Jyk7XG4gIGRvdGVudi5jb25maWcoKTtcblxuICBjb25zdCBvcHRpb25zOiBDbGlPcHRpb25zID0ge1xuICAgIG1pZ3JhdGlvbnNEaXI6IGNsaU9wdGlvbnMubWlncmF0aW9uc0RpciB8fCBwcm9jZXNzLmVudi5NSUdSQVRJT05TX0RJUiB8fCAnJyxcbiAgICBob3N0OiBjbGlPcHRpb25zLmhvc3QgfHwgcHJvY2Vzcy5lbnYuREJfSE9TVCB8fCAnbG9jYWxob3N0JyxcbiAgICBwb3J0OiBjbGlPcHRpb25zLnBvcnQgfHwgcGFyc2VJbnQocHJvY2Vzcy5lbnYuREJfUE9SVCB8fCAnMTQzMycsIDEwKSxcbiAgICBkYXRhYmFzZTogY2xpT3B0aW9ucy5kYXRhYmFzZSB8fCBwcm9jZXNzLmVudi5EQl9EQVRBQkFTRSB8fCAnJyxcbiAgICB1c2VybmFtZTogY2xpT3B0aW9ucy51c2VybmFtZSB8fCBwcm9jZXNzLmVudi5EQl9VU0VSTkFNRSxcbiAgICBwYXNzd29yZDogY2xpT3B0aW9ucy5wYXNzd29yZCB8fCBwcm9jZXNzLmVudi5EQl9QQVNTV09SRCxcbiAgICBlbmNyeXB0OiBjbGlPcHRpb25zLmVuY3J5cHQgfHwgcHJvY2Vzcy5lbnYuREJfRU5DUllQVCA9PT0gJ3RydWUnLFxuICAgIHRydXN0U2VydmVyQ2VydGlmaWNhdGU6IGNsaU9wdGlvbnMudHJ1c3RTZXJ2ZXJDZXJ0aWZpY2F0ZSB8fCBmYWxzZSxcbiAgICBkcnlSdW46IGNsaU9wdGlvbnMuZHJ5UnVuIHx8IGZhbHNlLFxuICAgIHZlcmJvc2U6IGNsaU9wdGlvbnMudmVyYm9zZSA/PyB0cnVlLFxuICB9O1xuXG4gIC8vIFJlc29sdmUgcmVsYXRpdmUgcGF0aHNcbiAgaWYgKG9wdGlvbnMubWlncmF0aW9uc0RpciAmJiAhcGF0aC5pc0Fic29sdXRlKG9wdGlvbnMubWlncmF0aW9uc0RpcikpIHtcbiAgICBvcHRpb25zLm1pZ3JhdGlvbnNEaXIgPSBwYXRoLnJlc29sdmUocHJvY2Vzcy5jd2QoKSwgb3B0aW9ucy5taWdyYXRpb25zRGlyKTtcbiAgfVxuXG4gIHJldHVybiBvcHRpb25zO1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZU9wdGlvbnMob3B0aW9uczogQ2xpT3B0aW9ucyk6IHZvaWQge1xuICBpZiAoIW9wdGlvbnMubWlncmF0aW9uc0Rpcikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yOiAtLW1pZ3JhdGlvbnMtZGlyIGlzIHJlcXVpcmVkJyk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG5cbiAgaWYgKCFvcHRpb25zLmRhdGFiYXNlKSB7XG4gICAgY29uc29sZS5lcnJvcignRXJyb3I6IC0tZGF0YWJhc2UgaXMgcmVxdWlyZWQnKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlRGF0YVNvdXJjZShvcHRpb25zOiBDbGlPcHRpb25zKTogUHJvbWlzZTxEYXRhU291cmNlPiB7XG4gIGNvbnN0IGRhdGFTb3VyY2UgPSBuZXcgRGF0YVNvdXJjZSh7XG4gICAgdHlwZTogJ21zc3FsJyxcbiAgICBob3N0OiBvcHRpb25zLmhvc3QsXG4gICAgcG9ydDogb3B0aW9ucy5wb3J0LFxuICAgIGRhdGFiYXNlOiBvcHRpb25zLmRhdGFiYXNlLFxuICAgIHVzZXJuYW1lOiBvcHRpb25zLnVzZXJuYW1lLFxuICAgIHBhc3N3b3JkOiBvcHRpb25zLnBhc3N3b3JkLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIGVuY3J5cHQ6IG9wdGlvbnMuZW5jcnlwdCB8fCBmYWxzZSxcbiAgICAgIHRydXN0U2VydmVyQ2VydGlmaWNhdGU6IG9wdGlvbnMudHJ1c3RTZXJ2ZXJDZXJ0aWZpY2F0ZSB8fCBmYWxzZSxcbiAgICB9LFxuICB9KTtcblxuICBhd2FpdCBkYXRhU291cmNlLmluaXRpYWxpemUoKTtcbiAgcmV0dXJuIGRhdGFTb3VyY2U7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1bkNvbW1hbmQob3B0aW9uczogQ2xpT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zb2xlLmxvZygnU3RhcnRpbmcgbWlncmF0aW9uIHJ1bm5lci4uLicpO1xuICBjb25zb2xlLmxvZyhgTWlncmF0aW9ucyBkaXJlY3Rvcnk6ICR7b3B0aW9ucy5taWdyYXRpb25zRGlyfWApO1xuICBjb25zb2xlLmxvZyhgRGF0YWJhc2U6ICR7b3B0aW9ucy5kYXRhYmFzZX1gKTtcbiAgY29uc29sZS5sb2coYEhvc3Q6ICR7b3B0aW9ucy5ob3N0fToke29wdGlvbnMucG9ydH1gKTtcbiAgY29uc29sZS5sb2coJycpO1xuXG4gIGNvbnN0IGRhdGFTb3VyY2UgPSBhd2FpdCBjcmVhdGVEYXRhU291cmNlKG9wdGlvbnMpO1xuICBjb25zb2xlLmxvZygnRGF0YWJhc2UgY29ubmVjdGlvbiBlc3RhYmxpc2hlZCcpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgbWlncmF0aW9uQ29yZSA9IG5ldyBNaWdyYXRpb25Db3JlKGRhdGFTb3VyY2UsIHtcbiAgICAgIG1pZ3JhdGlvbnNEaXI6IG9wdGlvbnMubWlncmF0aW9uc0RpcixcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG1pZ3JhdGlvbkNvcmUucnVuTWlncmF0aW9ucyh7XG4gICAgICBkcnlSdW46IG9wdGlvbnMuZHJ5UnVuLFxuICAgICAgdmVyYm9zZTogb3B0aW9ucy52ZXJib3NlLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICBjb25zb2xlLmxvZygnTWlncmF0aW9uIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHkhJyk7XG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGRhdGFTb3VyY2UuZGVzdHJveSgpO1xuICAgIGNvbnNvbGUubG9nKCdEYXRhYmFzZSBjb25uZWN0aW9uIGNsb3NlZCcpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN0YXR1c0NvbW1hbmQob3B0aW9uczogQ2xpT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zb2xlLmxvZygnQ2hlY2tpbmcgbWlncmF0aW9uIHN0YXR1cy4uLicpO1xuICBjb25zb2xlLmxvZyhgTWlncmF0aW9ucyBkaXJlY3Rvcnk6ICR7b3B0aW9ucy5taWdyYXRpb25zRGlyfWApO1xuICBjb25zb2xlLmxvZyhgRGF0YWJhc2U6ICR7b3B0aW9ucy5kYXRhYmFzZX1gKTtcbiAgY29uc29sZS5sb2coJycpO1xuXG4gIGNvbnN0IGRhdGFTb3VyY2UgPSBhd2FpdCBjcmVhdGVEYXRhU291cmNlKG9wdGlvbnMpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgbWlncmF0aW9uQ29yZSA9IG5ldyBNaWdyYXRpb25Db3JlKGRhdGFTb3VyY2UsIHtcbiAgICAgIG1pZ3JhdGlvbnNEaXI6IG9wdGlvbnMubWlncmF0aW9uc0RpcixcbiAgICB9KTtcblxuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IG1pZ3JhdGlvbkNvcmUuZ2V0U3RhdHVzKCk7XG5cbiAgICBjb25zb2xlLmxvZyhgVG90YWwgbWlncmF0aW9uczogJHtzdGF0dXMudG90YWx9YCk7XG4gICAgY29uc29sZS5sb2coYEFwcGxpZWQ6ICR7c3RhdHVzLmFwcGxpZWR9YCk7XG4gICAgY29uc29sZS5sb2coYFBlbmRpbmc6ICR7c3RhdHVzLnBlbmRpbmd9YCk7XG5cbiAgICBpZiAoc3RhdHVzLnBlbmRpbmdGaWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICBjb25zb2xlLmxvZygnUGVuZGluZyBtaWdyYXRpb25zOicpO1xuICAgICAgc3RhdHVzLnBlbmRpbmdGaWxlcy5mb3JFYWNoKChmaWxlKSA9PiBjb25zb2xlLmxvZyhgICAtICR7ZmlsZX1gKSk7XG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGRhdGFTb3VyY2UuZGVzdHJveSgpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1haW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGFyZ3MgPSBwcm9jZXNzLmFyZ3Yuc2xpY2UoMik7XG5cbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAwIHx8IGFyZ3MuaW5jbHVkZXMoJy0taGVscCcpKSB7XG4gICAgcHJpbnRVc2FnZSgpO1xuICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgfVxuXG4gIGNvbnN0IHsgY29tbWFuZCwgb3B0aW9uczogY2xpT3B0aW9ucyB9ID0gcGFyc2VBcmdzKGFyZ3MpO1xuICBjb25zdCBvcHRpb25zID0gcmVzb2x2ZU9wdGlvbnMoY2xpT3B0aW9ucyk7XG5cbiAgaWYgKCFjb21tYW5kKSB7XG4gICAgY29uc29sZS5lcnJvcignRXJyb3I6IE5vIGNvbW1hbmQgc3BlY2lmaWVkLiBVc2UgXCJydW5cIiBvciBcInN0YXR1c1wiLicpO1xuICAgIHByaW50VXNhZ2UoKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cblxuICB2YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG5cbiAgdHJ5IHtcbiAgICBzd2l0Y2ggKGNvbW1hbmQpIHtcbiAgICAgIGNhc2UgJ3J1bic6XG4gICAgICAgIGF3YWl0IHJ1bkNvbW1hbmQob3B0aW9ucyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnc3RhdHVzJzpcbiAgICAgICAgYXdhaXQgc3RhdHVzQ29tbWFuZChvcHRpb25zKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBjb25zb2xlLmVycm9yKGBVbmtub3duIGNvbW1hbmQ6ICR7Y29tbWFuZH1gKTtcbiAgICAgICAgcHJpbnRVc2FnZSgpO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ01pZ3JhdGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxufVxuXG5tYWluKCk7XG4iXX0=
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { MigrationModule } from './migration.module';
|
|
2
|
+
export { MigrationService } from './migration.service';
|
|
3
|
+
export { MigrationCore } from './migration-core';
|
|
4
|
+
export { MigrationModuleOptions, MigrationModuleAsyncOptions, MigrationModuleOptionsFactory, MigrationResult, MigrationRunOptions, MigrationCoreOptions, MIGRATION_MODULE_OPTIONS, } from './types';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MIGRATION_MODULE_OPTIONS = exports.MigrationCore = exports.MigrationService = exports.MigrationModule = void 0;
|
|
4
|
+
// Module
|
|
5
|
+
var migration_module_1 = require("./migration.module");
|
|
6
|
+
Object.defineProperty(exports, "MigrationModule", { enumerable: true, get: function () { return migration_module_1.MigrationModule; } });
|
|
7
|
+
// Service
|
|
8
|
+
var migration_service_1 = require("./migration.service");
|
|
9
|
+
Object.defineProperty(exports, "MigrationService", { enumerable: true, get: function () { return migration_service_1.MigrationService; } });
|
|
10
|
+
// Core (for standalone/CLI usage)
|
|
11
|
+
var migration_core_1 = require("./migration-core");
|
|
12
|
+
Object.defineProperty(exports, "MigrationCore", { enumerable: true, get: function () { return migration_core_1.MigrationCore; } });
|
|
13
|
+
// Types
|
|
14
|
+
var types_1 = require("./types");
|
|
15
|
+
Object.defineProperty(exports, "MIGRATION_MODULE_OPTIONS", { enumerable: true, get: function () { return types_1.MIGRATION_MODULE_OPTIONS; } });
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsU0FBUztBQUNULHVEQUFxRDtBQUE1QyxtSEFBQSxlQUFlLE9BQUE7QUFFeEIsVUFBVTtBQUNWLHlEQUF1RDtBQUE5QyxxSEFBQSxnQkFBZ0IsT0FBQTtBQUV6QixrQ0FBa0M7QUFDbEMsbURBQWlEO0FBQXhDLCtHQUFBLGFBQWEsT0FBQTtBQUV0QixRQUFRO0FBQ1IsaUNBUWlCO0FBRGYsaUhBQUEsd0JBQXdCLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBNb2R1bGVcbmV4cG9ydCB7IE1pZ3JhdGlvbk1vZHVsZSB9IGZyb20gJy4vbWlncmF0aW9uLm1vZHVsZSc7XG5cbi8vIFNlcnZpY2VcbmV4cG9ydCB7IE1pZ3JhdGlvblNlcnZpY2UgfSBmcm9tICcuL21pZ3JhdGlvbi5zZXJ2aWNlJztcblxuLy8gQ29yZSAoZm9yIHN0YW5kYWxvbmUvQ0xJIHVzYWdlKVxuZXhwb3J0IHsgTWlncmF0aW9uQ29yZSB9IGZyb20gJy4vbWlncmF0aW9uLWNvcmUnO1xuXG4vLyBUeXBlc1xuZXhwb3J0IHtcbiAgTWlncmF0aW9uTW9kdWxlT3B0aW9ucyxcbiAgTWlncmF0aW9uTW9kdWxlQXN5bmNPcHRpb25zLFxuICBNaWdyYXRpb25Nb2R1bGVPcHRpb25zRmFjdG9yeSxcbiAgTWlncmF0aW9uUmVzdWx0LFxuICBNaWdyYXRpb25SdW5PcHRpb25zLFxuICBNaWdyYXRpb25Db3JlT3B0aW9ucyxcbiAgTUlHUkFUSU9OX01PRFVMRV9PUFRJT05TLFxufSBmcm9tICcuL3R5cGVzJztcbiJdfQ==
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { DataSource, QueryRunner } from 'typeorm';
|
|
2
|
+
import { MigrationCoreOptions, MigrationResult, MigrationRunOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Core migration runner for SQL Server databases.
|
|
5
|
+
* Handles reading SQL migration files, tracking applied migrations,
|
|
6
|
+
* and executing pending migrations within transactions.
|
|
7
|
+
*/
|
|
8
|
+
export declare class MigrationCore {
|
|
9
|
+
private readonly dataSource;
|
|
10
|
+
private readonly migrationsDir;
|
|
11
|
+
constructor(dataSource: DataSource, options: MigrationCoreOptions);
|
|
12
|
+
/**
|
|
13
|
+
* Ensures the migrations tracking table exists in the database.
|
|
14
|
+
* Creates it if it doesn't exist.
|
|
15
|
+
*/
|
|
16
|
+
ensureMigrationsTable(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Gets the list of migrations that have already been applied.
|
|
19
|
+
*/
|
|
20
|
+
getAppliedMigrations(): Promise<string[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Gets all SQL migration files from the migrations directory.
|
|
23
|
+
* Files are sorted alphabetically (by convention, use numeric prefixes).
|
|
24
|
+
*/
|
|
25
|
+
getMigrationFiles(): Promise<string[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Runs a single migration file within the provided query runner.
|
|
28
|
+
* Handles SQL Server's GO batch separator.
|
|
29
|
+
*/
|
|
30
|
+
runSingleMigration(file: string, queryRunner: QueryRunner): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Runs all pending migrations.
|
|
33
|
+
* Each migration runs in its own transaction for isolation.
|
|
34
|
+
*/
|
|
35
|
+
runMigrations(options?: MigrationRunOptions): Promise<MigrationResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Gets the list of pending migrations without applying them.
|
|
38
|
+
*/
|
|
39
|
+
getPendingMigrations(): Promise<string[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Gets migration status information.
|
|
42
|
+
*/
|
|
43
|
+
getStatus(): Promise<{
|
|
44
|
+
total: number;
|
|
45
|
+
applied: number;
|
|
46
|
+
pending: number;
|
|
47
|
+
pendingFiles: string[];
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MigrationCore = void 0;
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const MIGRATION_TABLE = 'migrations';
|
|
7
|
+
/**
|
|
8
|
+
* Core migration runner for SQL Server databases.
|
|
9
|
+
* Handles reading SQL migration files, tracking applied migrations,
|
|
10
|
+
* and executing pending migrations within transactions.
|
|
11
|
+
*/
|
|
12
|
+
class MigrationCore {
|
|
13
|
+
dataSource;
|
|
14
|
+
migrationsDir;
|
|
15
|
+
constructor(dataSource, options) {
|
|
16
|
+
this.dataSource = dataSource;
|
|
17
|
+
this.migrationsDir = options.migrationsDir;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Ensures the migrations tracking table exists in the database.
|
|
21
|
+
* Creates it if it doesn't exist.
|
|
22
|
+
*/
|
|
23
|
+
async ensureMigrationsTable() {
|
|
24
|
+
const tableExists = await this.dataSource.query(`
|
|
25
|
+
SELECT COUNT(*) as count FROM sysobjects WHERE name='${MIGRATION_TABLE}' AND xtype='U'
|
|
26
|
+
`);
|
|
27
|
+
if (tableExists[0].count === 0) {
|
|
28
|
+
await this.dataSource.query(`
|
|
29
|
+
CREATE TABLE ${MIGRATION_TABLE} (
|
|
30
|
+
id INT IDENTITY(1,1) PRIMARY KEY,
|
|
31
|
+
name NVARCHAR(255) UNIQUE NOT NULL,
|
|
32
|
+
run_on DATETIME DEFAULT GETDATE() NOT NULL
|
|
33
|
+
)
|
|
34
|
+
`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Gets the list of migrations that have already been applied.
|
|
39
|
+
*/
|
|
40
|
+
async getAppliedMigrations() {
|
|
41
|
+
const rows = await this.dataSource.query(`SELECT name FROM ${MIGRATION_TABLE}`);
|
|
42
|
+
return rows.map((row) => row.name);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Gets all SQL migration files from the migrations directory.
|
|
46
|
+
* Files are sorted alphabetically (by convention, use numeric prefixes).
|
|
47
|
+
*/
|
|
48
|
+
async getMigrationFiles() {
|
|
49
|
+
if (!fs.existsSync(this.migrationsDir)) {
|
|
50
|
+
throw new Error(`Migrations directory not found: ${this.migrationsDir}`);
|
|
51
|
+
}
|
|
52
|
+
return fs
|
|
53
|
+
.readdirSync(this.migrationsDir)
|
|
54
|
+
.filter((f) => f.endsWith('.sql'))
|
|
55
|
+
.sort();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Runs a single migration file within the provided query runner.
|
|
59
|
+
* Handles SQL Server's GO batch separator.
|
|
60
|
+
*/
|
|
61
|
+
async runSingleMigration(file, queryRunner) {
|
|
62
|
+
const sql = fs.readFileSync(path.join(this.migrationsDir, file), 'utf8');
|
|
63
|
+
// Split SQL by GO statements (batch separator for SQL Server)
|
|
64
|
+
// GO is not part of T-SQL and must be handled by the client
|
|
65
|
+
const batches = sql
|
|
66
|
+
.split(/^\s*GO\s*$/im)
|
|
67
|
+
.map((batch) => batch.trim())
|
|
68
|
+
.filter((batch) => batch.length > 0);
|
|
69
|
+
// Run each batch separately
|
|
70
|
+
for (const batch of batches) {
|
|
71
|
+
await queryRunner.query(batch);
|
|
72
|
+
}
|
|
73
|
+
// Track the migration
|
|
74
|
+
await queryRunner.query(`INSERT INTO ${MIGRATION_TABLE} (name, run_on) VALUES (@0, GETDATE())`, [file]);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Runs all pending migrations.
|
|
78
|
+
* Each migration runs in its own transaction for isolation.
|
|
79
|
+
*/
|
|
80
|
+
async runMigrations(options) {
|
|
81
|
+
const result = {
|
|
82
|
+
success: false,
|
|
83
|
+
totalMigrations: 0,
|
|
84
|
+
appliedMigrations: 0,
|
|
85
|
+
pendingMigrations: 0,
|
|
86
|
+
};
|
|
87
|
+
try {
|
|
88
|
+
await this.ensureMigrationsTable();
|
|
89
|
+
const files = await this.getMigrationFiles();
|
|
90
|
+
const applied = await this.getAppliedMigrations();
|
|
91
|
+
result.totalMigrations = files.length;
|
|
92
|
+
result.appliedMigrations = applied.length;
|
|
93
|
+
if (options?.verbose) {
|
|
94
|
+
console.log(`Found ${files.length} migration files`);
|
|
95
|
+
console.log(`${applied.length} migrations already applied`);
|
|
96
|
+
}
|
|
97
|
+
const pendingMigrations = files.filter((file) => !applied.includes(file));
|
|
98
|
+
result.pendingMigrations = pendingMigrations.length;
|
|
99
|
+
if (pendingMigrations.length === 0) {
|
|
100
|
+
if (options?.verbose) {
|
|
101
|
+
console.log('No pending migrations to apply');
|
|
102
|
+
}
|
|
103
|
+
result.success = true;
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
if (options?.dryRun) {
|
|
107
|
+
console.log('Dry run mode - would apply:');
|
|
108
|
+
pendingMigrations.forEach((file) => console.log(` - ${file}`));
|
|
109
|
+
result.success = true;
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
if (options?.verbose) {
|
|
113
|
+
console.log(`Running ${pendingMigrations.length} pending migrations...`);
|
|
114
|
+
}
|
|
115
|
+
for (const file of pendingMigrations) {
|
|
116
|
+
if (options?.verbose) {
|
|
117
|
+
console.log(`Applying migration: ${file}`);
|
|
118
|
+
}
|
|
119
|
+
// Use a transaction for each migration
|
|
120
|
+
const queryRunner = this.dataSource.createQueryRunner();
|
|
121
|
+
await queryRunner.connect();
|
|
122
|
+
await queryRunner.startTransaction();
|
|
123
|
+
try {
|
|
124
|
+
await this.runSingleMigration(file, queryRunner);
|
|
125
|
+
await queryRunner.commitTransaction();
|
|
126
|
+
if (options?.verbose) {
|
|
127
|
+
console.log(`✓ Applied migration: ${file}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
await queryRunner.rollbackTransaction();
|
|
132
|
+
if (options?.verbose) {
|
|
133
|
+
console.error(`Failed to apply migration ${file}:`, error);
|
|
134
|
+
}
|
|
135
|
+
result.failedMigration = file;
|
|
136
|
+
result.error = error;
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
await queryRunner.release();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
result.success = true;
|
|
144
|
+
result.appliedMigrations += pendingMigrations.length;
|
|
145
|
+
if (options?.verbose) {
|
|
146
|
+
console.log('All migrations completed successfully!');
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
result.error = error;
|
|
152
|
+
if (options?.verbose) {
|
|
153
|
+
console.error('Migration failed:', error);
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Gets the list of pending migrations without applying them.
|
|
160
|
+
*/
|
|
161
|
+
async getPendingMigrations() {
|
|
162
|
+
await this.ensureMigrationsTable();
|
|
163
|
+
const files = await this.getMigrationFiles();
|
|
164
|
+
const applied = await this.getAppliedMigrations();
|
|
165
|
+
return files.filter((file) => !applied.includes(file));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Gets migration status information.
|
|
169
|
+
*/
|
|
170
|
+
async getStatus() {
|
|
171
|
+
await this.ensureMigrationsTable();
|
|
172
|
+
const files = await this.getMigrationFiles();
|
|
173
|
+
const applied = await this.getAppliedMigrations();
|
|
174
|
+
const pendingFiles = files.filter((file) => !applied.includes(file));
|
|
175
|
+
return {
|
|
176
|
+
total: files.length,
|
|
177
|
+
applied: applied.length,
|
|
178
|
+
pending: pendingFiles.length,
|
|
179
|
+
pendingFiles,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.MigrationCore = MigrationCore;
|
|
184
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLWNvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlncmF0aW9uLWNvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUc3QixNQUFNLGVBQWUsR0FBRyxZQUFZLENBQUM7QUFFckM7Ozs7R0FJRztBQUNILE1BQWEsYUFBYTtJQUlMO0lBSEYsYUFBYSxDQUFTO0lBRXZDLFlBQ21CLFVBQXNCLEVBQ3ZDLE9BQTZCO1FBRFosZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUd2QyxJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUM7SUFDN0MsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxxQkFBcUI7UUFDekIsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQzs2REFDUyxlQUFlO0tBQ3ZFLENBQUMsQ0FBQztRQUVILElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMvQixNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO3VCQUNYLGVBQWU7Ozs7O09BSy9CLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsb0JBQW9CO1FBQ3hCLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQ3RDLG9CQUFvQixlQUFlLEVBQUUsQ0FDdEMsQ0FBQztRQUNGLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsaUJBQWlCO1FBQ3JCLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFFRCxPQUFPLEVBQUU7YUFDTixXQUFXLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQzthQUMvQixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDakMsSUFBSSxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGtCQUFrQixDQUN0QixJQUFZLEVBQ1osV0FBd0I7UUFFeEIsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFekUsOERBQThEO1FBQzlELDREQUE0RDtRQUM1RCxNQUFNLE9BQU8sR0FBRyxHQUFHO2FBQ2hCLEtBQUssQ0FBQyxjQUFjLENBQUM7YUFDckIsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7YUFDNUIsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRXZDLDRCQUE0QjtRQUM1QixLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzVCLE1BQU0sV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBRUQsc0JBQXNCO1FBQ3RCLE1BQU0sV0FBVyxDQUFDLEtBQUssQ0FDckIsZUFBZSxlQUFlLHdDQUF3QyxFQUN0RSxDQUFDLElBQUksQ0FBQyxDQUNQLENBQUM7SUFDSixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGFBQWEsQ0FBQyxPQUE2QjtRQUMvQyxNQUFNLE1BQU0sR0FBb0I7WUFDOUIsT0FBTyxFQUFFLEtBQUs7WUFDZCxlQUFlLEVBQUUsQ0FBQztZQUNsQixpQkFBaUIsRUFBRSxDQUFDO1lBQ3BCLGlCQUFpQixFQUFFLENBQUM7U0FDckIsQ0FBQztRQUVGLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFFbkMsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUM3QyxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBRWxELE1BQU0sQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUN0QyxNQUFNLENBQUMsaUJBQWlCLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztZQUUxQyxJQUFJLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztnQkFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEtBQUssQ0FBQyxNQUFNLGtCQUFrQixDQUFDLENBQUM7Z0JBQ3JELE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSw2QkFBNkIsQ0FBQyxDQUFDO1lBQzlELENBQUM7WUFFRCxNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzFFLE1BQU0sQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLENBQUM7WUFFcEQsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ25DLElBQUksT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDO29CQUNyQixPQUFPLENBQUMsR0FBRyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7Z0JBQ2hELENBQUM7Z0JBQ0QsTUFBTSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7Z0JBQ3RCLE9BQU8sTUFBTSxDQUFDO1lBQ2hCLENBQUM7WUFFRCxJQUFJLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztnQkFDcEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO2dCQUMzQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hFLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO2dCQUN0QixPQUFPLE1BQU0sQ0FBQztZQUNoQixDQUFDO1lBRUQsSUFBSSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7Z0JBQ3JCLE9BQU8sQ0FBQyxHQUFHLENBQ1QsV0FBVyxpQkFBaUIsQ0FBQyxNQUFNLHdCQUF3QixDQUM1RCxDQUFDO1lBQ0osQ0FBQztZQUVELEtBQUssTUFBTSxJQUFJLElBQUksaUJBQWlCLEVBQUUsQ0FBQztnQkFDckMsSUFBSSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7b0JBQ3JCLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQzdDLENBQUM7Z0JBRUQsdUNBQXVDO2dCQUN2QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQ3hELE1BQU0sV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUM1QixNQUFNLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUVyQyxJQUFJLENBQUM7b0JBQ0gsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO29CQUNqRCxNQUFNLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO29CQUV0QyxJQUFJLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQzt3QkFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsSUFBSSxFQUFFLENBQUMsQ0FBQztvQkFDOUMsQ0FBQztnQkFDSCxDQUFDO2dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7b0JBQ2YsTUFBTSxXQUFXLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFFeEMsSUFBSSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7d0JBQ3JCLE9BQU8sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLElBQUksR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUM3RCxDQUFDO29CQUVELE1BQU0sQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDO29CQUM5QixNQUFNLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztvQkFDckIsTUFBTSxLQUFLLENBQUM7Z0JBQ2QsQ0FBQzt3QkFBUyxDQUFDO29CQUNULE1BQU0sV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUM5QixDQUFDO1lBQ0gsQ0FBQztZQUVELE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1lBQ3RCLE1BQU0sQ0FBQyxpQkFBaUIsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLENBQUM7WUFFckQsSUFBSSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7Z0JBQ3JCLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0NBQXdDLENBQUMsQ0FBQztZQUN4RCxDQUFDO1lBRUQsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztZQUVyQixJQUFJLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztnQkFDckIsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM1QyxDQUFDO1lBRUQsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLG9CQUFvQjtRQUN4QixNQUFNLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ25DLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDN0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUNsRCxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxTQUFTO1FBTWIsTUFBTSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNuQyxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQzdDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDbEQsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFFckUsT0FBTztZQUNMLEtBQUssRUFBRSxLQUFLLENBQUMsTUFBTTtZQUNuQixPQUFPLEVBQUUsT0FBTyxDQUFDLE1BQU07WUFDdkIsT0FBTyxFQUFFLFlBQVksQ0FBQyxNQUFNO1lBQzVCLFlBQVk7U0FDYixDQUFDO0lBQ0osQ0FBQztDQUNGO0FBeE5ELHNDQXdOQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGFTb3VyY2UsIFF1ZXJ5UnVubmVyIH0gZnJvbSAndHlwZW9ybSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgTWlncmF0aW9uQ29yZU9wdGlvbnMsIE1pZ3JhdGlvblJlc3VsdCwgTWlncmF0aW9uUnVuT3B0aW9ucyB9IGZyb20gJy4vdHlwZXMnO1xuXG5jb25zdCBNSUdSQVRJT05fVEFCTEUgPSAnbWlncmF0aW9ucyc7XG5cbi8qKlxuICogQ29yZSBtaWdyYXRpb24gcnVubmVyIGZvciBTUUwgU2VydmVyIGRhdGFiYXNlcy5cbiAqIEhhbmRsZXMgcmVhZGluZyBTUUwgbWlncmF0aW9uIGZpbGVzLCB0cmFja2luZyBhcHBsaWVkIG1pZ3JhdGlvbnMsXG4gKiBhbmQgZXhlY3V0aW5nIHBlbmRpbmcgbWlncmF0aW9ucyB3aXRoaW4gdHJhbnNhY3Rpb25zLlxuICovXG5leHBvcnQgY2xhc3MgTWlncmF0aW9uQ29yZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWlncmF0aW9uc0Rpcjogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZGF0YVNvdXJjZTogRGF0YVNvdXJjZSxcbiAgICBvcHRpb25zOiBNaWdyYXRpb25Db3JlT3B0aW9ucyxcbiAgKSB7XG4gICAgdGhpcy5taWdyYXRpb25zRGlyID0gb3B0aW9ucy5taWdyYXRpb25zRGlyO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZXMgdGhlIG1pZ3JhdGlvbnMgdHJhY2tpbmcgdGFibGUgZXhpc3RzIGluIHRoZSBkYXRhYmFzZS5cbiAgICogQ3JlYXRlcyBpdCBpZiBpdCBkb2Vzbid0IGV4aXN0LlxuICAgKi9cbiAgYXN5bmMgZW5zdXJlTWlncmF0aW9uc1RhYmxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRhYmxlRXhpc3RzID0gYXdhaXQgdGhpcy5kYXRhU291cmNlLnF1ZXJ5KGBcbiAgICAgIFNFTEVDVCBDT1VOVCgqKSBhcyBjb3VudCBGUk9NIHN5c29iamVjdHMgV0hFUkUgbmFtZT0nJHtNSUdSQVRJT05fVEFCTEV9JyBBTkQgeHR5cGU9J1UnXG4gICAgYCk7XG5cbiAgICBpZiAodGFibGVFeGlzdHNbMF0uY291bnQgPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuZGF0YVNvdXJjZS5xdWVyeShgXG4gICAgICAgIENSRUFURSBUQUJMRSAke01JR1JBVElPTl9UQUJMRX0gKFxuICAgICAgICAgIGlkIElOVCBJREVOVElUWSgxLDEpIFBSSU1BUlkgS0VZLFxuICAgICAgICAgIG5hbWUgTlZBUkNIQVIoMjU1KSBVTklRVUUgTk9UIE5VTEwsXG4gICAgICAgICAgcnVuX29uIERBVEVUSU1FIERFRkFVTFQgR0VUREFURSgpIE5PVCBOVUxMXG4gICAgICAgIClcbiAgICAgIGApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIG1pZ3JhdGlvbnMgdGhhdCBoYXZlIGFscmVhZHkgYmVlbiBhcHBsaWVkLlxuICAgKi9cbiAgYXN5bmMgZ2V0QXBwbGllZE1pZ3JhdGlvbnMoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IHJvd3MgPSBhd2FpdCB0aGlzLmRhdGFTb3VyY2UucXVlcnk8eyBuYW1lOiBzdHJpbmcgfVtdPihcbiAgICAgIGBTRUxFQ1QgbmFtZSBGUk9NICR7TUlHUkFUSU9OX1RBQkxFfWAsXG4gICAgKTtcbiAgICByZXR1cm4gcm93cy5tYXAoKHJvdykgPT4gcm93Lm5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgYWxsIFNRTCBtaWdyYXRpb24gZmlsZXMgZnJvbSB0aGUgbWlncmF0aW9ucyBkaXJlY3RvcnkuXG4gICAqIEZpbGVzIGFyZSBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkgKGJ5IGNvbnZlbnRpb24sIHVzZSBudW1lcmljIHByZWZpeGVzKS5cbiAgICovXG4gIGFzeW5jIGdldE1pZ3JhdGlvbkZpbGVzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmModGhpcy5taWdyYXRpb25zRGlyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNaWdyYXRpb25zIGRpcmVjdG9yeSBub3QgZm91bmQ6ICR7dGhpcy5taWdyYXRpb25zRGlyfWApO1xuICAgIH1cblxuICAgIHJldHVybiBmc1xuICAgICAgLnJlYWRkaXJTeW5jKHRoaXMubWlncmF0aW9uc0RpcilcbiAgICAgIC5maWx0ZXIoKGYpID0+IGYuZW5kc1dpdGgoJy5zcWwnKSlcbiAgICAgIC5zb3J0KCk7XG4gIH1cblxuICAvKipcbiAgICogUnVucyBhIHNpbmdsZSBtaWdyYXRpb24gZmlsZSB3aXRoaW4gdGhlIHByb3ZpZGVkIHF1ZXJ5IHJ1bm5lci5cbiAgICogSGFuZGxlcyBTUUwgU2VydmVyJ3MgR08gYmF0Y2ggc2VwYXJhdG9yLlxuICAgKi9cbiAgYXN5bmMgcnVuU2luZ2xlTWlncmF0aW9uKFxuICAgIGZpbGU6IHN0cmluZyxcbiAgICBxdWVyeVJ1bm5lcjogUXVlcnlSdW5uZXIsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHNxbCA9IGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4odGhpcy5taWdyYXRpb25zRGlyLCBmaWxlKSwgJ3V0ZjgnKTtcblxuICAgIC8vIFNwbGl0IFNRTCBieSBHTyBzdGF0ZW1lbnRzIChiYXRjaCBzZXBhcmF0b3IgZm9yIFNRTCBTZXJ2ZXIpXG4gICAgLy8gR08gaXMgbm90IHBhcnQgb2YgVC1TUUwgYW5kIG11c3QgYmUgaGFuZGxlZCBieSB0aGUgY2xpZW50XG4gICAgY29uc3QgYmF0Y2hlcyA9IHNxbFxuICAgICAgLnNwbGl0KC9eXFxzKkdPXFxzKiQvaW0pXG4gICAgICAubWFwKChiYXRjaCkgPT4gYmF0Y2gudHJpbSgpKVxuICAgICAgLmZpbHRlcigoYmF0Y2gpID0+IGJhdGNoLmxlbmd0aCA+IDApO1xuXG4gICAgLy8gUnVuIGVhY2ggYmF0Y2ggc2VwYXJhdGVseVxuICAgIGZvciAoY29uc3QgYmF0Y2ggb2YgYmF0Y2hlcykge1xuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucXVlcnkoYmF0Y2gpO1xuICAgIH1cblxuICAgIC8vIFRyYWNrIHRoZSBtaWdyYXRpb25cbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5xdWVyeShcbiAgICAgIGBJTlNFUlQgSU5UTyAke01JR1JBVElPTl9UQUJMRX0gKG5hbWUsIHJ1bl9vbikgVkFMVUVTIChAMCwgR0VUREFURSgpKWAsXG4gICAgICBbZmlsZV0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGFsbCBwZW5kaW5nIG1pZ3JhdGlvbnMuXG4gICAqIEVhY2ggbWlncmF0aW9uIHJ1bnMgaW4gaXRzIG93biB0cmFuc2FjdGlvbiBmb3IgaXNvbGF0aW9uLlxuICAgKi9cbiAgYXN5bmMgcnVuTWlncmF0aW9ucyhvcHRpb25zPzogTWlncmF0aW9uUnVuT3B0aW9ucyk6IFByb21pc2U8TWlncmF0aW9uUmVzdWx0PiB7XG4gICAgY29uc3QgcmVzdWx0OiBNaWdyYXRpb25SZXN1bHQgPSB7XG4gICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgIHRvdGFsTWlncmF0aW9uczogMCxcbiAgICAgIGFwcGxpZWRNaWdyYXRpb25zOiAwLFxuICAgICAgcGVuZGluZ01pZ3JhdGlvbnM6IDAsXG4gICAgfTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZU1pZ3JhdGlvbnNUYWJsZSgpO1xuXG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHRoaXMuZ2V0TWlncmF0aW9uRmlsZXMoKTtcbiAgICAgIGNvbnN0IGFwcGxpZWQgPSBhd2FpdCB0aGlzLmdldEFwcGxpZWRNaWdyYXRpb25zKCk7XG5cbiAgICAgIHJlc3VsdC50b3RhbE1pZ3JhdGlvbnMgPSBmaWxlcy5sZW5ndGg7XG4gICAgICByZXN1bHQuYXBwbGllZE1pZ3JhdGlvbnMgPSBhcHBsaWVkLmxlbmd0aDtcblxuICAgICAgaWYgKG9wdGlvbnM/LnZlcmJvc2UpIHtcbiAgICAgICAgY29uc29sZS5sb2coYEZvdW5kICR7ZmlsZXMubGVuZ3RofSBtaWdyYXRpb24gZmlsZXNgKTtcbiAgICAgICAgY29uc29sZS5sb2coYCR7YXBwbGllZC5sZW5ndGh9IG1pZ3JhdGlvbnMgYWxyZWFkeSBhcHBsaWVkYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBlbmRpbmdNaWdyYXRpb25zID0gZmlsZXMuZmlsdGVyKChmaWxlKSA9PiAhYXBwbGllZC5pbmNsdWRlcyhmaWxlKSk7XG4gICAgICByZXN1bHQucGVuZGluZ01pZ3JhdGlvbnMgPSBwZW5kaW5nTWlncmF0aW9ucy5sZW5ndGg7XG5cbiAgICAgIGlmIChwZW5kaW5nTWlncmF0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgaWYgKG9wdGlvbnM/LnZlcmJvc2UpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnTm8gcGVuZGluZyBtaWdyYXRpb25zIHRvIGFwcGx5Jyk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0LnN1Y2Nlc3MgPSB0cnVlO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucz8uZHJ5UnVuKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdEcnkgcnVuIG1vZGUgLSB3b3VsZCBhcHBseTonKTtcbiAgICAgICAgcGVuZGluZ01pZ3JhdGlvbnMuZm9yRWFjaCgoZmlsZSkgPT4gY29uc29sZS5sb2coYCAgLSAke2ZpbGV9YCkpO1xuICAgICAgICByZXN1bHQuc3VjY2VzcyA9IHRydWU7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zPy52ZXJib3NlKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBSdW5uaW5nICR7cGVuZGluZ01pZ3JhdGlvbnMubGVuZ3RofSBwZW5kaW5nIG1pZ3JhdGlvbnMuLi5gLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgcGVuZGluZ01pZ3JhdGlvbnMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnM/LnZlcmJvc2UpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgQXBwbHlpbmcgbWlncmF0aW9uOiAke2ZpbGV9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVc2UgYSB0cmFuc2FjdGlvbiBmb3IgZWFjaCBtaWdyYXRpb25cbiAgICAgICAgY29uc3QgcXVlcnlSdW5uZXIgPSB0aGlzLmRhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIoKTtcbiAgICAgICAgYXdhaXQgcXVlcnlSdW5uZXIuY29ubmVjdCgpO1xuICAgICAgICBhd2FpdCBxdWVyeVJ1bm5lci5zdGFydFRyYW5zYWN0aW9uKCk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnJ1blNpbmdsZU1pZ3JhdGlvbihmaWxlLCBxdWVyeVJ1bm5lcik7XG4gICAgICAgICAgYXdhaXQgcXVlcnlSdW5uZXIuY29tbWl0VHJhbnNhY3Rpb24oKTtcblxuICAgICAgICAgIGlmIChvcHRpb25zPy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhg4pyTIEFwcGxpZWQgbWlncmF0aW9uOiAke2ZpbGV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcblxuICAgICAgICAgIGlmIChvcHRpb25zPy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBGYWlsZWQgdG8gYXBwbHkgbWlncmF0aW9uICR7ZmlsZX06YCwgZXJyb3IpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJlc3VsdC5mYWlsZWRNaWdyYXRpb24gPSBmaWxlO1xuICAgICAgICAgIHJlc3VsdC5lcnJvciA9IGVycm9yO1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJlbGVhc2UoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXN1bHQuc3VjY2VzcyA9IHRydWU7XG4gICAgICByZXN1bHQuYXBwbGllZE1pZ3JhdGlvbnMgKz0gcGVuZGluZ01pZ3JhdGlvbnMubGVuZ3RoO1xuXG4gICAgICBpZiAob3B0aW9ucz8udmVyYm9zZSkge1xuICAgICAgICBjb25zb2xlLmxvZygnQWxsIG1pZ3JhdGlvbnMgY29tcGxldGVkIHN1Y2Nlc3NmdWxseSEnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmVzdWx0LmVycm9yID0gZXJyb3I7XG5cbiAgICAgIGlmIChvcHRpb25zPy52ZXJib3NlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01pZ3JhdGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiBwZW5kaW5nIG1pZ3JhdGlvbnMgd2l0aG91dCBhcHBseWluZyB0aGVtLlxuICAgKi9cbiAgYXN5bmMgZ2V0UGVuZGluZ01pZ3JhdGlvbnMoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlTWlncmF0aW9uc1RhYmxlKCk7XG4gICAgY29uc3QgZmlsZXMgPSBhd2FpdCB0aGlzLmdldE1pZ3JhdGlvbkZpbGVzKCk7XG4gICAgY29uc3QgYXBwbGllZCA9IGF3YWl0IHRoaXMuZ2V0QXBwbGllZE1pZ3JhdGlvbnMoKTtcbiAgICByZXR1cm4gZmlsZXMuZmlsdGVyKChmaWxlKSA9PiAhYXBwbGllZC5pbmNsdWRlcyhmaWxlKSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBtaWdyYXRpb24gc3RhdHVzIGluZm9ybWF0aW9uLlxuICAgKi9cbiAgYXN5bmMgZ2V0U3RhdHVzKCk6IFByb21pc2U8e1xuICAgIHRvdGFsOiBudW1iZXI7XG4gICAgYXBwbGllZDogbnVtYmVyO1xuICAgIHBlbmRpbmc6IG51bWJlcjtcbiAgICBwZW5kaW5nRmlsZXM6IHN0cmluZ1tdO1xuICB9PiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVNaWdyYXRpb25zVGFibGUoKTtcbiAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHRoaXMuZ2V0TWlncmF0aW9uRmlsZXMoKTtcbiAgICBjb25zdCBhcHBsaWVkID0gYXdhaXQgdGhpcy5nZXRBcHBsaWVkTWlncmF0aW9ucygpO1xuICAgIGNvbnN0IHBlbmRpbmdGaWxlcyA9IGZpbGVzLmZpbHRlcigoZmlsZSkgPT4gIWFwcGxpZWQuaW5jbHVkZXMoZmlsZSkpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRvdGFsOiBmaWxlcy5sZW5ndGgsXG4gICAgICBhcHBsaWVkOiBhcHBsaWVkLmxlbmd0aCxcbiAgICAgIHBlbmRpbmc6IHBlbmRpbmdGaWxlcy5sZW5ndGgsXG4gICAgICBwZW5kaW5nRmlsZXMsXG4gICAgfTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { MigrationModuleAsyncOptions, MigrationModuleOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* NestJS module for SQL Server migrations.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // Synchronous configuration
|
|
8
|
+
* MigrationModule.forRoot({
|
|
9
|
+
* migrationsDir: path.join(__dirname, '../migrations'),
|
|
10
|
+
* autoRun: true,
|
|
11
|
+
* verbose: true,
|
|
12
|
+
* })
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Asynchronous configuration with ConfigService
|
|
16
|
+
* MigrationModule.forRootAsync({
|
|
17
|
+
* imports: [ConfigModule],
|
|
18
|
+
* inject: [ConfigService],
|
|
19
|
+
* useFactory: (configService: ConfigService) => ({
|
|
20
|
+
* migrationsDir: path.join(__dirname, '../migrations'),
|
|
21
|
+
* autoRun: configService.get<boolean>('AUTO_RUN_MIGRATIONS', false),
|
|
22
|
+
* verbose: true,
|
|
23
|
+
* }),
|
|
24
|
+
* })
|
|
25
|
+
*/
|
|
26
|
+
export declare class MigrationModule {
|
|
27
|
+
/**
|
|
28
|
+
* Configure the migration module with static options.
|
|
29
|
+
*/
|
|
30
|
+
static forRoot(options: MigrationModuleOptions): DynamicModule;
|
|
31
|
+
/**
|
|
32
|
+
* Configure the migration module with async options.
|
|
33
|
+
* Useful when options depend on ConfigService or other async providers.
|
|
34
|
+
*/
|
|
35
|
+
static forRootAsync(options: MigrationModuleAsyncOptions): DynamicModule;
|
|
36
|
+
private static createAsyncProviders;
|
|
37
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var MigrationModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.MigrationModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const migration_service_1 = require("./migration.service");
|
|
13
|
+
const types_1 = require("./types");
|
|
14
|
+
/**
|
|
15
|
+
* NestJS module for SQL Server migrations.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Synchronous configuration
|
|
19
|
+
* MigrationModule.forRoot({
|
|
20
|
+
* migrationsDir: path.join(__dirname, '../migrations'),
|
|
21
|
+
* autoRun: true,
|
|
22
|
+
* verbose: true,
|
|
23
|
+
* })
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Asynchronous configuration with ConfigService
|
|
27
|
+
* MigrationModule.forRootAsync({
|
|
28
|
+
* imports: [ConfigModule],
|
|
29
|
+
* inject: [ConfigService],
|
|
30
|
+
* useFactory: (configService: ConfigService) => ({
|
|
31
|
+
* migrationsDir: path.join(__dirname, '../migrations'),
|
|
32
|
+
* autoRun: configService.get<boolean>('AUTO_RUN_MIGRATIONS', false),
|
|
33
|
+
* verbose: true,
|
|
34
|
+
* }),
|
|
35
|
+
* })
|
|
36
|
+
*/
|
|
37
|
+
let MigrationModule = MigrationModule_1 = class MigrationModule {
|
|
38
|
+
/**
|
|
39
|
+
* Configure the migration module with static options.
|
|
40
|
+
*/
|
|
41
|
+
static forRoot(options) {
|
|
42
|
+
return {
|
|
43
|
+
module: MigrationModule_1,
|
|
44
|
+
providers: [
|
|
45
|
+
{
|
|
46
|
+
provide: types_1.MIGRATION_MODULE_OPTIONS,
|
|
47
|
+
useValue: options,
|
|
48
|
+
},
|
|
49
|
+
migration_service_1.MigrationService,
|
|
50
|
+
],
|
|
51
|
+
exports: [migration_service_1.MigrationService],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Configure the migration module with async options.
|
|
56
|
+
* Useful when options depend on ConfigService or other async providers.
|
|
57
|
+
*/
|
|
58
|
+
static forRootAsync(options) {
|
|
59
|
+
return {
|
|
60
|
+
module: MigrationModule_1,
|
|
61
|
+
imports: options.imports || [],
|
|
62
|
+
providers: [
|
|
63
|
+
...this.createAsyncProviders(options),
|
|
64
|
+
migration_service_1.MigrationService,
|
|
65
|
+
],
|
|
66
|
+
exports: [migration_service_1.MigrationService],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
static createAsyncProviders(options) {
|
|
70
|
+
if (options.useFactory) {
|
|
71
|
+
return [
|
|
72
|
+
{
|
|
73
|
+
provide: types_1.MIGRATION_MODULE_OPTIONS,
|
|
74
|
+
useFactory: options.useFactory,
|
|
75
|
+
inject: options.inject || [],
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
if (options.useClass) {
|
|
80
|
+
return [
|
|
81
|
+
{
|
|
82
|
+
provide: options.useClass,
|
|
83
|
+
useClass: options.useClass,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
provide: types_1.MIGRATION_MODULE_OPTIONS,
|
|
87
|
+
useFactory: async (optionsFactory) => optionsFactory.createMigrationOptions(),
|
|
88
|
+
inject: [options.useClass],
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
if (options.useExisting) {
|
|
93
|
+
return [
|
|
94
|
+
{
|
|
95
|
+
provide: types_1.MIGRATION_MODULE_OPTIONS,
|
|
96
|
+
useFactory: async (optionsFactory) => optionsFactory.createMigrationOptions(),
|
|
97
|
+
inject: [options.useExisting],
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
exports.MigrationModule = MigrationModule;
|
|
105
|
+
exports.MigrationModule = MigrationModule = MigrationModule_1 = __decorate([
|
|
106
|
+
(0, common_1.Module)({})
|
|
107
|
+
], MigrationModule);
|
|
108
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWdyYXRpb24ubW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSwyQ0FBaUU7QUFDakUsMkRBQXVEO0FBQ3ZELG1DQUtpQjtBQUVqQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVJLElBQU0sZUFBZSx1QkFBckIsTUFBTSxlQUFlO0lBQzFCOztPQUVHO0lBQ0gsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUErQjtRQUM1QyxPQUFPO1lBQ0wsTUFBTSxFQUFFLGlCQUFlO1lBQ3ZCLFNBQVMsRUFBRTtnQkFDVDtvQkFDRSxPQUFPLEVBQUUsZ0NBQXdCO29CQUNqQyxRQUFRLEVBQUUsT0FBTztpQkFDbEI7Z0JBQ0Qsb0NBQWdCO2FBQ2pCO1lBQ0QsT0FBTyxFQUFFLENBQUMsb0NBQWdCLENBQUM7U0FDNUIsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQW9DO1FBQ3RELE9BQU87WUFDTCxNQUFNLEVBQUUsaUJBQWU7WUFDdkIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLElBQUksRUFBRTtZQUM5QixTQUFTLEVBQUU7Z0JBQ1QsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDO2dCQUNyQyxvQ0FBZ0I7YUFDakI7WUFDRCxPQUFPLEVBQUUsQ0FBQyxvQ0FBZ0IsQ0FBQztTQUM1QixDQUFDO0lBQ0osQ0FBQztJQUVPLE1BQU0sQ0FBQyxvQkFBb0IsQ0FDakMsT0FBb0M7UUFFcEMsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDdkIsT0FBTztnQkFDTDtvQkFDRSxPQUFPLEVBQUUsZ0NBQXdCO29CQUNqQyxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVU7b0JBQzlCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxJQUFJLEVBQUU7aUJBQzdCO2FBQ0YsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNyQixPQUFPO2dCQUNMO29CQUNFLE9BQU8sRUFBRSxPQUFPLENBQUMsUUFBUTtvQkFDekIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO2lCQUMzQjtnQkFDRDtvQkFDRSxPQUFPLEVBQUUsZ0NBQXdCO29CQUNqQyxVQUFVLEVBQUUsS0FBSyxFQUFFLGNBQTZDLEVBQUUsRUFBRSxDQUNsRSxjQUFjLENBQUMsc0JBQXNCLEVBQUU7b0JBQ3pDLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7aUJBQzNCO2FBQ0YsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QixPQUFPO2dCQUNMO29CQUNFLE9BQU8sRUFBRSxnQ0FBd0I7b0JBQ2pDLFVBQVUsRUFBRSxLQUFLLEVBQUUsY0FBNkMsRUFBRSxFQUFFLENBQ2xFLGNBQWMsQ0FBQyxzQkFBc0IsRUFBRTtvQkFDekMsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQztpQkFDOUI7YUFDRixDQUFDO1FBQ0osQ0FBQztRQUVELE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztDQUNGLENBQUE7QUEzRVksMENBQWU7MEJBQWYsZUFBZTtJQUQzQixJQUFBLGVBQU0sRUFBQyxFQUFFLENBQUM7R0FDRSxlQUFlLENBMkUzQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IER5bmFtaWNNb2R1bGUsIE1vZHVsZSwgUHJvdmlkZXIgfSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XG5pbXBvcnQgeyBNaWdyYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi9taWdyYXRpb24uc2VydmljZSc7XG5pbXBvcnQge1xuICBNSUdSQVRJT05fTU9EVUxFX09QVElPTlMsXG4gIE1pZ3JhdGlvbk1vZHVsZUFzeW5jT3B0aW9ucyxcbiAgTWlncmF0aW9uTW9kdWxlT3B0aW9ucyxcbiAgTWlncmF0aW9uTW9kdWxlT3B0aW9uc0ZhY3RvcnksXG59IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIE5lc3RKUyBtb2R1bGUgZm9yIFNRTCBTZXJ2ZXIgbWlncmF0aW9ucy5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU3luY2hyb25vdXMgY29uZmlndXJhdGlvblxuICogTWlncmF0aW9uTW9kdWxlLmZvclJvb3Qoe1xuICogICBtaWdyYXRpb25zRGlyOiBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vbWlncmF0aW9ucycpLFxuICogICBhdXRvUnVuOiB0cnVlLFxuICogICB2ZXJib3NlOiB0cnVlLFxuICogfSlcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gQXN5bmNocm9ub3VzIGNvbmZpZ3VyYXRpb24gd2l0aCBDb25maWdTZXJ2aWNlXG4gKiBNaWdyYXRpb25Nb2R1bGUuZm9yUm9vdEFzeW5jKHtcbiAqICAgaW1wb3J0czogW0NvbmZpZ01vZHVsZV0sXG4gKiAgIGluamVjdDogW0NvbmZpZ1NlcnZpY2VdLFxuICogICB1c2VGYWN0b3J5OiAoY29uZmlnU2VydmljZTogQ29uZmlnU2VydmljZSkgPT4gKHtcbiAqICAgICBtaWdyYXRpb25zRGlyOiBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vbWlncmF0aW9ucycpLFxuICogICAgIGF1dG9SdW46IGNvbmZpZ1NlcnZpY2UuZ2V0PGJvb2xlYW4+KCdBVVRPX1JVTl9NSUdSQVRJT05TJywgZmFsc2UpLFxuICogICAgIHZlcmJvc2U6IHRydWUsXG4gKiAgIH0pLFxuICogfSlcbiAqL1xuQE1vZHVsZSh7fSlcbmV4cG9ydCBjbGFzcyBNaWdyYXRpb25Nb2R1bGUge1xuICAvKipcbiAgICogQ29uZmlndXJlIHRoZSBtaWdyYXRpb24gbW9kdWxlIHdpdGggc3RhdGljIG9wdGlvbnMuXG4gICAqL1xuICBzdGF0aWMgZm9yUm9vdChvcHRpb25zOiBNaWdyYXRpb25Nb2R1bGVPcHRpb25zKTogRHluYW1pY01vZHVsZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG1vZHVsZTogTWlncmF0aW9uTW9kdWxlLFxuICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBNSUdSQVRJT05fTU9EVUxFX09QVElPTlMsXG4gICAgICAgICAgdXNlVmFsdWU6IG9wdGlvbnMsXG4gICAgICAgIH0sXG4gICAgICAgIE1pZ3JhdGlvblNlcnZpY2UsXG4gICAgICBdLFxuICAgICAgZXhwb3J0czogW01pZ3JhdGlvblNlcnZpY2VdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ29uZmlndXJlIHRoZSBtaWdyYXRpb24gbW9kdWxlIHdpdGggYXN5bmMgb3B0aW9ucy5cbiAgICogVXNlZnVsIHdoZW4gb3B0aW9ucyBkZXBlbmQgb24gQ29uZmlnU2VydmljZSBvciBvdGhlciBhc3luYyBwcm92aWRlcnMuXG4gICAqL1xuICBzdGF0aWMgZm9yUm9vdEFzeW5jKG9wdGlvbnM6IE1pZ3JhdGlvbk1vZHVsZUFzeW5jT3B0aW9ucyk6IER5bmFtaWNNb2R1bGUge1xuICAgIHJldHVybiB7XG4gICAgICBtb2R1bGU6IE1pZ3JhdGlvbk1vZHVsZSxcbiAgICAgIGltcG9ydHM6IG9wdGlvbnMuaW1wb3J0cyB8fCBbXSxcbiAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAuLi50aGlzLmNyZWF0ZUFzeW5jUHJvdmlkZXJzKG9wdGlvbnMpLFxuICAgICAgICBNaWdyYXRpb25TZXJ2aWNlLFxuICAgICAgXSxcbiAgICAgIGV4cG9ydHM6IFtNaWdyYXRpb25TZXJ2aWNlXSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgY3JlYXRlQXN5bmNQcm92aWRlcnMoXG4gICAgb3B0aW9uczogTWlncmF0aW9uTW9kdWxlQXN5bmNPcHRpb25zLFxuICApOiBQcm92aWRlcltdIHtcbiAgICBpZiAob3B0aW9ucy51c2VGYWN0b3J5KSB7XG4gICAgICByZXR1cm4gW1xuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogTUlHUkFUSU9OX01PRFVMRV9PUFRJT05TLFxuICAgICAgICAgIHVzZUZhY3Rvcnk6IG9wdGlvbnMudXNlRmFjdG9yeSxcbiAgICAgICAgICBpbmplY3Q6IG9wdGlvbnMuaW5qZWN0IHx8IFtdLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy51c2VDbGFzcykge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAge1xuICAgICAgICAgIHByb3ZpZGU6IG9wdGlvbnMudXNlQ2xhc3MsXG4gICAgICAgICAgdXNlQ2xhc3M6IG9wdGlvbnMudXNlQ2xhc3MsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBNSUdSQVRJT05fTU9EVUxFX09QVElPTlMsXG4gICAgICAgICAgdXNlRmFjdG9yeTogYXN5bmMgKG9wdGlvbnNGYWN0b3J5OiBNaWdyYXRpb25Nb2R1bGVPcHRpb25zRmFjdG9yeSkgPT5cbiAgICAgICAgICAgIG9wdGlvbnNGYWN0b3J5LmNyZWF0ZU1pZ3JhdGlvbk9wdGlvbnMoKSxcbiAgICAgICAgICBpbmplY3Q6IFtvcHRpb25zLnVzZUNsYXNzXSxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMudXNlRXhpc3RpbmcpIHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBNSUdSQVRJT05fTU9EVUxFX09QVElPTlMsXG4gICAgICAgICAgdXNlRmFjdG9yeTogYXN5bmMgKG9wdGlvbnNGYWN0b3J5OiBNaWdyYXRpb25Nb2R1bGVPcHRpb25zRmFjdG9yeSkgPT5cbiAgICAgICAgICAgIG9wdGlvbnNGYWN0b3J5LmNyZWF0ZU1pZ3JhdGlvbk9wdGlvbnMoKSxcbiAgICAgICAgICBpbmplY3Q6IFtvcHRpb25zLnVzZUV4aXN0aW5nXSxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgfVxuXG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { DataSource } from 'typeorm';
|
|
3
|
+
import { MigrationModuleOptions, MigrationResult, MigrationRunOptions } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* NestJS service for running SQL Server migrations.
|
|
6
|
+
* Automatically runs migrations on module initialization if autoRun is enabled.
|
|
7
|
+
*/
|
|
8
|
+
export declare class MigrationService implements OnModuleInit {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private readonly migrationCore;
|
|
11
|
+
private readonly autoRun;
|
|
12
|
+
private readonly verbose;
|
|
13
|
+
constructor(options: MigrationModuleOptions, dataSource: DataSource);
|
|
14
|
+
onModuleInit(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Run all pending migrations.
|
|
17
|
+
*/
|
|
18
|
+
runMigrations(options?: MigrationRunOptions): Promise<MigrationResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Get list of pending migration files.
|
|
21
|
+
*/
|
|
22
|
+
getPendingMigrations(): Promise<string[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Get migration status information.
|
|
25
|
+
*/
|
|
26
|
+
getStatus(): Promise<{
|
|
27
|
+
total: number;
|
|
28
|
+
applied: number;
|
|
29
|
+
pending: number;
|
|
30
|
+
pendingFiles: string[];
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.MigrationService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const typeorm_1 = require("typeorm");
|
|
18
|
+
const migration_core_1 = require("./migration-core");
|
|
19
|
+
const types_1 = require("./types");
|
|
20
|
+
/**
|
|
21
|
+
* NestJS service for running SQL Server migrations.
|
|
22
|
+
* Automatically runs migrations on module initialization if autoRun is enabled.
|
|
23
|
+
*/
|
|
24
|
+
let MigrationService = class MigrationService {
|
|
25
|
+
options;
|
|
26
|
+
migrationCore;
|
|
27
|
+
autoRun;
|
|
28
|
+
verbose;
|
|
29
|
+
constructor(options, dataSource) {
|
|
30
|
+
this.options = options;
|
|
31
|
+
this.migrationCore = new migration_core_1.MigrationCore(dataSource, {
|
|
32
|
+
migrationsDir: options.migrationsDir,
|
|
33
|
+
});
|
|
34
|
+
this.autoRun = options.autoRun ?? false;
|
|
35
|
+
this.verbose = options.verbose ?? true;
|
|
36
|
+
}
|
|
37
|
+
async onModuleInit() {
|
|
38
|
+
if (!this.autoRun) {
|
|
39
|
+
if (this.verbose) {
|
|
40
|
+
console.log('Auto migrations are disabled');
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (this.verbose) {
|
|
45
|
+
console.log('Auto-running migrations...');
|
|
46
|
+
}
|
|
47
|
+
await this.runMigrations();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run all pending migrations.
|
|
51
|
+
*/
|
|
52
|
+
async runMigrations(options) {
|
|
53
|
+
return this.migrationCore.runMigrations({
|
|
54
|
+
verbose: this.verbose,
|
|
55
|
+
...options,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get list of pending migration files.
|
|
60
|
+
*/
|
|
61
|
+
async getPendingMigrations() {
|
|
62
|
+
return this.migrationCore.getPendingMigrations();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get migration status information.
|
|
66
|
+
*/
|
|
67
|
+
async getStatus() {
|
|
68
|
+
return this.migrationCore.getStatus();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
exports.MigrationService = MigrationService;
|
|
72
|
+
exports.MigrationService = MigrationService = __decorate([
|
|
73
|
+
(0, common_1.Injectable)(),
|
|
74
|
+
__param(0, (0, common_1.Inject)(types_1.MIGRATION_MODULE_OPTIONS)),
|
|
75
|
+
__metadata("design:paramtypes", [Object, typeorm_1.DataSource])
|
|
76
|
+
], MigrationService);
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlncmF0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMkNBQWtFO0FBQ2xFLHFDQUFxQztBQUNyQyxxREFBaUQ7QUFDakQsbUNBS2lCO0FBRWpCOzs7R0FHRztBQUVJLElBQU0sZ0JBQWdCLEdBQXRCLE1BQU0sZ0JBQWdCO0lBT1I7SUFORixhQUFhLENBQWdCO0lBQzdCLE9BQU8sQ0FBVTtJQUNqQixPQUFPLENBQVU7SUFFbEMsWUFFbUIsT0FBK0IsRUFDaEQsVUFBc0I7UUFETCxZQUFPLEdBQVAsT0FBTyxDQUF3QjtRQUdoRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksOEJBQWEsQ0FBQyxVQUFVLEVBQUU7WUFDakQsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhO1NBQ3JDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sSUFBSSxLQUFLLENBQUM7UUFDeEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQztJQUN6QyxDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVk7UUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNsQixJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1lBQzlDLENBQUM7WUFDRCxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENBQUMsQ0FBQztRQUM1QyxDQUFDO1FBRUQsTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGFBQWEsQ0FBQyxPQUE2QjtRQUMvQyxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDO1lBQ3RDLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztZQUNyQixHQUFHLE9BQU87U0FDWCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsb0JBQW9CO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQ25ELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxTQUFTO1FBTWIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ3hDLENBQUM7Q0FDRixDQUFBO0FBNURZLDRDQUFnQjsyQkFBaEIsZ0JBQWdCO0lBRDVCLElBQUEsbUJBQVUsR0FBRTtJQU9SLFdBQUEsSUFBQSxlQUFNLEVBQUMsZ0NBQXdCLENBQUMsQ0FBQTs2Q0FFckIsb0JBQVU7R0FSYixnQkFBZ0IsQ0E0RDVCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBPbk1vZHVsZUluaXQgfSBmcm9tICdAbmVzdGpzL2NvbW1vbic7XG5pbXBvcnQgeyBEYXRhU291cmNlIH0gZnJvbSAndHlwZW9ybSc7XG5pbXBvcnQgeyBNaWdyYXRpb25Db3JlIH0gZnJvbSAnLi9taWdyYXRpb24tY29yZSc7XG5pbXBvcnQge1xuICBNSUdSQVRJT05fTU9EVUxFX09QVElPTlMsXG4gIE1pZ3JhdGlvbk1vZHVsZU9wdGlvbnMsXG4gIE1pZ3JhdGlvblJlc3VsdCxcbiAgTWlncmF0aW9uUnVuT3B0aW9ucyxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogTmVzdEpTIHNlcnZpY2UgZm9yIHJ1bm5pbmcgU1FMIFNlcnZlciBtaWdyYXRpb25zLlxuICogQXV0b21hdGljYWxseSBydW5zIG1pZ3JhdGlvbnMgb24gbW9kdWxlIGluaXRpYWxpemF0aW9uIGlmIGF1dG9SdW4gaXMgZW5hYmxlZC5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE1pZ3JhdGlvblNlcnZpY2UgaW1wbGVtZW50cyBPbk1vZHVsZUluaXQge1xuICBwcml2YXRlIHJlYWRvbmx5IG1pZ3JhdGlvbkNvcmU6IE1pZ3JhdGlvbkNvcmU7XG4gIHByaXZhdGUgcmVhZG9ubHkgYXV0b1J1bjogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSB2ZXJib3NlOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoTUlHUkFUSU9OX01PRFVMRV9PUFRJT05TKVxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogTWlncmF0aW9uTW9kdWxlT3B0aW9ucyxcbiAgICBkYXRhU291cmNlOiBEYXRhU291cmNlLFxuICApIHtcbiAgICB0aGlzLm1pZ3JhdGlvbkNvcmUgPSBuZXcgTWlncmF0aW9uQ29yZShkYXRhU291cmNlLCB7XG4gICAgICBtaWdyYXRpb25zRGlyOiBvcHRpb25zLm1pZ3JhdGlvbnNEaXIsXG4gICAgfSk7XG4gICAgdGhpcy5hdXRvUnVuID0gb3B0aW9ucy5hdXRvUnVuID8/IGZhbHNlO1xuICAgIHRoaXMudmVyYm9zZSA9IG9wdGlvbnMudmVyYm9zZSA/PyB0cnVlO1xuICB9XG5cbiAgYXN5bmMgb25Nb2R1bGVJbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5hdXRvUnVuKSB7XG4gICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdBdXRvIG1pZ3JhdGlvbnMgYXJlIGRpc2FibGVkJyk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgY29uc29sZS5sb2coJ0F1dG8tcnVubmluZyBtaWdyYXRpb25zLi4uJyk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5ydW5NaWdyYXRpb25zKCk7XG4gIH1cblxuICAvKipcbiAgICogUnVuIGFsbCBwZW5kaW5nIG1pZ3JhdGlvbnMuXG4gICAqL1xuICBhc3luYyBydW5NaWdyYXRpb25zKG9wdGlvbnM/OiBNaWdyYXRpb25SdW5PcHRpb25zKTogUHJvbWlzZTxNaWdyYXRpb25SZXN1bHQ+IHtcbiAgICByZXR1cm4gdGhpcy5taWdyYXRpb25Db3JlLnJ1bk1pZ3JhdGlvbnMoe1xuICAgICAgdmVyYm9zZTogdGhpcy52ZXJib3NlLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgbGlzdCBvZiBwZW5kaW5nIG1pZ3JhdGlvbiBmaWxlcy5cbiAgICovXG4gIGFzeW5jIGdldFBlbmRpbmdNaWdyYXRpb25zKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICByZXR1cm4gdGhpcy5taWdyYXRpb25Db3JlLmdldFBlbmRpbmdNaWdyYXRpb25zKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IG1pZ3JhdGlvbiBzdGF0dXMgaW5mb3JtYXRpb24uXG4gICAqL1xuICBhc3luYyBnZXRTdGF0dXMoKTogUHJvbWlzZTx7XG4gICAgdG90YWw6IG51bWJlcjtcbiAgICBhcHBsaWVkOiBudW1iZXI7XG4gICAgcGVuZGluZzogbnVtYmVyO1xuICAgIHBlbmRpbmdGaWxlczogc3RyaW5nW107XG4gIH0+IHtcbiAgICByZXR1cm4gdGhpcy5taWdyYXRpb25Db3JlLmdldFN0YXR1cygpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ModuleMetadata, Type } from '@nestjs/common';
|
|
2
|
+
export interface MigrationModuleOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Path to the directory containing SQL migration files
|
|
5
|
+
*/
|
|
6
|
+
migrationsDir: string;
|
|
7
|
+
/**
|
|
8
|
+
* Whether to automatically run migrations on module initialization
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
autoRun?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Whether to log verbose output during migration execution
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
verbose?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface MigrationModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
19
|
+
/**
|
|
20
|
+
* Factory function to create MigrationModuleOptions
|
|
21
|
+
*/
|
|
22
|
+
useFactory: (...args: any[]) => Promise<MigrationModuleOptions> | MigrationModuleOptions;
|
|
23
|
+
/**
|
|
24
|
+
* Dependencies to inject into the factory function
|
|
25
|
+
*/
|
|
26
|
+
inject?: any[];
|
|
27
|
+
/**
|
|
28
|
+
* Optional class to use for creating options
|
|
29
|
+
*/
|
|
30
|
+
useClass?: Type<MigrationModuleOptionsFactory>;
|
|
31
|
+
/**
|
|
32
|
+
* Optional existing instance to use for options
|
|
33
|
+
*/
|
|
34
|
+
useExisting?: Type<MigrationModuleOptionsFactory>;
|
|
35
|
+
}
|
|
36
|
+
export interface MigrationModuleOptionsFactory {
|
|
37
|
+
createMigrationOptions(): Promise<MigrationModuleOptions> | MigrationModuleOptions;
|
|
38
|
+
}
|
|
39
|
+
export interface MigrationResult {
|
|
40
|
+
/**
|
|
41
|
+
* Whether the migration run was successful
|
|
42
|
+
*/
|
|
43
|
+
success: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Total number of migration files found
|
|
46
|
+
*/
|
|
47
|
+
totalMigrations: number;
|
|
48
|
+
/**
|
|
49
|
+
* Number of migrations already applied
|
|
50
|
+
*/
|
|
51
|
+
appliedMigrations: number;
|
|
52
|
+
/**
|
|
53
|
+
* Number of pending migrations to apply
|
|
54
|
+
*/
|
|
55
|
+
pendingMigrations: number;
|
|
56
|
+
/**
|
|
57
|
+
* Name of the failed migration file (if any)
|
|
58
|
+
*/
|
|
59
|
+
failedMigration?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Error object if migration failed
|
|
62
|
+
*/
|
|
63
|
+
error?: any;
|
|
64
|
+
}
|
|
65
|
+
export interface MigrationRunOptions {
|
|
66
|
+
/**
|
|
67
|
+
* If true, only list pending migrations without applying them
|
|
68
|
+
* @default false
|
|
69
|
+
*/
|
|
70
|
+
dryRun?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Whether to log verbose output
|
|
73
|
+
* @default false
|
|
74
|
+
*/
|
|
75
|
+
verbose?: boolean;
|
|
76
|
+
}
|
|
77
|
+
export interface MigrationCoreOptions {
|
|
78
|
+
/**
|
|
79
|
+
* Path to the directory containing SQL migration files
|
|
80
|
+
*/
|
|
81
|
+
migrationsDir: string;
|
|
82
|
+
}
|
|
83
|
+
export declare const MIGRATION_MODULE_OPTIONS: unique symbol;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MIGRATION_MODULE_OPTIONS = void 0;
|
|
4
|
+
exports.MIGRATION_MODULE_OPTIONS = Symbol('MIGRATION_MODULE_OPTIONS');
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBeUdhLFFBQUEsd0JBQXdCLEdBQUcsTUFBTSxDQUFDLDBCQUEwQixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNb2R1bGVNZXRhZGF0YSwgVHlwZSB9IGZyb20gJ0BuZXN0anMvY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBNaWdyYXRpb25Nb2R1bGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIGRpcmVjdG9yeSBjb250YWluaW5nIFNRTCBtaWdyYXRpb24gZmlsZXNcbiAgICovXG4gIG1pZ3JhdGlvbnNEaXI6IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0byBhdXRvbWF0aWNhbGx5IHJ1biBtaWdyYXRpb25zIG9uIG1vZHVsZSBpbml0aWFsaXphdGlvblxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgYXV0b1J1bj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gbG9nIHZlcmJvc2Ugb3V0cHV0IGR1cmluZyBtaWdyYXRpb24gZXhlY3V0aW9uXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHZlcmJvc2U/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1pZ3JhdGlvbk1vZHVsZUFzeW5jT3B0aW9uc1xuICBleHRlbmRzIFBpY2s8TW9kdWxlTWV0YWRhdGEsICdpbXBvcnRzJz4ge1xuICAvKipcbiAgICogRmFjdG9yeSBmdW5jdGlvbiB0byBjcmVhdGUgTWlncmF0aW9uTW9kdWxlT3B0aW9uc1xuICAgKi9cbiAgdXNlRmFjdG9yeTogKFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICkgPT4gUHJvbWlzZTxNaWdyYXRpb25Nb2R1bGVPcHRpb25zPiB8IE1pZ3JhdGlvbk1vZHVsZU9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIERlcGVuZGVuY2llcyB0byBpbmplY3QgaW50byB0aGUgZmFjdG9yeSBmdW5jdGlvblxuICAgKi9cbiAgaW5qZWN0PzogYW55W107XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGNsYXNzIHRvIHVzZSBmb3IgY3JlYXRpbmcgb3B0aW9uc1xuICAgKi9cbiAgdXNlQ2xhc3M/OiBUeXBlPE1pZ3JhdGlvbk1vZHVsZU9wdGlvbnNGYWN0b3J5PjtcblxuICAvKipcbiAgICogT3B0aW9uYWwgZXhpc3RpbmcgaW5zdGFuY2UgdG8gdXNlIGZvciBvcHRpb25zXG4gICAqL1xuICB1c2VFeGlzdGluZz86IFR5cGU8TWlncmF0aW9uTW9kdWxlT3B0aW9uc0ZhY3Rvcnk+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1pZ3JhdGlvbk1vZHVsZU9wdGlvbnNGYWN0b3J5IHtcbiAgY3JlYXRlTWlncmF0aW9uT3B0aW9ucygpOlxuICAgIHwgUHJvbWlzZTxNaWdyYXRpb25Nb2R1bGVPcHRpb25zPlxuICAgIHwgTWlncmF0aW9uTW9kdWxlT3B0aW9ucztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNaWdyYXRpb25SZXN1bHQge1xuICAvKipcbiAgICogV2hldGhlciB0aGUgbWlncmF0aW9uIHJ1biB3YXMgc3VjY2Vzc2Z1bFxuICAgKi9cbiAgc3VjY2VzczogYm9vbGVhbjtcblxuICAvKipcbiAgICogVG90YWwgbnVtYmVyIG9mIG1pZ3JhdGlvbiBmaWxlcyBmb3VuZFxuICAgKi9cbiAgdG90YWxNaWdyYXRpb25zOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiBtaWdyYXRpb25zIGFscmVhZHkgYXBwbGllZFxuICAgKi9cbiAgYXBwbGllZE1pZ3JhdGlvbnM6IG51bWJlcjtcblxuICAvKipcbiAgICogTnVtYmVyIG9mIHBlbmRpbmcgbWlncmF0aW9ucyB0byBhcHBseVxuICAgKi9cbiAgcGVuZGluZ01pZ3JhdGlvbnM6IG51bWJlcjtcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgZmFpbGVkIG1pZ3JhdGlvbiBmaWxlIChpZiBhbnkpXG4gICAqL1xuICBmYWlsZWRNaWdyYXRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEVycm9yIG9iamVjdCBpZiBtaWdyYXRpb24gZmFpbGVkXG4gICAqL1xuICBlcnJvcj86IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNaWdyYXRpb25SdW5PcHRpb25zIHtcbiAgLyoqXG4gICAqIElmIHRydWUsIG9ubHkgbGlzdCBwZW5kaW5nIG1pZ3JhdGlvbnMgd2l0aG91dCBhcHBseWluZyB0aGVtXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBkcnlSdW4/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGxvZyB2ZXJib3NlIG91dHB1dFxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgdmVyYm9zZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWlncmF0aW9uQ29yZU9wdGlvbnMge1xuICAvKipcbiAgICogUGF0aCB0byB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgU1FMIG1pZ3JhdGlvbiBmaWxlc1xuICAgKi9cbiAgbWlncmF0aW9uc0Rpcjogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgTUlHUkFUSU9OX01PRFVMRV9PUFRJT05TID0gU3ltYm9sKCdNSUdSQVRJT05fTU9EVUxFX09QVElPTlMnKTtcbiJdfQ==
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@studiosonrai/nestjs-migrations",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SQL Server migrations module for NestJS applications",
|
|
5
|
+
"main": "dist/src/index.js",
|
|
6
|
+
"types": "dist/src/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"nestjs-migrations": "./dist/bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "rm -rf dist && tsc",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"clean": "rm -rf dist"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"nestjs",
|
|
20
|
+
"migrations",
|
|
21
|
+
"sql-server",
|
|
22
|
+
"mssql",
|
|
23
|
+
"typeorm"
|
|
24
|
+
],
|
|
25
|
+
"author": "",
|
|
26
|
+
"license": "UNLICENSED",
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@nestjs/common": "^11.0.0",
|
|
29
|
+
"@nestjs/config": "^4.0.0",
|
|
30
|
+
"@nestjs/core": "^11.0.0",
|
|
31
|
+
"typeorm": "^0.3.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"dotenv": "^17.2.1"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@nestjs/common": "^11.0.1",
|
|
38
|
+
"@nestjs/config": "^4.0.2",
|
|
39
|
+
"@nestjs/core": "^11.0.1",
|
|
40
|
+
"@types/node": "^22.10.7",
|
|
41
|
+
"reflect-metadata": "^0.2.2",
|
|
42
|
+
"rxjs": "^7.8.1",
|
|
43
|
+
"typeorm": "^0.3.25",
|
|
44
|
+
"typescript": "^5.7.3"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|