<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title type="text">good coders code, great reuse</title>
  <id>http://www.catonmat.net/feed</id>
  <updated>2012-02-02T05:34:44Z</updated>
  <link href="http://www.catonmat.net" />
  
  <author>
    <name>Peteris Krumins</name>
    <uri>http://www.catonmat.net/about</uri>
    <email>peter@catonmat.net</email>
  </author>
  <subtitle type="text">Peteris Krumins' blog about programming, hacking, software reuse, software ideas, computer security, google and technology.</subtitle>
  <icon>http://www.catonmat.net/favicon.ico</icon>
  <generator uri="http://www.catonmat.net" version="v1.0">catonmat blog</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/catonmat" /><feedburner:info uri="catonmat" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>catonmat</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Announcing my third e-book "Perl One-Liners Explained"</title>
    <id>303</id>
    <updated>2012-02-02T05:34:44Z</updated>
    <published>2012-02-01T13:40:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/27oRonhWXEU/perl-book" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yaCf8gxnVwB5cmfMMEZyDajRyhQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yaCf8gxnVwB5cmfMMEZyDajRyhQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yaCf8gxnVwB5cmfMMEZyDajRyhQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yaCf8gxnVwB5cmfMMEZyDajRyhQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="float:right; margin-left: 5px"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/perl-book/cover.png" width="260" height="310"&gt;&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;p&gt;&lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=2HMCK3EJRM6MC"&gt;Buy it now for just $9.95&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;&lt;p&gt;&lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=2HMCK3EJRM6MC" class="nohover"&gt;&lt;img src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1"&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Hello ladies and gentlemen! &lt;strong&gt;I'm happy to announce my 3rd e-book called "Perl One-Liners Explained."&lt;/strong&gt; This book is based on the "&lt;a href="http://www.catonmat.net/blog/perl-one-liners-explained-part-one/"&gt;Famous Perl One-Liners Explained&lt;/a&gt;" article series that I wrote over the last 3 years and that has been read over 500,000 times!&lt;/p&gt;
&lt;p&gt;I went through all the one-liners in the article series, improved explanations, fixed mistakes and typos, added a bunch of new one-liners, added an introduction to Perl one-liners and a new chapter on Perl's special variables.&lt;/p&gt;
&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;p&gt;The e-book has 111 pages and it explains 130 unique one-liners. Many of one-liners are presented in several different ways so the total number of one-liners in the book is over 200.&lt;/p&gt;
&lt;p&gt;The e-book is divided into the following chapters:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Preface.&lt;/li&gt;
&lt;li&gt;1. Introduction to Perl One-Liners.&lt;/li&gt;
&lt;li&gt;2. Spacing.&lt;/li&gt;
&lt;li&gt;3. Numbering.&lt;/li&gt;
&lt;li&gt;4. Calculations&lt;/li&gt;
&lt;li&gt;5. String Creation and Array Creation.&lt;/li&gt;
&lt;li&gt;6. Text Conversion and Substitution.&lt;/li&gt;
&lt;li&gt;7. Selective Printing and Deleting of Lines.&lt;/li&gt;
&lt;li&gt;8. Handy Regular Expressions.&lt;/li&gt;
&lt;li&gt;9. perl1line.txt&lt;/li&gt;
&lt;li&gt;Appendix A. Perl's Special Variables.&lt;/li&gt;
&lt;li&gt;Index.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What are Perl One-Liners?&lt;/h2&gt;
&lt;p&gt;Perl one-liners are small and awesome Perl programs that fit in a single line of code and they do one thing really well. These things include changing line spacing, numbering lines, doing calculations, converting and substituting text, deleting and printing certain lines, parsing logs, editing files in-place, doing statistics, carrying out system administration tasks, updating a bunch of files at once, and many more.&lt;/p&gt;
&lt;p&gt;Let's take a look at several practical examples that you can easily do with one-liners. All these examples and many more are explained in the e-book.&lt;/p&gt;
&lt;p&gt;I have also made the first chapter of the book, &lt;em&gt;Introduction to Perl One-Liners&lt;/em&gt;, freely available. Please download &lt;a href="http://www.catonmat.net/download/perlbook-preview.pdf"&gt;the e-book preview&lt;/a&gt; to read it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example 1: Replace a string in multiple files at once&lt;/strong&gt;&lt;/p&gt;
&lt;pre &gt;
perl -p -i.bak -e 's/Config/config/g' conf1 conf2 conf3
&lt;/pre&gt;
&lt;p&gt;Suppose you have 3 configuration files, and you discover that you made a mistake and need to replace all occurrences of &lt;code&gt;Config&lt;/code&gt; with &lt;code&gt;config&lt;/code&gt;. This one-liner does just that. It executes the &lt;code&gt;s/Config/config/g&lt;/code&gt; that replaces all occurrences of &lt;code&gt;Config&lt;/code&gt; with &lt;code&gt;config&lt;/code&gt; on all lines. And since you're smart about it, you always do &lt;code&gt;-i.bak&lt;/code&gt; to make backup files in case something goes wrong.&lt;/p&gt;
&lt;p&gt;I explain the &lt;code&gt;-i&lt;/code&gt;, &lt;code&gt;-p&lt;/code&gt;, and &lt;code&gt;-e&lt;/code&gt; arguments in the e-book in great detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example 2: Generate a random 8 character password&lt;/strong&gt;&lt;/p&gt;
&lt;pre &gt;
perl -le 'print map { ("a".."z")[rand 26] } 1..8'
&lt;/pre&gt;
&lt;p&gt;This one-liner generates and prints a random 8 character password. It uses the list range operator &lt;code&gt;..&lt;/code&gt; operator to produce all strings from &lt;code&gt;"a"&lt;/code&gt; to &lt;code&gt;"z"&lt;/code&gt;, which is the alphabet. Then a random letter is chosen by &lt;code&gt;rand 26&lt;/code&gt; and this operation is repeated 8 times.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example 3: URL-escape a string&lt;/strong&gt;&lt;/p&gt;
&lt;pre &gt;
perl -MURI::Escape -lne 'print uri_escape($string)'
&lt;/pre&gt;
&lt;p&gt;Here we use the &lt;code&gt;URI::Escape&lt;/code&gt; module from CPAN. It exports the &lt;code&gt;uri_escape&lt;/code&gt; function that does URL-escaping.&lt;/p&gt;
&lt;p&gt;You can install this module from CPAN by running &lt;code&gt;perl -MCPAN -e'install URI::Escape'&lt;/code&gt; on the command line.&lt;/p&gt;
&lt;p&gt;I have this one-liner as an alias actually for both URL-escaping and unescaping URL-escaping as it's such a common thing to do:&lt;/p&gt;
&lt;pre &gt;
urlescape () { perl -MURI::Escape -lne 'print uri_escape($_)' &amp;lt;&amp;lt;&amp;lt; "$1" }
urlunescape () { perl -MURI::Escape -lne 'print uri_unescape($_)' &amp;lt;&amp;lt;&amp;lt; "$1"; }
&lt;/pre&gt;
&lt;p&gt;Then I can do this in the shell:&lt;/p&gt;
&lt;pre &gt;
$ urlescape "http://www.catonmat.net"
http%3A%2F%2Fwww.catonmat.net

