From 64f5f2f642e47039de2319884b173a4d679ebe9f Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Sat, 31 Aug 2019 11:42:12 +0700 Subject: [PATCH] Replace Application.ts with createAppication and configureApplication --- packages/server/src/application/Bootstrap.ts | 4 +- .../server/src/application/IApplication.ts | 3 - .../src/application/IApplicationConfig.ts | 31 +++++++ .../src/application/configureApplication.ts | 83 +++++++++++++++++++ .../src/application/createApplication.ts | 39 +++++++++ 5 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 packages/server/src/application/IApplicationConfig.ts create mode 100644 packages/server/src/application/configureApplication.ts create mode 100644 packages/server/src/application/createApplication.ts diff --git a/packages/server/src/application/Bootstrap.ts b/packages/server/src/application/Bootstrap.ts index fa08a84..bd33014 100644 --- a/packages/server/src/application/Bootstrap.ts +++ b/packages/server/src/application/Bootstrap.ts @@ -9,6 +9,8 @@ import {IDatabase} from '../database/IDatabase' import {Server} from 'http' import {SqlLogger, loggerFactory} from '../logger' import {createNamespace, Namespace} from 'cls-hooked' +import { configureApplication } from './configureApplication' +import { createApplication } from './createApplication' export class Bootstrap implements IBootstrap { protected server?: Server @@ -36,7 +38,7 @@ export class Bootstrap implements IBootstrap { } protected createApplication(database: IDatabase): IApplication { - return new Application(this.getConfig(), database) + return createApplication(configureApplication(this.getConfig(), database)) } async exec(command: string = 'listen') { diff --git a/packages/server/src/application/IApplication.ts b/packages/server/src/application/IApplication.ts index 47093c4..9a6d6bb 100644 --- a/packages/server/src/application/IApplication.ts +++ b/packages/server/src/application/IApplication.ts @@ -6,7 +6,4 @@ import {IDatabase} from '../database/IDatabase' export interface IApplication { readonly server: express.Application readonly database: IDatabase - - createAsyncRouter(): AsyncRouter - createTransactionalRouter(): AsyncRouter } diff --git a/packages/server/src/application/IApplicationConfig.ts b/packages/server/src/application/IApplicationConfig.ts new file mode 100644 index 0000000..6f46be4 --- /dev/null +++ b/packages/server/src/application/IApplicationConfig.ts @@ -0,0 +1,31 @@ +import { IConfig } from './IConfig' +import { IDatabase } from '../database' +import { ILogger } from '@rondo.dev/logger' +import { IServices } from './IServices' +import { RequestHandlerParams, ErrorRequestHandler } from 'express-serve-static-core' + +export interface IFramework { + readonly middleware: RequestHandlerParams[] + // TODO remove app, i believe this is used in tests + readonly app: RequestHandlerParams[] + readonly api: RequestHandlerParams[] + readonly apiError: ErrorRequestHandler + readonly frontend: RequestHandlerParams[] + readonly error: ErrorRequestHandler +} + +export interface IFrameworkPaths { + readonly middleware: string + readonly app: string + readonly api: string + readonly frontend: string +} + +export interface IApplicationConfig { + readonly config: IConfig + readonly database: IDatabase + readonly logger: ILogger + readonly services: IServices + readonly paths?: Partial + readonly framework: IFramework +} diff --git a/packages/server/src/application/configureApplication.ts b/packages/server/src/application/configureApplication.ts new file mode 100644 index 0000000..7e9d968 --- /dev/null +++ b/packages/server/src/application/configureApplication.ts @@ -0,0 +1,83 @@ +import cookieParser from 'cookie-parser' +import { json } from 'body-parser' +import { IDatabase } from '../database' +import { loggerFactory } from '../logger' +import * as Middleware from '../middleware' +import * as Services from '../services' +import * as Team from '../team' +import * as User from '../user' +import { IApplicationConfig } from './IApplicationConfig' +import { IConfig } from './IConfig' +import { IServices } from './IServices' +import * as routes from '../routes' +import { TransactionalRouter } from '../router' +import { IRoutes, IContext } from '@rondo.dev/common' +import { Express } from 'express-serve-static-core' + +export function configureApplication( + config: IConfig, + database: IDatabase, +): IApplicationConfig { + + const logger = loggerFactory.getLogger('api') + + const services: IServices = { + userService: new Services.UserService(database), + teamService: new Team.TeamService(database), + userPermissions: new User.UserPermissions(database), + } + + const authenticator = new Middleware.Authenticator(services.userService) + const transactionManager = database.transactionManager + + const createTransactionalRouter = () => + new TransactionalRouter(transactionManager) + + const getContext = (req: Express.Request): IContext => ({user: req.user}) + + return { + config, + database, + logger, + services, + framework: { + middleware: [ + new Middleware.SessionMiddleware({ + transactionManager, + baseUrl: config.app.baseUrl, + sessionName: config.app.session.name, + sessionSecret: config.app.session.secret, + }).handle, + new Middleware.RequestLogger(logger).handle, + json(), + cookieParser(config.app.session.secret), + new Middleware.CSRFMiddleware({ + baseUrl: config.app.baseUrl, + cookieName: config.app.session.name + '_csrf', + }).handle, + new Middleware.Transaction(database.namespace).handle, + authenticator.handle, + ], + app: [routes.application], + api: [ + new routes.LoginRoutes( + services.userService, + authenticator, + createTransactionalRouter(), + ).handle, + new routes.UserRoutes( + services.userService, + createTransactionalRouter(), + ).handle, + new Team.TeamRoutes( + services.teamService, + services.userPermissions, + createTransactionalRouter(), + ).handle, + ], + apiError: new Middleware.ErrorApiHandler(logger).handle, + frontend: [], + error: new Middleware.ErrorPageHandler(logger).handle, + }, + } +} diff --git a/packages/server/src/application/createApplication.ts b/packages/server/src/application/createApplication.ts new file mode 100644 index 0000000..e7f0587 --- /dev/null +++ b/packages/server/src/application/createApplication.ts @@ -0,0 +1,39 @@ +import { IApplicationConfig, IFrameworkPaths } from './IApplicationConfig' +import { IApplication } from './IApplication' +import express from 'express' + +export const defaultPaths: IFrameworkPaths = { + middleware: '/', + app: '/app', + api: '/api', + frontend: '/', +} + +export function createApplication(appConfig: IApplicationConfig): IApplication { + const {config, database, framework} = appConfig + const server = express() + + const paths = { + ...defaultPaths, + ...(appConfig.paths || {}), + } + + server.set('trust proxy', 1) + server.disable('x-powered-by') + + const router = express.Router() + router.use(paths.middleware, ...framework.middleware) + router.use(paths.app, ...framework.app) + router.use(paths.api, ...framework.api) + router.use(paths.api, framework.apiError) + if (framework.frontend.length) { + router.use(paths.frontend, ...framework.frontend) + } + + server.use(config.app.context, router) + server.use(framework.error) + return { + server, + database, + } +}