RK !

Let's make comprehension easy ...

Javascript Server Tour

Author: Romaan, Last Updated: Feb. 17, 2016, 9:22 a.m.

Gone are those days when JavaScript was only being used to bolster HTML and blow life into web browser pages. Now a days JavaScript is used on server side to write business logic, automate tasks, talk to databases and do almost anything to everything. In this blog, let us review a bunch of popular tools that helps us in achieving our goal of using JavaScript on server easily.

Node Package Manager: NPM

Inorder to get started, we need a good package manager that helps us get the JavaScript libraries and frameworks. NPM does exactly that. Inorder to install NPM on your machine, you need to:

  • sudo apt-get install nodejs npm  # On ubuntu

In order to upgrade NPM, once can just use NPM itself:

  • sudo npm install -g npm

Commonly requred commands:

  • npm list --global                # List globally installed packages
  • npm list                             # List locally installed packages
  • npm uninstall <package>  # Uninstall package
  • npm install <package>@<version> --save  # Install particular version of package and saves it to package.json
  • npm update <package>    # Update the package to latest available
  • npm cache clean            # When npm installs a package it keeps a copy, so next time you want to install that package, it doesn't need to hit network. The copies are cached in $HOME/.npm directory. To remove the cached copies use this command
  • npm init                          # Creates package.json and helps manage dependencies, entry point, test command, git repository and author details

Yeoman: Yo

Every project has a directory structure, conventions and configurations. Setting up or remembering one or two is okay, but remembering and using thousands of them is any developers' nightmare. Yoeman is here for the rescue. It is a scaffolding tool that can quickly help develop start a project. To install Yeoman using NPM:

sudo npm install -g yo    # Install Yo
sudo npm install -g generator-webapp  # Install generator
yo webapp   #run it

There are extra generators that one can install and use, for the complete list refer to http://yeoman.io/generators/ or do:

npm search yeoman-generator   # and install

Grunt

While in development, we will come across many repetative tasks that we will have to do. These tasks are monotnours and take aways the time, for example, populating fixutes, creating database schemas, initializing environment. Grunt is a rask runner, in order words, explicity used for automation. Grant uses plugins and most of the tasks we want to do can be found and used from plugin listing. Inorder to install grunt, simply type:

npm install -g grunt-cli

 

Node JS 

NodeJS is a server side platform built on Google Chrome's JavaScript Engine. It is famous for its noble features like Asynchronous and Event Driven technology, Single Threaded but highly scalable and open source. Some of the concepts we will explore in this article are:

  • Debugger
  • Modules
  • Console
  • Cluster
  • Add-ons
  • Buffer
  • Callbacks
  • Crypto
  • Error Handling
  • Net
  • Global
  • Domain
  • DNS
  • Streaming

Node Debugger

Now that we have the hello-world program in Node JS, the next common question is, I am given this large source code and I want to debug and understand better, how do I do it? The answer is, use debugger. Node debugger package enables you to debug the source code in any web-browser. In-order to install Node Debugger globally on your system:

sudo npm install -g node-inspector

and then run the code:

node-debug <my_app.js>

When you make http request to your app, it will automatically kick a debugger window with all the access to source code. 

OR Another way is to attach the debugger. First run the node-inspector which will start lisening on port 5858 by default.

node-inspector

Then, open a web-browser with URL: http://127.0.0.1:8080/?port=5858

Then, when you launch you application with debug flag, it will attach to the debugger. For example, in the Sails JS application explained below, the command "sails debug" will attach to debugger and helps us debug the code.

Sails JS

Sails JS is a web MVC framework built on top of Node JS. Installing a Sails JS, starting a projecting and quickly executing is dead simple as mentioned in the below steps:

  • sudo npm install -g sails
  • sails new <project_name> && cd <project_name>     # Creates a scaffold of Sails 
  • sails lift                                                                         # Execute the web-project
  • sails debug                                                                  # Debug sails web-project
  • sails generate api <app_name>                                        # Creates a model and a controller in api directory
  • sails console                                                              # Drops you into sails console, lets user play with models, services and configuration, helps try Waterline querying
  • sails www                                                                   # Run in production