$ urlunescape http%3A%2F%2Fwww.catonmat.net
http://www.catonmat.net
&lt;/pre&gt;
&lt;p&gt;Very useful!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example 4: Print all lines from line 17 to line 30&lt;/strong&gt;&lt;/p&gt;
&lt;pre &gt;
perl -ne 'print if 17..30'
&lt;/pre&gt;
&lt;p&gt;Here we use the binary flip-flop operator &lt;code&gt;..&lt;/code&gt; that becomes true when the input line number is 17, stays true while the line number is less than or equal to 30, and then becomes false. Combining the flip-flop operator with &lt;code&gt;print if&lt;/code&gt; makes it print only lines 17-30.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example 5: Remove all consecutive blank lines, leaving just one&lt;/strong&gt;&lt;/p&gt;
&lt;pre &gt;
perl -00pe0
&lt;/pre&gt;
&lt;p&gt;I included this one-liner here in the examples just to show you how funny and obscure one-liners can get. This one-liner deletes all repeated blank lines from the input or from the given file. It does it by enabling the paragraph slurp mode through &lt;code&gt;-00&lt;/code&gt; command line argument, which reads the input paragraph-by-paragraph, rather than line-by-line, and prints the paragraphs. This way any number of blank lines between the paragraphs get ignored.&lt;/p&gt;
&lt;p&gt;I explain this one-liner in more details in the e-book.&lt;/p&gt;
&lt;p&gt;As I hope you can see, knowing how to write one-liners is very useful. It was one of my top priority tasks through the years to become very efficient in the shell. Literally every day when I'm programming, I have to do all kinds of data processing tasks, changing files, verifying output, doing quick calculations, parsing data, etc, and knowing Perl one-liners makes it really fast to get things done.&lt;/p&gt;
&lt;p&gt;Now that I have written this e-book, you can become very efficient, too. Enjoy!&lt;/p&gt;
&lt;h2&gt;Book Preview&lt;/h2&gt;
&lt;p&gt;I prepared a free book preview that contains the first 13 pages of the book. It includes the table of contents, preface, introduction to Perl one-liners and the first page of the second chapter.&lt;/p&gt;
&lt;div class="c" style="padding-top: 1em; padding-bottom: 1em;"&gt;&lt;p&gt;&lt;big&gt;&lt;a href="http://www.catonmat.net/download/perlbook-preview.pdf"&gt;Perl One-Liners Explained. Book Preview.&lt;/a&gt;&lt;/big&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;Buy it now!&lt;/h2&gt;
&lt;p&gt;The price of the e-book is &lt;strong&gt;$9.95&lt;/strong&gt; and it can be &lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=2HMCK3EJRM6MC"&gt;purchased via PayPal&lt;/a&gt;:&lt;/p&gt;
&lt;div class="c" style="padding-top: 1em; padding-bottom: 1em;"&gt;&lt;p&gt;&lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=2HMCK3EJRM6MC" class="nohover"&gt;&lt;img src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"&gt;&lt;/a&gt;&lt;br&gt;
&lt;img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1"&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;After you have made the payment, my automated e-book processing system will send you the PDF e-book in a few minutes!&lt;/p&gt;
&lt;h2&gt;Tweet about my book!&lt;/h2&gt;
&lt;p&gt;Help me spread the word about my new book! I prepared a special link that you can use to tweet about it:&lt;/p&gt;
&lt;div class="c" style="padding-top: 1em"&gt;&lt;p&gt;&lt;a href="http://bit.ly/perlebook" class="nohover"&gt;&lt;img src="http://www.catonmat.net/images/tweet-my-book.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;What's next?&lt;/h2&gt;
&lt;p&gt;I really love writing about programming and I have planned writing many more books. The next few are going to be a book on mastering vim, a practical guide on how to be anonymous on the web, and the catonmat book.&lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;Enjoy the book and don't forget to leave comments about it! Ask me anything you wish and I'll help you out.&lt;/p&gt;
&lt;p&gt;Also if you're interested, take a look at my other two e-books. The 1st one is called "&lt;a href="http://www.catonmat.net/blog/awk-book/"&gt;Awk One-Liners Explained&lt;/a&gt;" and the 2nd one is called "&lt;a href="http://www.catonmat.net/blog/sed-book/"&gt;Sed One-Liners Explained&lt;/a&gt;" They're written in a similar style as this e-book and they teach practical Awk and Sed through many examples.&lt;/p&gt;
&lt;p&gt;Finally, if you enjoy my writing, you can &lt;a href="http://www.catonmat.net/feed/"&gt;subscribe to my blog&lt;/a&gt;, &lt;a href="http://twitter.com/pkrumins"&gt;follow me on Twitter&lt;/a&gt; or &lt;strong&gt;&lt;a href="http://google.com/profiles/peteris.krumins"&gt;&lt;span style="color: blue"&gt;G&lt;/span&gt;&lt;span style="color: red"&gt;o&lt;/span&gt;&lt;span style="color: #EE9A00"&gt;o&lt;/span&gt;&lt;span style="color: blue"&gt;g&lt;/span&gt;&lt;span style="color: green"&gt;l&lt;/span&gt;&lt;span style="color: red"&gt;e&lt;/span&gt;&lt;span style="color: gray"&gt;+&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=27oRonhWXEU:37g9ZCZSaa0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=27oRonhWXEU:37g9ZCZSaa0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=27oRonhWXEU:37g9ZCZSaa0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=27oRonhWXEU:37g9ZCZSaa0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=27oRonhWXEU:37g9ZCZSaa0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=27oRonhWXEU:37g9ZCZSaa0:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=27oRonhWXEU:37g9ZCZSaa0:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/27oRonhWXEU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/perl-book</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">How Browserling Works [art]</title>
    <id>308</id>
    <updated>2012-01-29T23:19:54Z</updated>
    <published>2012-01-29T23:20:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/YZLYyk1MXQc/how-browserling-works" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3v0XinExttP68iNtD_SBSanVu_o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3v0XinExttP68iNtD_SBSanVu_o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3v0XinExttP68iNtD_SBSanVu_o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3v0XinExttP68iNtD_SBSanVu_o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/how-browserling-works.png"&gt;&lt;br&gt;
&lt;small&gt;Art by &lt;a href="http://substack.net"&gt;James Halliday&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;1. We run the browsers on our servers.&lt;br&gt;
2. You use the browsers from the graphical web console.&lt;br&gt;
3. If the servers are full, you wait in the queue.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.browserling.com"&gt;Try Browserling!&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=YZLYyk1MXQc:-V-vfW6jKWE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=YZLYyk1MXQc:-V-vfW6jKWE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=YZLYyk1MXQc:-V-vfW6jKWE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=YZLYyk1MXQc:-V-vfW6jKWE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=YZLYyk1MXQc:-V-vfW6jKWE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=YZLYyk1MXQc:-V-vfW6jKWE:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=YZLYyk1MXQc:-V-vfW6jKWE:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/YZLYyk1MXQc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/how-browserling-works</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: procstreams</title>
    <id>305</id>
    <updated>2012-01-24T17:49:17Z</updated>
    <published>2012-01-24T16:20:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/VpZVHQUt9tw/nodejs-modules-procstreams" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vYG9f7yjoOf0VtC2zHxqKA9JKrA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vYG9f7yjoOf0VtC2zHxqKA9JKrA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vYG9f7yjoOf0VtC2zHxqKA9JKrA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vYG9f7yjoOf0VtC2zHxqKA9JKrA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the 15th post in the &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node, the eighth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-socketio/"&gt;socket.io&lt;/a&gt; that makes websockets and realtime possible in all browsers, the ninth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-redis/"&gt;redis&lt;/a&gt; - the best redis client API library for node, the tenth was on &lt;a href="http://www.catonmat.net/blog/nodejs-modules-express/"&gt;express&lt;/a&gt; - an insanely small and fast web framework for node, the eleventh was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-semver/"&gt;semver&lt;/a&gt; - a node module that takes care of versioning, the twelfth was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-cradle/"&gt;cradle&lt;/a&gt; - a high-level, caching, CouchDB client for node, the thirteenth was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-jsonstream/"&gt;jsonstream&lt;/a&gt; - streaming JSON parsing library, the fourteenth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-everyauth/"&gt;everyauth&lt;/a&gt; - a module for authenticating your webapp with facebook, twitter, etc.&lt;/p&gt;
&lt;p&gt;Today I'm gonna introduce you to &lt;a href="https://github.com/polotek/procstreams"&gt;procstreams&lt;/a&gt; by &lt;a href="http://marcorogers.com/blog/"&gt;Marco Rogers&lt;/a&gt; aka &lt;a href="https://twitter.com/#!/polotek"&gt;polotek&lt;/a&gt;. Procstreams is a little experiment with shell scripting in node. Here is an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;$p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;procstreams&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;$p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cat lines.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;wc -l&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// prints number of lines in the file lines.txt&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This example executes the shell command &lt;code&gt;cat lines.txt&lt;/code&gt;, then pipes the output to &lt;code&gt;wc -l&lt;/code&gt;, and then collects the output through a callback that prints the number of lines in &lt;code&gt;lines.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Here is another example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;$p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;procstreams&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;$p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mkdir foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cp file.txt foo/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;rm file.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;exit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;done&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This example executes &lt;code&gt;mkdir foo&lt;/code&gt;, and if that succeeds, it executes &lt;code&gt;cp file.txt foo/&lt;/code&gt;, and if that succeeds, it executes &lt;code&gt;rm file.txt&lt;/code&gt;. In shells scripting you'd write this as:&lt;/p&gt;
&lt;pre &gt;
mkdir foo &amp;&amp; cp file.txt foo/ &amp;&amp; rm file.txt
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;.and(...)&lt;/code&gt; is the same as &lt;code&gt;&amp;&amp;&lt;/code&gt; in the shell scripting.&lt;/p&gt;
&lt;p&gt;Procstreams also support &lt;code&gt;.or(...)&lt;/code&gt;, which is &lt;code&gt;||&lt;/code&gt; in the shell and &lt;code&gt;.then(...)&lt;/code&gt;, which is &lt;code&gt;;&lt;/code&gt; in the shell.&lt;/p&gt;
&lt;p&gt;Here is an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;$p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;procstreams&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;$p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mkdir foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cp file.txt file2.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;echo &amp;quot;failed&amp;quot; &amp;gt; ~/notify&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This example &lt;code&gt;mkdirs foo&lt;/code&gt;, then copies file.txt to file2.txt, if that fails, it echos "failed" to &lt;code&gt;~/notify&lt;/code&gt;. Shell equivalent:&lt;/p&gt;
&lt;pre &gt;
mkdir foo; cp file.txt file2.txt || echo "failed" &gt; ~/notify
&lt;/pre&gt;
&lt;p&gt;See &lt;a href="https://github.com/polotek/procstreams"&gt;procstreams documentation&lt;/a&gt; on GitHub for full info on other thingies it supports.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;procstreams&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install procstreams
&lt;/pre&gt;
&lt;p&gt;Procstreams on GitHub: &lt;a href="https://github.com/polotek/procstreams"&gt;https://github.com/polotek/procstreams&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=VpZVHQUt9tw:B8DYaijzyfc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=VpZVHQUt9tw:B8DYaijzyfc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=VpZVHQUt9tw:B8DYaijzyfc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=VpZVHQUt9tw:B8DYaijzyfc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=VpZVHQUt9tw:B8DYaijzyfc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=VpZVHQUt9tw:B8DYaijzyfc:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=VpZVHQUt9tw:B8DYaijzyfc:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/VpZVHQUt9tw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-procstreams</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Browserling has a new design!</title>
    <id>302</id>
    <updated>2012-01-16T18:51:51Z</updated>
    <published>2012-01-16T18:50:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/t5nha2qE-aQ/new-browserling-design" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/22ghEXryR95X6YMVGQKFgTOIgR0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/22ghEXryR95X6YMVGQKFgTOIgR0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/22ghEXryR95X6YMVGQKFgTOIgR0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/22ghEXryR95X6YMVGQKFgTOIgR0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Awesome news everyone! We launched new design for &lt;a href="http://www.browserling.com"&gt;Browserling&lt;/a&gt;! We also switched to &lt;a href="http://www.catonmat.net/blog/stripe-payments-with-node/"&gt;Stripe&lt;/a&gt; for accepting payments and also added a bunch more browsers!&lt;/p&gt;
