{"id":1225,"date":"2013-06-17T09:34:10","date_gmt":"2013-06-17T01:34:10","guid":{"rendered":"http:\/\/www.strongd.net\/?p=1225"},"modified":"2013-06-17T09:34:10","modified_gmt":"2013-06-17T01:34:10","slug":"6-must-have-node-js-modules","status":"publish","type":"post","link":"https:\/\/www.strongd.net\/?p=1225","title":{"rendered":"6 Must Have Node.js Modules"},"content":{"rendered":"<p>So you&#8217;re thinking about using node.js: awesome. If you&#8217;re new to the community you&#8217;re probably thinking &#8220;what&#8217;s the best node.js module \/ library for X?&#8221; I think it&#8217;s really true when experienced language gurus say &#8220;80% of your favorite language is your favorite library.&#8221; This is the first in a series of articles will give you a high-level overview of some of our favorite node.js libraries at Nodejitsu. Today we&#8217;ll take a look at these libraries:<\/p>\n<p>&nbsp;<\/p>\n<ol>\n<li><a href=\"https:\/\/github.com\/cloudhead\/cradle\">cradle<\/a>: A high-level, caching, CouchDB library for Node.js<\/li>\n<li><a href=\"https:\/\/github.com\/substack\/node-findit\">findit<\/a>: Walk a directory tree in node.js<\/li>\n<li><a href=\"https:\/\/github.com\/mranney\/node_redis\">node_redis<\/a>: Redis client for node<\/li>\n<li><a href=\"https:\/\/github.com\/cloudhead\/node-static\">node-static<\/a>: RFC2616 compliant HTTP static-file server module, with built-in caching.<\/li>\n<li><a href=\"https:\/\/github.com\/substack\/node-optimist\">optimist<\/a>: Light-weight option parsing for node.js<\/li>\n<li><a href=\"https:\/\/github.com\/Leonidas-from-XIV\/node-xml2js\">xml2js<\/a>: Simple XML to JavaScript object converter.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h2><\/h2>\n<h1>cradle: A high-level, caching, CouchDB library for Node.js<\/h1>\n<p>If you&#8217;re using\u00a0<a href=\"http:\/\/couchdb.apache.org\/\">CouchDB<\/a>\u00a0you should be using\u00a0<a href=\"https:\/\/github.com\/cloudhead\/cradle\">cradle<\/a>. Cradle stands above the other CouchDB libraries in the node.js community: it has a robust LRU (least recently used) cache, bulk document processing, and a simple and elegant API:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>\/\/\r\n\/\/ Create a connection\r\n\/\/\r\nvar conn = new(cradle.Connection)('http:\/\/living-room.couch', 5984, {\r\n  cache: true,\r\n  raw: false\r\n});\r\n\r\n\/\/\r\n\/\/ Get a database\r\n\/\/\r\nvar database = conn.database('newyorkcity');\r\n\r\n\/\/\r\n\/\/ Now work with it\r\n\/\/\r\ndatabase.save('flatiron', {\r\n  description: 'The neighborhood surrounding the Flatiron building',\r\n  boundaries: {\r\n    north: '28 Street',\r\n    south: '18 Street',\r\n    east: 'Park Avenue',\r\n    west: '6 Avenue'\r\n  }\r\n}, function (err, res) {\r\n  console.log(res.ok) \/\/ True\r\n});<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h1>findit: Walk a directory tree in Node.js<\/h1>\n<p>A common set of problems that I see on the\u00a0<a href=\"http:\/\/groups.google.com\/group\/nodejs\">nodejs mailing list<\/a>\u00a0are advanced file system operations: watching\u00a0<strong>all<\/strong>\u00a0the files in a directory, enumerating an entire directory, etc. Recently, when working on my fork of\u00a0<a href=\"https:\/\/github.com\/indexzero\/docco\">docco<\/a>\u00a0to respect directory structure in the documentation produced I needed such a feature. It was surprisingly\u00a0<a href=\"https:\/\/github.com\/indexzero\/docco\/blob\/master\/src\/docco.coffee#L251\">easy<\/a>:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>var findit = require('findit');\r\n\r\nfindit.find('\/dir\/to\/walk', function (file) {\r\n  \/\/\r\n  \/\/ This function is called each time a file is enumerated in the dir tree\r\n  \/\/\r\n  console.log(file);\r\n});<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h1>node_redis: Redis client for Node.js<\/h1>\n<p>There have been a lot of\u00a0<a href=\"http:\/\/redis.io\/\">redis<\/a>\u00a0clients released for node.js. The question has become: which client is the right one to use? When selecting an answer to this question for any library you want to look for a few things including:\u00a0<strong>the author, the recent activity, and the number of followers on GitHub.<\/strong>\u00a0In this case the author is\u00a0<a href=\"https:\/\/github.com\/mranney\">Matt Ranney<\/a>, a member of the node.js core team. The most recent commit was\u00a0<a href=\"https:\/\/github.com\/mranney\/node_redis\/commit\/1a14e24faa130c561ce75d138a54f1ecddb45c6e\">yesterday<\/a>, and the repository has over 300 followers.<\/p>\n<p>Redis is really fast, and extremely useful for storing volatile information like sessions and cached data. Lets take a look at some sample usage:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>var redis = require(\"redis\"),\r\n    client = redis.createClient();\r\n\r\nclient.on(\"error\", function (err) {\r\n  console.log(\"Error \" + err);\r\n});\r\n\r\nclient.set(\"string key\", \"string val\", redis.print);\r\nclient.hset(\"hash key\", \"hashtest 1\", \"some value\", redis.print);\r\nclient.hset([\"hash key\", \"hashtest 2\", \"some other value\"], redis.print);\r\nclient.hkeys(\"hash key\", function (err, replies) {\r\n  console.log(replies.length + \" replies:\");\r\n  replies.forEach(function (reply, i) {\r\n      console.log(\"    \" + i + \": \" + reply);\r\n  });\r\n  client.quit();\r\n});<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h1>node-static: RFC2616 compliant HTTP static-file server module, with built-in caching<\/h1>\n<p>I bet you&#8217;re wondering &#8220;What the $%^@ is RFC2616?&#8221;\u00a0<a href=\"http:\/\/www.ietf.org\/rfc\/rfc2616.txt\">RFC2616<\/a>\u00a0is the standards specification for HTTP 1.1, released in 1999. This spec is responsible for outlining how (among other things) files should be served over HTTP. Thus, when choosing a node.js static file server, its important to understand which libraries are standards compliant and which are not:\u00a0<a href=\"https:\/\/github.com\/cloudhead\/node-static\">node-static<\/a>\u00a0is. In addition, it has some great built-in caching which will speed up your file serving in highly concurrent scenarios.<\/p>\n<p>Using node-static is easy, lets make a static file server in 7 lines of Javascript:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>var static = require('node-static');\r\n\r\n\/\/\r\n\/\/ Create a node-static server instance to serve the '.\/public' folder\r\n\/\/\r\nvar file = new(static.Server)('.\/public');\r\n\r\nrequire('http').createServer(function (request, response) {\r\n  request.addListener('end', function () {\r\n    \/\/\r\n    \/\/ Serve files!\r\n    \/\/\r\n    file.serve(request, response);\r\n  });\r\n}).listen(8080);<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h1>optimist: Light-weight option parsing for Node.js<\/h1>\n<p>One of the great things about node.js is how easy it is to write (and later publish with\u00a0<a href=\"http:\/\/npmjs.org\/\">npm<\/a>) simple command-line tools in Javascript. Clearly, when one is writing a command line tool one of the most important things is to have a robust command line options parser. Our library of choice for this at\u00a0<a href=\"http:\/\/nodejitsu.com\/\">Nodejitsu<\/a>\u00a0is\u00a0<a href=\"https:\/\/github.com\/substack\/node-optimist\">optimist<\/a>\u00a0by\u00a0<a href=\"https:\/\/github.com\/substack\">substack<\/a>.<\/p>\n<p>Lets take a look at a sample CLI script reminiscent of\u00a0<a href=\"http:\/\/en.wikipedia.org\/wiki\/Bizz_buzz\">FizzBuzz<\/a>:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>#!\/usr\/bin\/env node\r\nvar argv = require('optimist').argv;\r\n\r\nif (argv.rif - 5 * argv.xup &gt; 7.138) {\r\n  console.log('Buy more riffiwobbles');\r\n}\r\nelse {\r\n  console.log('Sell the xupptumblers');\r\n}<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Using this CLI script is easy:<\/p>\n<pre>$ .\/node-optimist.js --rif=55 --xup=9.52\r\nBuy more riffiwobbles\r\n\r\n$ .\/node-optimist.js --rif 12 --xup 8.1\r\nSell the xupptumblers<\/pre>\n<p>This library has support for\u00a0<code>-a<\/code>\u00a0style arguments and\u00a0<code>--argument<\/code>\u00a0style arguments. In addition any arguments passed without an option will be available in\u00a0<code>argv._<\/code>. For more information on this library check out the\u00a0<a href=\"https:\/\/github.com\/substack\/node-optimist\">repository on GitHub<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h1>xml2js: Simple XML to Javascript object converter<\/h1>\n<p>Writing clients in node.js for APIs that expose data through\u00a0<a href=\"http:\/\/json.org\/\">JSON<\/a>\u00a0is almost too easy. There is no need for a complex, language-specific JSON parsing library that one might find in languages such as\u00a0<a href=\"http:\/\/flori.github.com\/json\/\">Ruby<\/a>\u00a0or\u00a0<a href=\"http:\/\/docs.python.org\/library\/json.html\">Python<\/a>. Just use the built-in Javascript\u00a0<code>JSON.parse<\/code>\u00a0method on the data returned and\u00a0<strong>voila!<\/strong>\u00a0you&#8217;ve got native Javascript objects.<\/p>\n<p>But what about APIs that only expose their data through\u00a0<strong>XML<\/strong>? You could use the native\u00a0<a href=\"https:\/\/github.com\/polotek\/libxmljs\">libxmljs<\/a>module from\u00a0<a href=\"https:\/\/github.com\/polotek\">polotek<\/a>, but the overhead of dealing with individual XML nodes is non-trivial and (in my opinion) can lead to excess complexity. There is another, simpler option: the lesser known<a href=\"https:\/\/github.com\/Leonidas-from-XIV\/node-xml2js\">xml2js<\/a>\u00a0library available on\u00a0<a href=\"http:\/\/npmjs.org\/\">npm<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/Leonidas-from-XIV\/node-xml2js\">GitHub<\/a>.<\/p>\n<p>Lets suppose that we had some\u00a0<strong>XML<\/strong>\u00a0(\/me dies a little inside):<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;root&gt;\r\n  &lt;child foo=\"bar\"&gt;\r\n    &lt;grandchild baz=\"fizbuzz\"&gt;grandchild content&lt;\/grandchild&gt;\r\n  &lt;\/child&gt;\r\n  &lt;sibling&gt;with content!&lt;\/sibling&gt;\r\n&lt;\/root&gt;<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Parsing this using xml2js is actually surprisingly easy:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>var fs = require('fs'),\r\n    eyes = require('eyes'),\r\n    xml2js = require('xml2js');\r\n\r\nvar parser = new xml2js.Parser();\r\n\r\nparser.on('end', function(result) {\r\n  eyes.inspect(result);\r\n});\r\n\r\nfs.readFile(__dirname + '\/foo.xml', function(err, data) {\r\n  parser.parseString(data);\r\n});<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The output we would see is:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre><code>{\r\n  child: {\r\n    @: { foo: 'bar' },\r\n    grandchild: {\r\n      #: 'grandchild content',\r\n      @: { baz: 'fizbuzz' }\r\n    }\r\n  },\r\n  sibling: 'with content!'\r\n}\r\n<\/code><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>If you haven&#8217;t already noticed, xml2js transforms arbitrary XML to JSON in the following way:<\/p>\n<ul>\n<li>All entity tags like\u00a0<code>&lt;child&gt;<\/code>\u00a0become keys in the corresponding JSON.<\/li>\n<li>Simple tags like\u00a0<code>&lt;sibling&gt;with\u00a0content&lt;\/sibling&gt;<\/code>\u00a0become simple key:value pairs (e.g. sibling: &#8216;with content!&#8217;)<\/li>\n<li>More complex tags like\u00a0<code>&lt;child&gt;...<\/code>\u00a0and\u00a0<code>&lt;grandchild&gt;...<\/code>\u00a0become complex key:value pairs where the value is an Object literal with two important properties:\n<ol>\n<li><code>@<\/code>: An Object representing all attributes on the specified tag<\/li>\n<li><code>#<\/code>: Any text content for this XML node.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<p>This simple mapping can greatly simplify the XML parsing logic in your node.js application and is worth checking out if you ever have to deal with the three-headed dog we all love to hate.<\/p>\n<p>&nbsp;<\/p>\n<h1>Just getting started<\/h1>\n<p>This is the first in a series of articles where we will outline at a high level the best-of-the-best for modules, libraries and techniques in node.js that you should be aware of. If you&#8217;re interested in writing your own node.js modules and publishing them to\u00a0<a href=\"http:\/\/npmjs.org\/\">npm<\/a>, check out\u00a0<a href=\"http:\/\/howtonode.org\/how-to-module\">isaacs new article: How to Module<\/a>\u00a0over at\u00a0<a href=\"http:\/\/howtonode.org\/\">howtonode.org<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So you&#8217;re thinking about using node.js: awesome. If you&#8217;re new to the community you&#8217;re probably thinking &#8220;what&#8217;s the best node.js module \/ library for X?&#8221; I think it&#8217;s really true when experienced language gurus say &#8220;80% of your favorite language is your favorite library.&#8221; This is the first in a series of articles will give &hellip; <a href=\"https:\/\/www.strongd.net\/?p=1225\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">6 Must Have Node.js Modules<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[195],"class_list":["post-1225","post","type-post","status-publish","format-standard","hentry","category-20","tag-node"],"_links":{"self":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/1225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1225"}],"version-history":[{"count":1,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/1225\/revisions"}],"predecessor-version":[{"id":1226,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/1225\/revisions\/1226"}],"wp:attachment":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}