AsyncPipe; table schemata; migrations; File logging
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
98
src/orm/services/Migrations.ts
Normal file
98
src/orm/services/Migrations.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import {Inject, Singleton} from '../../di'
|
||||
import {CanonicalInstantiable} from '../../service/CanonicalInstantiable'
|
||||
import {Migration} from '../migrations/Migration'
|
||||
import {CanonicalDefinition, CanonicalResolver} from '../../service/Canonical'
|
||||
import {Migrator} from '../migrations/Migrator'
|
||||
import {UniversalPath} from '../../util'
|
||||
import {lib} from '../../lib'
|
||||
import {CommandLine} from '../../cli'
|
||||
import {MigrateDirective} from '../directive/MigrateDirective'
|
||||
import {RollbackDirective} from '../directive/RollbackDirective'
|
||||
import {CreateMigrationDirective} from '../directive/CreateMigrationDirective'
|
||||
|
||||
/**
|
||||
* Service unit that loads and instantiates migration classes.
|
||||
*/
|
||||
@Singleton()
|
||||
export class Migrations extends CanonicalInstantiable<Migration> {
|
||||
@Inject()
|
||||
protected readonly migrator!: Migrator
|
||||
|
||||
@Inject()
|
||||
protected readonly cli!: CommandLine
|
||||
|
||||
protected appPath = ['migrations']
|
||||
|
||||
protected canonicalItem = 'migration'
|
||||
|
||||
protected suffix = '.migration.js'
|
||||
|
||||
async up(): Promise<void> {
|
||||
if ( await this.path.exists() ) {
|
||||
await super.up()
|
||||
} else {
|
||||
this.logging.debug(`Base migration path does not exist, or has no files: ${this.path}`)
|
||||
}
|
||||
|
||||
// Register the migrations for @extollo/lib
|
||||
const basePath = lib().concat('migrations')
|
||||
const resolver = await this.buildMigrationNamespaceResolver('@extollo', basePath)
|
||||
this.registerNamespace('@extollo', resolver)
|
||||
|
||||
// Register the migrate CLI directives
|
||||
this.cli.registerDirective(MigrateDirective)
|
||||
this.cli.registerDirective(RollbackDirective)
|
||||
this.cli.registerDirective(CreateMigrationDirective)
|
||||
}
|
||||
|
||||
async initCanonicalItem(definition: CanonicalDefinition): Promise<Migration> {
|
||||
const instance = await super.initCanonicalItem(definition)
|
||||
|
||||
if ( !(instance instanceof Migration) ) {
|
||||
throw new TypeError(`Invalid migration: ${definition.originalName}. Migrations must extend from @extollo/lib.Migration.`)
|
||||
}
|
||||
|
||||
instance.setMigrationIdentifier(definition.canonicalName)
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a CanonicalResolver for a directory that contains migration files.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const path = universalPath('path', 'to', 'migrations', 'folder')
|
||||
* const namespace = '@mypackage'
|
||||
*
|
||||
* const resolver = await migrations.buildMigrationNamespaceResolver(namespace, path)
|
||||
* migrations.registerNamespace(namespace, resolver)
|
||||
* ```
|
||||
* @param name
|
||||
* @param basePath
|
||||
*/
|
||||
public async buildMigrationNamespaceResolver(name: string, basePath: UniversalPath): Promise<CanonicalResolver<Migration>> {
|
||||
if ( !name.startsWith('@') ) {
|
||||
name = `@${name}`
|
||||
}
|
||||
|
||||
const namespace: {[key: string]: Migration} = {}
|
||||
|
||||
for await ( const entry of basePath.walk() ) {
|
||||
if ( !entry.endsWith(this.suffix) ) {
|
||||
this.logging.debug(`buildMigrationNamespaceResolver - Skipping file with invalid suffix: ${entry}`)
|
||||
continue
|
||||
}
|
||||
|
||||
const definition = await this.buildCanonicalDefinition(entry, basePath)
|
||||
this.logging.verbose(`buildMigrationNamespaceResolver - Discovered canonical ${this.canonicalItem} "${definition.canonicalName}" from ${entry}`)
|
||||
namespace[definition.canonicalName] = await this.initCanonicalItem(definition)
|
||||
namespace[definition.canonicalName].setMigrationIdentifier(`${name}:${namespace[definition.canonicalName].identifier}`)
|
||||
}
|
||||
|
||||
return {
|
||||
get: (key: string) => namespace[key],
|
||||
all: () => Object.keys(namespace),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user