@@ -48,6 +48,40 @@ export class MigrationExecutor {
48
48
// Public Methods
49
49
// -------------------------------------------------------------------------
50
50
51
+ public async executeMigration ( migration : Migration ) : Promise < Migration > {
52
+ return this . withQueryRunner ( async ( queryRunner ) => {
53
+ await this . createMigrationsTableIfNotExist ( queryRunner ) ;
54
+ await ( migration . instance as any ) . up ( queryRunner ) ;
55
+ await this . insertExecutedMigration ( queryRunner , migration ) ;
56
+
57
+ return migration ;
58
+ } )
59
+ }
60
+
61
+ public async getAllMigrations ( ) : Promise < Migration [ ] > {
62
+ return this . getMigrations ( )
63
+ }
64
+
65
+ public async getExecutedMigrations ( ) : Promise < Migration [ ] > {
66
+ return this . withQueryRunner ( async queryRunner => {
67
+ await this . createMigrationsTableIfNotExist ( queryRunner ) ;
68
+
69
+ return await this . loadExecutedMigrations ( queryRunner ) ;
70
+ } ) ;
71
+ }
72
+
73
+ public async getPendingMigrations ( ) : Promise < Migration [ ] > {
74
+ const allMigrations = await this . getAllMigrations ( ) ;
75
+ const executedMigrations = await this . getExecutedMigrations ( ) ;
76
+
77
+ return allMigrations . filter ( migration =>
78
+ executedMigrations . find (
79
+ executedMigration =>
80
+ executedMigration . name === migration . name
81
+ )
82
+ ) ;
83
+ }
84
+
51
85
/**
52
86
* Lists all migrations and whether they have been executed or not
53
87
* returns true if there are unapplied migrations
@@ -315,9 +349,11 @@ export class MigrationExecutor {
315
349
protected getMigrations ( ) : Migration [ ] {
316
350
const migrations = this . connection . migrations . map ( migration => {
317
351
const migrationClassName = ( migration . constructor as any ) . name ;
318
- const migrationTimestamp = parseInt ( migrationClassName . substr ( - 13 ) ) ;
319
- if ( ! migrationTimestamp )
352
+ const migrationTimestamp = parseInt ( migrationClassName . substr ( - 13 ) , 10 ) ;
353
+
354
+ if ( ! migrationTimestamp || isNaN ( migrationTimestamp ) ) {
320
355
throw new Error ( `${ migrationClassName } migration name is wrong. Migration class name should have a JavaScript timestamp appended.` ) ;
356
+ }
321
357
322
358
return new Migration ( undefined , migrationTimestamp , migrationClassName , migration ) ;
323
359
} ) ;
@@ -342,6 +378,12 @@ export class MigrationExecutor {
342
378
return sortedMigrations . length > 0 ? sortedMigrations [ 0 ] : undefined ;
343
379
}
344
380
381
+ public insertMigration ( migration : Migration ) {
382
+ return this . withQueryRunner ( async queryRunner => {
383
+ return await this . insertExecutedMigration ( queryRunner , migration )
384
+ } )
385
+ }
386
+
345
387
/**
346
388
* Inserts new executed migration's data into migrations table.
347
389
*/
@@ -354,9 +396,9 @@ export class MigrationExecutor {
354
396
values [ "timestamp" ] = migration . timestamp ;
355
397
values [ "name" ] = migration . name ;
356
398
}
357
- if ( this . connection . driver instanceof MongoDriver ) {
399
+ if ( this . connection . driver instanceof MongoDriver ) {
358
400
const mongoRunner = queryRunner as MongoQueryRunner ;
359
- mongoRunner . databaseConnection . db ( this . connection . driver . database ! ) . collection ( this . migrationsTableName ) . insert ( values ) ;
401
+ mongoRunner . databaseConnection . db ( this . connection . driver . database ! ) . collection ( this . migrationsTableName ) . insert ( values ) ;
360
402
} else {
361
403
const qb = queryRunner . manager . createQueryBuilder ( ) ;
362
404
await qb . insert ( )
@@ -366,6 +408,12 @@ export class MigrationExecutor {
366
408
}
367
409
}
368
410
411
+ public deleteMigration ( migration : Migration ) {
412
+ return this . withQueryRunner ( async queryRunner => {
413
+ return await this . deleteExecutedMigration ( queryRunner , migration ) ;
414
+ } )
415
+ }
416
+
369
417
/**
370
418
* Delete previously executed migration's data from the migrations table.
371
419
*/
@@ -382,7 +430,7 @@ export class MigrationExecutor {
382
430
383
431
if ( this . connection . driver instanceof MongoDriver ) {
384
432
const mongoRunner = queryRunner as MongoQueryRunner ;
385
- mongoRunner . databaseConnection . db ( this . connection . driver . database ! ) . collection ( this . migrationsTableName ) . deleteOne ( conditions ) ;
433
+ mongoRunner . databaseConnection . db ( this . connection . driver . database ! ) . collection ( this . migrationsTableName ) . deleteOne ( conditions ) ;
386
434
} else {
387
435
const qb = queryRunner . manager . createQueryBuilder ( ) ;
388
436
await qb . delete ( )
@@ -395,4 +443,15 @@ export class MigrationExecutor {
395
443
396
444
}
397
445
446
+ private async withQueryRunner < T extends any > ( callback : ( queryRunner : QueryRunner ) => T ) {
447
+ const queryRunner = this . queryRunner || this . connection . createQueryRunner ( "master" ) ;
448
+
449
+ try {
450
+ return callback ( queryRunner )
451
+ } finally {
452
+ if ( ! this . queryRunner ) {
453
+ queryRunner . release ( )
454
+ }
455
+ }
456
+ }
398
457
}
0 commit comments