Last active
December 21, 2018 07:12
-
-
Save digitalsadhu/4a3839983a8a384882be28154f830c62 to your computer and use it in GitHub Desktop.
App scaffold proposal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
class AppScaffold { | |
/* | |
Method used to register a plugin function that will be run in the constructor | |
Plugins can be used to | |
* register middleware | |
* add functions to the startup queue | |
* add functions to the shutdown queue | |
* register metrics streams to be consumed | |
* log messages | |
* access the express app instance (register routes etc) | |
* access the app scaffold instance including user options | |
*/ | |
static plugin(fn) { | |
if (!this.plugins) this.plugins = []; | |
this.plugins.push(fn); | |
} | |
constructor(options = {}) { | |
this.startQueue = []; | |
this.stopQueue = []; | |
this.metricsStreams = []; | |
this.middlewares = []; | |
this.app = express(); | |
this.options = { | |
port: 8080, | |
grace: 0, | |
logger: null, | |
metrics: false, | |
prometheus: null, | |
...options, | |
}; | |
this.log = abslog(this.options.logger); | |
// run all registered plugins | |
for (const plugin of this.constructor.plugins) { | |
plugin(this); | |
} | |
// mount all registered middleware | |
for (const middleware of this.middlewares) { | |
this.app.use(middleware); | |
} | |
// setup app start | |
this.appStart = new AppStart(this.app, { | |
port: this.options.port, | |
grace: this.options.grace, | |
logger: this.log, | |
}); | |
this.registerMetrics(this.appStart.metrics); | |
// setup metrics consumption, compose all streams registered with this.registerMetrics | |
if (this.options.metrics) { | |
Object.defineProperty(this, 'consumer', { | |
value: new MetricsConsumer({ client: this.options.prometheus }), | |
}); | |
pipeline(...this.metricsStreams, this.consumer, err => { | |
if (err) this.log.error('an error occurred', err); | |
}); | |
} | |
} | |
/* | |
Register a metrics stream created by @metrics/client to be consumed | |
*/ | |
registerMetrics(stream) { | |
this.metricsStreams.push(stream); | |
} | |
/* | |
Register a middleware function to be mounted into the express app | |
*/ | |
registerMiddleware(fn) { | |
this.middlewares.push(fn); | |
} | |
/* | |
Register a function (that returns a promise) that will be run immediately before the app starts | |
*/ | |
onStart(fn) { | |
this.startQueue.push(fn); | |
} | |
/* | |
Register a function (that returns a promise) that will be run immediately before the app stops | |
*/ | |
onStop(fn) { | |
this.stopQueue.push(fn); | |
} | |
/* | |
Public API to start the app | |
*/ | |
async start() { | |
// run through on start queue | |
for (const op of this.startQueue) { | |
await op(); | |
} | |
for (const op of this.stopQueue) { | |
this.appStart.proc.set(async next => { | |
await op(); | |
next(); | |
}); | |
} | |
await this.appStart.start(); | |
} | |
/* | |
Public API to stop the app | |
*/ | |
stop() { | |
await this.appStart.stop(); | |
} | |
} | |
module.exports = AppScaffold; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const ExampleApp = require('./custom-app.js'); | |
const example = new ExampleApp({ | |
port: 3004, | |
grace: 5000, | |
}); | |
example.app.get('/', (req, res) => { | |
res.send('this is my pre-configured app'); | |
}); | |
example.start(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const ExpressTiming = require('express-timing-middleware'); | |
const AppScaffold = require('./app-scaffold'); | |
class ExampleApp extends AppScaffold {} | |
// add express timing middleware plugin | |
ExampleApp.plugin(instance => { | |
const timing = new ExpressTiming(); | |
instance.registerMiddleware(timing.middleware()); | |
instance.registerMetrics(timing.metrics); | |
}); | |
module.exports = ExampleApp; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment