diff --git a/packages/server/src/application/Bootstrap.ts b/packages/server/src/application/Bootstrap.ts index 7a72069..f200df8 100644 --- a/packages/server/src/application/Bootstrap.ts +++ b/packages/server/src/application/Bootstrap.ts @@ -5,23 +5,60 @@ import { AddressInfo } from 'net' import { Database } from '../database/Database' import { IDatabase } from '../database/IDatabase' import { loggerFactory, SqlLogger } from '../logger' -import { configureServer } from './configureServer' +import { ServerConfigurator } from './configureServer' import { createServer } from './createServer' import { IApplication } from './IApplication' import { IBootstrap } from './IBootstrap' import { IConfig } from './IConfig' +import { IServerConfig } from './IServerConfig' + +export interface IBootstrapParams { + readonly config: IConfig + readonly configureServer: ServerConfigurator + readonly namespace?: Namespace + readonly exit?: (code: number) => void + readonly entities?: object + readonly migrations?: object +} + +// tslint:disable-next-line +function getFunctions(obj: object): Function[] { + return Object.keys(obj) + .map(k => (obj as any)[k]) + .filter(f => typeof f === 'function') +} export class Bootstrap implements IBootstrap { + protected config: IConfig + protected configureServer: ServerConfigurator + protected namespace: Namespace + protected exit: (code: number) => void + protected server?: Server protected inUse: boolean = false readonly application: IApplication readonly database: IDatabase - constructor( - private readonly config: IConfig, - protected readonly namespace: Namespace = createNamespace('application'), - protected readonly exit: (code: number) => void = process.exit, - ) { + constructor(params: IBootstrapParams) { + this.config = { + ...params.config, + app: { + ...params.config.app, + db: { + ...params.config.app.db, + entities: params.entities + ? getFunctions(params.entities) + : params.config.app.db.entities, + migrations: params.migrations + ? getFunctions(params.migrations) + : params.config.app.db.migrations, + }, + }, + } + this.configureServer = params.configureServer + this.namespace = params.namespace || createNamespace('application') + this.exit = params.exit || process.exit + this.database = this.createDatabase() this.application = this.createApplication(this.database) } @@ -31,12 +68,13 @@ export class Bootstrap implements IBootstrap { } protected createDatabase(): IDatabase { - const sqlLogger = new SqlLogger( - loggerFactory.getLogger('sql'), this.namespace) - return new Database(this.namespace, sqlLogger, this.getConfig().app.db) + const {namespace} = this + const sqlLogger = new SqlLogger(loggerFactory.getLogger('sql'), namespace) + return new Database(namespace, sqlLogger, this.getConfig().app.db) } protected createApplication(database: IDatabase): IApplication { + const {configureServer} = this return createServer(configureServer(this.getConfig(), database)) } diff --git a/packages/server/src/application/configureServer.ts b/packages/server/src/application/configureServer.ts index 750e56a..ddb7ddb 100644 --- a/packages/server/src/application/configureServer.ts +++ b/packages/server/src/application/configureServer.ts @@ -14,14 +14,14 @@ import { TransactionalRouter } from '../router' import { IRoutes, IContext } from '@rondo.dev/common' import { Express } from 'express-serve-static-core' -export type AppConfigurator< +export type ServerConfigurator< T extends IServerConfig = IServerConfig > = ( config: IConfig, database: IDatabase, ) => T -export const configureServer: AppConfigurator = (config, database) => { +export const configureServer: ServerConfigurator = (config, database) => { const logger = loggerFactory.getLogger('api') diff --git a/packages/server/src/bootstrap.ts b/packages/server/src/bootstrap.ts index 0d145db..cec1db3 100644 --- a/packages/server/src/bootstrap.ts +++ b/packages/server/src/bootstrap.ts @@ -1,12 +1,8 @@ -if (!process.env.LOG) { - process.env.LOG = 'api,sql:warn' -} - import {config} from './config' import {Bootstrap} from './application/Bootstrap' +import {configureServer} from './application/configureServer' -export const bootstrap = new Bootstrap(config) -// FIXME determine a port by parsing app url from config -const port: string | number = process.env.PORT || 3000 - -bootstrap.listen(port) +export default new Bootstrap({ + config, + configureServer, +}) diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 6770366..85f1d9e 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -1,3 +1,8 @@ +if (require.main === module) { + if (!process.env.LOG) { + process.env.LOG = 'api,sql:warn' + } +} export * from './application' export * from './database' export * from './entities' @@ -14,3 +19,9 @@ export * from './validator' import * as rpc from './rpc' export {rpc} + +import bootstrap from './bootstrap' + +if (require.main === module) { + bootstrap.exec(process.argv[2]) +} diff --git a/packages/server/src/test.ts b/packages/server/src/test.ts index 95210cc..c1685f7 100644 --- a/packages/server/src/test.ts +++ b/packages/server/src/test.ts @@ -1,4 +1,5 @@ import {Bootstrap} from './application/Bootstrap' +import {configureServer} from './application/configureServer' import {IAPIDef} from '@rondo.dev/common' import {TestUtils} from './test-utils' import {config} from './config' @@ -6,11 +7,12 @@ import {createNamespace} from 'cls-hooked' export const exit = jest.fn() -export const bootstrap = new Bootstrap( +export const bootstrap = new Bootstrap({ config, - createNamespace('test'), + configureServer, + namespace: createNamespace('test'), exit, -) +}) // TODO separate IAPIDef between projects export const test = new TestUtils(bootstrap)