import { Connection } from 'typeorm' ; import logger from '@mds-core/mds-logger' ; import { pluralize } from '@mds-core/mds-utils' ; import { ConnectionManager , ConnectionManagerOptions , ConnectionMode , ConnectionManagerCliOptions } from './connection' ; import { CreateRepositoryMigration } from './migration' ; export type RepositoryOptions = Pick < ConnectionManagerOptions , 'entities' | 'migrations' > ; abstract class BaseRepository < TConnectionMode extends ConnectionMode > { protected readonly manager : ConnectionManager < TConnectionMode > ; protected abstract initialize ( ) ; protected connect = async ( mode ) : Promise < Omit < Connection , 'connect' | 'close' > > => { const { connect } = this . manager ; const connection = await connect ( mode ) ; return connection ; } ; protected abstract shutdown ( ) ; constructor ( public readonly name , { entities , migrations } ) { const migrationsTableName = `${ name }-migrations` ; this . manager = new ConnectionManager ( name , { migrationsTableName , entities , migrations : migrations . length === 0 ? [ ] : [ CreateRepositoryMigration ( migrationsTableName ) , ... migrations ] } ) ; } } export abstract class ReadOnlyRepository extends BaseRepository < 'ro' > { public initialize = async ( ) : Promise < void > => { const { name } = this ; logger . info ( `Initializing R/O repository: ${ name }` ) ; } ; public shutdown = async ( ) : Promise < void > => { const { name , manager : { disconnect } } = this ; logger . info ( `Terminating R/O repository: ${ name }` ) ; await disconnect ( 'ro' ) ; } ; public cli = ( ) => { const { cli } = this . manager ; return cli ( 'ro' ) ; } ; constructor ( name , { entities = [ ] } = { } ) { super ( name , { entities , migrations : [ ] } ) ; } } export abstract class ReadWriteRepository extends BaseRepository < 'ro' | 'rw' > { public initialize = async ( ) : Promise < void > => { const { name , manager : { connect } } = this ; logger . info ( `Initializing R/W repository: ${ name }` ) ; const { PG_MIGRATIONS = 'true' } = process . env ; if ( PG_MIGRATIONS === 'true' ) { const connection = await connect ( 'rw' ) ; const { options : { migrationsTableName } } = connection ; if ( migrationsTableName ) { const migrations = await connection . runMigrations ( { transaction : 'all' } ) ; logger . info ( `Ran ${ migrations . length || 'no' } ${ pluralize ( migrations . length , 'migration' , 'migrations' ) } (${ migrationsTableName })${ migrations . length ? `: ${ migrations . map ( migration => migration . name ) . join ( ', ' ) }` : '' }` ) ; } } } ; public shutdown = async ( ) : Promise < void > => { const { name , manager : { disconnect } } = this ; logger . info ( `Terminating R/W repository: ${ name }` ) ; await Promise . all ( [ disconnect ( 'rw' ) , disconnect ( 'ro' ) ] ) ; } ; public cli = ( options ? ) => { const { cli } = this . manager ; return cli ( 'rw' , options ) ; } ; constructor ( name , { entities = [ ] , migrations = [ ] } = { } ) { super ( name , { entities , migrations } ) ; } }