&lt;p&gt;The new design is much cleaner, and everything is driven through ajax calls, we don't even use HTML templates anymore!&lt;/p&gt;
&lt;p&gt;Here is a screenshot of Browserling with the new design:&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/browserling-new-design.jpg"&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="http://www.browserling.com"&gt;Browserling&lt;/a&gt; is interactive cross-browser testing tool that allows you to see what your webpage looks like in Internet Explorer, Firefox, Chrome, Opera, and Safari.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=t5nha2qE-aQ:h5Hesn8cpQg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=t5nha2qE-aQ:h5Hesn8cpQg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=t5nha2qE-aQ:h5Hesn8cpQg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=t5nha2qE-aQ:h5Hesn8cpQg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=t5nha2qE-aQ:h5Hesn8cpQg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=t5nha2qE-aQ:h5Hesn8cpQg:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=t5nha2qE-aQ:h5Hesn8cpQg:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/t5nha2qE-aQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/new-browserling-design</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: everyauth</title>
    <id>301</id>
    <updated>2012-01-03T18:34:38Z</updated>
    <published>2012-01-03T17:25:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/Lo25io4y6dg/nodejs-modules-everyauth" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kBYejLhzynBVrHsfSsjpJApHrBY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kBYejLhzynBVrHsfSsjpJApHrBY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kBYejLhzynBVrHsfSsjpJApHrBY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kBYejLhzynBVrHsfSsjpJApHrBY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the 14th post in the &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node, the eighth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-socketio/"&gt;socket.io&lt;/a&gt; that makes websockets and realtime possible in all browsers, the ninth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-redis/"&gt;redis&lt;/a&gt; - the best redis client API library for node, the tenth was on &lt;a href="http://www.catonmat.net/blog/nodejs-modules-express/"&gt;express&lt;/a&gt; - an insanely small and fast web framework for node, the eleventh was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-semver/"&gt;semver&lt;/a&gt; - a node module that takes care of versioning, the twelfth was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-cradle/"&gt;cradle&lt;/a&gt; - a high-level, caching, CouchDB client for node, the thirteenth was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-jsonstream/"&gt;jsonstream&lt;/a&gt; - streaming JSON parsing library.&lt;/p&gt;
&lt;p&gt;Today I'm gonna introduce you to &lt;a href="https://github.com/bnoguchi/everyauth"&gt;everyauth&lt;/a&gt; by &lt;a href="https://github.com/bnoguchi"&gt;Brian Noguchi&lt;/a&gt;. Everyauth is a &lt;a href="http://senchalabs.github.com/connect/"&gt;connect&lt;/a&gt; middleware that allows you to setup authentication for your app via facebook, twitter, google, vimeo, tumblr, 4square, etc.&lt;/p&gt;
&lt;p&gt;Here is a list of all the sites you can use to login into your app:&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/everyauth.png"&gt;&lt;br&gt;
&lt;small&gt;Everyauth supports a plenty of sites.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Everyauth supports OpenID, Google, Twitter, LinkedIn, Yahoo, Readability, Dropbox, Justin.tv, Vimeo, Tumblr, Facebook, Github, Instagram, Foursquare, Gowalla, 37signals, AngelList, Dwolla, Box.net.&lt;/p&gt;
&lt;p&gt;Using it is as simple as setting up a middleware for connect:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;everyauth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;everyauth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;connect&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;everyauth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And setting up &lt;code&gt;config.json&lt;/code&gt; that contains secret keys from the sites you are going to be using for authentication:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fb&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;111565172259433&amp;#39;&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;appSecret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;85f7e0a0cc804886180b887c1f04a3c1&amp;#39;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;twit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;consumerKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;JLCGyLzuOK1BjnKPKGyQ&amp;#39;&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;consumerSecret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GNqKfPqtzOcsCtFbGTMqinoATHvBcy1nzCTimeA9M0&amp;#39;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;github&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;11932f2b6d05d2a5fa18&amp;#39;&lt;/span&gt;
      &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;appSecret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2603d1bc663b74d6732500c1e9ad05b0f4013593&amp;#39;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then you setup routes for logging in for each particular site you want to support (in this example facebook) and you're done:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./config.json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;usersByFbId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="nx"&gt;everyauth&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;facebook&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSecret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findOrCreateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;accessTokenExtra&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fbUserMetadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;usersByFbId&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fbUserMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usersByFbId&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fbUserMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;addUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;facebook&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fbUserMetadata&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redirectPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can install &lt;code&gt;everyauth&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install everyauth
&lt;/pre&gt;
&lt;p&gt;EveryAuth on GitHub: &lt;a href="https://github.com/bnoguchi/everyauth"&gt;https://github.com/bnoguchi/everyauth&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Lo25io4y6dg:McqshYeKZL8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Lo25io4y6dg:McqshYeKZL8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=Lo25io4y6dg:McqshYeKZL8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Lo25io4y6dg:McqshYeKZL8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=Lo25io4y6dg:McqshYeKZL8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Lo25io4y6dg:McqshYeKZL8:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Lo25io4y6dg:McqshYeKZL8:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/Lo25io4y6dg" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-everyauth</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">How to setup Stripe payments with node.js</title>
    <id>300</id>
    <updated>2011-12-31T12:17:18Z</updated>
    <published>2011-12-29T14:55:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/1an8KBau4ZA/stripe-payments-with-node" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6vAdMX56iPE0eGlMi1lXFsLSKg0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6vAdMX56iPE0eGlMi1lXFsLSKg0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6vAdMX56iPE0eGlMi1lXFsLSKg0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6vAdMX56iPE0eGlMi1lXFsLSKg0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This is going to be a super quick tutorial on how to accept payments with &lt;a href="https://stripe.com/"&gt;Stripe&lt;/a&gt; payment processor and node.js. At &lt;a href="http://www.catonmat.net/blog/how-i-raised-money-for-browserling/"&gt;Browserling&lt;/a&gt; we're moving to Stripe right this very moment so I thought I'd write this quick post. Stripe is the most incredible payment processor -  it took me like 30 minutes to figure everything out. Everything is well documented and works like a charm!&lt;/p&gt;
