The random utterances of David Arno

Writing a node.js module in CoffeeScript

coffeescript logoThis article seeks to detail how to write a node.js module in CoffeeScript, for both Windows and Linux. The Linux instructions may well work on OS X too, but as I do not have a Mac, I haven’t tested that environment. The article takes you through ensuring node.js and required modules are installed, that the coffee-script library can be accessed and then on to writing, installing and running an executable module. Finally it shows you some refactoring to enable all of the module code to be written in CoffeeScript.

Before you start, install node.js, npm and the coffee-script module
To take advantage of this guide, you need to install node.js and its coffee-script module if you haven’t yet done so. If you are on a Windows machine, take a look at my “Beginners guide to using CoffeeScript on Windows with node.js” article. If you are on Linux, please refer to Installing Node.js via package manager and the npm home page for details on installing node.js and npm respectively. To then install coffee-script on Linux, enter the following on the command line:

sudo npm install -g coffee-script

You should then be ready to follow the rest of the article.

Also before you start, let’s talk about NODE_PATH
One of the weaknesses of node.js, that v0.6 has sought to fix, is the handling of dependency paths. In earlier versions, it was necessary to explicitly declare the path to everything for node.js to find things. Version 0.6 improved things greatly by adding a path search algorithm that searches node_modules subdirectories to look for modules. However the developers seem to have overlooked one important addition: support for npm’s globally installed modules. For some reason, node doesn’t implicitly know about these modules. For CoffeeScript-based modules to work well, we need to fix this issue.

It turns out that this can be easily fixed by adding npm’s global node_modules directory to the NODE_PATH environment variable. How to do this, depends on whether you are running on a Linux or a Windows machine.

Windows
On Windows, select <Windows Key>-R to bring up the Run dialogue and run systempropertiesadvanced.exe. There select “Environment Variables…” and create a new user variable:

Variable name: NODE_PATH
Variable value: %APPDATA%\npm\node_modules

Click on OK to close all the dialogues, then – here’s the bad news – log out and back in again so that your environment picks up the change.

Linux
In some ways, it is easier to set up NODE_PATH on Linux. In other ways it’s more complex. The complex part is that the instructions vary depending on which shell you use. To check, type the following in a terminal window:

echo $SHELL

Chances are, it’ll say /bin/bash or /bin/sh (or some other path to bash or sh.) If it does, next type the following in a terminal window:

echo $NODE_PATH

and note whether it is empty, or displays something like /usr/lib/nodejs:/usr/share/javascript.

The next step is to edit ~/.profile. If the previous command displayed nothing, add the following line to the end of your .profile file:

export NODE_PATH=/usr/lib/node_modules

If not blank, add this instead:

export NODE_PATH=$NODE_PATH:/usr/lib/node_modules

Save your edits and then type the following in a terminal window:

. ~/.profile

This updates your environment in the terminal window (without the need to log out and in again as Windows folk must.)

Test you have access to the coffee-script module
There are – in crude terms – two types of module that one can write: library modules and executables. Library modules provide functionality that can be used by other modules. Executables can be run from the command line, much like any other command line tool. CoffeeScript is both of these. It provides the coffee executable and the coffee-script library. We are going to make use of the latter here. Assuming all has gone well in the previous steps, we should be ready to make use of it. To test that, open a terminal (or cmd) window and run node within it. When presented with the “>” prompt, type:

require("coffee-script");

If you get an error saying that the module cannot be found, then there is something wrong with your set up. Check you have followed the previous steps correctly and if there is still a problem, leave me a comment and I’ll try and help you resolve it. If you get a long output starting with something like

