Node.js — for Scripting

I have to admit, JavaScript has been my favorite language since around 2000. It’s a functional language that allows you to create objects by addressing the this keyword in your functions and using the new operator. It can operate dynamically or statically. You can pass functions as objects, and objects and arrays are nearly interchangeable.

In 2000, JavaScript was almost only in the browser and you had lots of “if” statements to support multiple browsers. Fast forward to today, and JavaScript is everywhere from the client to the server to the command prompt. Of course this omits that JavaScript was on the server and used for scripting through Microsoft Windows and their plugible WSH and ASP as well as with Netscape Server. It was far superior to VBScript on Windows and IIS and allowed for both front and back end development in JS, a paradigm I followed until the release of .NET.

With the advent of Node.JS, we now have a solid end-to-end JavaScript environment for both client and server. Rather than talk about this stack, which has been covered in detail everywhere else, I want to talk about using Node as a scripting engine.

I just started using Node to script my release management and web service unit tests. Why just have Node be the front end and server? It can also support replacing Bash, PowerShell, or other scripting. On top of that, it is a cross-platform option that supports all major OS’s. It has a ton of libraries and a package manager to keep track of them, npm. One package I use is fs-extra. Below is the command for using this package:

npm install --save fs-extra

For the purpose of handling release management, I am using the built-in Node package for the file system, fs, and also the fs-extra package that has several functions to help navigate the file system more easily. At the top of my script I use these two commands:

// Load the fs and path modules.
var fs = require('fs-extra'); // Installed via $ npm install --save fs-extra
var path = require('path');

I ended up finding a bug (or at least what I think is a bug) in the fs-extra package. (I need to contact the maintainer.) When you pass a filter to the copy command on a folder, it appears to filter the source path given and not each file that needs to be copied. I wrote my own version of this command. I need to send the maintainer a suggested patch to correct this, or perhaps get clarification:

function CopyFolder(source, dest, rxFilter)
?????? var sSrcRoot = path.resolve(source);

?????? // Since copying folder with filter didn't work, 
    // walking path and copying.
?????? fs.walk(source)
???? ??.on('data', function (item) 
???? ??{ 
???? ?????? ??if (rxFilter.test(item.path))
???? ?????? ??{
???? ?????? ??  var sRelativePath = item.path.substr(sSrcRoot.length);
???? ?????? ??  var sDestPath = dest + sRelativePath;
???? ?????? ??  fs.copy(item.path, sDestPath, { 'clobber': true,
???? ?????? ?????? ?????? ?????? ?????? ??'preserveTimestamps': true },
???? ?????? ?????? ??function (err) {
???? ?????? ?????? ???????? if (err) return console.error('Error copying ' + item.path + ': ' + err);
???? ?????? ?????? ???????? console.log('Copied file ' + item.path);
???? ?????? ?????? ??})
???? ???????? }
???? ??} );

I do want to refactor some of my code using promises, but I’ll get to that later. Also, I need to not only copy folders to the local folder, I also need to rsync them to my remote site.

So I can do something like:

CopyFolder('~/Projects/WebSite', '~/public_html/', 

There are other tools to do this, but this gives us a nice scripting environment using the JavaScript language.

The full documentation of the built-in Node functions and objects can be found here at Besides expected file system functions, there are functions for interacting with the OS and the console, doing encryption, unit testing (assertions), networking, and of course a ton of modules for dealing with web connections as an HTTP server.

As I continue to explore Node.js, I will write more about the features of the scripting engine from a console point-of-view.