&lt;p&gt;First, you will need the &lt;a href="https://github.com/abh/node-stripe"&gt;node-stripe&lt;/a&gt; module. Install it through npm, as always:&lt;/p&gt;
&lt;pre &gt;
npm install stripe
&lt;/pre&gt;
&lt;p&gt;Next, you'll need to login into Stripe, and setup a plan:&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/stripe/new-stripe-plan.png"&gt;&lt;br&gt;
&lt;small&gt;Setting up a new Stripe plan.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Next, you'll need to find the test and live keys that are used in the payment code. They are located in Account Settings -&gt; API Keys.&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/stripe/stripe-api-keys.png"&gt;&lt;br&gt;
&lt;small&gt;Stripe keys are located in Account Settings -&gt; API keys.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Next, you'll need to include Stripe's JavaScript library in your HTML code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://js.stripe.com/v1/&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, you'll need to setup an HTML form with card name, cvc, expiration date, amount (&lt;strong&gt;in cents!&lt;/strong&gt;). You don't need to ask the name or address, that stuff is old school:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stripe-form&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/plans/browserling_developer&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;payment-form&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;form-row&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cc-text&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card Number&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;30&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;off&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;card-number&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;form-row&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cc-text&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;CVC&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;off&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;card-cvc&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;form-row&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cc-text&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Expiration (MM/YYYY)&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;card-expiry-month&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; / &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;card-expiry-year&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;amount&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2000&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cc-amount&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;submit-button&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit Payment&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;error&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;success&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Thanks for signing up at Browserling!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, you'll need to generate a token when the form gets submitted, and submit it to your node.js application, instead of submitting credit card number and other info:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;publicStripeApiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;publicStripeApiKeyTesting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setPublishableKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicStripeApiKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;stripeResponseHandler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slideDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#stripe-form .submit-button&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;removeAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;#payment-form&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;input type=&amp;#39;hidden&amp;#39; name=&amp;#39;stripeToken&amp;#39; value=&amp;#39;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;#39;/&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;action&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slideDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#success&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slideDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.submit-button&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;removeAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// http://stripe.com/docs/tutorials/forms&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;#payment-form&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// disable the submit button to prevent repeated clicks&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.submit-button&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;disabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#cc-amount&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// amount you want to charge in cents&lt;/span&gt;
  &lt;span class="nx"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createToken&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.card-number&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;cvc&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.card-cvc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;exp_month&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.card-expiry-month&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;exp_year&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.card-expiry-year&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stripeResponseHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// prevent the form from submitting with the default action&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, you need to setup a route handler in node.js web server for all your plan names. In this tutorial I'll handle just &lt;code&gt;browserling_developer&lt;/code&gt; plan:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;stripeApiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;stripeApiKeyTesting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;...&amp;quot;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stripe&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;stripeApiKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bodyDecoder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/plans/browserling_developer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stripeToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// customer&amp;#39;s email (get it from db or session)&lt;/span&gt;
    &lt;span class="nx"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;browserling_developer&amp;quot;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;unknown&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Error while processing your payment: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Success! Customer with Stripe ID &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; just signed up!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// save this customer to your database here!&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That's it! This simple node.js code handles POST requests to &lt;code&gt;/plans/browserling_developer&lt;/code&gt;, and creates a new customer at Stripe. Notice that it uses &lt;code&gt;req.body.stripeToken&lt;/code&gt; and doesn't even touch credit card info.&lt;/p&gt;
&lt;p&gt;I have never worked with a payment processor which was easier to setup. It's a pure pleasure to use Stripe!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=1an8KBau4ZA:7kUnVZf2AhM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=1an8KBau4ZA:7kUnVZf2AhM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=1an8KBau4ZA:7kUnVZf2AhM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=1an8KBau4ZA:7kUnVZf2AhM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=1an8KBau4ZA:7kUnVZf2AhM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=1an8KBau4ZA:7kUnVZf2AhM:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=1an8KBau4ZA:7kUnVZf2AhM:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/1an8KBau4ZA" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/stripe-payments-with-node</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">A Perl Regular Expression That Matches Prime Numbers</title>
    <id>298</id>
    <updated>2011-12-26T16:23:24Z</updated>
    <published>2011-12-25T20:00:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/FNJjWQWu3lo/perl-regex-that-matches-prime-numbers" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aeu2V6F_xZKmpKQHftYmXE5gXaM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aeu2V6F_xZKmpKQHftYmXE5gXaM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aeu2V6F_xZKmpKQHftYmXE5gXaM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aeu2V6F_xZKmpKQHftYmXE5gXaM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;pre &gt;
perl -lne '(1x$_) =~ /^1?$|^(11+?)\1+$/ || print "$_ is prime"'
&lt;/pre&gt;
&lt;p&gt;Can you figure out how it works? I give an explanation below, but try to figure it out yourself. Here is what happens when you run it:&lt;/p&gt;
&lt;pre &gt;
$ perl -lne '(1x$_) =~ /^1?$|^(11+?)\1+$/ || print "$_ is prime"'
1
2
2 is prime
3
3 is prime
4
5
5 is prime
6
7
7 is prime
8
9
10
11
11 is prime
&lt;/pre&gt;
&lt;p&gt;Here is how it works.&lt;/p&gt;
&lt;p&gt;First, the number is converted in its unary representation by &lt;code&gt;(1x$_)&lt;/code&gt;. For example, the number &lt;code&gt;5&lt;/code&gt; gets converted into &lt;code&gt;1x5&lt;/code&gt;, which is &lt;code&gt;11111&lt;/code&gt; (&lt;code&gt;1&lt;/code&gt; repeated &lt;code&gt;5&lt;/code&gt; times.)&lt;/p&gt;
&lt;p&gt;Next, the unary string gets tested against the regular expression. If it matches, the number is a composite, otherwise it's a prime.&lt;/p&gt;
&lt;p&gt;The regular expression works this way. It consists of two parts &lt;code&gt;^1?$&lt;/code&gt; and &lt;code&gt;^(11+?)\1+$&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The first part matches number &lt;code&gt;1&lt;/code&gt; and the empty string. Clearly, the empty string and number &lt;code&gt;1&lt;/code&gt; are not prime numbers, therefore this regular expression matches, which indicates that they are not prime numbers.&lt;/p&gt;
&lt;p&gt;The second part determines if two or more &lt;code&gt;1&lt;/code&gt;s repeatedly make up the whole number. If two or more &lt;code&gt;1&lt;/code&gt;s repeatedly make up the whole number, the regex matches, which means that the number is composite. Otherwise it's a prime.&lt;/p&gt;
&lt;p&gt;Let's look at the second regex part on numbers &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The number &lt;code&gt;5&lt;/code&gt; in unary representation is &lt;code&gt;11111&lt;/code&gt;. The &lt;code&gt;(11+?)&lt;/code&gt; matches the first two ones &lt;code&gt;11&lt;/code&gt;. The back-reference &lt;code&gt;\1&lt;/code&gt; becomes &lt;code&gt;11&lt;/code&gt; and the whole regex now becomes &lt;code&gt;^11(11)+$&lt;/code&gt;. It can't match five ones, therefore it fails. But since it used &lt;code&gt;+?&lt;/code&gt;, it backtracks and matches the first three ones &lt;code&gt;111&lt;/code&gt;. The back-reference becomes &lt;code&gt;111&lt;/code&gt; and the whole regex becomes &lt;code&gt;^111(111)+$&lt;/code&gt;. It doesn't match again. This repeats for &lt;code&gt;1111&lt;/code&gt; and &lt;code&gt;11111&lt;/code&gt;, which also don't match, therefore the whole regex doesn't match and the number is a prime.&lt;/p&gt;
&lt;p&gt;The number &lt;code&gt;4&lt;/code&gt; in unary representation is &lt;code&gt;1111&lt;/code&gt;. The &lt;code&gt;(11+?)&lt;/code&gt; matches the first two ones &lt;code&gt;11&lt;/code&gt;. The back-reference &lt;code&gt;\1&lt;/code&gt; becomes &lt;code&gt;11&lt;/code&gt; and the regex becomes &lt;code&gt;^11(11)+$&lt;/code&gt;. It matches the original string, therefore the number is not a prime.&lt;/p&gt;
&lt;p&gt;PS. I didn't invent this regular expression, it was invented in 1998 by &lt;a href="http://www.abigail.be/"&gt;Abigail&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Don't take this regular expression too seriously, it's actually neither a regular expression (as defined in automata theory), nor a way to check if a number is a prime. It's just an awesome thing that Perl can do. See this cool article called &lt;a href="http://zmievski.org/2010/08/the-prime-that-wasnt"&gt;The Prime That Wasn't&lt;/a&gt; by Andrei Zmievski for a discussion about how this regex fails for larger numbers because of backtracking.&lt;/p&gt;
&lt;p&gt;Also if you wish to learn more about Perl one-liners, check out my &lt;a href="http://www.catonmat.net/blog/perl-one-liners-explained-part-one/"&gt;Perl One-Liners Explained&lt;/a&gt; article series and download the &lt;a href="http://www.catonmat.net/download/perl1line.txt"&gt;perl1line.txt&lt;/a&gt; file.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=FNJjWQWu3lo:JfP9SbL7Hbg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=FNJjWQWu3lo:JfP9SbL7Hbg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=FNJjWQWu3lo:JfP9SbL7Hbg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=FNJjWQWu3lo:JfP9SbL7Hbg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=FNJjWQWu3lo:JfP9SbL7Hbg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=FNJjWQWu3lo:JfP9SbL7Hbg:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=FNJjWQWu3lo:JfP9SbL7Hbg:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/FNJjWQWu3lo" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/perl-regex-that-matches-prime-numbers</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: jsonstream</title>
    <id>285</id>
    <updated>2012-01-03T18:42:47Z</updated>
    <published>2011-12-22T14:00:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/X7r_RjoOs6M/nodejs-modules-jsonstream" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JpxsD4oLFsAA3BbtqlbMV--vSos/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JpxsD4oLFsAA3BbtqlbMV--vSos/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JpxsD4oLFsAA3BbtqlbMV--vSos/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JpxsD4oLFsAA3BbtqlbMV--vSos/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the thirteenth post in the &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node, the eighth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-socketio/"&gt;socket.io&lt;/a&gt; that makes websockets and realtime possible in all browsers, the ninth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-redis/"&gt;redis&lt;/a&gt; - the best redis client API library for node, the tenth was on &lt;a href="http://www.catonmat.net/blog/nodejs-modules-express/"&gt;express&lt;/a&gt; - an insanely small and fast web framework for node, the eleventh was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-semver/"&gt;semver&lt;/a&gt; - a node module that takes care of versioning, the twelfth was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-cradle/"&gt;cradle&lt;/a&gt; - a high-level, caching, CouchDB client for node.&lt;/p&gt;