{ VERSION: '1.2.0',
  RESERVED: 
   [ 'case',
...

then you are ready to write your own module.

Write the module
We are going to write a super-simple executable module that demonstrates some key points of creating a module in CoffeeScript. To start, pick a suitable place on your file system and create a nodeinfo directory. Below that, create lib and bin.

In the bin directory, create a file called nodeinfo (with no extension. This applies to Windows users too.) Add the following content:

#!/usr/bin/env node
require("coffee-script");
var nodeinfo = require("../lib/nodeinfo");
nodeinfo.run();

To explain what you have created, let’s take it a line at a time:

#!/usr/bin/env node

This is “unix magic” that tells the OS to find the path to the node executable and to run the rest of the file using node. The rest of the file is thus JavaScript, as that is what node runs. Don’t worry, we’ll revist the file and make it CoffeeScript at the end, but for now, it’s useful to write it as JavaScript.

require("coffee-script");

This tells node to load the coffee-script module for us.

var nodeinfo = require("../lib/nodeinfo");

This tells node to load the (as yet unwritten) CoffeeScript code that is our module. It stores a reference to the module in the nodeinfo variable.

nodeinfo.run();

Finally, we call the run function in our (about to be written) CoffeeScript module.

Next, create the file nodeinfo.coffee in the lib directory. Add the following content:

run = ->
  console.log("Your node.js details:")
  console.log("Version: " + process.version)
  console.log("Platform: " + process.platform)
  console.log("Architecture: " + process.arch)
  console.log("NODE_PATH: " + process.env.NODE_PATH)

exports.run = run

This is fairly basic CoffeeScript: it defines a run function that prints some information to the terminal or cmd window. As CoffeeScript wraps the contents of our file in a function to give us encapsulation, we need to provide node.js with details of any externally accessible functions. exports.run = run does just that. This provides our bin/nodeinfo file access to the module.

Run the executable (Linux only)

Because bin/nodeinfo is a unix shell script, we can run it straight away. On Windows, it needs to be turned into a .cmd filer by npm, so this step only applies to Linux. Type the following in a terminal window from within the bin directory:

./nodeinfo 

This should print something like:

Your node.js details:
Version: v0.6.10
Platform: linux
Architecture: x64
NODE_PATH: /usr/lib/nodejs:/usr/share/javascript:/usr/lib/node_modules

Create the package.json file
The final step to creating our module is to create a package.json file in the nodeinfo directory. Open up your editor and create the file with the following content:

{
  "author": "David Arno",
  "name": "nodeinfo",
  "description": "Simple example of writing a node.js module in CoffeeScript",
  "version": "0.0.0",
  "repository": {
    "url": ""
  },
  "engines": {
    "node": "~0.6.6"
  },
  "dependencies": {},
  "devDependencies": {},
  "bin": {"nodeinfo": "./bin/nodeinfo"}
}

(Obviously feel free to change the comment and put you own name as the author.)

Install and run your module
Still in the nodeinfo directory, type the following on Windows:

npm install -g .

and on Linux:

sudo npm install -g .

Assuming no errors, run nodeinfo and you should see a similar output to above. Well done, you have written your first CoffeeScript node.js executable.

Rewrite nodeinfo executable in CoffeeScript
Earlier, we wrote JavaScript in the nodeinfo file. This was to demonstrate how to write a node executable. However, as I mentioned previously, the CoffeeScript module for node.js is both a library and executable module. We can take advantage of this to enable us to rewrite nodeinfo in CoffeeScript. Simply replace the contents of the file with:

#!/usr/bin/env coffee
nodeinfo = require '../lib/nodeinfo'
nodeinfo.run()

You’ll notice that we now ask the “unix magic” to run the coffee executable instead of node. This allows us to lose the require("coffee-script") line (as we are already using it) and to replace the other two lines with CoffeeScript code.

And that’s it. Hopefully this article will both assist and inspire you to use CoffeeScript in creating your next node.js module.


Share This Post...
2 comments so far, click here to read them or add another

2 Comments so far

  1. \*/ February 10th, 2012 16:47

    pity node doesn’t set NODE_PATH by default
    btw you can set it on windows without logging of

    set NODE_PATH=%APPDATA%\npm\node_modules
    setX NODE_PATH %APPDATA%\npm\node_modules
    echo %NODE_PATH%

  2. Jeff R December 20th, 2012 20:18

    FYI, it looks like the whole “global to local” coffee script issue can be resolved in a simpler way. The program npm has a feature called link, whose sole purpose is to make a given global package available in your local packages. Syntax is like this:

    npm link coffee-script

    Simply running that allowed me to require(“coffee-script”); in the REPL without receiving an error about node being unable to locate the module.