Skip to content

Commit

Permalink
feat: export Migration Execution API from main package (fixes #4880) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardofalk authored and pleerock committed Nov 22, 2019
1 parent f9fdaee commit 8f4f908
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ export {DeleteResult} from "./query-builder/result/DeleteResult";
export {QueryRunner} from "./query-runner/QueryRunner";
export {EntityManager} from "./entity-manager/EntityManager";
export {MongoEntityManager} from "./entity-manager/MongoEntityManager";
export {Migration} from "./migration/Migration";
export {MigrationExecutor} from "./migration/MigrationExecutor";
export {MigrationInterface} from "./migration/MigrationInterface";
export {DefaultNamingStrategy} from "./naming-strategy/DefaultNamingStrategy";
export {NamingStrategyInterface} from "./naming-strategy/NamingStrategyInterface";
Expand Down
89 changes: 87 additions & 2 deletions src/migration/MigrationExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,78 @@ export class MigrationExecutor {
// Public Methods
// -------------------------------------------------------------------------

/**
* Tries to execute a single migration given.
*/
public async executeMigration(migration: Migration): Promise<Migration> {
return this.withQueryRunner(async (queryRunner) => {
await this.createMigrationsTableIfNotExist(queryRunner);
await (migration.instance as any).up(queryRunner);
await this.insertExecutedMigration(queryRunner, migration);

return migration;
});
}

/**
* Returns an array of all migrations.
*/
public async getAllMigrations(): Promise<Migration[]> {
return Promise.resolve(this.getMigrations());
}

/**
* Returns an array of all executed migrations.
*/
public async getExecutedMigrations(): Promise<Migration[]> {
return this.withQueryRunner(async queryRunner => {
await this.createMigrationsTableIfNotExist(queryRunner);

return await this.loadExecutedMigrations(queryRunner);
});
}

/**
* Returns an array of all pending migrations.
*/
public async getPendingMigrations(): Promise<Migration[]> {
const allMigrations = await this.getAllMigrations();
const executedMigrations = await this.getExecutedMigrations();

return allMigrations.filter(migration =>
executedMigrations.find(
executedMigration =>
executedMigration.name === migration.name
)
);
}

/**
* Inserts an executed migration.
*/
public insertMigration(migration: Migration): Promise<void> {
return new Promise((resolve, reject) => {
this.withQueryRunner(queryRunner => {
this.insertExecutedMigration(queryRunner, migration)
.then(resolve)
.catch(reject);
});
});
}

/**
* Deletes an executed migration.
*/
public deleteMigration(migration: Migration): Promise<void> {
return new Promise((resolve, reject) => {
this.withQueryRunner(queryRunner => {
this.deleteExecutedMigration(queryRunner, migration)
.then(resolve)
.catch(reject);
});
});
}

/**
* Lists all migrations and whether they have been executed or not
* returns true if there are unapplied migrations
Expand Down Expand Up @@ -332,9 +404,10 @@ export class MigrationExecutor {
protected getMigrations(): Migration[] {
const migrations = this.connection.migrations.map(migration => {
const migrationClassName = migration.name || (migration.constructor as any).name;
const migrationTimestamp = parseInt(migrationClassName.substr(-13));
if (!migrationTimestamp)
const migrationTimestamp = parseInt(migrationClassName.substr(-13), 10);
if (!migrationTimestamp || isNaN(migrationTimestamp)) {
throw new Error(`${migrationClassName} migration name is wrong. Migration class name should have a JavaScript timestamp appended.`);
}

return new Migration(undefined, migrationTimestamp, migrationClassName, migration);
});
Expand Down Expand Up @@ -421,4 +494,16 @@ export class MigrationExecutor {
}

}

protected async withQueryRunner<T extends any>(callback: (queryRunner: QueryRunner) => T) {
const queryRunner = this.queryRunner || this.connection.createQueryRunner("master");

try {
return callback(queryRunner);
} finally {
if (!this.queryRunner) {
await queryRunner.release();
}
}
}
}

0 comments on commit 8f4f908

Please sign in to comment.