&lt;p&gt;This time I'll introduce you to a very awesome module called &lt;a href="https://github.com/dominictarr/JSONStream"&gt;JSONStream&lt;/a&gt;. JSONStream is written by &lt;a href="https://github.com/dominictarr"&gt;Dominic Tarr&lt;/a&gt; and it parses streaming JSON.&lt;/p&gt;
&lt;p&gt;Here is an example. Suppose you have couchdb view like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;total_rows&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;129&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;offset&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;rows&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;change1_0.6995461115147918&amp;quot;&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;key&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;change1_0.6995461115147918&amp;quot;&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;rev&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1-e240bae28c7bb3667f02760f6398d508&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;doc&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s2"&gt;&amp;quot;change1_0.6995461115147918&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;_rev&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;1-e240bae28c7bb3667f02760f6398d508&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;change2_0.6995461115147918&amp;quot;&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;key&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;change2_0.6995461115147918&amp;quot;&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;rev&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1-13677d36b98c0c075145bb8975105153&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;doc&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;change2_0.6995461115147918&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;_rev&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1-13677d36b98c0c075145bb8975105153&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And you wish to only filter out &lt;code&gt;doc&lt;/code&gt; values from the &lt;code&gt;rows&lt;/code&gt;. You can do it easily with JSONStream this way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSONStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;rows&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/./&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;doc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This creates a &lt;a href="http://nodejs.org/docs/latest/api/all.html#streams"&gt;stream&lt;/a&gt; that parses out &lt;code&gt;rows.*.doc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since it's a stream you have to feed it data and then have it output the data somewhere. You can do it very nicely and idiomatically in node this way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is the output:&lt;/p&gt;
&lt;pre &gt;
{
  _id: 'change1_0.6995461115147918',
  _rev: '1-e240bae28c7bb3667f02760f6398d508',
  hello: 1
}
{
  _id: 'change2_0.6995461115147918',
  _rev: '1-13677d36b98c0c075145bb8975105153',
  hello: 2
}
&lt;/pre&gt;
&lt;p&gt;Where &lt;code&gt;req&lt;/code&gt; is request to couchdb view and &lt;code&gt;parser&lt;/code&gt; is the JSONStream parser, and it all gets piped to process.stdout. The output, as you can see, is only the &lt;code&gt;rows.*.doc&lt;/code&gt;. That was a really easy way to parse a JSON stream without reading the whole JSON into memory.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;JSONStream&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install JSONStream
&lt;/pre&gt;
&lt;p&gt;JSONStream on GitHub: &lt;a href="https://github.com/dominictarr/JSONStream"&gt;https://github.com/dominictarr/JSONStream&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=X7r_RjoOs6M:6dgXlmfj3Lg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=X7r_RjoOs6M:6dgXlmfj3Lg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=X7r_RjoOs6M:6dgXlmfj3Lg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=X7r_RjoOs6M:6dgXlmfj3Lg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=X7r_RjoOs6M:6dgXlmfj3Lg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=X7r_RjoOs6M:6dgXlmfj3Lg:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=X7r_RjoOs6M:6dgXlmfj3Lg:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/X7r_RjoOs6M" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-jsonstream</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: cradle</title>
    <id>296</id>
    <updated>2012-01-03T18:44:50Z</updated>
    <published>2011-12-16T19:30:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/y_Fz0z0spTg/nodejs-modules-cradle" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nTtcfouruSpRCn-_TZdOWERqCk4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nTtcfouruSpRCn-_TZdOWERqCk4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nTtcfouruSpRCn-_TZdOWERqCk4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nTtcfouruSpRCn-_TZdOWERqCk4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the twelfth post in the &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node, the eighth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-socketio/"&gt;socket.io&lt;/a&gt; that makes websockets and realtime possible in all browsers, the ninth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-redis/"&gt;redis&lt;/a&gt; - the best redis client API library for node, the tenth was on &lt;a href="http://www.catonmat.net/blog/nodejs-modules-express/"&gt;express&lt;/a&gt; - an insanely small and fast web framework for node, the eleventh was &lt;a href="http://www.catonmat.net/blog/nodejs-modules-semver/"&gt;semver&lt;/a&gt; - a node module that takes care of versioning.&lt;/p&gt;
&lt;p&gt;Today I'll introduce you to cradle - a high-level, caching, CouchDB client for Node.js. Cradle is written by &lt;a href="http://cloudhead.io/"&gt;Alexis Sellier (cloudhead)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cradle is somewhat higher-level than most other CouchDB clients, requiring a little less knowledge of CouchDB's REST API. Cradle also has built-in write-through caching, giving you an extra level of speed, and making document updates and deletion easier. Cradle was built from the love of CouchDB and Node.js, and tries to make the most out of this wonderful marriage of technologies.&lt;/p&gt;
&lt;p&gt;Here is an example of how simple it's to use cradle:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;cradle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cradle&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cradle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)().&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;starwars&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;vader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;#39;Darth Vader&amp;#39;&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;force&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;skywalker&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;force&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Luke Skywalker&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle success&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Cradle supports all the operations that you'd expect an API for CouchDB to support like creating a database:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;starwars&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Checking if a db exists:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;the force is with you.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;database does not exists.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="cm"&gt;/* populate design documents */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Destroying a db:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Fetching a document:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;vader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Querying a view:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;characters/all&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; is on the &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;force&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; side of the force.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Creating and updating documents:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;vader&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;darth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;force&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle response&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Creating views:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_design/characters&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;darkside&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;force&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Deleting documents:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;luke&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1-94B6F82&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle response&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And it also supports streaming, changes api, and many other things. See the &lt;a href="https://github.com/cloudhead/cradle"&gt;cradle documentation&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;cradle&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install cradle
&lt;/pre&gt;
&lt;p&gt;Cradle on GitHub: &lt;a href="https://github.com/cloudhead/cradle"&gt;https://github.com/cloudhead/cradle&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=y_Fz0z0spTg:5-yBYuNY1Sc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=y_Fz0z0spTg:5-yBYuNY1Sc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=y_Fz0z0spTg:5-yBYuNY1Sc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=y_Fz0z0spTg:5-yBYuNY1Sc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=y_Fz0z0spTg:5-yBYuNY1Sc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=y_Fz0z0spTg:5-yBYuNY1Sc:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=y_Fz0z0spTg:5-yBYuNY1Sc:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/y_Fz0z0spTg" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-cradle</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: semver</title>
    <id>295</id>
    <updated>2012-01-03T18:44:41Z</updated>
    <published>2011-12-15T17:20:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/zDpy_2w5yUQ/nodejs-modules-semver" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MzQgIQZud3f2GNpn6EDhJVWM08M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MzQgIQZud3f2GNpn6EDhJVWM08M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MzQgIQZud3f2GNpn6EDhJVWM08M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MzQgIQZud3f2GNpn6EDhJVWM08M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the eleventh post in the &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node, the eighth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-socketio/"&gt;socket.io&lt;/a&gt; that makes websockets and realtime possible in all browsers, the ninth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-redis/"&gt;redis&lt;/a&gt; - the best redis client API library for node, the tenth was on &lt;a href="http://www.catonmat.net/blog/nodejs-modules-express/"&gt;express&lt;/a&gt; - an insanely small and fast web framework for node.&lt;/p&gt;
