Node.js

Description
Node.js est un canevas événementiel (mono-thread) pour réaliser des applications serveur en Javascript. L'ensemble des événements est traité par une seule thread: Node.js privilégie les appels non bloquants. Node.js facilite le push (serveur --> client Web)

Cours
 * Formation Valtech : http://public.valtech-training.fr/DekNOD/slideshow/dist/#1

Docs
 * http://docs.nodejitsu.com

Alternatives

 * IO.js
 * Vert.x

Modules
Des nombreuses bibliothèques sont disponibles : Assertion Testing, Buffer, C/C++ Addons, Child Processes, Cluster, Crypto, Debugger, DNS, Domain, Events, File System, Globals, HTTP, HTTPS, Modules, Net, OS, Path, Process, Punycode, Query Strings, Readline, REPL, STDIO, Stream, String Decoder, Timers, TLS/SSL, TTY, UDP/Datagram, URL, Utilities, VM, ZLIB

Canevas
Des nombreux canevas sont construits sur Node.js
 * MEAN
 * Meteor
 * ql.io
 * https://npmjs.org/package/jade templates HTML (voir http://cssdeck.com/labs/learning-the-jade-templating-engine-syntax)
 * http://backbonejs.org
 * http://underscorejs.org

Installeur / Manager de version de Node.js
détails

nvm script

Registre NPM
Plusieurs modules sont catalogués depuis le registre https://npmjs.org/ et installables avec npm (Node Package Manager)

npm ls
 * 1) Voir les packages disponibles

npm ls installed
 * 1) Voir les packages installés

npm search duino
 * 1) Rechercher un package

npm install duino
 * 1) Installer un package pour le contrôle d'une carte Arduino

npm publish mypackage
 * 1) Installer un package

Modules pour les projets AIR

 * node-serialport access serial ports for reading and writing
 * duino A framework for working with Arduinos in node.js
 * firmata A Node library to interact with an Arduino running the firmata protocol.

Usine logicielle

 * voir Javascript
 * Test unitaire : nodeunit
 * IDEs :
 * Visual Studio https://nodejstools.codeplex.com
 * Eclispe http://www.nodeclipse.org/

Debugging

 * Integrated Debugger
 * Joyent Dev Guide :: Debug

Debug with [github.com/dannycoates/node-inspector Node Inspector]

 * Debug a NodeJS App With Chrome Dev Tools

node debug script_to_debug.js

sudo npm install -g node-inspector node-inspector

Browse http://127.0.0.1:8080/debug?port=5XXX

pgrep -l node node -e "process._debugProcess(NODEPID)"

Builders

 * Grunt
 * Gulp

Déploiement sur PaaS

 * http://www.heroku.com/
 * http://www.cloudfoundry.com/
 * https://www.joyent.com/products

Installation
dpkg --get-selections | grep node sudo apt-get remove --purge node dpkg --get-selections | grep nodejs sudo apt-get remove --purge nodejs

sudo apt-get install build-essential checkinstall sudo apt-get install libssl-dev curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash exit

Se logger command -v nvm nvm install 5.0 nvm use 5.0 nvm alias default node

Lancement
Aide node --help

Interactif node

En ligne node -p -e "Boolean(process.stdout.isTTY)"

En argument (process.argv[1]) node httpserver.js 8080

En mode debug node debug script_to_debug.js

HTTP script
var port = process.argv[2];

var http = require("http");

function onRequest(request, response) { console.log("Receiving a request"); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end; }

http.createServer(onRequest).listen(port); console.log("Server started. ^C to kill it");

node hello.js 8888

Express
var express = require('express'); var app = express; app.get('/hello.txt', function(req, res){ res.send('Hello World'); }); app.listen(8080);

npm install express node webserver.js 8080

start http://localhost:3000/hello.txt

Un peu plus avec Express.js

Express en HTTPS
Générer un certificat en répondant aux questions openssl req -newkey rsa:2048 -new -nodes -x509 -days 365 -keyout key.pem -out cert.pem

Editer securehttpd.js

var fs = require('fs'), https = require('https'), express = require('express'), app = express;

https.createServer({     key: fs.readFileSync('key.pem'),      cert: fs.readFileSync('cert.pem')    }, app).listen(8443);

