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

   1 su
   2 cd /tmp
   3 wget http://slackbuilds.org/slackbuilds/14.0/network/node.tar.gz
   4 tar xvzf node.tar.gz
   5 cd node
   6 wget http://nodejs.org/dist/v0.10.12/node-v0.10.12.tar.gz
   7 ./node.SlackBuild 
   8 installpkg /tmp/node-0.10.12-x86_64-1_SBo.tgz 

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

Sample app

main.js

   1 var assert = require('assert'); // TDD
   2 var fs = require('fs'); // file system
   3 var util = require('util');
   4 //--------------------
   5 var Dummy = require('./dummy.js');
   6 var Local = require('./local.js');
   7 var conf=require('./config.js') // Configuration
   8 
   9 console.log( conf.configX['foo'] );
  10 console.log( conf.configX['bar'] );
  11 
  12 var d1 = new Dummy(12345);
  13 var d2 = new Dummy(67890);
  14 var d3 = new Dummy(112233);
  15 
  16 assert.equal(d1.methodA.call(d2),67890,'');
  17 assert.equal(d1.methodA.call(d3),112233,'');
  18 assert.equal(d3.methodA.call(d1),12345,'');
  19 
  20 var l1 = new Local('local1',10,11);
  21 var l2 = new Local('local2',20,21);
  22 var l3 = new Local('local3',30,31);
  23 
  24 assert.equal(l1.getPoint().getX(),10,'');
  25 assert.equal(l2.getPoint().getX(),20,'');
  26 assert.equal(l3.getPoint().getX(),30,'');
  27 
  28 // async readdir
  29 fs.readdir('/tmp', cbReaddir);
  30 
  31 function cbReaddir(err,files){
  32     for(var i=0; i< files.length;i++){
  33         console.log(files[i]);
  34     }
  35 }
  36 
  37 //async append file
  38 fs.appendFile('/tmp/test.txt', 'data to append\r\n', cbAppendFile);
  39 
  40 function cbAppendFile(err) {
  41     if (!err) {
  42         console.log('The "data to append" was appended to file!');
  43     }
  44 }
  45 
  46 function hexcounter(value,callback){
  47     console.log('HC:',value);
  48     if(value<15){
  49       setImmediate(function(){callback(value+1,callback);});
  50     }
  51     else{
  52       setImmediate(function(){callback(0,callback);});
  53     }
  54 }
  55 
  56 function octalcounter(){
  57     var timeout=500;
  58     if(arguments.length===1){
  59         console.log('OC:',arguments[0]);
  60         setTimeout(octalcounter,timeout,1,2)
  61     }
  62 
  63     if(arguments.length===2){
  64         var a0=Number(arguments[0]);
  65         var a1=Number(arguments[1]);
  66         console.log(util.format('%s %d %d','OC:',a0,a1));
  67         setTimeout(octalcounter,timeout,a0+1,a1+1);
  68     }
  69 }
  70 
  71 hexcounter(2,hexcounter);
  72 octalcounter(12300);
  73 
  74 process.on('SIGHUP', onSIGHUP);
  75 function onSIGHUP() {
  76   console.log('SIGHUP received',arguments.length);
  77 }
  78 
  79 process.on('SIGTERM', onSIGTERM);
  80 function onSIGTERM() {
  81   console.log('SIGTERM received',arguments.length);
  82 }

config.js

   1 exports.configX=
   2     {
   3         "foo":"fooValue",
   4         "bar":123
   5     }

dummy.js

   1 function Dummy(value1) {
   2     var self = this;
   3     self._value1 = value1;
   4 }
   5 
   6 Dummy.prototype.methodA = function() {
   7     var self = this;
   8     return self._value1;
   9 };
  10 
  11 module.exports = Dummy;

point.js

   1 function Point(x,y){
   2     this.x=x;
   3     this.y=y;
   4 }
   5 
   6 Point.prototype.getX=function(){
   7     return this.x;
   8 };
   9 
  10 Point.prototype.getY=function(){
  11     return this.y;
  12 };
  13 
  14 module.exports = Point;

local.js

   1 var Point = require('./point.js');
   2 
   3 function Local(name,x,y){
   4     this.name = name;
   5     this.point = new Point(x,y);
   6 }
   7 
   8 Local.prototype.getName=function(){
   9     return this.name;
  10 };
  11 
  12 Local.prototype.getPoint=function(){
  13     return this.point;
  14 };
  15 
  16 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

   1 su
   2 npm install -g node-gyp
   3 node-gyp

Hello world gyp

Based on https://github.com/joyent/node/tree/master/test/addons/hello-world

   1 cd /tmp/ 
   2 nano test.js
   3 nano binding.cc
   4 nano binding.gyp
   5 node-gyp configure #The configure step looks for the binding.gyp file in the current directory
   6 node-gyp build # gave an error building !
   7 

Based on https://github.com/rvagg/node-addon-examples

binding.gyp

{
  "targets": [
    {
      "target_name": "hello",
      "sources": [ "hello.cc" ]
    }
  ]
}