&lt;p&gt;Today I'll introduce you to a module called &lt;a href="https://github.com/isaacs/node-semver"&gt;semver&lt;/a&gt;. Semver is the semantic versioner. Semver is written by &lt;a href="http://blog.izs.me"&gt;Isaac Z. Schlueter&lt;/a&gt;, the author of &lt;a href="http://npmjs.org/"&gt;npm&lt;/a&gt;. Semver is used in npm to handle all the node.js module versioning problems.&lt;/p&gt;
&lt;p&gt;Here is an example of what it does:&lt;/p&gt;
&lt;pre &gt;
semver.valid('1.2.3') // true
semver.valid('a.b.c') // false
semver.clean('  =v1.2.3   ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || &gt;=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7')  // false
semver.lt('1.2.3', '9.8.7')  // true
&lt;/pre&gt;
&lt;p&gt;The ordering of versions is done using the following algorithm - given two versions and asked to find the greater of the two:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;If the majors are numerically different, then take the one with a bigger major number. For example, 2.3.4 &gt; 1.3.4.&lt;/li&gt;
&lt;li&gt;If the minors are numerically different, then take the one with the bigger minor number. For example, 2.3.4 &gt; 2.2.4.&lt;/li&gt;
&lt;li&gt;If the patches are numerically different, then take the one with the bigger patch number. For example, 2.3.4 &gt; 2.3.3.&lt;/li&gt;
&lt;li&gt;If only one of them has a build number, then take the one with the build number. For example, 2.3.4-0 &gt; 2.3.4.&lt;/li&gt;
&lt;li&gt;If they both have build numbers, and the build numbers are numerically different, then take the one with the bigger build number. For example, 2.3.4-10 &gt; 2.3.4-9.&lt;/li&gt;
&lt;li&gt;If only one of them has a tag, then take the one without the tag. For example, 2.3.4 &gt; 2.3.4-beta.&lt;/li&gt;
&lt;li&gt;If they both have tags, then take the one with the lexicographically larger tag. For example, 2.3.4-beta &gt; 2.3.4-alpha.&lt;/li&gt;
&lt;li&gt;At this point, they're equal.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Semver supports the following ranges and styles:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;&gt;1.2.3&lt;/code&gt; means greater than a specific version.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;1.2.3&lt;/code&gt; means less than a specific version.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1.2.3 - 2.3.4&lt;/code&gt; means &lt;code&gt;&gt;=1.2.3 &amp;lt;=2.3.4&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~1.2.3&lt;/code&gt; means &lt;code&gt;&gt;=1.2.3 &amp;lt;1.3.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~1.2&lt;/code&gt; means &lt;code&gt;&gt;=1.2.0 &amp;lt;2.0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~1&lt;/code&gt; means &lt;code&gt;&gt;=1.0.0 &amp;lt;2.0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1.2.x&lt;/code&gt; means &lt;code&gt;&gt;=1.2.0 &amp;lt;1.3.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1.x&lt;/code&gt; means &lt;code&gt;&gt;=1.0.0 &amp;lt;2.0.0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ranges can be joined with either a space (which implies "and") or a &lt;code&gt;||&lt;/code&gt; (which implies "or").&lt;/p&gt;
&lt;p&gt;Semver supports the following functions:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;valid(v)&lt;/code&gt; - return the parsed version, or null if it's not valid.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inc(v, release)&lt;/code&gt; - return the version incremented by the release type (major, minor, patch, or build), or null if it's not valid.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Semver supports the following comparisons:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;gt(v1, v2)&lt;/code&gt; - &lt;code&gt;v1 &gt; v2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gte(v1, v2)&lt;/code&gt; - &lt;code&gt;v1 &gt;= v2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lt(v1, v2)&lt;/code&gt; - &lt;code&gt;v1 &amp;lt; v2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lte(v1, v2)&lt;/code&gt; - &lt;code&gt;v1 &amp;lt;= v2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eq(v1, v2)&lt;/code&gt; - &lt;code&gt;v1 == v2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;neq(v1, v2)&lt;/code&gt; - &lt;code&gt;v1 != v2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cmp(v1, comparator, v2)&lt;/code&gt; - pass in a comparison string, and it'll call the corresponding function above. "===" and "!==" do simple string comparison, but are included for completeness. Throws if an invalid comparison string is provided.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compare(v1, v2)&lt;/code&gt; - return 0 if v1 == v2, or 1 if v1 is greater, or -1 if v2 is greater. Sorts in ascending order if passed to Array.sort().&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rcompare(v1, v2)&lt;/code&gt; - the reverse of compare. Sorts an array of versions in descending order when passed to Array.sort().&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Semver supports the following range functions:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;code&gt;validRange(range)&lt;/code&gt; - Return the valid range or null if it's not valid. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;satisfies(version, range)&lt;/code&gt; - return true if the version satisfies the range.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;maxSatisfying(versions, range)&lt;/code&gt; - return the highest version in the list that satisfies the range, or null if none of them do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can install &lt;code&gt;semver&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install semver
&lt;/pre&gt;
&lt;p&gt;Semver on GitHub: &lt;a href="https://github.com/isaacs/node-semver"&gt;https://github.com/isaacs/node-semver&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=zDpy_2w5yUQ:UTJxAL_n2EE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=zDpy_2w5yUQ:UTJxAL_n2EE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=zDpy_2w5yUQ:UTJxAL_n2EE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=zDpy_2w5yUQ:UTJxAL_n2EE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=zDpy_2w5yUQ:UTJxAL_n2EE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=zDpy_2w5yUQ:UTJxAL_n2EE:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=zDpy_2w5yUQ:UTJxAL_n2EE:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/zDpy_2w5yUQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-semver</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: express</title>
    <id>294</id>
    <updated>2012-01-03T18:44:32Z</updated>
    <published>2011-12-14T19:10:30Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/kday0C0jhc4/nodejs-modules-express" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ImNmYKMrKY0pe8UQN1vvPj6Wkgk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ImNmYKMrKY0pe8UQN1vvPj6Wkgk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ImNmYKMrKY0pe8UQN1vvPj6Wkgk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ImNmYKMrKY0pe8UQN1vvPj6Wkgk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the tenth post in my new &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node, the eighth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-socketio/"&gt;socket.io&lt;/a&gt; that makes websockets and realtime possible in all browsers, the ninth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-redis/"&gt;redis&lt;/a&gt; - the best redis client API library for node.&lt;/p&gt;
&lt;p&gt;Today I'm going to introduce you to &lt;a href="http://expressjs.com/"&gt;express&lt;/a&gt; - an insanely fast and small server-side web development framework built on &lt;a href="https://github.com/senchalabs/connect"&gt;connect&lt;/a&gt;. Express is written by &lt;a href="http://tjholowaychuk.com/"&gt;TJ Holowaychuk&lt;/a&gt;. TJ has written 85 node.js modules so far so expect many more of his modules in this series!&lt;/p&gt;
&lt;p&gt;Check this out:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Hello World&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This creates a web server that listens on port 3000 and handles the requests to &lt;code&gt;/&lt;/code&gt;, returning &lt;code&gt;Hello World&lt;/code&gt; string as a response.&lt;/p&gt;
&lt;p&gt;Express has really powerful routing system. See this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/user/:id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This handles requests to &lt;code&gt;/user/foo&lt;/code&gt; and automatically sets &lt;code&gt;req.params.id&lt;/code&gt; to &lt;code&gt;foo&lt;/code&gt;. You can also use regular expressions to handle routes.&lt;/p&gt;
&lt;p&gt;If you want to handle POST requests, you have to make your app use &lt;code&gt;bodyParser&lt;/code&gt; middleware. That can be done through &lt;code&gt;app.use(express.bodyParser())&lt;/code&gt;. BodyParser basically parses the &lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt; and &lt;code&gt;application/json&lt;/code&gt; request bodies and sets up &lt;code&gt;req.body&lt;/code&gt; for you. For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This echos the body variables to console and sends back &lt;code&gt;ok&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are a bunch of different middlewares that you can use with express, such as:&lt;/p&gt;
&lt;pre &gt;
app.use(express.logger(...));
app.use(express.cookieParser(...));
app.use(express.session(...));
app.use(express.static(...));
app.use(express.errorHandler(...));
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;logger&lt;/code&gt; middleware handles logging of HTTP requests, &lt;code&gt;cookieParser&lt;/code&gt; handles cookies, &lt;code&gt;session&lt;/code&gt; handles HTTP sessions, &lt;code&gt;static&lt;/code&gt; for static content, such as images, css and scripts, and &lt;code&gt;errorHandler&lt;/code&gt; for handling exceptions and errors.&lt;/p&gt;
&lt;p&gt;See &lt;a href="http://expressjs.com/guide.html#middleware"&gt;the express documentation&lt;/a&gt; to learn more about middlewares.&lt;/p&gt;
&lt;p&gt;Express also integrates with various templating engines. For example, my favorite templating language is &lt;a href="http://jade-lang.com/"&gt;jade&lt;/a&gt; (also written by TJ) and here is how you'd render a jade template with express:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;index.jade&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;My Site&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Template filenames take the form &lt;code&gt;&amp;lt;name&gt;.&amp;lt;engine&gt;&lt;/code&gt;, where &lt;code&gt;&amp;lt;engine&gt;&lt;/code&gt; is the name of the module that will be required. For example the template &lt;code&gt;layout.ejs&lt;/code&gt; will tell express's view system to &lt;code&gt;require('ejs')&lt;/code&gt;. The module being loaded must export the method &lt;code&gt;exports.compile(str, options)&lt;/code&gt;, and return a &lt;code&gt;Function&lt;/code&gt; to comply with express.&lt;/p&gt;
&lt;p&gt;Express features:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Robust routing.&lt;/li&gt;
&lt;li&gt;Redirection helpers.&lt;/li&gt;
&lt;li&gt;Dynamic view helpers.&lt;/li&gt;
&lt;li&gt;Content negotiation.&lt;/li&gt;
&lt;li&gt;Focus on high performance.&lt;/li&gt;
&lt;li&gt;View rendering and partials support.&lt;/li&gt;
&lt;li&gt;Environment based configuration.&lt;/li&gt;
&lt;li&gt;Session based flash notifications.&lt;/li&gt;
&lt;li&gt;High test coverage.&lt;/li&gt;
&lt;li&gt;Executable for generating applications quickly.&lt;/li&gt;
&lt;li&gt;Application level view options.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As well as:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Session support.&lt;/li&gt;
&lt;li&gt;Cache API.&lt;/li&gt;
&lt;li&gt;Mime helpers.&lt;/li&gt;
&lt;li&gt;ETag support.&lt;/li&gt;
&lt;li&gt;Persistent flash notifications.&lt;/li&gt;
&lt;li&gt;Cookie support.&lt;/li&gt;
&lt;li&gt;JSON-RPC.&lt;/li&gt;
&lt;li&gt;Logging.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also see this screencast on express by TJ:&lt;/p&gt;
&lt;div class="c"&gt;&lt;iframe src="http://www.screenr.com/embed/mAL" width="600" height="396" frameborder="0"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;For more examples see the &lt;a href="https://github.com/visionmedia/express/tree/master/examples"&gt;examples&lt;/a&gt; directory in express source tree. Express also has &lt;a href="http://expressjs.com/guide.html"&gt;awesome documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;express&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install express
&lt;/pre&gt;
&lt;p&gt;Express on GitHub: &lt;a href="https://github.com/visionmedia/express"&gt;https://github.com/visionmedia/express&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kday0C0jhc4:kbEQ2HvCkqM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kday0C0jhc4:kbEQ2HvCkqM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=kday0C0jhc4:kbEQ2HvCkqM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kday0C0jhc4:kbEQ2HvCkqM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=kday0C0jhc4:kbEQ2HvCkqM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kday0C0jhc4:kbEQ2HvCkqM:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kday0C0jhc4:kbEQ2HvCkqM:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/kday0C0jhc4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-express</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: redis</title>
    <id>293</id>
    <updated>2012-01-03T18:44:23Z</updated>
    <published>2011-12-13T19:50:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/rokkoHXpr1Y/nodejs-modules-redis" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qUcmUpkjtEYpzsNNGPo9B74shrw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qUcmUpkjtEYpzsNNGPo9B74shrw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qUcmUpkjtEYpzsNNGPo9B74shrw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qUcmUpkjtEYpzsNNGPo9B74shrw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the ninth post in my new &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node, the eighth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-socketio/"&gt;socket.io&lt;/a&gt; that makes websockets and realtime possible in all browsers.&lt;/p&gt;
