Nikola Brežnjak blog - Tackling software development with a dose of humor
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Home
Daily Thoughts
Ionic
Stack Overflow
Books
About me
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Nikola Brežnjak blog - Tackling software development with a dose of humor
NodeJS, Quick tips

How to use nodemon

Nodemon is a utility that will monitor for any changes in your source and automatically restart your server. Perfect for development. Install it using npm.

npm install -g nodemon

Once installed, instead of node app.js  use nodemon app.js . It will save you a lot of time in the long run, because you won't need to manually restart the server each time you make a change.

edit: These days I'm using a ever so slightly more popular PM2.

CodeSchool, NodeJS

How to get started with Node.js

Recently I started using CodeSchool to explore new languages/technologies in the web world, and I will post every Tuesday something new that I learn. So far, all I have for them is pure praise, so if you fancy learning something new go check them out. I like them because of one thing in how they do their presentations: first you watch a video in which they explain the concept and then, more importantly (at least in my case), you get the set of challenges where you yourself have to write the code in order to pass on to the next level - awesome! So I would say that their slogan "Learn by doing" is right on the spot.

This is by no means meant as a tutorial, but merely as my notebook where I write down things which I've learned. Ok, without further to do, lets check out what's all this mumbo jumbo buzzword about Node.js.

Node.js (by Ryan Dahl) is in fact a wrapper, written in C, around V8 JavaScript runtime of Google Chrome engine which can be executed on the server.

Blocking vs non-blocking code: Node.js makes non-blocking possible by providing us with a callback function when the process (for example: file reading) is done.

var http = require("http");
var fs = require("fs");

http.createServer(function(request, response){
    response.writeHead(200);
    fs.readFile("file.txt", function(err, contents){
        response.write(contents);
        response.end();
    });
    response.write("This will most likely be printed before the file contents");
}).listen(8080);

To view this, visit http://localhost:8080  in your browser or do a curl request. Interesting thing to note though is that you will not get the same effect if you run it via curl in terminal and in browser, and here is my question on StackOverflow which helps answer why. Long story short (with more info about it later in the post):

...this is simply due to the behavior of the browser rendering engine which cashes the contents until response.end(); arrives, and then renders whole response. Socket.IO and this article should be of help

As explained in the StackOverflow post, I solved this by using Socket.IO (explained in more detail below in the post) and here is the simple example:

//timeoutTest.js
var express = require('express'),
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server);

server.listen(8080);

app.use(express.static(__dirname + '/'));

app.get('/', function (req, res) {
   res.sendfile(__dirname + '/timeoutTest.html');
});

io.sockets.on('connection', function (client) {
   client.emit('msg', "This prints right now on connection.");

   setTimeout(function(){
      client.emit('msg', "This prints out after 3 secs.");      
   }, 3000);
});

//timeoutTest.html
<!DOCTYPE html>
<html>
<head>
    <script src="/socket.io/socket.io.js"></script>
    <script src="jquery.js"></script>
    <script>
    $(document).ready(function(){
        var server = io.connect('http://localhost');
        server.on('msg', function(data){
            $('body').append(data + "<br/>");
        });
    });
    </script>
</head>
<body>
</body>
</html>

Upon first execution of the code Node registers events and then it goes into the so called "event loop".

Instead of response.write(string)  as the last command, you can put it in end() function like this response.end (string);

How to use event emmiters:

var EventEmitter = require('events').EventEmitter;

var logger = new EventEmitter();

logger.on('error', function (msg){
    console.log('error: ' + msg);
});

logger.emit('error', 'sth went wrong');

Same "#$! different packaging:

http.createServer(function(req, resp){}); 

//is the same as:

var server = http.createServer();
server.on("request", function(req, resp){};

Pip | ing:

var fs = require('fs');
var http = require('http');

http.createServer(function(request, response){
    var newFile = fs.createWriteStream('newFile.md');
    request.pipe(newFile);

    request.on('end', function(){
        response.end('uploaded');
    });
}).listen(8080);

//test like this:
curl --upload-file someFile.txt http://localhost:8080

File uploader:

var fs = require('fs');
var http = require('http');

http.createServer(function(request, response) {
	var newFile = fs.createWriteStream("readme_copy.md");
	var fileBytes = request.headers['content-length'];
	var uploadedBytes = 0;

	request.pipe(newFile);

	request.on('data', function(chunk) {
		uploadedBytes += chunk.length;
		var progress = (uploadedBytes / fileBytes) * 100;
		response.write("progress: " + parseInt(progress, 10) + "%\n");
	});

	request.on('end', function(){
        response.end('uploaded');
    });
}).listen(8080);

A side-note; console.log()  does in fact call process.stdout.write.

While calling your own modules, you require them without the ".js"

//custom_hello.js file
var hello = function() {
    console.log("hello!");
}
exports = hello;

//custom_goodbye.js file
exports.goodbye = function(){
    console.log("whot!?");
}

//--usage:
var hello = require('./custom_hello');
var gb = require('./custom_goodbye');

hello();
gb.goodbye();

When you're requiring with "./" it searches in the current file directory. When, however, you search without it and just write the name of the module it first searches in the file directory for a folder named node_modules, then it goes folder up if it doesn't find it in recursive.

npm install request  installs it locally and you can (only then!) require it in your code, whilst you should do a global installation  npm install coffee-script -g  if the module has an executable.

//package.json
{
  "name": "My Awesome Node App",
  "version": "1",
  "dependencies": {
    "connect" : "2.2.1",
      "underscore" : "1.3.3"
  }
}

package.json  file is cool as you can distribute the "barebones" app, which once downloaded can be fully installed by doing npm install  (it also installs sub-dependencies if needed).

Express - web application framework for Node.js: npm install express

var express = require('express');

var app = express(); //prior versions: express.createServer();
app.get('/:param', function(request, response){
    var param = request.params.param;
    response.send(param);

    //or, templates are also supported!
    response.render('tweet.ejs', {tweets: tweets, name: username});
});

app.listen(8080);

//tweet.ejs
<h1>Tweets for <%= name %></h1>
<ul>
    <% tweets.forEach(function(tweet)){ %>
        <li><%= tweet.text %></li>
   <% }; %>
</ul>

//but, also you need layout.ejs
<!DOCTYPE html>
<html>
    <head>
        <title>Some cool title</tile>
    </head>
    <body>
        <%- body %>
    </body>
</html>


Socket.IO
 - aims to make realtime apps possible in every browser and mobile device.
npm install socket.io

Simple chat application

var express = require('express'),
	app = express(),
   	server = require('http').createServer(app),
   	io = require('socket.io').listen(server);

server.listen(8080);

app.use(express.static(__dirname + '/'));

app.get('/', function (req, res) {
   	res.sendfile(__dirname + '/chat.html');
});

io.sockets.on('connection', function (client) {
   	client.on('join', function(name){
   		client.set("nickname", name);
   	});

   	client.on("msg", function(data){
      	client.get("nickname", function(err, name){
      		client.broadcast.emit('msg', name + ":" + data);
      	});
   	});
});

Very important thing to note here is that in order to make use of jQuery library you have to set the correct path to your js files in the app.use()  function.

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="jquery.js"></script>
    <script>
    $(document).ready(function(){
        var server = io.connect('http://localhost');

        server.on("connect", function(data){
            nickname = prompt("Your nickname:");

            server.emit("join", nickname);
        });

        server.on('msg', function(data){

           $('#recv').append(data + "<br/>");
	    });

	    $("#send").on("click", function(event){
            event.preventDefault();

            $('#recv').append($('#msg').val() + "<br/>");
    	    server.emit('msg', $('#msg').val());
    	});
    });
    </script>
</head>
<body>
    <input type="text" id="msg" name="msg" value="testets"/>
    <input type="submit" id="send" name="send"/>

    <div id="recv" name="recv"></div>
</body>
</html>

mongoDB -  open-source document database, and the leading NoSQL database written in C++. mongojs - A Node.js module for mongodb, that emulates the official mongodb API as much as possible. Installation via npm: npm install mongojs .

//db.js
var databaseURI = "mydb";
var collections = ["users"];
var db = require("mongojs").connect(databaseURI, collections);

module.exports = db;

//dbtest.js
var db = require("./db");

db.users.save({email: "[email protected]", group: "A"}, function(err, saved) {
  if( err || !saved ) console.log("User not saved");
  else console.log("User saved");
});

db.users.find({group: "A"}, function(err, users) {
  if( err || !users) console.log("No A group users found");
  else users.forEach( function(user) {
    console.log(user);
  });
});

In order for this to work mongoDB has to be installed on your system and it has to be running.  Installation instructions are clear and concise on their website, but a tl;dr is: download the zip package, unzip in c:\mongodb , make c:\data\db  folder, run c:\mongodb\bin\mongod.exe.

CodeProject, NodeJS

Using CasperJS on Webfaction to automatically send emails with attached images via Gmail

Why?

Recently I had to make a script which runs once per week and gathers images of an admin interface (login required) and sends it to its manager by email for quick overview. This is great because it saves the manager's time as he doesn't have to login to the website and click through all of the graphs and wait for them to load, instead he gets a weekly (YMMV) summary. The site was hosted on Webfaction, which, as it turns out, is a cool web host (haven't come across it before) because it allows you to compile source code and run custom binaries.

How?

The task of automatically logging in the admin dashboard and taking screenshots  proved to be an excellent job for CasperJS, an open source navigation scripting & testing utility written in Javascript for the PhantomJS WebKit headless browser.

Installation

In order to run CasperJS scripts, you need to have NodeJS installed. Installing NodeJS on Webfaction is as straightforward as it can get, as it's done via their control panel in the Applications tab, as shown on the illustration below:
webfactionNodeInstall

It's useful to put NodeJS executable in your path because then you can run node from any folder. You can do this by going to your NodeJS application’s bin directory and execute the following command:

export PATH=$PATH:$PWD/bin/

Installing CasperJS is easy via npm (Node package manager):

npm install -g casperjs

However,  in order for CasperJS to work, you need to install PhantomJS and you can do it by cloning it from its GitHub repository and running the build.sh script:

mkdir -p $HOME/src

cd $HOME/src

git clone git://github.com/ariya/phantomjs.git && cd phantomjs

git checkout 1.5

./build.sh

cp $HOME/src/phantomjs/bin/phantomjs $HOME/bin

To test if PhantomJS has been successfully installed you can run:

phantomjs --version

To have the binaries in my path every time I log in I added this alias to my .bashrc:

alias nodeset="export PATH=$PATH:/home/webapp/node/bin:/home/webapp/bin"

and my .bash_profile looks like this:

# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
nodeset

CasperJS script for automatically saving images

var casper = require("casper").create({
	verbose: false,
	logLevel: 'debug'
});

var url = "http://your-app.com/", 
	saveDir = "/home/app/savedImages";

casper.start(url, function() {
	this.fill('form#fm_login', {
        'username':    'username',
        'password':    'password',
    });

    this.echo("I filled the form");
});

casper.then(function(){
	this.click('#btn_login');
	this.echo("I'm, logging in");
});

//first graph fetch
casper.thenOpen("http://your-app.com/graph_1", function(){
    this.wait(3000, function() {
        this.echo("I've waited for 3 seconds for the graphs to load.");

        casper.then(function(){
            var fileName = saveDir + '/graph_1.png';
            this.viewport(1920, 1080);
            this.captureSelector(fileName, '#page_content');
            this.echo('first snapshot taken');
        });
    }); 
});

casper.run(function() {
    this.echo('done').exit();
});

First I initialize casper and set few variables (url, saveDir - note that it has to be full path). Then I start casper by visiting the passed in url and fill the login form by using caspers fill() function. After that I click on the login button and woila - I'm logged in. After that I open up the link with the graph and wait 3 seconds for the graph to load, and then I save the selected area by using the captureSelector() function and a CSS selector of the area I want to save.

NodeJS script for automatically sending email with attachment via Gmail SMTP

This node script uses nodemailer which can be installed using npm:

node install -g nodemailer

This script uses Gmail SMTP (if you want to test it make sure to enter correct Gmail account credentials), but nodemailer offers many more options for sending the email. The simple email sending script is here:

var nodemailer = require("nodemailer");
var rootFolder = "/home/app/savedImages/";
// create reusable transport method (opens pool of SMTP connections)
var smtpTransport = nodemailer.createTransport("SMTP",{
    service: "Gmail",
    auth: {
        user: "[email protected]",
        pass: "your.gmail.pass"
    }
});

// setup e-mail data with unicode symbols
var mailOptions = {
    from: "Automatic Graph Sender <[email protected]>", // sender address
    to: "[email protected]", // list of receivers
    subject: "Automatic Graph Sender", // Subject line
    text: "Hello, I'm Roboty, an automatic report sending robot. You will find your files in attachment. I wish you a great day! Bye, Roboty", // plaintext body
    html: "Hello,<br/><br/>I'm Roboty, an automatic report sending robot. You will find your files in attachment.<br/><br/>I wish you a great day!<br/><br/>Bye,<br/>Roboty",
    attachments: [
        { filePath: rootFolder + "graph_1.png"},
        { filePath: rootFolder + "graph_2.png"},
        //add as many as you wish
    ]
}

// send mail with defined transport object
smtpTransport.sendMail(mailOptions, function(error, response){
    if(error){
        console.log(error);
    }else{
        console.log("Message sent: " + response.message);
    }

    // if you don't want to use this transport object anymore, uncomment following line
    smtpTransport.close(); // shut down the connection pool, no more messages
});

 

Cron jobs

The following script will run every day at exactly 19:50h. I added the PHANTOMJS_EXECUTABLE needed by CasperJS executable, then I wrote the path to CasperJS and the script that we want to execute and finally I redirected all the output to the temporary file for later inspection if needed.

50 19 * * * PHANTOMJS_EXECUTABLE=/home/app/bin/phantomjs /home/app/node/bin/casperjs /home/app/casper/saveImages.js > /tmp/outputCheck.txt

Mailing script runs 5 minutes after the image gathering script and also outputs everything to the temporary file used in some other success status checking script.

55 19 * * * /home/emtool/webapps/node/bin/node /home/emtool/my_folder/casper/mail.node.js > /tmp/emailOut.txt

Hope this proved useful to someone, and hit me with comments or questions you may have.

CodeProject

Page 13 of 13« First...«10111213

Recent posts

  • 8Questions™
  • Using Puppeteer to automate ASC Analytics screenshots
  • Do it when you don’t feel like it
  • Self-mastery
  • Writing well

Categories

  • Android (3)
  • Books (111)
    • Programming (22)
  • CodeProject (35)
  • Daily Thoughts (71)
  • Go (3)
  • iOS (5)
  • JavaScript (123)
    • Angular (4)
    • Angular 2 (3)
    • Ionic (61)
    • Ionic2 (2)
    • Ionic3 (8)
    • MEAN (3)
    • NodeJS (27)
    • Phaser (1)
    • Three.js (1)
    • Vue.js (1)
  • Leadership (1)
  • Meetups (8)
  • Miscellaneou$ (76)
    • Breaking News (8)
    • CodeSchool (2)
    • Hacker Games (3)
    • Pluralsight (7)
    • Projects (2)
    • Sublime Text (2)
  • PHP (6)
  • Quick tips (36)
  • Servers (7)
    • Heroku (1)
    • Linux (2)
  • Stack Overflow (81)
  • Unity3D (9)
  • Windows (8)
    • C# (2)
    • WPF (3)
  • Wordpress (2)

"There's no short-term solution for a long-term result." ~ Greg Plitt

"Everything around you that you call life was made up by people that were no smarter than you." ~ S. Jobs

"Hard work beats talent when talent doesn't work hard." ~ Tim Notke

© since 2016 - Nikola Brežnjak