hello.cc

   1 #include <node.h>
   2 #include <v8.h>
   3 
   4 using namespace v8;
   5 
   6 Handle<Value> Method(const Arguments& args) {
   7   HandleScope scope;
   8   return scope.Close(String::New("world"));
   9 }
  10 
  11 void init(Handle<Object> exports) {
  12   exports->Set(String::NewSymbol("hello"),
  13       FunctionTemplate::New(Method)->GetFunction());
  14 }
  15 
  16 NODE_MODULE(hello, init)

   1 var addon = require('./build/Release/hello');
   2 
   3 console.log(addon.hello()); // 'world'
   4 

   1 node hello.js 

build.sh

   1 #!/bin/sh
   2 GYP=/usr/local/lib/node_modules/npm/bin/node-gyp-bin/node-gyp
   3 $GYP clean
   4 $GYP configure
   5 $GYP build

Read text file example

   1 var fs = require('fs'); // file system
   2 
   3 function cbReadFile(err, data) {
   4         if (err) {
   5                 throw err;
   6         }
   7         var ds = data.toString(); // data is of type Buffer
   8         var buffer = '';
   9         for ( var idx = 0; idx < ds.length; idx++) {
  10                 if (ds[idx] != '\n') {
  11                         buffer = buffer + ds[idx];
  12                 } else {
  13                         console.log(buffer);
  14                         buffer = '';
  15                 }
  16         }
  17 
  18 }
  19 
  20 fs.readFile('/etc/passwd', cbReadFile);

Context with this and bind

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

   1 /*Constructor function*/
   2 function Counter(){     
   3     this.counter=0;
   4 }
   5 
   6 Counter.prototype.run=function(){
   7     console.log('counter:',this.counter);
   8     this.counter++;
   9     //recall run
  10     setTimeout(this.run.bind(this),1000);
  11 };
  12 
  13 var c = new Counter();
  14 setTimeout( c.run.bind(c) ,1000); // apply context of c to this
  15 

Install from source Node 4.6.0

   1 wget https://nodejs.org/dist/v4.6.0/node-v4.6.0.tar.gz
   2 cp  node-v4.6.0.tar.gz /tmp
   3 cd /tmp
   4 tar xvif node-v4.6.0.tar.gz
   5 cd node-4.6.0
   6 ./configure
   7 make clean
   8 make
   9 make install

Install node 6.9.1 on Slackware64 14.2

   1 cd /tmp
   2 wget https://slackbuilds.org/slackbuilds/14.2/development/nodejs.tar.gz
   3 tar xvzf nodejs.tar.gz
   4 cd nodejs 
   5 wget https://nodejs.org/dist/v6.9.1/node-v6.9.1.tar.xz
   6 ./nodejs.SlackBuild 
   7 installpkg /tmp/nodejs-6.9.1-x86_64-1_SBo.tgz 

testApp with mongoose for AWS ElasticBeanstalk

Install Node 6.x in Ubuntu (vagrant on Windows)

   1 sudo bash 
   2 apt-get purge nodejs npm
   3 curl -sL https://deb.nodesource.com/setup_6.x | bash -
   4 apt-get install -y nodejs  
   5 exit 
   6 npm config set bin-links false # /vagrant folder in reality hosted in windows 
   7 npm install 

Structure

.
├── app.js
├── config.js
├── index.html
├── package.json
└── utils.js

app.js

   1 /**
   2  * npm install 
   3  * npm start
   4  * MONGOURL=mongodb://127.0.0.1/testdb npm start 
   5  * mongo 
   6  * use testdb
   7  * show collections
   8  * dummies
   9  * db.dummies.find()
  10  * 
  11  * zip ../testAppNodeJS.zip app.js config.js index.html package.json utils.js 
  12  * 
  13  * Deploying an Artifact Instead of the Project Folder
  14  * You can tell the EB CLI to deploy a ZIP or WAR file that you generate as part of a separate 
  15  * build process by adding the following lines to .elasticbeanstalk/config.yml in your project 
  16  * folder.
  17  * deploy:
  18  *   artifact: path/to/buildartifact.zip
  19  */
  20 var mongoose = require('mongoose');
  21 var http = require('http');
  22 var ut = require('./utils')
  23 var cfg = require('./config')
  24     
  25 var dummyModel = mongoose.model('Dummy', mongoose.Schema( { foo: String }) );
  26 
  27 mongoose.connect( cfg.getMongoURL() );    
  28 
  29 mongoose.connection.once('open', function(){
  30   ut.log('Connected to ' + cfg.getMongoURL() );
  31   var dummy = new dummyModel({ foo: 'Connected to MongoDB ' +  new Date().toISOString()  });
  32   dummy.save();
  33 });
  34 
  35 function requestListener(req, res) {
  36     if (req.method === ut.HTTP_METHOD_POST) {
  37         var body = '';
  38 
  39         req.on('data', function(chunk) {
  40             body += chunk;
  41         });
  42 
  43         req.on('end', function() {
  44             ut.log('Received URL ' + req.url );
  45             if (req.url === '/') {
  46                 ut.log('Received message: ' + body);
  47             } else if (req.url === '/scheduled') {
  48                 ut.log('Received task ' + req.headers['x-aws-sqsd-taskname'] + ' scheduled at ' + req.headers['x-aws-sqsd-scheduled-at']);
  49             }
  50             else if (req.url === '/addDummy') {
  51                 var dummy = req.headers['dummy'];
  52                 ut.log('Received dummy ' + dummy );             
  53                 dummyModel.create({ foo: dummy });
  54             }
  55             
  56             res.writeHead(ut.HTTP_200_OK, 'OK', ut.getTextPlain() );
  57             res.end();
  58         });
  59     } 
  60     else {
  61         res.writeHead(ut.HTTP_200_OK);
  62         res.write( ut.getIndex() );
  63         res.end();      
  64     }
  65 }
  66 
  67 var server = http.createServer(requestListener);
  68 // Listen on port 3000, IP defaults to 127.0.0.1
  69 server.listen( cfg.getPort() );
  70 // Put a friendly message on the terminal
  71 ut.log('Server running at http://127.0.0.1:' + cfg.getPort() + '/');
  72 ut.showEnvironmentVars();