&lt;p&gt;Today I'm going to introduce you to &lt;a href="https://github.com/mranney/node_redis"&gt;node_redis&lt;/a&gt; - the best node.js Redis client API library. Redis node.js module is written by &lt;a href="http://ranney.com/"&gt;Matt Ranney&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This library is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from experimental Redis server branches.&lt;/p&gt;
&lt;p&gt;Here is an example of using redis library:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;redis&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Error &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;string key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;string val&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hash key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;hashtest 1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;some value&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hset&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hash key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;hashtest 2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;some other value&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hkeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hash key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; replies:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;    &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is the output when you run this example:&lt;/p&gt;
&lt;pre &gt;
mjr:~/work/node_redis (master)$ node example.js
Reply: OK
Reply: 0
Reply: 0
2 replies:
    0: hashtest 1
    1: hashtest 2
mjr:~/work/node_redis (master)$ 
&lt;/pre&gt;
&lt;p&gt;Each Redis command is exposed as a function on the &lt;code&gt;client&lt;/code&gt; object. All functions take either an &lt;code&gt;args&lt;/code&gt; Array plus optional &lt;code&gt;callback&lt;/code&gt; Function or a variable number of individual arguments followed by an optional callback.&lt;/p&gt;
&lt;p&gt;Here is an example of passing an array of arguments and a callback:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mset&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;key 1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;val 1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is that same call in the second style:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;key 1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;val 1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that in either form the callback is optional:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;some key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;some val&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;some other key&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;some val&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For a list of Redis commands, see &lt;a href="http://redis.io/commands"&gt;Redis Command Reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The commands can be specified in uppercase or lowercase for convenience - &lt;code&gt;client.get()&lt;/code&gt; is the same as &lt;code&gt;client.GET()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;redis&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install redis
&lt;/pre&gt;
&lt;p&gt;Redis on GitHub: &lt;a href="https://github.com/mranney/node_redis"&gt;https://github.com/mranney/node_redis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pietern"&gt;Pieter Noordhuis&lt;/a&gt; has written a binding to the official hiredis C library, which is non-blocking and fast. It's called &lt;a href="https://github.com/pietern/hiredis-node"&gt;hiredis-node&lt;/a&gt;. To use hiredis, do:&lt;/p&gt;
&lt;pre &gt;
npm install hiredis redis
&lt;/pre&gt;
&lt;p&gt;If hiredis is installed, node_redis will use it by default. Otherwise, a pure JavaScript parser will be used.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=rokkoHXpr1Y:_sr6YaQ9-Mc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=rokkoHXpr1Y:_sr6YaQ9-Mc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=rokkoHXpr1Y:_sr6YaQ9-Mc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=rokkoHXpr1Y:_sr6YaQ9-Mc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=rokkoHXpr1Y:_sr6YaQ9-Mc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=rokkoHXpr1Y:_sr6YaQ9-Mc:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=rokkoHXpr1Y:_sr6YaQ9-Mc:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/rokkoHXpr1Y" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-redis</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: socket.io</title>
    <id>292</id>
    <updated>2012-01-03T18:44:16Z</updated>
    <published>2011-12-12T20:15:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/EJTt1AJbDoY/nodejs-modules-socketio" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2nJLfp37fPueFk4TjfW_Z36z15E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2nJLfp37fPueFk4TjfW_Z36z15E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2nJLfp37fPueFk4TjfW_Z36z15E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2nJLfp37fPueFk4TjfW_Z36z15E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the eighth post in my new &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin, the seventh was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-ntwitter/"&gt;ntwitter&lt;/a&gt; - twitter api for node.&lt;/p&gt;
&lt;p&gt;This time I'll introduce you to &lt;a href="https://github.com/LearnBoost/socket.io"&gt;socket.io&lt;/a&gt;. I bet that most all of you already know socket.io, however I had several people message me to do an article on socket.io, so here it is.&lt;/p&gt;
&lt;p&gt;Socket.io makes websockets and realtime possible in all browsers. It also enhances websockets by providing built-in multiplexing, horizontal scalability, and automatic JSON encoding/decoding. Socket.io is written by &lt;a href="http://devthought.com/"&gt;Guillermo Rauch&lt;/a&gt;, who's the co-founder of &lt;a href="https://www.learnboost.com/"&gt;LearnBoost&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Socket.io always chooses the best realtime communication method possible. Here is the list of all the communication methods it supports:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;WebSocket&lt;/li&gt;
&lt;li&gt;Adobe® Flash® Socket&lt;/li&gt;
&lt;li&gt;AJAX long polling&lt;/li&gt;
&lt;li&gt;AJAX multipart streaming&lt;/li&gt;
&lt;li&gt;Forever Iframe&lt;/li&gt;
&lt;li&gt;JSONP Polling&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, if you're using Chrome, then socket.io will use websockets. If your browser doesn't support websockets, it will try to use flash sockets, then it will try long polling, etc.&lt;/p&gt;
&lt;p&gt;Now let's look at a very basic socket.io example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sockets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;connection&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;news&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;world&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my other event&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;disconnect&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user disconnected&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This example uses the awesome &lt;a href="http://expressjs.com/"&gt;express&lt;/a&gt; node web framework (I'll blog about it soon) to setup a web server on port 80, and attaches socket.io to it.&lt;/p&gt;
&lt;p&gt;Socket.io then listens for new connections and when a new connection from the browser is created, it emits &lt;code&gt;news&lt;/code&gt; event that sends the &lt;code&gt;{ hello: 'world' }&lt;/code&gt; hash back to the browser.&lt;/p&gt;
&lt;p&gt;It also setups a listener for &lt;code&gt;my other event&lt;/code&gt; and it listens for &lt;code&gt;disconnect&lt;/code&gt;s. When the web application emits this event, socket.io calls the &lt;code&gt;function (data) { console.log(data); }&lt;/code&gt; callback, that just prints the data to console. When the client disconnects, it logs this event to console also.&lt;/p&gt;
&lt;p&gt;Here is the client side (in the web browser):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/socket.io/socket.io.js&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;news&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my other event&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;First we include the &lt;code&gt;socket.io.js&lt;/code&gt; script, and then we create a socket.io connection to &lt;code&gt;http://localhost&lt;/code&gt;. Here socket.io chooses the best communication method that the browser supports. If it's Chrome then it will be websockets, then if you have flash, then it will try flash sockets, then long polling, then multipart streaming, then forever iframe method, and finally jsonp polling. Then we listen on &lt;code&gt;news&lt;/code&gt; event and when we receive it, we emit &lt;code&gt;my other event&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This way you can build all kinds of awesome realtime applications, such as &lt;a href="https://github.com/LearnBoost/socket.io/tree/master/examples/chat"&gt;web chat servers&lt;/a&gt; and &lt;a href="https://github.com/LearnBoost/socket.io/tree/master/examples/irc-output"&gt;web irc clients&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are many other features that socket.io supports, such as namespaces, volatile messages, message confirmations and message broadcasting. See &lt;a href="https://github.com/LearnBoost/socket.io"&gt;the documentation&lt;/a&gt; to learn all about this awesomeness!&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;socket.io&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install socket.io
&lt;/pre&gt;
&lt;p&gt;Socket.io on GitHub: &lt;a href="https://github.com/LearnBoost/socket.io"&gt;https://github.com/LearnBoost/socket.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also take a look at &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; that allows to call functions over socket.io!&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=EJTt1AJbDoY:9K_acHi3IVY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=EJTt1AJbDoY:9K_acHi3IVY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=EJTt1AJbDoY:9K_acHi3IVY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=EJTt1AJbDoY:9K_acHi3IVY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=EJTt1AJbDoY:9K_acHi3IVY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=EJTt1AJbDoY:9K_acHi3IVY:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=EJTt1AJbDoY:9K_acHi3IVY:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/EJTt1AJbDoY" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-socketio</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: ntwitter</title>
    <id>290</id>
    <updated>2012-01-03T18:44:08Z</updated>
    <published>2011-12-09T20:02:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/bUxIdXpbNuI/nodejs-modules-ntwitter" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/c48xUHgB7_gucdVdpYxaIQafn7g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c48xUHgB7_gucdVdpYxaIQafn7g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/c48xUHgB7_gucdVdpYxaIQafn7g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c48xUHgB7_gucdVdpYxaIQafn7g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the seventh post in my new &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library, the sixth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-read/"&gt;read&lt;/a&gt; - easy reading from stdin.&lt;/p&gt;
