
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Rock-solid structured application layout for building APIs and web apps in Node.js
Rock-solid structured application layout for building APIs and web apps in Node.js.
The goal of slay is to provide the absolute minimum amount of consistency in a Node.js
application without forcing an enormous amount of convention onto users. The consistency
goal also centers around encouraging modularity in application-level code for maximum reuse.
This is accomplished through three simple features: application layout, "preboots", and a consistent application startup.
By convention slay looks for user-defined modules in the following locations:
lib/preboots
lib/middlewares
lib/routes
This is done using standard, built-in Node.js module loading which means that each of these could be individual files of the same name instead of folders. Feel free to mix and match as your application's complexity grows. e.g.:
lib/preboots/index.js
lib/middlewares.js
lib/routes/index.js
"A preboot is a middleware for application extensibility"
That is, instead of function (req, res, next) a preboot is function (app, options, done).
By enforcing a consistent function signature to application extensibility all require ordering
problems become trivial. For example:
lib/preboots/index.js
module.exports = function (app, options, done) {
//
// **SCHEDULE** the attachment and initialization of
// connections to our models.
//
app.preboot(require('./models'));
done();
};
lib/preboots/models.js
module.exports = function (app, options, next) {
//
// Attach all of the models for our API / microservices
// to the app itself and connect to them
// (e.g. initialize TCP sockets, etc).
//
app.models = require('../models');
app.models.connect(next);
};
While this may seem too obvious it does several things:
lib/preboots/index.js.const slay = require('slay');
const app = new slay.App(__dirname);
app.start(options, function (err) {
if (err) { throw err; }
app.log.info(`Listening on ${app.config.get('http')`);
});
Calling app.start above will trigger two main interceptors:
"setup" interceptor./preboots will be loaded in app.before('setup')routers
app.perform('routers') triggered in app.before('setup')app.router will be available by app.after('routers') or by app.perform('setup')"start" interceptorlib/routes will be loaded in app.before('start')
lib/routes/index.js should call app.perform('actions') once to make sure all routes from app.router are loaded in the app.lib/middlewares will be loaded in before('start')For more information look at
App.Bootstrap
The App exposed by slay has all of the functionality exposed by an app created by express along with:
| Method | Description | Inherited from |
|---|---|---|
App.bootstrap | Core slay bootstrap flow | slay.App |
app.hookable | Defines a hookable action | slay.App |
app.stack | Defines a middleware stack | slay.App |
app.config | Config loading through nconf | config preboot |
app.log | Logger defined through winston | logger preboot |
app.routes | Top-level express Router | routers preboot |
app.preboot | Schedule a preboot | broadway |
app.mixin | Add functionality into the app | broadway |
app.start | Start the application | broadway |
app.close | Shutdown the application | broadway |
app.perform | Execute a named interceptor | understudy |
app.before | Execute before a named interceptor | understudy |
app.after | Execute after a named interceptor | understudy |
| Name | Description | Invoked by |
|---|---|---|
setup | Pre-start bootstrap setup | slay |
start | Main application startup | slay |
routers | Definition of app.routes | slay |
actions | Critical path application functionality | User |
A Stack is a lightweight container for a set of before and after middlewares. This becomes very useful when you have potentially multiple routers in your application. A Stack can be defined using app.stack as follows:
middlewares.js
module.exports = function (app, options, next) {
//
// An authorization middleware for different roles
// returns an HTTP middleware function when invoked.
//
var authorize = require('./authorize');
//
// Stack middlewares can be declared and used inline
//
app.use(
app.stack({
name: 'admin-only',
before: [authorize('admin')]
}).middleware(function (req, res, next) {
// Dispatch (req, res) to a router.
})
);
//
// Or extended from a previous declaration and used inline
//
app.use(
app.stacks['designer-only']
.before(authorize('designer'))
.middleware(function (req, res, next) {
// Dispatch (req, res) to a router.
})
);
};
All Stack instances created by invoking app.stack will be exposed on the app.stacks object.
app.start([options], callback); is invoked.app.perform('setup') performs before "setup" interceptors (see: understudy interceptors). This executes the built-in slay preboots which:app.config(an instance of nconf.Provider).app.log (an instance of winston.Logger).lib/preboots[.js]?). This allows arbitrary user-defined preboots for extensibility in a sync or async fashion.lib/middlewares[.js]?).lib/routes[.js]?).after "setup" interceptors are invoked. (see: understudy interceptors). slay runs nothing by default here.app.perform('start') performs before "start" interceptors (see: understudy interceptors). This executes the built-in slay preboots which:app.perform('routers') which performs before "routers" interceptors, adds app.routes, and performs after "routers" interceptors.lib/preboots[.js]?). scheduled in (2) above.lib/middlewares[.js]?) scheduled in (2) above.lib/routes[.js]?) scheduled in (2) above.app.routes.App.prototype._listen is invoked which creates any http and/or https servers.after "start" interceptors are invoked. (see: understudy interceptors). slay runs nothing by default here.callback from app.start([options], callback); is invoked. The app is now started and ready for use.
npm test
MIT
FAQs
Rock-solid structured application layout for building APIs and web apps in Node.js
We found that slay demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 15 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.