JavaScript everywhere one language to rule them all
We have JavaScript on the Browser, Mobile devices, Server, and now in the shell ;) what else can we ask for. JavaScript in our dreams? Maybe not but I really do love having one language to do all my work in. Not to long ago, I had to master a minimum of four languages to be productive. I would need to write my code in C#, JavaScript, PowerShell, SQL or PHP, JavaScript, BASH, SQL you get the point. Now with NodeJS I just need JavaScript to do it all. A few days ago, I needed to write a script that would create an account in the database, encrypt the password and link up all the permissions for that user across a few different tables. Then it would update some HTML based on rows added by the newly created user and push the code to the production server. It was easy as pie and came with all the benefits that the same code could run on my web server, command line, or cron job because its just a nodeJS package. In other words, its all JavaScript. I did not have to struggle to remember the crazy commands to do the work in BASH looking up man pages on sed/awk that I only use 4 times a year. It just is great to be able to use all the same tools you use every day. The same SQL client libraries, parsing tools, etc.
Writing a node shell script is easy it is no different from a Bash, Perl, or Python script. You just start the script with #!/usr/bin/env node and away you go! One hard thing with writing shell scripts is handling argument parsing and doing all the cool term outputs like progress bars, etc. You can just use packages like CLI or other NodeJS argument parsers to do all the heavy lifting so you can focus on writing code. I have started creating node shell script to do little tasks that I did manually. I am in love with my new workflow.
#!/usr/bin/env node
var cli = require('cli')
, crypto = require("crypto")
, dbclient = require('mysql').Client
, db = new dbclient()
, clId;
var options = cli.parse({
host: ['host', 'DB Host', 'string', '0.0.0.0']
, db: ['db', 'DB Database', 'string', 'database']
, dbuser: ['dbu', 'DB username', 'string', 'admin']
, dbpass: ['dbp', 'DB password', 'string', 'hummmmmm']
, username: ['u', 'New Username', 'string']
, password: ['p', 'Password', 'string']
});
var md5 = crypto.createHash('md5')
.update(options.password).digest('hex');
db.user = options.dbuser;
db.password = options.dbpass;
db.host = options.host;
db.database = options.db;
db.connect();
db.query('INSERT INTO tableA (foo) VALUES(?)',
[options.username], function(err, r) {
if(err) return cli.fatal(err.message);
cli.ok('INSERT INTO tableA >> ' +
(clId = r.insertId));
db.query('INSERT INTO login (uid,pwd,clId) VALUES(?, ?, ?)',
[options.username, md5, clId], function(err, r) {
if(err) return cli.fatal(err.message);
cli.ok('INSERT INTO login >> ' + options.username +
','+ md5 +','+ clId);
// do other crazy work
db.end();
});
});
JavaScript feels very good in a shell script with node supporting a REPL (Read Eval Print Loop) and its interpreted language it is a perfect fit. C# has PowerShell and Java has BeanShell but I just like the feel of nodeJS because the language is just a better fit.
Javascript Reflection & Introspection? huh
Javascript is such a cool language because it is so flexible. A friend challenged me to get JavaScript to support a feature that is commonly used in C#. In C# you can have custom attributes that can be applied to class, functions, arguments, packages, etc. This is very useful if you want to add metadata or declarative information to the code. I have built many things using this feature in C# like a REST API that uses the attributes to define documentation, ACLs, field validation, etc. This is very powerful because the code is very clean and declarative.
For exampl, lets say you want to make a generic REST API library so people can easily expose functions to be called throw a RESTful API. The standard way of doing this is to require the developer to explicitly add each function they want exposed to the REST interface by defining a configuration that maps a function to a RESTful endpoint. This setup and configuration code is separate from the code that has all the logic. Alternatively if you wanted a way to add metadata to the code that would not effect the way the function executes and stores the configuration details you could comment the code and use reflection to retrieve the metadata. C# and Java support this feature as a first class citizen but I do not know of a way to do this in JavaScript. So how can we do this?
Let’s enter into the world of JavaScript and why I love it! JavaScript is interpreted at runtime so we can just ask for the code and parse out the metadata. So how do we do this its easy! I will walk you through the code below.
function parseMetaTags(metadata) {
var tags = metadata.match(/\[@(.*?)\]/g)
, restult = {};
if(!tags) {
return false;
}
for(var i in tags) {
var str = tags[i]
, len = str.indexOf('{')
, tag = str.substring(str.indexOf('@') + 1,
(len != -1 ? len : str.length - 1))
, details = (len == -1 ? true :
eval('(' + str.substring(len, str.length - 1) + ')'));
restult[tag] = details;
}
return restult;
}
Function.prototype.reflect = exports.reflect = function(obj) {
obj = obj || this;
if(typeof obj === 'function') {
if(obj.args) {
return false;
}
var fnStr = obj.toString().replace(/[\n\t]/g,' ')
, argStr = fnStr.match(/\(.+?\)/)
, len = (argStr ? (argStr.index + argStr[0].length) : 11)
, fnBodyStr = fnStr.substring(len)
, metaData = {func:[], args:{}};
if(argStr) {
argStr = fnStr.substring(argStr.index + 1, len - 1);
var argList = argStr.match(
/(([$\s\w]+)?(\/\*.+?\*\/)?([$\s\w]+)?)+/g);
for(var i in argList) {
if(argList[i] != '') {
var meta = argList[i].match(
/(\/\*.+?\*\/)|([a-zA-Z_$][0-9a-zA-Z_$]*)/g);
var key = false
, val = [];
for(var j in meta) {
if(meta[j][0] == '/') {
var details = parseMetaTags(meta[j]);
if(details) {
val.push(details);
}
}
else key = meta[j];
}
metaData.args[key] = val;
}
}
}
if(fnBodyStr) {
var bodyList = fnBodyStr.match(/(\/\*.+?\*\/)/g);
for(var i in bodyList) {
if(bodyList[i] != '') {
var details = parseMetaTags(bodyList[i]);
if(details) {
metaData.func.push(details);
}
}
}
}
obj.args = metaData.args;
obj.func = metaData.func;
return true;
} else if(typeof obj === 'object') {
for(var i in obj) {
exports.reflect(obj[i]);
}
return true;
}
return false;
}
/* #### EXAMPLE #### */
function exampleAddUserToDB(
arg1 /* [@REST{postName:'name', type:'string'}] */
, arg2 /* [@REST{postName:'age', min:16, max:100}] */
) {
/* [@REST{type:'POST', access:'public'}] */
return true;
}
exampleAddUserToDB.reflect();
console.log(exampleAddUserToDB.args);
console.log(exampleAddUserToDB.func);
So what is going on in the code is very basic. The idea is we want to look for comments in the code that are formatted like /* [@attribute{json}]*/ and parse the comments out and turn them into metadata that can be attached to the function or its arguments. Because we want to add reflection to everything we add a prototype to Function. This makes it possible for any function to have reflect capabilities. The reflect function will call the toString() on itself. This gets the string representation of the function including all the comments so its just a matter of parsing out the tags in the code. After getting all the tags, we add the parsed tags onto the function itself so its easy to ask the function for its metadata. The function that parses the tags is parseMetaTags so you could build any kind of parser that would return any type of tags i.e. string, function, object, numbers.
This lets you add any kind of metadata to your code via comments that follow a standard format. Than at any time, you can call reflect that will parse out all the metadata and return an object that your code can query against. Lets take an example of having a RESTFul service. We now can comment in our code to let the RESTFul controller query to find out if the function should be called using GET, POST, what the endpoint URL is, rules around required arguments, inline documentation that the RESTFul service can return, etc. Basicly anything you can dream up. When you call the exampleAddUserToDB.reflect() it parses out the metadata so it can be accessed by exampleAddUserToDB.args and exampleAddUserToDB.reflect.func. Below is the output of the example above. As you can see all the metadata has been pulled out of the code. You can now build any function you want and add metadata to it and use reflection to retrieve it. What is more amazing is this is not apart of the JavaScript language but we still can support it in just a few lines. That is what I love about JavaScript it is so powerful.
{ arg1: [ { REST: { postName: 'name', type: 'string' } } ],
arg2: [ { REST: { postName: 'age', min: 16, max: 100 } } ] }
[ { REST: { type: 'POST', access: 'public' } } ]
I am not saying this is a good way to solve a problem but it is cool that we can do stuff like this. I love many things about C#, ObjC and Java each have their strengths and weaknesses but JavaScript seems to be more terse and flexible. This is both a good and bad thing! I really thing JavaScript is very very powerful, exciting, and fun to use and I hope sharing my weekend playground. I hope this with inspire you and your creativity to do other crazy cool things with JavaScript that it was not designed to do.
You can git (get) the code a github: demetriusj/js-reflection
TJ Holowaychuk: Cluster Live 0.0.1
cluster-live is a plugin for the Cluster server manager written for node. Cluster is similar to Ruby’s “Unicorn”, however is extremely extensible via a simple plugin system. Cluster is built with the Express web framework, Jade for templates, Stylus for CSS, and Socket.IO for communication. Below is a screenshot of cluster-live in action. Each worker process is represented by its own smoothie chart, showing the active connections, total connections, and requests issued to the worker. Connections appear as theblue line, and requests as gray, however in the screenshot below a single connection was issued per simulated request. Currently the only administration task that can be performed from cluster-live is the spawning and removal of workers by pressing the plus or minus buttons in the top-right corner. Using cluster, and cluster-live is extremely simple, first install the modules: Then initialize cluster with By default the cluster-live port is This plugin is still very much a work-in-progress, but it’s somewhat usable for now although optimizations are still required in order to provide sufficient performance. With minimal profiling it seems that smoothie is currently one of the largest benchmarks but it is something I will have to dig into deeper. It would be great to add some more administration capabilities, as well as more reporting, as many statistics are still currently left out.Cluster Live 0.0.1

Administration

Example
$ npm install cluster cluster-live
cluster(server), and use() the stats() plugin which produces the events that cluster-live uses for reporting, and then of course finally live() itself.var http = require('http')
, cluster = require('cluster')
, live = require('cluster-live');
var server = http.createServer(function(req, res){
res.end('Hello World');
});
cluster(server)
.set('workers', 4)
.use(cluster.stats({ connections: true, lightRequests: true }))
.use(live())
.listen(3000);
8888, so fire up 3000 and 8888 in your browser to see it in action. See the readme for information changing the port, host, or TLS options.Future
More Information