Standard libraries that lift up your code.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

104 lines
3.2 KiB

import {Directive, OptionDefinition} from '../../cli'
import {Container, Inject, Injectable} from '../../di'
import {EventBus} from '../../event/EventBus'
import {Migrator} from '../migrations/Migrator'
import {Migrations} from '../services/Migrations'
import {RollingBackMigrationEvent} from '../migrations/events/RollingBackMigrationEvent'
import {RolledBackMigrationEvent} from '../migrations/events/RolledBackMigrationEvent'
import {EventSubscription} from '../../event/types'
import {NothingToMigrateError} from '../migrations/NothingToMigrateError'
import {CLIDirective} from '../../cli/decorators'
/**
* CLI directive that undoes applied migrations using the default Migrator.
* @fixme Support dry run mode
*/
@Injectable()
@CLIDirective()
export class RollbackDirective extends Directive {
@Inject()
protected readonly bus!: EventBus
@Inject('injector')
protected readonly injector!: Container
@Inject()
protected readonly migrations!: Migrations
/** Event bus subscriptions. */
protected subscriptions: EventSubscription[] = []
getKeywords(): string | string[] {
return ['rollback']
}
getDescription(): string {
return 'roll-back applied migrations'
}
getOptions(): OptionDefinition[] {
return [
'--identifier -i {name} | roll-back a specific migration, by identifier',
]
}
getHelpText(): string {
return [
'Use this command to undo one or more migrations that were applied.',
'',
'By default, the command will undo all of the migrations applied the last time the migrate command was run.',
'',
'To undo a specific migration, pass its identifier using the --identifier option.',
'',
].join('\n')
}
async handle(): Promise<void> {
await this.registerListeners()
const identifier = this.option('identifier')
let identifiers
if ( identifier ) {
identifiers = [identifier]
}
let error
try {
await (this.injector.make<Migrator>(Migrator)).rollback(identifiers)
} catch (e) {
if ( e instanceof NothingToMigrateError ) {
this.info(e.message)
} else {
error = e
this.error(e)
}
} finally {
await this.removeListeners()
}
if ( error ) {
throw error
}
}
/**
* Register event-bus listeners to print messages for the user.
* @protected
*/
protected async registerListeners(): Promise<void> {
this.subscriptions.push(await this.bus.subscribe(RollingBackMigrationEvent, event => {
this.info(`Rolling-back migration ${event.migration.identifier}...`)
}))
this.subscriptions.push(await this.bus.subscribe(RolledBackMigrationEvent, event => {
this.success(`Rolled-back migration: ${event.migration.identifier}`)
}))
}
/** Remove event bus listeners before finish. */
protected async removeListeners(): Promise<void> {
await Promise.all(this.subscriptions.map(x => x.unsubscribe()))
this.subscriptions = []
}
}