Sails File Structure:

  • app.js                             ---> Starting point of the web-application
  • api                                  ---> Directory containing the following
    • controllers           ---> All the controller logic
    • models                ---> All the models files that represent a database table, object, document or key-value pair
    • policies               ---> Implement authentication and authorization
    • responses
    • services
  • assets                                ---> Place to store all JavaScript files
  • config                                 ---> Place where all configuration files are stored
    • connections.js        ---> Contains configurations to connect to different databases
    • http.js                    ---> HTTP middleware for every Sails request
    • models.js               ---> Application's default connection to database
    • policies.js             ---> Default policy for all controllers and actions
    • routes.js                 ---> Add custom routes to application
    • sessions.js            ---> Setting related to session
  • node_modules
  • tasks                                  ---> Set of grunt tasks
  • views

Sails Terminology:

  • Adapters: A bit of code that provides generic methods to perform database specific operations while encapsulating all the database specific nitigrities.
  • Blueprints: Are Sails way of quickly generating API routes and actions based on the application design. Blueprint routes and actions together constitute the blueprint API. 
    • The different blueprint actions are: find, findOne, create, update, destroy, populate, add and remove
    • The different blueprint routes are: RESTful routes, Shortcut routes and Action routes
  • ORM: Sails uses Waterline as its Object Relational Mapper. 
  • Policies: Simple functions which run before controllers. We can apply one or more policies, or protect its actions individually.

Basic MVC application

In this section, let is aim to develop a basic application to familiarize ourselves with Sails framework. Let us start by createing a new sails application:

sails new test_sails
cd test_sails

Now let us generate a controller and a model for people. This generates PeopleController in controller directory and People model in model direcoty.

sails generate api people

Inorder to test the application, bring up the sails project by saying:

sails debug
sails lift

and use any REST client to make a GET and POST request to http://localhost:1337/people

Viola... You can store and retrieve any key, values for the 'people'. In my opinion, Sails really has made our development efforts less.

Waterline ORM

In this section let us explore more about Waterline models and queries. A model is basically defined as below inside a model class:

module.exports = {
  connection: 'my_connection',
  tableName: 'people',
  attributes: {
    id: {
      type: 'integer',
      unique: true,
      primaryKey: true,
      columnName: 'the_primary_key'
    },
    name: {
      type: 'string',
      columnName: 'full_name'
    },
    password: {
      type: 'string',
      columnName: 'seriously_encrypted_password'
    },
    email: {
      type: 'email',
      unique: true,
      columnName: 'email_address'
    }
  }
};

 Source: http://sailsjs.org/documentation/concepts/models-and-orm/attributes

The supported types are: string, text, integer, float, date, datetime, boolean, binary, array, json.

In order to support relation or link between the models, waterline offers the following associations: One Way Association, Dominance, Many-to-Many, One-to-Many, One-to-one and Though Associations.

Inorder to query a model, one can simply try something like below:

People.find({where: {name: 'Romaan'}, skip: 20, limit: 10, sort: 'name DESC' });

One can use Sails console feature to try more data manipulations:

sails console
People.create({name: 'Khadeer'}).exec(console.log)
People.update({name: 'Khadeer'}, {name: 'Ahmed'}).exec(console.log)
People.destroy({name: 'Khadeer'}).exec(console.log)
People.findOrCreate({name:'FinderPeter'}, {name:'NewPeter', age: 25}).exec(console.log)
People.cound({ }).exec(console.log)
 

CRUD Example:

Let us create a Rabbit api to create rabbits and list them:

sails generate api rabbit
 
This generates Rabbit model and Rabbit controller. Let us create attributes for the Rabbit model:
 
  attributes: {
      name: {
          type: 'string',
          required: true
      },
      eatable: {
          type: 'string',
          enum: ['pasta', 'salad', 'vegetables']
      }
  }

and add the controller logic:

