kobp
Version:
Koa Boilerplate with MikroORM
131 lines (110 loc) • 2.98 kB
text/typescript
import type Router from 'koa-router'
import Koa from 'koa'
export interface KobpCustomization {
/**
* Before app is being created
*/
onInit?: () => Promise<void>
/**
* After app has been created
*/
onAppCreated?: (app: Koa) => void
/**
* Attach all necessary middlewares.
*/
middlewares?: (app: Koa) => void
/**
* Handle signal received for graceful shutdown.
*/
onSignalReceived?: (signal: NodeJS.Signals, app: Koa) => Promise<void>
}
const _compileCustomization = (options: KobpCustomization[]): KobpCustomization => {
const allOpts = options
return {
onInit: async () => {
for(const opt of allOpts) {
if (opt.onInit) {
await opt.onInit()
}
}
},
onAppCreated: (app: Koa) => {
for(const opt of allOpts) {
if (opt.onAppCreated) {
opt.onAppCreated(app)
}
}
},
middlewares: (app: Koa) => {
for(const opt of allOpts) {
if (opt.middlewares) {
opt.middlewares(app)
}
}
},
onSignalReceived: async (signal: NodeJS.Signals, app: Koa): Promise<void> => {
for(const opt of allOpts) {
if (opt.onSignalReceived) {
await opt.onSignalReceived(signal, app)
}
}
}
}
}
export interface KobpModule {
customization(): KobpCustomization
}
export class BootstrapLoader {
private modules: KobpModule[] = []
public addModule(module: KobpModule): this {
this.modules.push(module)
return this
}
public buildSync(serviceRoutes: Router, appCustomization: KobpCustomization): Koa {
const opts = _compileCustomization([
...(this.modules.map((o) => o.customization())),
appCustomization,
])
// Actual Bootstraping
const app = new Koa()
// Fork
let initPromise = opts.onInit()
app.use(async (context, next) => {
await initPromise
await next()
})
this._launchKoa(serviceRoutes, app, opts)
return app
}
public async build(serviceRoutes: Router, appCustomization: KobpCustomization): Promise<Koa> {
const opts = _compileCustomization([
...(this.modules.map((o) => o.customization())),
appCustomization,
])
await opts.onInit()
// Actual Bootstraping
const app = new Koa()
this._launchKoa(serviceRoutes, app, opts)
return app
}
private _launchKoa(serviceRoutes: Router, koa: Koa, opts: KobpCustomization) {
// Fork
opts.middlewares && opts.middlewares(koa)
// Register actual application
koa.use(serviceRoutes.routes())
koa.use(serviceRoutes.allowedMethods())
opts.onAppCreated && opts.onAppCreated(koa)
if (opts.onSignalReceived) {
// register onSignalReceived handler.
process.on('SIGTERM', (signal) => {
opts.onSignalReceived(signal, koa)
.then(() => {
process.exit(0)
})
.catch((e) => {
process.exit(1)
})
})
}
}
}