config.js

   1 // Constructor function
   2 function Config(){  
   3 };
   4 
   5 //Static 
   6 Config.getPort = function() {
   7   return process.env.PORT || 8081;
   8 };
   9 
  10 Config.getTestVar = function() {
  11   return process.env.TESTVAR || '????';
  12 };
  13 
  14 Config.getMongoURL = function() {
  15   return process.env.MONGOURL || '????';
  16 };
  17 
  18 module.exports = Config

utils.js

   1 var fs = require('fs');
   2 
   3 // Constructor function 
   4 function Utils() {
   5 };
   6 
   7 // Constants 
   8 Utils.HTTP_METHOD_POST='POST';
   9 Utils.HTTP_METHOD_GET='GET';
  10 Utils.HTTP_200_OK=200;
  11 
  12 // Static
  13 Utils.showEnvironmentVars= function() {
  14     Utils.log('## Environment variables ##');
  15     for(var key in process.env){
  16         Utils.log('Environment variable ' + key + '==' + process.env[key] ); 
  17     }  
  18 };
  19 
  20 Utils.log = function(entry) {
  21     var msg = new Date().toISOString() + ' - ' + entry + '\n';
  22     fs.appendFileSync('/tmp/sample-app.log', msg);
  23     console.log(entry);
  24 };
  25 
  26 Utils.getIndex = function() {
  27   return fs.readFileSync('index.html');
  28 };
  29 
  30 Utils.getTextPlain = function() {
  31   return {'Content-Type': 'text/plain'};   
  32 };
  33 
  34 module.exports = Utils

package.json

   1 {
   2   "name": "Elastic-Beanstalk-Sample-App",
   3   "version": "0.0.1",
   4   "private": true,
   5   "dependencies": {
   6     "mongoose":"latest"
   7   },
   8   "scripts": {
   9     "start": "node app.js",
  10     "package": "CURRDATE=$(date -u \"+%Y%m%dT%H%m%S%Z\"); rm testAppNodeJS*.zip; zip -r  testAppNodeJS-$CURRDATE.zip app.js config.js index.html package.json utils.js node_modules"
  11   }
  12 }

index.html

   1 <!DOCTYPE html>
   2 <html>
   3   <head>
   4     <title>Elastic Beanstalk VB test</title>
   5     <style>
   6     </style>
   7   </head>
   8   <body>
   9     <div class="textColumn">
  10       <h1>Congratulations</h1>
  11       <p>Your first AWS Elastic Beanstalk Node.js application is now running on your own dedicated environment in the AWS Cloud</p>
  12     </div>
  13     <div class="linksColumn">
  14       <h2>What's Next?</h2>
  15     </div>
  16   </body>
  17 </html>

   1 npm install
   2 MONGOURL=mongodb://aaaaaa npm start
   3 MONGOURL=mongodb://aaaaaa npm run-script start
   4 curl -k -X POST http://127.0.0.1:8081/addDummy --header "dummy:valueLocal" 

Install from source node 10.16.1

   1 cd /tmp
   2 wget https://nodejs.org/dist/v10.16.1/node-v10.16.1.tar.gz
   3 ./configure
   4 make clean
   5 make
   6 make install

Usage of encodeURIComponent and decodeURIComponent

   1 $node
   2 Welcome to Node.js v12.20.0.
   3 Type ".help" for more information.
   4 > encodeURIComponent("aa:%bb")
   5 'aa%3A%25bb'
   6 > decodeURIComponent("aa%3A%25bb")
   7 'aa:%bb'
   8 > .exit

Install Node 12 on raspberry pi/Raspbian

   1 curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
   2 sudo apt install nodejs npm 
   3 node -v
   4 npm -v

Javascript/NodeJS (last edited 2023-05-29 09:19:58 by 127)