No F*cking Idea

Common answer to everything

Building node.js Module Using Npm

| Comments

I have spend a bit time to find out how to build modules, where to put dependencies and how to form package.json so i decided to create this post to gather some of this info in one place. This modules are more like ruby gems than parts of language grouping functions also called modules (eg. Erlang). I was recently on conference and i want to post something about module i was working on at airport but before next post i need to add this so i will have something to reference to.

npm

Npm stands for node package manager and it is something like gems in ruby, eggs in python or apt in debian. It lets you search, install and update your node or application modules. You can create node.js modules without npm but if you want to publish your module its better to do it this way. If you have node.js >0.6.10 you should have npm bundled with your instalation if not go to http://npmjs.org/ and follow the instructions. (for normal platforms all you have to do i run http://npmjs.org/install.sh)

scaffold

First thing to do is to initialize our module, to do this we need to create a directory for it and run npm init like this.

1
2
λ mkdir my_first_module && cd my_first_module
λ npm init

Next he will ask us few questions, we should answer ;). example output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Package name: (my_first_module)
Description: my first module
Package version: (0.0.0)
Project homepage: (none) no-fucking-idea.com
Project git repository: (none)
Author name: Jakub Oboza
Author email: (none) jakub.oboza@gmail.com
Author url: (none) no-fucking-idea.com
Main module/entry point: (none)
Test command: (none) mocha -R landing lib/my_first_module.js
About to write to /private/tmp/my_first_module/package.json

{
  "author": "Jakub Oboza <jakub.oboza@gmail.com> (no-fucking-idea.com)",
  "name": "my_first_module",
  "description": "my first module",
  "version": "0.0.0",
  "homepage": "no-fucking-idea.com",
  "scripts": {
    "test": "mocha -R landing lib/my_first_module.js"
  },
  "dependencies": {},
  "devDependencies": {},
  "optionalDependencies": {},
  "engines": {
    "node": "*"
  }
}



Is this ok? (yes) yes

This will create for us package.json. Now we have fully functional module and we could stop now…. but

package.json

This file is description of our package. It is in form of json so it should be easy to read and change. Most of this fields don’t need a lot of description because keys are self explaining but things that we should look at is "scripts" where we defined "test" key. If we will now run npm test he will execute this command that is very useful.

Engines defined on what version of node.js our code will work leaving it to * is a bit hazard. You can set it to something specific if you want.

Important thing! If we will not specify entry point to our module by default it will be looking for index.js so for now lets leave it this way.

tests with mocha

If we want to write reasonable code that we want to rely on we should be doing massive testing. I think mocha is a very good library for this purpose! I strongly suggest installing it with flag -g so it will be accessible in global scope of npm

1
λ npm install -g mocha

Code

Ok but we don’t have any code yet ;/. Yes lets start coding.

1
2
3
λ mkdir lib
λ touch index.js
λ touch lib/my_first_module.js

Ok so we created lib directory with out module code, empty module file and index file. Now lets run the tests and see what happened.

1
2
3
4
5
6
7
8
9
λ npm test

> my_first_module@0.0.0 test /private/my_first_module
> mocha -R landing lib/my_first_module.js




  ✔ 0 tests complete (1ms)

Everything passed, that is expected because we don’t have any tests :) Now lets add to package.json one more thing development dependency for should.js it will enable us to use mocha in a bit rspec bdd style. Like this:

package.json
1
2
3
  "devDependencies": {
    "should": ">= 0.0.0"
  },

And again npm install -l to get everything installed locally.

First test

Initial mocha test for our module

lib/my_first_module.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function MyFirstFoo(a, b){

}


module.exports = MyFirstFoo

require('should')

describe('MyFirstFoo', function(){
  it("should be able to add", function(){
    MyFirstFoo(2, 3).should.be[5];
  });
});

First we define empty body of function next we have module.exports = this is to mark which functions will be visible outside this module when other clients will require this module. If you need more info about writing specs in mocha please read my earlier post http://no-fucking-idea.com/blog/2012/04/05/testing-handlebars-with-mocha/. Now lets run npm test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 λ npm test

> my_first_module@0.0.0 test /private/tmp/my_first_module
> mocha -R landing lib/my_first_module.js
  -----------------------------------------------------------------------------------------------------------------------------------------------
  ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅✈
  -----------------------------------------------------------------------------------------------------------------------------------------------

  ✖ 1 of 1 tests failed:

  1) MyFirstFoo should be able to add:
     TypeError: Cannot read property 'should' of undefined
      at Context.<anonymous> (/private/tmp/lol/my_first_module/lib/my_first_module.js:13:21)
      at Test.run (/opt/local/lib/node_modules/mocha/lib/runnable.js:156:32)
      at Runner.runTest (/opt/local/lib/node_modules/mocha/lib/runner.js:272:10)
      at /opt/local/lib/node_modules/mocha/lib/runner.js:316:12
      at next (/opt/local/lib/node_modules/mocha/lib/runner.js:199:14)
      at /opt/local/lib/node_modules/mocha/lib/runner.js:208:7
      at next (/opt/local/lib/node_modules/mocha/lib/runner.js:157:23)
      at Array.0 (/opt/local/lib/node_modules/mocha/lib/runner.js:176:5)
      at EventEmitter._tickCallback (node.js:192:40)

...

Fails as expected so lets ad implementation to our function.

lib/my_first_module.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function MyFirstFoo(a, b){
  return a + b;
}


module.exports = MyFirstFoo

require('should')

describe('MyFirstFoo', function(){
  it("should be able to add", function(){
    MyFirstFoo(2, 3).should.be[5];
  });
});

And run npm test

1
2
3
4
5
6
7
8
9
λ npm test

> my_first_module@0.0.0 test /private/tmp/lol/my_first_module
> mocha -R landing lib/my_first_module.js
  -----------------------------------------------------------------------------------------------------------------------------------------------
  ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅✈
  -----------------------------------------------------------------------------------------------------------------------------------------------

  ✔ 1 tests complete (2ms)

We have landed safely ;) Now we are ready for development!

Summary

Creating good quality of code requires testing in node.js thats why i decided to join this two things and explain how to marry them both fast. More info can be found here http://howtonode.org/how-to-module.

I hope it helped a bit. Cheers!

Comments