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

lifecycles

v1.0.0

Published

Container for productionized applications

Downloads

5

Readme

Lifecycle

Lifecycle provides a structured way to start and stop your application, allowing for libraries to provide their own hooks into the lifecycle which executes at a known point in the startup and shutdown process.

These hooks can be used to load applications, setup configuration, setup connections and graceful shutdowns etc.

There are two other things provided to help manage your applications startup.

  • Configuration
  • Commands

Essentially, Lifecycle is a bootloader with defined segments, and provides both a setup and teardown sequence.

You can use as much or as little of Lifecycle as you like, the intention is to provide modules with the ability to integrate cleanly via a known API.

Lifecycle also provides a command interface so that plugins can provide commands for your application that run in the correct lifecycles.

Usage

Create a lifecycle app in lifecycle.js:

var Lifecycle = require('lifecycle');

var myApp = new Lifecycle({
  appName: 'Bruce',
  appDir:  Path.resolve(Path.join(__dirname, '..'))
});

module.exports = myApp;

Stages

Lifecycle contains a number of specific lifecycle stages.

  • bootstrap - load things
  • initialize - initialize things
  • connections - setup external connections
  • starting - bind to listening ports etc
  • running - when everything is running

Each of these stages can have initializers added to them. Each group of initializers runs in order for startup, and then in reverse order for shutdown. Each stage will wait for all initializers to complete before moving on to the next.

This provides a structured, and shared way to start your applications, and because it's structured, libraries can provide their own initialization functions that allow them to wire themselves up for your application.

For example, to setup a connection to a database, and then tear it down on shutdown, you'd do something like:

  Lifecycle.up.connections('database.connect', function ( lifecycleApp ) {
    // setup the connection, and optionally return a promise.
  });

  Lifecycle.down.connections('database.disconnect', function ( lifecycleApp ) {
    // Tear down the connections and optionally return a promise.
  });

Lifecycle files

Each file under the 'lifecycle' directory will be loaded before the bootstrap stage is executed. You can use this to create your own lifecycle setup code. You can also load a lifecycle setup function from a library that is Lifecycle aware.

For example.

lifecycle/protob.js

require('protob/lifecycle')( require('lifecycle') );

It's up to the library that you're using to setup the correct stages if you use this method, but it can save a lot of boiler plate code.

Starting your application

Console (aliased to lifecycle c)

$> lifecycle console

The console contains your app available at 'app'

$> lifecycle c

myApp:development> app.config // your lifecycle apps config

Console loads all stages up to and including connections but it does not load starting nor running.

Server (aliased to lifecycle s)

$> lifecycle server

Starting the server runs all stages.

Stages

Stages come in two flavours: setup, and teardown.

Lifecycle will load all files inside the 'lifecycle' directory as part of it's bootstrap where you can either initialize Lifecycle aware modules, or create your own initializers for a lifecycle.

Lifecycles and Initializers

Stages contain initializers which all require a name. These names can be used within the same stage, to run one initializer before or after some other initializer.

var Lifecycle = require('lifecycle');

Lifecycle.up.running('gns.ping', {after: 'something.else', before: 'something'}, function(app) {
  console.log("Coming up in GNS");
  return pingGnsUp(app);
});

Lifecycle.down.running('gns.ping', function(app) {
  console.log("Going down in GNS");
  return pingGnsDown(app);
});

These are TSorted so if you want to make sure you have a specific position in your order, you should include a before and after. You should only include these if you need to position one initializer relative to another.

All initializers may return promises if they are async and need the bootloader to wait while they do their job. Non-promise returns immediately move on to the next initializer in parallel.

Making your module Lifecycle-aware.

To become aware of Lifecycle, expose a function in your module that can be called in an initializer. The first argument of this should be the Lifecycle library. An application should always pass you the Lifecycle object. Inside this function, just create your setup and teardown initializers in the right lifecycle and you're done.

module.exports = function lifecycleInit(Lifecycle){
  Lifecycle.up.starting('foo', function(app) {
    console.log("My module is so cool", app.config.appName);
  });
};

Then, in the application's lifecycle/foo.js file

require('foo/lifecycle') (require('lifecycle') );

Commands

Lifecycle provides a command structure so that you can add commands. Commands are provided by 'commander-plus'

These are executed like:

  $> lifecycle my-command

You can list the commands by using the --help flag

  $> lifecycle --help

List the initializers setup for the application:

  $> lifecycle initializers

Setup your own commands

  Lifecycle.up.bootstrap('my-lib.commands', function(app) {
    app.commands.command('some:command')
      .description('Do something')
      .action(function() { stuff() });
  });