New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

inits

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

inits - npm Package Compare versions

Comparing version 0.0.2 to 0.0.5

runTests.js

256

lib/initSystem.js

@@ -14,9 +14,16 @@ 'use strict';

var events = require('events');
var testing = require('testing');
var domain = require('domain');
// globals
var log = new Log('info');
var globalDomain = domain.create();
// constants
var EVENTS = ['first', 'start', 'stop', 'last'];
var EVENTS = ['init', 'start', 'stop', 'finish'];
var DEFAULT_OPTIONS = {
catchErrors: true,
catchSignals: true,
showErrors: true,
logTimes: true,
};

@@ -29,13 +36,17 @@

// attributes
var callbackQueues = {};
var flags = {};
var standaloneCallback = null;
var flags = {};
var callbackQueues = {};
var initing = false;
var finishing = false;
var startingUp = false;
var shuttingDown = false;
var errored = false;
var phase = 'pre';
self.options = {};
self.options.overwriteWith(DEFAULT_OPTIONS);
// init
init();
startup();
function init()
function startup()
{

@@ -48,3 +59,2 @@ EVENTS.forEach(function(event)

events.EventEmitter.call(self);
self.on('error', showError);
setImmediate(function()

@@ -54,3 +64,3 @@ {

{
reallyInit();
reallyStartup();
}, 0);

@@ -66,3 +76,3 @@ });

{
return self.emit('error', 'Could not add ' + event + ' to queue after it has run');
return manageInternalError('Could not add ' + event + ' to queue after it has run');
}

@@ -73,20 +83,17 @@ callbackQueues[event].push(callback);

function showError(error)
function reallyStartup()
{
log.error('Initialization error: %s', error);
}
function reallyInit()
{
if (initing)
if (startingUp)
{
self.emit('error', 'Could not init again');
return;
return manageInternalError('Could not start up again');
}
initing = true;
runAll('first', function(error)
startingUp = true;
var start = Date.now();
self.emit('startup');
setupErrors();
runAll('init', function(error)
{
if (error)
{
return self.emit('error', 'Could not run first callbacks: ' + error);
return manageInternalError('Could not run init callbacks: ' + error);
}

@@ -97,8 +104,9 @@ runAll('start', function(error)

{
return self.emit('error', 'Could not run start callbacks: ' + error);
return manageInternalError('Could not run start callbacks: ' + error);
}
self.emit('ready');
if (standaloneCallback)
if (self.options.logTimes)
{
runStandalone();
var elapsedSeconds = (Date.now() - start) / 1000;
log.info('Initialization took %s seconds', elapsedSeconds.toFixed(1));
}

@@ -109,2 +117,12 @@ });

function manageInternalError(error)
{
self.emit('error', error);
if (self.options.showErrors)
{
log.error('Error in phase %s: %s', phase, error);
}
startShutdownByError();
}
function runAll(event, callback)

@@ -116,2 +134,4 @@ {

}
phase = event;
self.emit(event + 'ing');
runQueue(callbackQueues[event], function(error)

@@ -124,2 +144,3 @@ {

flags[event] = true;
self.emit(event + 'ed');
return callback(null);

@@ -135,27 +156,95 @@ });

}
var next = queue.shift();
next(callback);
var current = queue.shift();
run(current, function(error)
{
if (error)
{
return callback(error);
}
return runQueue(queue, callback);
});
}
function runStandalone()
function run(current, callback)
{
standaloneCallback(function(error)
globalDomain.run(function()
{
if (error)
current(callback);
});
}
function setupErrors()
{
if (self.options.catchErrors)
{
globalDomain.on('error', function(error)
{
if (error)
{
return self.emit('error', 'Could not run start callbacks: ' + error);
}
manageUnexpectedError('error', error);
});
process.on('uncaughtException', function(error)
{
manageUnexpectedError('uncaught exception', error);
});
}
if (self.options.catchSignals)
{
process.on('SIGINT', function()
{
log.notice('User pressed control-C');
signalled();
});
process.on('SIGTERM', function()
{
log.notice('Process killed');
signalled();
});
}
}
function manageUnexpectedError(type, error)
{
if (!self.options.catchErrors)
{
return;
}
self.emit('error', 'Unexpected ' + type + ': ' + error);
if (self.options.showErrors)
{
log.alert('Unexpected %s: %s', type, error);
if (error.stack)
{
log.alert(error.stack);
}
});
}
startShutdownByError();
}
self.finish = function()
function startShutdownByError()
{
if (finishing)
if (errored)
{
return self.emit('error', 'Could not finish again');
return;
}
finishing = true;
errored = true;
self.shutdown();
}
function signalled()
{
if (!self.options.catchSignals)
{
return;
}
self.shutdown();
}
self.shutdown = function()
{
if (shuttingDown)
{
return manageInternalError('Could not shutdown again');
}
shuttingDown = true;
var start = Date.now();
self.emit('shutdown');
runAll('stop', function(error)

@@ -165,10 +254,15 @@ {

{
return self.emit('error', 'Could not run stop callbacks: ' + error);
return manageInternalError('Could not run stop callbacks: ' + error);
}
runAll('last', function(error)
runAll('finish', function(error)
{
if (error)
{
return self.emit('error', 'Could not run last callbacks: ' + error);
return manageInternalError('Could not run finish callbacks: ' + error);
}
if (self.options.logTimes)
{
var elapsedSeconds = (Date.now() - start) / 1000;
log.info('Shutdown took %s seconds', elapsedSeconds.toFixed(1));
}
self.emit('end');

@@ -178,60 +272,30 @@ });

};
};
util.inherits(InitSystem, events.EventEmitter);
module.exports = InitSystem;
self.standalone = function(callback)
{
if (standaloneCallback)
{
return manageInternalError('Already have standalone callback');
}
standaloneCallback = callback;
self.on('ready', runStandalone);
};
function testInitSystem(callback)
{
var system = new InitSystem();
system.on('error', function(error)
function runStandalone()
{
console.trace('here');
testing.failure(error, callback);
});
system.first(function(next)
{
log.debug('first');
next(null);
});
system.start(function(next)
{
log.debug('start');
system.finish();
next(null);
});
system.stop(function(next)
{
log.debug('stop');
next(null);
});
system.last(function(next)
{
log.debug('last');
next(null);
});
system.on('started', function()
{
system.finish();
});
system.on('end', function()
{
testing.success(callback);
});
}
/**
* Run all tests.
*/
exports.test = function(callback)
{
testing.run([testInitSystem], callback);
standaloneCallback(function(error)
{
if (error)
{
return manageInternalError('Could not run start callbacks: ' + error);
}
self.shutdown();
});
}
};
// run tests if invoked directly
if (__filename == process.argv[1])
{
log = new Log('debug');
exports.test(testing.show);
}
util.inherits(InitSystem, events.EventEmitter);
module.exports = new InitSystem();
// exported for tests
module.exports.InitSystem = InitSystem;
{
"name": "inits",
"version": "0.0.2",
"version": "0.0.5",
"description": "Init system for Node.js.",

@@ -15,3 +15,5 @@ "homepage": "https://github.com/alexfernandez/inits",

"prototypes": "*",
"log": "1.4.*",
"log": "1.4.*"
},
"devDependencies": {
"testing": "*"

@@ -25,5 +27,5 @@ },

"scripts": {
"test": "node test.js"
"test": "node runTests.js"
},
"private": false
}
# inits
Init system for Node.js
A simple init system for Node.js.
Manages initialization tasks, and optionally also shutdown tasks.
Useful to simplify initialization of complex systems
with asynchronous tasks.
## Installation
Simply run:
```
npm install inits
```
Or add `inits` to your `package.json`:
```
"dependencies": {
...
"inits": "*",
...
},
```
and run `npm install`.
## Lifecycle of a System
There are four distinct phases in `inits`:
* init,
* start,
* stop,
* and finish.
They are intended to be symmetric:
if a certain capability is open in `init`
it should be closed in `finish`,
and whatever starts in `start`
should be stopped in (surprise!) `stop`.
### Init Phase
Initialization tasks, such as connecting to the database.
The init system will make sure that all `require`'d code files have been loaded
before starting this phase.
### Start Phase
Tasks to start the system, such as starting a web server.
These run after all `init` tasks have finished.
### Stop Phase
Tasks to stop the system, such as stopping any open servers.
These run when the system initiates shutdown: either by a signal
(SIGTERM, SIGKILL or control-C) or by an uncaught exception
or an error.
### Finish Phase
Final shutdown tasks, such as disconnecting from the database:
whatever needs to be done before the system definitely closes down.
### Callbacks
All callbacks passed to the four phases must receive another callback
of the form `function(error)` following the Node.js convention,
and chain-call them at the end with either an error
or a falsy value (`null`, `undefined`, nothing) to signal success.
Example:
```
inits.init(function(next)
{
DatabaseDriver.connect(url, function(error, connected)
{
if (error)
{
return next(error);
}
db = connected;
next(null);
});
});
```
Note how the callback `next` is invoked before the function ends;
this allows `inits` to run asynchronous tasks,
and to regain execution and run any other callbacks.
If your callback is synchronous, simply invoke the callback at the end:
```
inits.finish(function(next)
{
db.close();
next(null);
});
```
Note: the choice of callback names is not important,
we have used `next` here but `callback` elsewhere;
whatever is clearer to you.
### No Dependencies
There is no dependency management in `inits`.
This is deliberate; it would be much more complex
for something that is not generally needed.
If you need a certain task to run before another one,
just run them in sequence.
### Other Lifecycles
Sometimes four phases are not enough.
`inits` might be designed to support custom phases in the future
if there is interest; just create an issue if you are interested,
or even better, send a pull request.
## API
The following functions and events are available.
### inits.init(callback)
Add a callback to the initialization.
### inits.start(callback)
Add a callback to be called when starting (after initialization).
### inits.stop(callback)
Add a callback to be called when stopping.
### inits.finish(callback)
Add a callback to be called before finishing.
### inits.standalone(callback)
Set a callback as a standalone task.
Useful when your script consists solely of a task
that must run after startup, followed by shutdown.
### Event: 'ready'
Sent when initialization has finished and the system is ready.
### Event: 'end'
Sent after the system has finished and is about to exit.
Can be used e.g. to call `process.exit()` (which `inits` doesn't do by itself).
### Event: 'error'
Sent when there is an error in any phase.
## Options
To configure `inits` you can set some attributes in `inits.options`
that will modify how the init system behaves.
### catchErrors
If set to `true` (or any other truthy value),
`inits` will catch uncaught exceptions and errors
and shutdown automatically when any of those happens.
Default: `true`.
### catchSignals
If set to `true` (or any other truthy value),
`inits` will intercept SIGTERM and SIGKILL (e.g. control-C) signals
and shutdown when one of them is received.
Default: `true`.
### showErrors
If set to `true` (or any other truthy value),
`inits` will show a log message for every error.
Default: `true`.
### logTimes
If set to `true` (or any other truthy value),
`inits` will log how long initialization and shutdown took.
Default: `true`.
## Full example
How to make a web server that connects to a MongoDB database.
We will hook database startup to the `init` phase,
and server start to the `start` phase.
On `stop` we stop the server,
and on `finish` we close the connection to the database.
``` javascript
var inits = require('inits');
var MongoClient = require('mongodb').MongoClient
var mongodb = require('mongodb');
var http = require('http');
var db;
inits.init(function(callback)
{
MongoClient.connect(url, function(error, connected)
{
if (error)
{
return callback(error);
}
db = connected;
callback(null);
});
});
inits.start(function(callback)
{
server = http.createServer(listener);
server.on('error', function(error)
{
return callback(error);
});
server.on('listening', function()
{
callback(null);
});
});
inits.stop(function(callback)
{
server.close(callback);
});
inits.finish(function(callback)
{
db.close();
callback(null);
});
```
## Licensed under The MIT License

@@ -8,0 +245,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc