import { EntityManager } from './EntityManager' ; import { PoolConfig , ReplicationConfig , SingleConfig , Store } from './Store' ; import { Homefront } from 'homefront' ; import { Scope } from './Scope' ; import { EntityCtor , EntityInterface } from './EntityInterface' ; import { Migrator } from './Migrator/Migrator' ; import * as fs from 'fs' ; import * as mkdirp from 'mkdirp' ; import * as path from 'path' ; import { SnapshotManager } from './SnapshotManager' ; import { SchemaManager } from './SchemaManager' ; import { Populate } from './Populate' ; import { Seeder } from './Seeder' ; import { Cleaner } from './Cleaner' ; export const entityFilterRegexp = /^(?!.*index\.(js|ts)$).*(^.?|\.[^d]|[^.]d|[^.][^d])\.(js|ts)$/ ; export const entityExtensionRegexp = /\.(js|ts)$/ ; export class Wetland { type { EntityManager } private entityManager : EntityManager = new EntityManager ( this ) ; type { Migrator } private migrator : Migrator ; type { SnapshotManager } private snapshotManager : SnapshotManager ; type { Homefront } private config : Homefront = new Homefront ( { debug : false , useForeignKeys : true , dataDirectory : path . resolve ( process . cwd ( ) , '.data' ) , defaultStore : 'defaultStore' , mapping : { defaultNamesToUnderscore : false , defaults : { cascades : [ ] } , } , entityManager : { refreshCreated : true , refreshUpdated : true , } , } ) ; type { { } } private stores : { [ key ] : Store ; } = { } ; type { SchemaManager } private schema : SchemaManager ; param { { } } config public constructor ( config ? ) { this . ensureDataDirectory ( this . config . fetch ( 'dataDirectory' ) ) ; this . setupExitListeners ( ) ; this . initializeConfig ( config ) ; } returns { Homefront } public getConfig ( ) { return this . config ; } param { EntityInterface } entity returns { Wetland } public registerEntity ( entity ) { this . entityManager . registerEntity ( entity ) ; return this ; } param { EntityInterface [ ] } entities returns { Wetland } public registerEntities ( entities ) { this . entityManager . registerEntities ( entities ) ; return this ; } param { Object } stores returns { Wetland } public registerStores ( stores ) { for ( const store in stores ) { this . registerStore ( store , stores [ store ] ) ; } return this ; } param { string } store param { { } } config returns { Wetland } public registerStore ( store , config ) { if ( this . config . fetch ( 'debug' ) ) { config . debug = true ; } this . stores [ store ] = new Store ( store , config ) ; this . config . fetchOrPut ( 'defaultStore' , store ) ; return this ; } param { string } storeName returns { Store } public getStore ( storeName ? ) { storeName = storeName || this . config . fetch ( 'defaultStore' ) ; if ( ! storeName ) { throw new Error ( 'No store name supplied, and no default store found.' ) ; } const store = this . stores [ storeName ] ; if ( ! store ) { throw new Error ( `No store called "${ storeName }" found.` ) ; } return store ; } return { Seeder } public getSeeder ( ) { return new Seeder ( this ) ; } return { Cleaner } public getCleaner ( ) { return new Cleaner ( this ) ; } returns { Scope } public getManager ( ) { return this . entityManager . createScope ( ) ; } returns { EntityManager } public getEntityManager ( ) { return this . entityManager ; } returns { Migrator } public getMigrator ( ) { if ( ! this . migrator ) { this . migrator = new Migrator ( this ) ; } return this . migrator ; } returns { SchemaManager } public getSchemaManager ( ) { if ( ! this . schema ) { this . schema = new SchemaManager ( this ) ; } return this . schema ; } returns { SnapshotManager } public getSnapshotManager ( ) { if ( ! this . snapshotManager ) { this . snapshotManager = new SnapshotManager ( this ) ; } return this . snapshotManager ; } returns { Populate } public getPopulator ( scope ) { return new Populate ( scope ) ; } returns { Promise < any > } public destroyConnections ( ) { const destroys = [ ] ; Object . getOwnPropertyNames ( this . stores ) . forEach ( storeName => { const connections = this . stores [ storeName ] . getConnections ( ) ; connections [ Store . ROLE_SLAVE ] . forEach ( connection => { destroys . push ( connection . destroy ( ) . then ( ) ) ; } ) ; connections [ Store . ROLE_MASTER ] . forEach ( connection => { destroys . push ( connection . destroy ( ) . then ( ) ) ; } ) ; } ) ; return Promise . all ( destroys ) ; } param { { } } config private initializeConfig ( config ) { if ( config ) { this . config . merge ( config ) ; } const stores = this . config . fetch ( 'stores' ) ; const entities = this . config . fetch ( 'entities' ) ; const entityPaths = this . config . fetch ( 'entityPaths' , [ ] ) ; const entityPath = this . config . fetch ( 'entityPath' ) ; if ( stores ) { this . registerStores ( stores ) ; } else { this . registerDefaultStore ( ) ; } if ( entities ) { this . registerEntities ( entities ) ; } if ( entityPath ) { entityPaths . push ( entityPath ) ; } if ( ! entityPaths . length ) { return ; } entityPaths . forEach ( entityPath => { fs . readdirSync ( entityPath ) . filter ( match => match . search ( entityFilterRegexp ) > - 1 ) . map ( entity => entity . replace ( entityExtensionRegexp , '' ) ) . forEach ( entity => { const filePath = path . resolve ( entityPath , entity ) ; const entityModule = require ( filePath ) ; let ToRegister = entityModule ; if ( typeof ToRegister !== 'function' ) { ToRegister = entityModule . default ; } if ( typeof ToRegister !== 'function' ) { ToRegister = entityModule [ entity ] ; } if ( typeof ToRegister !== 'function' ) { throw new Error ( `Error loading entity '${ entity }'. No constructor exported.` ) ; } this . registerEntity ( ToRegister ) ; } ) ; } ) ; } /**
     * set of listeners for the exit event.
     */ private setupExitListeners ( ) { process . on ( 'beforeExit' , ( ) => this . destroyConnections ( ) ) ; } /**
     * Register a default (fallback) store (sqlite3).
     */ private registerDefaultStore ( ) { try { require ( 'sqlite3' ) ; } catch ( error ) { throw new Error ( 'No stores configured and sqlite3 not found as dependency. ' + 'Configure a store, or run `npm i --save sqlite3`.' ) ; } this . registerStore ( this . config . fetch ( 'defaultStore' ) , { client : 'sqlite3' , useNullAsDefault : true , connection : { filename : `${ this . config . fetch ( 'dataDirectory' ) }/wetland.sqlite` } , } ) ; } param { string } dataDirectory private ensureDataDirectory ( dataDirectory ) { try { fs . statSync ( dataDirectory ) ; } catch ( error ) { try { mkdirp . sync ( dataDirectory ) ; } catch ( error ) { throw new Error ( `Unable to create data directory at '${ dataDirectory }'` ) ; } } } }