= NodeJS =
Node.js is a platform built on Chrome's Javascript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

[[http://www.nodejs.org/]]

http://blog.4psa.com/the-callback-syndrome-in-node-js/

== SlackBuild Slackware64 14.0 ==
 * su
 * cd /tmp
 * wget http://slackbuilds.org/slackbuilds/14.0/network/node.tar.gz
 * tar xvzf node.tar.gz
 * cd node
 * wget http://nodejs.org/dist/v0.10.12/node-v0.10.12.tar.gz
 * ./node.SlackBuild 
 * installpkg /tmp/node-0.10.12-x86_64-1_SBo.tgz 

Package 64 bit: [[attachment:node-0.10.12-x86_64-1_SBo.tgz]]

== Sample app ==

main.js
{{{#!highlight javascript
var assert = require('assert'); // TDD
var fs = require('fs'); // file system
var util = require('util');
//--------------------
var Dummy = require('./dummy.js');
var Local = require('./local.js');
var conf=require('./config.js') // Configuration

console.log( conf.configX['foo'] );
console.log( conf.configX['bar'] );

var d1 = new Dummy(12345);
var d2 = new Dummy(67890);
var d3 = new Dummy(112233);

assert.equal(d1.methodA.call(d2),67890,'');
assert.equal(d1.methodA.call(d3),112233,'');
assert.equal(d3.methodA.call(d1),12345,'');

var l1 = new Local('local1',10,11);
var l2 = new Local('local2',20,21);
var l3 = new Local('local3',30,31);

assert.equal(l1.getPoint().getX(),10,'');
assert.equal(l2.getPoint().getX(),20,'');
assert.equal(l3.getPoint().getX(),30,'');

// async readdir
fs.readdir('/tmp', cbReaddir);

function cbReaddir(err,files){
    for(var i=0; i< files.length;i++){
	console.log(files[i]);
    }
}

//async append file
fs.appendFile('/tmp/test.txt', 'data to append\r\n', cbAppendFile);

function cbAppendFile(err) {
    if (!err) {
	console.log('The "data to append" was appended to file!');
    }
}

function hexcounter(value,callback){
    console.log('HC:',value);
    if(value<15){
      setImmediate(function(){callback(value+1,callback);});
    }
    else{
      setImmediate(function(){callback(0,callback);});
    }
}

function octalcounter(){
    var timeout=500;
    if(arguments.length===1){
	console.log('OC:',arguments[0]);
        setTimeout(octalcounter,timeout,1,2)
    }

    if(arguments.length===2){
        var a0=Number(arguments[0]);
	var a1=Number(arguments[1]);
	console.log(util.format('%s %d %d','OC:',a0,a1));
	setTimeout(octalcounter,timeout,a0+1,a1+1);
    }
}

hexcounter(2,hexcounter);
octalcounter(12300);

process.on('SIGHUP', onSIGHUP);
function onSIGHUP() {
  console.log('SIGHUP received',arguments.length);
}

process.on('SIGTERM', onSIGTERM);
function onSIGTERM() {
  console.log('SIGTERM received',arguments.length);
}
}}}

config.js
{{{#!highlight javascript
exports.configX=
    {
        "foo":"fooValue",
        "bar":123
    }
}}}

dummy.js
{{{#!highlight javascript
function Dummy(value1) {
    var self = this;
    self._value1 = value1;
}

Dummy.prototype.methodA = function() {
    var self = this;
    return self._value1;
};

module.exports = Dummy;
}}}

point.js
{{{#!highlight javascript
function Point(x,y){
    this.x=x;
    this.y=y;
}

Point.prototype.getX=function(){
    return this.x;
};

Point.prototype.getY=function(){
    return this.y;
};

module.exports = Point;
}}}

local.js
{{{#!highlight javascript
var Point = require('./point.js');

function Local(name,x,y){
    this.name = name;
    this.point = new Point(x,y);
}

Local.prototype.getName=function(){
    return this.name;
};

Local.prototype.getPoint=function(){
    return this.point;
};

module.exports = Local;
}}}

== node-gyp ==
node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js.

https://github.com/TooTallNate/node-gyp

=== Install with npm ===
 * su
 * npm install -g node-gyp
 * node-gyp

=== Hello world gyp ===
Based on https://github.com/joyent/node/tree/master/test/addons/hello-world
 * cd /tmp/ 
 * nano test.js
 * nano binding.cc
 * nano binding.gyp
 * node-gyp configure #The configure step looks for the binding.gyp file in the current directory
 * node-gyp build # gave an error building !

Based on https://github.com/rvagg/node-addon-examples
 * nano binding.gyp 
{{{
{
  "targets": [
    {
      "target_name": "hello",
      "sources": [ "hello.cc" ]
    }
  ]
}
}}}
 * nano hello.cc
{{{#!highlight cpp
#include <node.h>
#include <v8.h>

using namespace v8;

Handle<Value> Method(const Arguments& args) {
  HandleScope scope;
  return scope.Close(String::New("world"));
}

void init(Handle<Object> exports) {
  exports->Set(String::NewSymbol("hello"),
      FunctionTemplate::New(Method)->GetFunction());
}

NODE_MODULE(hello, init)
}}}
 * nano hello.js
{{{#!highlight javascript
var addon = require('./build/Release/hello');

console.log(addon.hello()); // 'world'
}}}
 * node hello.js 

== Read text file example ==
{{{#!highlight javascript
var fs = require('fs'); // file system

function cbReadFile(err, data) {
	if (err) {
		throw err;
	}
	var ds = data.toString(); // data is of type Buffer
	var buffer = '';
	for ( var idx = 0; idx < ds.length; idx++) {
		if (ds[idx] != '\n') {
			buffer = buffer + ds[idx];
		} else {
			console.log(buffer);
			buffer = '';
		}
	}

}

fs.readFile('/etc/passwd', cbReadFile);
}}}