Application architecture framework with pluggable services


KickApp is an application architecture framework for organizing the logic into runnable services.

Split your logical components into services contained in a top-level Applicaton object, define service dependencies and launch them all with a single app.start()!

Key features:

  • Structured application architecture approach
  • Service workflow: init(), start(), stop()
  • Service dependencies resolution
  • Can deal with hierarchical services
  • Promise-based: using the q package
  • Unit-tested

Table of Contents

Core Components

A Service is an arbitrary constructor function or an object that implements the IService interface:

  • Its constructor function gets an Application as the first argument. More arguments can be provided with the Application.addService() method.
  • It can optionally have the init() method: here you can perform some preparation steps
  • It must have the start() and stop() methods which bring your service up and down respectively.

Consider an example:

/** Database service
 * @param {Application} app
 *     The parent Application
 * @param {String} url
 *     Connection string
 * @constructor
 * @implements {IService}
var DbService = function(appurl){ = app;
    this.url = url;
    this.client = undefined;
DbService.prototype.init = function(){
    this.client = new DatabaseClient(this.url); // init some imaginary client 
DbService.prototype.start = function(){
    return this.client.connect(); // assuming it's promise-based 
DbService.prototype.stop = function(){
    return this.client.disconnect();

Having such a service, you can:

  • Add it to an Application
  • Define service dependencies
  • Launch them all in the correct order

If your service is simple, you don't have to implement the constructor and everything. Use an object instead, which is also a valid service:

var DbService = {
    app: undefined,
    client: new DatabaseClient('db://localhost/'),
        return this.client.connect();
        return this.client.disconnect();

It will automatically get the app property when added to the Application.

An Application is the container for your services.

You define an application by creating an instance of it, providing a constructor function as an argument:

var kickapp = require('kickapp');
var App = new kickapp.Application(function(configFile){
    this.config = require(configFile); // init the configuraton 
}, 'app/config.js');

By design, an Application does not have custom start/stop behavior: instead, it wraps services.

Add a service to the application.

  • name: String: Name of the service. Use any reasonable string.
  • serviceConstructor: Function: Constructor function for an object that implements the IService interface.
  • ...args: Variadic arguments for the service constructor

Returns: an instance of ServiceWrapper (see below).

This function can also be called inside the Application constructor:

var kickapp = require('kickapp');
var App = new kickapp.Application(function(configFile){
    // Load the configuration 
    this.config = require(configFile);
    // Add services 
    this.addService('db', require('./services/db.js'), this.config.db );
    this.addService('web', require('./services/web.js'), this.config.web )
        .dependsOn('db'); // Define a dependency on other services 
}, 'app/config.js');

Add dependencies for the recently added Service.

When a Service depends on other services, they will be started before starting this one.

Dependencies can be given either as arguments, or as a single array argument.

Get the Service object by name:

app.get('db').client; // get the Service property 

Get the ServiceWrapper object by name.

See: ServiceWrapper

Get the list of service names added to this Application object.

Check whether the Application is running.

An Application is running if all its services are running.

Service methods are run in the following fashion:

  • Service constructors are called immediately whilst you add your services to the Application
  • init(), start(), stop() methods are called when the corresponding Application method is called. Unlike the constructor, these honor the service dependencies.

Call init() on all services, honoring the dependencies. Returns a promise.

Note that IService.init is optional.

Call start() on all services, honoring the dependencies. Returns a promise.

If some services were not yet initialized with init(), Application does that.

Call stop() on all services, honoring the dependencies in reverse order. Returns a promise.

Application is an EventEmitter which fires the following events:

  • 'init': All services have been initialized
  • 'start': All services have been started
  • 'stop': All services have been stopped

Each Service is internally wrapped in ServiceWrapper which controls the service state.

  • ServiceWrapper is an EventEmitter which fires the 'init', 'start', 'stop' events of the service
  • Contains metainformation about the Service: service, initialized, running, dependencies

Usually, you won't need it. See the source code: ServiceWrapper.

Full Example

var kickapp = require('kickapp');
// Application 
var App = new kickapp.Application(function(configFile){ // Application constructor 
    // Load the configuration 
    this.config = require(configFile);
    // Services 
        'db', // Service name 
        require('./services/db.js'), // Service constructor with init()/start()/stop() methods 
        this.config.db // Arguments for the Service constructor 
    this.addService('web', require('./services/web.js'), this.config.web )
        .dependsOn('db'); // Dependencies on other services 
}, 'app/config.js'); // Arguments for the Application constructor 
// Launch it 
        console.log('Application initialized and started!');
        console.error('Application.start failed:', err.stack);
// Stop the services properly when the application exitsq 
process.on('SIGINT', process.exit);
process.on('exit', function(){
            console.error('Application.stop failed:', err.stack);


If you dislike promises, you can always get back to the old good NodeJS-style callbacks:

var App = new kickapp.Application(function(){
    if (err)
        console.error('Application.start failed:', err.stack);
        console.log('Application initialized and started!');

Application as a Service

The Application object can be used as a service as it implements the IService interface. This allows creating reusable components from sustainable application parts and add them to other applications as a service:

var app = new kickapp.Application(function(){
    // ... init some services 
var top = new kickapp.Application(function(){
    this.addService('app', app); // added as a service 

Bundled Services

KickApp comes with some handy bundled services.

NetService is a helper to wrap net.Server, http.Server, https.Server, tls.Server, dgram.createSocket network servers in a KickApp service. It also supports static configuration with generalized interface.

NetService accepts two arguments:

  • config: Object: Server configuration object:

    • config.lib: String: The server type to create. Supported values: 'net' (TCP socket), 'tls' (TLS socket), 'http' (HTTP server), 'https' (HTTPS server), 'udp4' (UDP IPv4 socket), 'udp6' (UDP IPv6 socket).

    • config.listen: Array: Array of arguments for the listen() function.

      For 'net', 'http', 'https': port, [hostname], [backlog]

      For 'tls': port, [host]

      For 'udp4', 'udp6': port, [address]

    • config.options: Object: Options for the createServer() function. See NodeJS Manual.

      Note: for 'tls' and 'https' certificates & stuff, you can optionally specify filenames for the following keys: 'pfx', 'key', 'cert', 'ca', 'crl'.

  • accept: Function: Method used to accept the incoming connections.

      For `'net', 'tls'`: `function(sock: net.Socket)`
      For `'http'`, `'https'`: `function(req: http.ClientRequest, res: http.ServerResponse)`
      For `'udp4'`, `'udp6'`: `function(msg: String|Buffer, rinfo: Object)`

Wielding the service, you can start/stop it an get error handling:

var app = new kickapp.Application(function(){
        { lib: 'net', listen: [6001, 'localhost'] },
        { lib: 'http', listen: [6080, 'localhost'] },

NetService has the following properties:

  • config: Server configuration object
  • server: The created server

TimerService handles timers as a Service, which are stopped together with the application.

The service provides the following methods which wrap global counterparts:

  • setTimeout(), clearTimeout()
  • setInterval(), clearInterval()

By using the set*() family of methods, you add the timer to the internal service registry, and when the server is stopped -- it clears the timers automatically.

This is especially important with unit-tests: when unit-testing an application which uses timers -- these continue to function even after the tested application was restarted for a new test case.

These public methods have same signatures with the methods they wrap, except for the requirement to use these through the service:

// Define the application 
var app = new kickapp.Application(function(){
    // Timers 
    // Custom service that depends on timers 
    this.addService('my-service', MyService)
// Custom service 
function MyService(app){ = app;
MyService.prototype.start = function(){
    // Get the 'timer' service'timer')
        // beep every second :) 
        }, 1000);

When the application is started with app.start(), it starts its services. The custom service "my-service" sets a timer through the "timers" service.

Now, when the application is stopped through app.stop(), the timers service will clear all timers that were set on it.