app.get('/', function (req, res) {     res.header('Content-type', 'text/html');      return res.end(' Hello, Secure World! ');   });

node securehttpd.js

Naviguer sur https://localhost:8443/ en acceptant le certificat

UDP Datagrams
// udpreceiver.js var port = process.argv[2];

var dgram = require("dgram");

var server = dgram.createSocket("udp4");

server.on("message", function (msg, rinfo) { console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port); });

server.on("listening", function {  var address = server.address;  console.log("server listening " + address.address + ":" + address.port); });

server.bind(port);

// node udpsender.js

var host = process.argv[2]; var port = process.argv[3];

var dgram = require("dgram"); var readline = require('readline');

var client = dgram.createSocket("udp4"); var rl = readline.createInterface(process.stdin,process.stdout);

rl.setPrompt('> '); rl.prompt;

rl.on('line', function(line) { switch(line.trim) {    case 'exit':      rl.close;      break;    default:    var msg = {  		payload: line,  		timestamp: new Date,  		expires: "NEVER"	};    var message = new Buffer(JSON.stringify(msg));    //if(message.length<=0) break;	client.send(message, 0, message.length, port, host, function(err, bytes) { console.log("message "+ message + " sent"); });     break;  }  rl.prompt; }).on('close', function {  console.log('Bye Bye!');  process.exit(0); });

Terminal 1 npm install readline node udpreceiver.js 5000

Terminal 2 node udpsender.js localhost 5000

Terminal 3 node udpsender.js 0.0.0.0 5000

DTLS
node-dtls

Remote Shell
https://gist.github.com/mastahyeti/1283301

var port = process.argv[2];

var spawn = require('child_process').spawn; var net = require('net'); var stream = require('stream'); var console = require('console'); var server = net.createServer(function(socket){ var sh = spawn('/bin/sh');

sh.stdin.resume;

sh.stdout.on("data",function (data){   //Node makes async stuff easy.     //You can do cool things like:    //socket.write(Base64_encode(data));    //or any other encoding/obfuscation    //for that matter.    socket.write(data);  });

sh.stderr.on("data",function (data){   socket.write(data);  });

socket.on("data",function (data){   sh.stdin.write(data);  });

});

server.listen(port,'0.0.0.0');

node remoteshell.js 1337

nc localhost 1337

XMPP
var jid = process.argv[2]; var password = process.argv[3]; var friend = process.argv[4];

var xmpp = require('simple-xmpp'); //var readline = require('readline');

xmpp.on('online', function {   console.log('Yes, I\'m connected!'); });

xmpp.on('chat', function(from, message) {  //  xmpp.send(from, 'echo: ' + message);    console.log('%s says %s', from, message); });

xmpp.on('stanza', function(stanza) {       console.log(stanza); });

xmpp.on('error', function(err) {   console.error(err); });

xmpp.on('subscribe', function(from) { if (from === friend) {   xmpp.acceptSubscription(from);    } });

xmpp.on('buddy', function(jid, state, statusText) {   console.log('%s is in %s state - %s', jid, state, statusText); });

xmpp.connect({   jid         : jid,    password    : password,    host        : 'talk.google.com',    port        : 5222 });

xmpp.subscribe(friend); // check for incoming subscription requests xmpp.getRoster;

// TO BE CONTINUED WITH readline

node install simple-xmpp node minigtalk.js me@gmail.com MyPaSSwOrD my.friend@gmail.com

Crypto: SHA1 Hashing
var filename = process.argv[2]; var crypto = require('crypto'); var fs = require('fs');

var shasum = crypto.createHash('sha1');

var s = fs.ReadStream(filename); s.on('data', function(d) { shasum.update(d); });

s.on('end', function { var d = shasum.digest('hex');  console.log(d + '  ' + filename); });

node hash.js hash.js

TTY
process.stdout.on('resize', function { console.log('screen size has changed!');  console.log(process.stdout.columns + 'x' + process.stdout.rows); });

node resize.js

$ node -p -e "Boolean(process.stdout.isTTY)" true $ node -p -e "Boolean(process.stdout.isTTY)" | cat false

REPL (Read-Eval-Print-Loop)
var net = require("net"), repl = require("repl");

connections = 0;

repl.start({ prompt: "node via stdin> ",  input: process.stdin,  output: process.stdout });

net.createServer(function (socket) { connections += 1;  repl.start({ prompt: "node via TCP socket> ", input: socket, output: socket }).on('exit', function { connections -= 1; socket.end; }); }).listen(5001);

node repl.js

1+2+3+4+5

telnet localhost 5001

1+2+3+4+5

.help

.exit

Cluster
var port = process.argv[2]; var cluster = require('cluster'); var http = require('http'); var numCPUs = require('os').cpus.length;

if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork; }

cluster.on('exit', function(worker, code, signal) {   console.log('worker ' + worker.process.pid + ' died');  }); } else { // Workers can share any TCP connection // In this case its a HTTP server http.createServer(function(req, res) {   res.writeHead(200);    res.end("hello world\n");  }).listen(port); }

node httpcluster.js 8080

Simple Arduino Test
Placez la patte du milieu d'un potentiomètre sur la pin analogique A0 (les pattes des bords sur GND et +5V). Téléversez l'exemple File > Examples > 01.Basics > AnalogReadSerial de l'IDE sur votre Arduino.

// AnalogReadSerial.js var port = process.argv[2]; var serialport = require('serialport');

var sp = new serialport.SerialPort(port, {               baudrate: 9600,                parser: serialport.parsers.readline('\r\n')});

sp.on('data', function(line) {   console.log(line); });

npm install serialport node AnalogReadSerial.js /dev/tty.usbmodemfa131

Arduino avec Firmata
Placez la patte du milieu d'un potentiomètre sur la pin analogique A0 (les pattes des bords sur GND et +5V). Téléversez l'exemple File > Examples > Firmata > StandardFirmata sur votre Arduino

// testfirmata.js var port = process.argv[2];

var firmata = require('firmata'); var board = new firmata.Board(port,function{ //arduino is ready to communicate  board.analogRead(0,function(data){ console.log(data); }) });

npm install firmata node testfirmata.js /dev/tty.usbmodemfa131 node testfirmata.js /dev/ttyACM0

Voir https://github.com/jgautier/firmata

NMEA 0183 Parsing
var nmea = require('nmea')

var sentences = [ "$GPGSA,A,1,,,,,,,,,,,,,,,*1E", "$GPGSV,3,1,12,29,75,266,39,05,48,047,,26,43,108,,15,35,157,*78", "$GPGSV,3,2,12,21,30,292,,18,21,234,,02,18,093,,25,13,215,*7F", "$GPGSV,3,3,12,30,11,308,,16,,333,,12,,191,,07,-4,033,*62", "$GPRMC,085542.023,V,,,,,,,041211,,,N*45", "$GPGGA,085543.023,,,,,0,00,,,M,0.0,M,,0000*58", ];

for (var i=0; i < s.length; i++) { console.log(nmea.parse(sentences[i])); };

npm install nmea node testnmea.js

// serialnmea.js var port = process.argv[2]; var serialport = require('serialport'); var nmea = require('nmea');

var sp = new serialport.SerialPort(port, {               baudrate: 4800,                parser: serialport.parsers.readline('\r\n')});

sp.on('data', function(line) {   console.log(nmea.parse(line)); });

npm install nmea node serialnmea.js /dev/cu.usbserial

see also https://npmjs.org/package/coordinator

NFC RFID Readers
See:
 * https://npmjs.org/package/node-hid
 * http://svay.com/blog/hacking-rfid-with-nodejs/

var HID = require('node-hid'); console.log(HID.devices);

npm install node-hid node listhid.js

Autres

 * BSON
 * Persistance des objets avec MongoDB https://wiki.10gen.com/display/DOCS/node.JS
 * H-Ubu Component Model with Node.js

Robot

 * Cylon.js

Robot Operating System

 * rosnodejs Programming robots with JavaScript & Node.js

XMPP

 * Client https://github.com/astro/node-xmpp
 * Server https://github.com/superfeedr/xmpp-server

Twitter

 * Client Twitter https://github.com/jdub/node-twitter

REST

 * Écrire un service REST avec NodeJS et Express http://naholyr.fr/2011/08/ecrire-service-rest-nodejs-express-partie-1/
 * Client REST https://github.com/danwrong/Restler/
 * Serveur REST

MySQL

 * https://github.com/felixge/node-mysql/blob/master/Readme.md