Let's Make a Framework: npm

2011-07-28 00:00:00 +0100 by Alex R. Young
*Let's Make a Framework* is an ongoing series about building a JavaScript framework from the ground up. These articles are tagged with [lmaf](http://dailyjs.com/tags.html#lmaf). The project we're creating is called [Turing](http://github.com/alexyoung/turing.js). Documentation is available at [turingjs.com](http://turingjs.com/).

There's no reason why you can't distribute your client-side JavaScript
using npm! In this tutorial I'll look at adapting parts of Turing to
work using the popular package manager.


Distributing packages with npm is extremely easy. This is partly due to
the fact that npm itself is very simple, but it's also because npm has
great documentation.

If you don't already have npm, the basic installation is just:

curl http://npmjs.org/install.sh | sh

There's more information in the npm

Registry Account Creation

A registry user account is required to distribute npm packages. Use
man npm-adduser to read how this works. If you've forgotten
your password, npm now has a password reset page at


Once you've got an account, you'll need to create a
package.json file. You don't really need a tool to do this;
it's pretty trivial as long as you write well-formed JSON. Like most
people I usually forget what various supported options are, so I usually
check man npm-json to make sure I've got everything I want
set up.

When working on most Node projects, I'll have a
dependencies property, but this project doesn't really have
any. We do have some development dependencies though, so these can be
put into the devDependencies property. This is preferable
to dependencies because people who just want to use your
module don't usually want to build or test it.

This is what the Turing package.json file looks like:

{ "name": "turing"
, "description": "A library for enumeration, functional programming, promises, and more"
, "version": "0.0.73"
, "url": "http://turingjs.com/"
, "author": "Alex R. Young "
, "engines": ["node >= 0.4.0"]
, "main": "./lib/index.js"
, "devDependencies": {
    "dox": "latest"
  , "jake": "latest"
, "repository": {
    "type" : "git"
  , "url" : "https://github.com/alexyoung/turing.js.git"

Adapting Turing's Modules

In the browser Turing uses a global to stitch various modules together.
This was done so it can be safely split into self-contained modules.
However, this pattern makes adapting it to a CommonJS module slightly

As an example, consider Turing's enumerable module and
turing.init. The init method is from the Core
module, and allows us to extend the behaviour of turing().
That means we get jQuery-like polymorphic initialization:

turing([1, 2, 3]).map(function(i) { return i * 10; }).values();

Great! But that means the enumerable looks for turing.init.
We can't share globals in the same way using CommonJS modules. That
means the anonymous function wrapper isn't quite enough.

This old pattern worked well in the browser, but doesn't suit CommonJS
without modification:

(function() {
  turing.myModule = {
    // Methods

What we need is a way of passing turing after it's
instantiated in turing.core.js. That gives rise to this

(function() {
  function myModule(global) {
    global.myModule = {
      // Methods

  if (typeof module !== 'undefined') {
    // For Node
    module.exports = function(t) {
      return EnumerableModule(t);
  } else {

Now, in the lib/index.js mentioned by the example

var turing = require(__dirname + '/../turing.core.js').turing;
require(__dirname + '/../turing.promise.js')(turing);
require(__dirname + '/../turing.enumerable.js')(turing);
module.exports = turing;

Now Turing can be loaded using Node:

var t = require('turing');

t([1, 2, 3]).map(function(i) { return i * 10; }).values();

Further iterations could make it load certain modules on demand. Ideally
people should be able to do this:

var lessCommonModule = require('turing').lessCommonModule;


I actually wrote a small unit test for this in

var assert = require('assert')
  , turing = require(__dirname + '/../lib/index.js');


var sum = 0;
turing.enumerable.each([1, 2, 3], function(i) {
  sum += i;
assert.equal(6, sum);

It just makes sure everything gets loaded as expected.

Another way to test your npm modules is to use npm link.
This links your package system-wide, so it behaves as if it's been
installed. This is useful for loading your modules in the Node REPL, or
testing binary scripts that you might distribute alongside your package.


Once you're done with all that, run npm publish and your
code will be available for distribution through npm.


Check all of this out in commit
And, if you've ever wanted to create a project website using GitHub,
I've already got you covered in Part 48: Project