@@ -51,6 +51,78 @@ export class MigrationExecutor {
51
51
// Public Methods
52
52
// -------------------------------------------------------------------------
53
53
54
+ /**
55
+ * Tries to execute a single migration given.
56
+ */
57
+ public async executeMigration ( migration : Migration ) : Promise < Migration > {
58
+ return this . withQueryRunner ( async ( queryRunner ) => {
59
+ await this . createMigrationsTableIfNotExist ( queryRunner ) ;
60
+ await ( migration . instance as any ) . up ( queryRunner ) ;
61
+ await this . insertExecutedMigration ( queryRunner , migration ) ;
62
+
63
+ return migration ;
64
+ } ) ;
65
+ }
66
+
67
+ /**
68
+ * Returns an array of all migrations.
69
+ */
70
+ public async getAllMigrations ( ) : Promise < Migration [ ] > {
71
+ return Promise . resolve ( this . getMigrations ( ) ) ;
72
+ }
73
+
74
+ /**
75
+ * Returns an array of all executed migrations.
76
+ */
77
+ public async getExecutedMigrations ( ) : Promise < Migration [ ] > {
78
+ return this . withQueryRunner ( async queryRunner => {
79
+ await this . createMigrationsTableIfNotExist ( queryRunner ) ;
80
+
81
+ return await this . loadExecutedMigrations ( queryRunner ) ;
82
+ } ) ;
83
+ }
84
+
85
+ /**
86
+ * Returns an array of all pending migrations.
87
+ */
88
+ public async getPendingMigrations ( ) : Promise < Migration [ ] > {
89
+ const allMigrations = await this . getAllMigrations ( ) ;
90
+ const executedMigrations = await this . getExecutedMigrations ( ) ;
91
+
92
+ return allMigrations . filter ( migration =>
93
+ executedMigrations . find (
94
+ executedMigration =>
95
+ executedMigration . name === migration . name
96
+ )
97
+ ) ;
98
+ }
99
+
100
+ /**
101
+ * Inserts an executed migration.
102
+ */
103
+ public insertMigration ( migration : Migration ) : Promise < void > {
104
+ return new Promise ( ( resolve , reject ) => {
105
+ this . withQueryRunner ( queryRunner => {
106
+ this . insertExecutedMigration ( queryRunner , migration )
107
+ . then ( resolve )
108
+ . catch ( reject ) ;
109
+ } ) ;
110
+ } ) ;
111
+ }
112
+
113
+ /**
114
+ * Deletes an executed migration.
115
+ */
116
+ public deleteMigration ( migration : Migration ) : Promise < void > {
117
+ return new Promise ( ( resolve , reject ) => {
118
+ this . withQueryRunner ( queryRunner => {
119
+ this . deleteExecutedMigration ( queryRunner , migration )
120
+ . then ( resolve )
121
+ . catch ( reject ) ;
122
+ } ) ;
123
+ } ) ;
124
+ }
125
+
54
126
/**
55
127
* Lists all migrations and whether they have been executed or not
56
128
* returns true if there are unapplied migrations
@@ -333,8 +405,9 @@ export class MigrationExecutor {
333
405
const migrations = this . connection . migrations . map ( migration => {
334
406
const migrationClassName = migration . name || ( migration . constructor as any ) . name ;
335
407
const migrationTimestamp = parseInt ( migrationClassName . substr ( - 13 ) ) ;
336
- if ( ! migrationTimestamp )
408
+ if ( ! migrationTimestamp || isNaN ( migrationTimestamp ) ) {
337
409
throw new Error ( `${ migrationClassName } migration name is wrong. Migration class name should have a JavaScript timestamp appended.` ) ;
410
+ }
338
411
339
412
return new Migration ( undefined , migrationTimestamp , migrationClassName , migration ) ;
340
413
} ) ;
@@ -421,4 +494,16 @@ export class MigrationExecutor {
421
494
}
422
495
423
496
}
497
+
498
+ protected async withQueryRunner < T extends any > ( callback : ( queryRunner : QueryRunner ) => T ) {
499
+ const queryRunner = this . queryRunner || this . connection . createQueryRunner ( "master" ) ;
500
+
501
+ try {
502
+ return callback ( queryRunner ) ;
503
+ } finally {
504
+ if ( ! this . queryRunner ) {
505
+ await queryRunner . release ( ) ;
506
+ }
507
+ }
508
+ }
424
509
}
0 commit comments