&lt;p&gt;This time I'll introduce you to &lt;a href="https://github.com/AvianFlu/ntwitter"&gt;ntwitter&lt;/a&gt; - asynchronous Twitter REST, streaming and searching client API. This module is maintained by &lt;a href="https://github.com/AvianFlu"&gt;Charlie McConnell, aka AvianFlu&lt;/a&gt;. Ntwitter was actually created by &lt;a href="https://github.com/technoweenie"&gt;technoweenie&lt;/a&gt;, but since then maintainers have changed several times.&lt;/p&gt;
&lt;p&gt;To use it, you'll need to get the API keys. That can easily be done at &lt;a href="http://dev.twitter.com"&gt;dev.twitter.com&lt;/a&gt;. Just register a new App, and you'll get the keys.&lt;/p&gt;
&lt;p&gt;Here is an example ntwitter app that tweets:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ntwitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Twitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;API&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;keys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;go here&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;twit&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verifyCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Error verifying credentials: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Test tweet from ntwitter/&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VERSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Tweeting failed: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Success!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is how to search through ntwitter API:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ntwitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Twitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;API&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;keys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;go here&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;twit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;nodejs OR #node&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Twitter search failed!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Search results:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can also use Twitter's streaming API:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ntwitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Twitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;API&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;keys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;go here&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;twit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;statuses/sample&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://dev.twitter.com/docs/streaming-api/methods"&gt;Here&lt;/a&gt; is a list of all the possible &lt;code&gt;statuses/*&lt;/code&gt; that you can stream from.&lt;/p&gt;
&lt;p&gt;Note how you don't need to login into twitter to do searching and streaming.&lt;/p&gt;
&lt;p&gt;You can stream someone's tweets this way:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ntwitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Twitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;API&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;keys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;go here&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;twit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;nodejs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle a disconnection&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;destroy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle a &amp;#39;silent&amp;#39; disconnection from Twitter, no end/error event fired&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, you can stream tweets from certain locations, defined by bounding boxes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ntwitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;twit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Twitter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;consumer_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;API&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;keys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;access_token_secret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;go here&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;twit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;statuses/filter&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;locations&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;-122.75,36.8,-121.75,37.8,-74,40,-73,41&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can use &lt;a href="http://twitter.com/#!/theCole"&gt;Cole Gillespie&lt;/a&gt;'s &lt;a href="https://github.com/coleGillespie/node-finden"&gt;node-finden&lt;/a&gt; module to get the geographical coordinates for bounding boxes. Here is how Cole's software looks:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/finden.jpg"&gt;&lt;/p&gt;
&lt;p&gt;That's it. Super easy way to do all things twitter with ntwitter.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;ntwitter&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install ntwitter
&lt;/pre&gt;
&lt;p&gt;Ntwitter on GitHub: &lt;a href="https://github.com/AvianFlu/ntwitter"&gt;https://github.com/AvianFlu/ntwitter&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=bUxIdXpbNuI:tCCyf45cmK8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=bUxIdXpbNuI:tCCyf45cmK8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=bUxIdXpbNuI:tCCyf45cmK8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=bUxIdXpbNuI:tCCyf45cmK8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=bUxIdXpbNuI:tCCyf45cmK8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=bUxIdXpbNuI:tCCyf45cmK8:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=bUxIdXpbNuI:tCCyf45cmK8:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/bUxIdXpbNuI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-ntwitter</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Node.js modules you should know about: read</title>
    <id>288</id>
    <updated>2012-01-03T18:43:49Z</updated>
    <published>2011-12-08T14:25:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/4vTKWscwyE8/nodejs-modules-read" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LYY6Eg4YRl3PSfExWwrKz4gYBFk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LYY6Eg4YRl3PSfExWwrKz4gYBFk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LYY6Eg4YRl3PSfExWwrKz4gYBFk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LYY6Eg4YRl3PSfExWwrKz4gYBFk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/nodejs-modules/nodejs-logo.png" alt="node logo" class="post-icon" align="left"&gt;Hello everyone! This is the sixth post in my new &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;node.js modules you should know about&lt;/a&gt; article series.&lt;/p&gt;
&lt;p&gt;The first post was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-dnode/"&gt;dnode&lt;/a&gt; - the freestyle rpc library for node, the second was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-optimist/"&gt;optimist&lt;/a&gt; - the lightweight options parser for node, the third was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-lazy/"&gt;lazy&lt;/a&gt; - lazy lists for node, the fourth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-request/"&gt;request&lt;/a&gt; - the swiss army knife of HTTP streaming, the fifth was about &lt;a href="http://www.catonmat.net/blog/nodejs-modules-hashish/"&gt;hashish&lt;/a&gt; - hash combinators library.&lt;/p&gt;
&lt;p&gt;This time I'll introduce you to a brand new module called &lt;a href="https://github.com/isaacs/read"&gt;read&lt;/a&gt;. Read was created just yesterday by &lt;a href="http://blog.izs.me"&gt;Isaac Z. Schlueter&lt;/a&gt;, the author of &lt;a href="http://npmjs.org/"&gt;npm&lt;/a&gt;. Read is basically &lt;a href="http://linux.die.net/man/1/read"&gt;read(1)&lt;/a&gt; for node. You can read input from stdin with it easily.&lt;/p&gt;
&lt;p&gt;Here is an example, &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;read&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Username: &amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Password: &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;silent&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nesting functions like this is ugly, so you better use &lt;a href="https://github.com/substack/node-seq"&gt;seq&lt;/a&gt;, the asynchronous flow combinators library, by &lt;a href="http://substack.net/"&gt;James Halliday&lt;/a&gt;. (I'll introduce you to this module some time soon.) Here is how it looks with seq:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;read&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;seq&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Username: &amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;into&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Password: &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;silent&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;into&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pass&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here are all the options &lt;code&gt;read&lt;/code&gt; supports:&lt;/p&gt;
&lt;pre &gt;
prompt  - What to write to stdout before reading input.
silent  - Don't echo the output as the user types it.
num     - Max number of chars to read from terminal.
delim   - The char that means we're done. Default: "\n"
timeout - Number of ms to wait for user input before giving up.
&lt;/pre&gt;
&lt;p&gt;Note: If &lt;code&gt;silent&lt;/code&gt; is true, or num is set, or &lt;code&gt;delim&lt;/code&gt; is something other than "\n", then read will set raw mode, and read character by character.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;read&lt;/code&gt; through npm as always:&lt;/p&gt;
&lt;pre &gt;
npm install read
&lt;/pre&gt;
&lt;h2&gt;Sponsor this blog series!&lt;/h2&gt;
&lt;p&gt;Doing a node.js company and want your ad to appear in the series? The ad will go out to 14,000 rss subscribers, 7,000 email subscribers, and it will get viewed by thousands of my blog visitors! &lt;a href="http://www.catonmat.net/feedback/"&gt;Email me&lt;/a&gt; and we'll set it up! &lt;/p&gt;
&lt;h2&gt;Enjoy!&lt;/h2&gt;
&lt;p&gt;If you love these articles, &lt;a href="http://www.catonmat.net/feed/" title="Subscribe to catonmat.net RSS feed"&gt;subscribe to my blog&lt;/a&gt; for more, &lt;a href="http://twitter.com/pkrumins" title="Peteris Krumins on Twitter"&gt;follow me on Twitter&lt;/a&gt; to find about my adventures, and &lt;a href="http://github.com/pkrumins" title="Peteris Krumins on GitHub"&gt;watch me produce code on GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4vTKWscwyE8:sNjn3MASz6M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4vTKWscwyE8:sNjn3MASz6M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=4vTKWscwyE8:sNjn3MASz6M:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4vTKWscwyE8:sNjn3MASz6M:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=4vTKWscwyE8:sNjn3MASz6M:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4vTKWscwyE8:sNjn3MASz6M:XiUCZPyL81w"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=XiUCZPyL81w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4vTKWscwyE8:sNjn3MASz6M:DhrJZwOgkxs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=DhrJZwOgkxs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/4vTKWscwyE8" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/nodejs-modules-read</feedburner:origLink></entry>
</feed>

