import { AbstractFactory, DependencyRequirement, PropertyDependency, isInstantiable, DEPENDENCY_KEYS_METADATA_KEY, DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, Instantiable, Injectable, Inject, FactoryProducer, } from '../../di' import {Collection, ErrorWithContext} from '../../util' import {Logging} from '../../service/Logging' import {Config} from '../../service/Config' import {Migrator} from './Migrator' import {DatabaseMigrator} from './DatabaseMigrator' /** * A dependency injection factory that matches the abstract Migrator class * and produces an instance of the configured session driver implementation. */ @Injectable() @FactoryProducer() export class MigratorFactory extends AbstractFactory { @Inject() protected readonly logging!: Logging @Inject() protected readonly config!: Config constructor() { super({}) } produce(): Migrator { return new (this.getMigratorClass())() } match(something: unknown): boolean { return something === Migrator } getDependencyKeys(): Collection { const meta = Reflect.getMetadata(DEPENDENCY_KEYS_METADATA_KEY, this.getMigratorClass()) if ( meta ) { return meta } return new Collection() } getInjectedProperties(): Collection { const meta = new Collection() let currentToken = this.getMigratorClass() do { const loadedMeta = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, currentToken) if ( loadedMeta ) { meta.concat(loadedMeta) } currentToken = Object.getPrototypeOf(currentToken) } while (Object.getPrototypeOf(currentToken) !== Function.prototype && Object.getPrototypeOf(currentToken) !== Object.prototype) return meta } /** * Return the instantiable class of the configured migrator backend. * @protected * @return Instantiable */ protected getMigratorClass(): Instantiable { const MigratorClass = this.config.get('database.migrations.driver', DatabaseMigrator) if ( !isInstantiable(MigratorClass) || !(MigratorClass.prototype instanceof Migrator) ) { const e = new ErrorWithContext('Provided migration driver class does not extend from @extollo/lib.Migrator') e.context = { configKey: 'database.migrations.driver', class: MigratorClass.toString(), } } return MigratorClass } }