/**
 * RabbitController
 *
 * @description :: Server-side logic for managing rabbits
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 */
module.exports = {
    feed: function(req, res) {
        var param = req.param('rname');
        Rabbit.findOrCreate({name: param }).exec(function (err, data) { 
            if (err)
             res.send("Error creating rabbit");
            else
              res.send("Rabbit " + data.name + " created successfully")
        });
    },
    index: function(req, res) {
        Rabbit.find().exec(function (err, rabbits) {
            res.render('rabbit/index.ejs', {'rabbits': rabbits})
        })
    },
    
    bye: function(req, res) {
        return res.view("rabbit/bye.ejs");
    }
};
 
The controller defines three actions: feed, index and bye. And below are the views created inside the views directory:
 
<html>
    <head>
        <title>Rabbit</title>
    </head>
    <body>
        <h2>All the Rabbits</h2>
            <% rabbits.forEach( function( model ){ %>
                  <li><%= model.name %></li>
            <% }); %>
    </body>
</html>
 

Forever JS

A simple command line tool to run JS apps continously. All we have to do is install forever:

sudo npm install -g forever

and then run the app using forever:

forever start <app.js>
forever list               # List apps being run and managed by forever
forever stop <pid>  # Stop apps being run by forever
forever -w start <app>  # Starts the app and instantly restarts if any changes made to app

Nodemon

May be, if you get sick of restarting the service during development, use nodemon. It will monitor for any changes in the file system and restart the nodejs service automatically for you. All you have to do is, install and use it:

sudo npm install -g nodemon
nodemon <app.js>

Mocha: Test Framework

If you want to write unit tests, here is a javascript framework to help you confirm the behaviour of your code. You can install mocha with the following command:

npm install mocha

Other packages required during testing:

  • should.js  # BDD style assertions
    • npm install should --save
  • supertest.js  # Library for testing HTTP request response
    • npm install supertest --save

Then create a directory structure as below:

  • test
    • models
      • model.test.js
    • controller
      • controller_name.test.js
    • bootstrap.test.js
    • mocha.opts

Edit the file model.test.js with the following content:

describe('UserAccountModel', function() {
    describe('#create()', function() {
        it('Should create User Account', function(done) {
            MyModel.create({user_uuid:'as', username: 'romaan', password: 'xcsa', license_number: '12312-2323'}).exec(function(err, data) {
                data.username.should.be.eql('romaan');
                done();
            })
        });
    });
});

bootstrap.test.js with content:

var Sails = require('sails');
before(function(done) {
  Sails.lift({
    // configuration for testing purposes
  }, function(err, server) {
    if (err) return done(err);
    // here you can load fixtures, etc.
    done(err, Sails);
  });
  // Increase the Mocha timeout so that Sails has enough time to lift.
  this.timeout(8000);
});
after(function(done) {
  // here you can clear fixtures, etc.
  Sails.lower(done);
});

So if we were to test a functionality in Sails, we need to get the sails up and then do the testing, hence the above code in bootstrap.test.js starts the sails before running any other test.

Update file mocha.opts with:

--require should
--reporter dot
--ui bdd
--timeout 5000

Update file controller.test.js with:

var request = require('supertest');
describe('UserAccountController', function() {
    describe('#login()', function() {
        it('succeed', function(done) {
            request(sails.hooks.http.app)
            .post('/useraccount/login')
            .send({username: 'romaan', password: 'test'})
            .expect(200)
            done();
        });
    });
});

Run the test in either one of the two ways:

  • Using NPM:
    • Edit package.json and add the line:    
      • "test": "node node_modules/mocha/bin/mocha test/bootstrap.test.js test/**/*.test.js"  # inside scripts
    • Call the command to execute the test: npm test
  • From command line
    • node_modules/mocha/bin/mocha test/bootstrap.test.js test/models/mymodel.test.js  # To execute test individually

Wallaby.js

If you want to run your tests continously while developing, you can checkout wallaby.js. It is described as an intelligent test runner for JavaScript.

 

In Summary, JavaScript has an ecosystem of libraries to help developers perform every development, automation and tasks and make life easier.

Popular Tags:


Related Articles:


Comments: