npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-express-ex-boilerplate

v0.2.4

Published

A really extendable Express app boilerplate

Downloads

11

Readme

Express App Extended Boilerplate

Build Status

Features:

  • app object is Dependency Injection Container
  • asynchronous app initialization out of the box
  • service layer
  • non-http entry points (console, etc)
  • extremely testable architecture

Intro

It's convenient to divide NodeJS modules into 3 types:

  • pure functional (provide pure function(s) without any state)
  • factories (provide constructors/factories functions)
  • executable

First two types of modules don't have any internal state. It's a very useful property, because such modules easy to test and use.

Executable modules do have an internal state (since the code in each NodeJS module is executed only once during a first time require call of the module). However, if one has the same module placed on two or more different paths, it's possible that the code of such module will be executed as many times as it's required by different paths. Also, having a shared state withing the module makes it less testable.

That is, it's very convenient to have modules only of first two types in your project. In ideal scenario, only entry point modules should be executable.

Most of the Express boilerplate projects are focused on having things as simple as possible. They have pretty flat directory structure, don't consider an asynchronous app initialization code and have a lot of executable modules (all routes, app, logger, etc). It could be an appropriate choice for very small applications. However, having such structure for a long-living project leads to a unsupportable code.

This boilerplate offers an executable-less architecture. All modules except entry points are factories or pure functional. Even the routing system.

Another important feature of this boilerplate is a separated service layer. For more information about it see Example section.

Example

// services.js
var monk = require('monk');
var UserRepo = require('./dao/UserRepo');

module.exports.register = function(app) {
    app.set('db', function(app, callback) {  
        // will be called only once
        var db = monk(app.options.mongo.dsn);
        callback(null, db);
    });

    app.set('userRepo', function(app, callback) {
        // will be called only once
        app.get('db', function(err, db) {
            callback(null, new UserRepo(db));
        });
    });
};


// route.js
var Router = require('express').Router;

var usersHandler = module.exports.usersHandler = function(app) {
    return function handler(req, res, next) {
        app.get('repo.user', function(err, userRepo) {
            userRepo.findAll(function(err, users) {
                res.render('users', {users: users});
            });
        });
    }
};

module.exports.register = function(app) {
    var router = Router();
    router.get('/', usersHandler(app));
    app.expressApp.use('/users', router);
};


// app.js
var services = require('./services');

function Application(options) {
    ...
    services.register(this);
}


// web/app.js
...
function WebApp(options) {
    ...
    for (var r in routes) {
        r.register(this);
    }
}
    

// www (entry point)    
var config = require('../config');
var WebApp = require('../web/app');

var app = new WebApp(config);
app.init(function(err) {
    if (!err) {
        app.startServer();
    }        
});

Usage

Run web server

npm run server_start  # default is localhost:3000
 

Execute command line task

npm run command ping
npm run command users

Documentation

The boilerplate provides an Application object, that is not an Express app. This Application object is extended by WebApp object, which holds an Express app object as a member. The Application object by itself can be used in entry points which don't require web functional, for example console scripts.

Also the Application object is a Dependency Inject Container. One can use app.set(name, service) and app.get(name, callback) to register new services and then access it within the route handlers or console scripts.

For more information about it see Application::get() and Application::set() JsDocs.