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

asimov

v1.3.2

Published

A better toolkit for building awesome websites and apps

Downloads

71

Readme

asimov.js

NPM version Build Status Code Climate Dependency Status

A better toolkit for building awesome websites and apps

Made by Adam Renklint, Berlin 2014. MIT licensed.

asimov.js is at its core only two simple things: a command line interface that loads and executes command scripts in your project and node_modules folder, and a plugin interface for adding initializers and extend the app lifecycle.

On it's own, asimov.js doesn't really do much - it leaves all the heavy lifting to plugins. The two most basic ones are asimov-server and asimov-static. Together you get an awesome static site generator with extendable, chained processing and a high-performance clustered server, with express-compatible middleware.

Or you roll your own plugin in a just a few seconds.

Getting started

Install asimov.js globally to use the cli

npm install -g asimov

Start your project and execute any registered initializers. This assumes your index.js exports a member function called start. More on that later.

asimov start

And any other command, you execute the same way. Later in this guide, you'll learn to build a command that counts lines of code.

asimov loc

Create a new project

So let's create our very first asimov.js app, a tiny thing that will load an initializer that logs a message.

Every app is also a plugin, meaning you can easily compose large applications from lots of smaller pieces of functionality, or publish your app to npm and let others use it as a plugin.

/asimov-log-message
  /lib
    /init
      logMessage.js
  index.js
  package.json

Install and add asimov.js to your projects dependencies.

$ npm install --save asimov

logMessage.js should export an initializer, a function that is passed a next function, which continues the chain.

// lib/init/logMessage.js
module.exports = function initializer (next) {
  console.log("Hello world");
  next();
};

Then, we add some bootstrap code in index.js.

var asimov = require('asimov');
var logMessage = require('./lib/init/logMessage');

// This is our plugin hook, the function that other modules
// can use to load our modules functionality
module.exports = function plugin () {
  asimov.init(logMessage);
};

// The "start" method should bootstrap your app
// by adding the plugin hook and starting asimov.js
module.exports.start = function bootstrap () {
  asimov
    .use(module.exports)
    .start();
};

// If we are not loaded as a plugin, start the app
module.parent || module.exports.start();

And run it...

$ asimov
> Hello world

asimov is short for asimov start, which is actually just calling node index.js.

Adding plugins

Every asimov.js app is also a plugin, and has the same interface as our app. In our projects plugin hook, we add all the plugins we need to get the job done. If we published the project above, we could add it in our next projects index.js.

var logger = require('asimov-log-message');
module.exports = function plugin (options) {
  asimov.use(logger);
};

Plugins can configure your app, add initializers and extend the public interface of asimov with new methods.

Development plugins that shouldn't be included when you app is loaded as a plugin are added in the bootstrap function.

var debuggerPlugin = require('asimov-some-debugger-plugin');
module.exports.start = function bootstrap () {
  asimov
    .use(module.exports)
    .use(debuggerPlugin)
    .start();  
};

Initializers

Initializers come in three flavours: vanilla, pre and post. For most apps and plugins, vanilla initializers will be enough, but in some case you might need to override the entire vanilla chain.

var overrider = require('./lib/init/overrider');
module.exports = function plugin (options) {
  asimov.preinit(overrider);
};

If you want your initializer to be executed last, register it with asimov.postinit().

var doneLogger = require('./lib/init/doneLogger');
module.exports = function plugin (options) {
  asimov.postinit(doneLogger);
};

Remember, you can break the chain at any time by not calling next() in your initializer, and create new, alternate chains. For example, this is how asimov-server can be used as both cluster master and worker, by having two very different chain of initializers.

Create a new command

Let's say we want to extend asimov.js with a new command that counts the lines of code in the lib folder. We could later publish it to npm, and use it in other asimov.js projects as a plugin.

Create a new module structure, and add lib/commands/loc.js - it will be loaded when you call asimov loc.

/asimov-loc
  /lib
    /commands
      loc.js
  index.js
  package.json

In lib/commands/loc.js, we add the code to recursively count the lines of javascript code in the lib folder.

var asimov = require('../../index');

function countLinesInPath (path) {
  // A function that recursively counts
  // the lines in all the javascript files
  // You'll need to figure that part out on your own
}

module.exports = function () {

  // Some basic setup
  var path = process.cwd() + '/lib';
  var namespace = 'loc';
  var started = new Date();

  // And get the count
  var count = countLinesInPath(path);

  // Log the result, and how long it took to count
  var message = 'Counted ' + count + ' lines in ' + path;
  asimov.logger.since(namespace, message, started);
};

If you publish this on npm, any other project that installs it to their node_modules folder will have the command asimov loc available, unless they create lib/commands/loc.js in their project.

Add and run sequences

You can add your own sequences to asimov.js, and let other projects hook into your processing. This is how asimov-server implements middleware and asimov-pages implements rendering processors.

asimov.addSequence('chain');
asimov.chain(myChainFactory());

asimov.runSequence('chain')
  .done(function (
    'yay! done.'
  ))
  .fail(function (err) {
    console.log('ooops', err)
  });

Configuration

You can change the behavior of plugins and configure your app with the asimov.config method.

// Set a configuration variable. Chainable.
asimov.config('myConfigVar', true);

// And get it.
var myVar = asimov.config('myConfigVar');

// Or get the whole config object.
var myConfig = asimov.config();

// Also supports constants, just uppercase the name.
// Trying to set it again will throw an error.
asimov.config('SOMETHING_CONSTANT', true);

// Use an object literal, or a JSON file. Also chainable.
var production = require('./env/production.json');
asimov.config(production);

Signals and rolling restarts

Out of the box, asimov.js supports zero-downtime updates with "rolling restarts", using POSIX signals.

For your convience, the master process' PID is saved in process.pid in your project root. This file is created when you start your app, removed when you stop it and can be used to send signals to asimov's master process.

To reload all code and restart your app, send SIGHUP to the master process.

$ kill -HUP $(cat process.pid)

Add shutdown handlers

You can register functions that will be executed when your app is being restarted or forcefully shutdown. These work exactly the same way as initializers, are executed in sequence and you can change or override the chain of side effects by not calling the next() callback.

asimov.shutdown(function (next) {
  // do some cleanup here
  next();
});

Register a public interface

Your app or plugin could need to register methods or variables on asimov's public interface. Chainable method.

asimov.register('doNothing', function () {});

For example, this is how asimov-pages exposes its main collection as asimov.pages.

Verbose logging

To get detailed logging on everything that happens in your app and plugins, set the env var VERBOSE to true. Or take the shortcut, call asimov debug.


Develop and contribute

  1. First, fork this repo.
  2. Implement something awesome
  3. Write tests and run them with npm test
  4. Submit a pull request

Credits

Author: Adam Renklint. Contributors: Marvin Labod, Timothy Achumba.