├── .gitignore ├── README.md ├── async-you ├── each.js ├── map.js ├── reduce.js ├── series-object.js ├── times.js ├── waterfall.js └── whilst.js ├── browserify-adventure ├── .gitignore ├── beep-boop.js ├── build-a-widget.js ├── builtins.js ├── multi-export.js ├── ndjson.js ├── single-export.js ├── uniquely.js ├── using-npm-packages.js ├── using-transforms.js ├── wake.txt ├── writing-transforms-main.js ├── writing-transforms-tr.js └── writing-transforms-transform.js ├── bytewiser ├── array-buffers.js ├── buffer-concat.js ├── buffer-from-string.js ├── hexadecimal-encoding.js ├── line-splitter.js ├── modifying-buffers.js └── typed-arrays.js ├── expressworks ├── good-old-form.js ├── hello-world.js ├── jade.js ├── json-me.js ├── static.js ├── stylus-css.js └── templates │ └── index.jade ├── functional-javascript ├── async-loop.js ├── call-duck-typing.js ├── curryn.js ├── dependency-tree.js ├── every-some.js ├── filter.js ├── function-call.js ├── hello-world.js ├── higher-order-function.js ├── map-using-reduce.js ├── map.js ├── non-blocking-recursion.js ├── partial-apply-with-bind.js ├── partial-apply-without-bind.js ├── recursive-reduce.js ├── reduce.js ├── spies.js └── trampoline.js ├── learn-generators ├── 01-run-stop-run.js ├── 02-generator-iterator.js ├── 03-delegating-generators.js ├── 04-catch-error.js ├── 05-look-sync-do-async.js └── 06-look-sync-make-promise.js ├── learnyounode ├── baby-steps.js ├── filter-dir.js ├── filtered-ls.js ├── hello-world.js ├── http-client.js ├── http-collect.js ├── http-file-server.js ├── http-json-api-server.js ├── http-reverserer.js ├── juggling-async.js ├── make-it-modular.js ├── my-first-async-io.js ├── my-first-io.js └── time-server.js ├── learnyoureact └── hello-react │ ├── app.js │ ├── program.js │ └── views │ └── index.jsx ├── levelmeup ├── .gitignore ├── all-you-base.js ├── basics-batch.js ├── basics-get.js ├── basics-put.js ├── get-your-level-on.js ├── horse_js-count.js ├── horse_js-tweets.js ├── keywise.js ├── multilevel.js ├── short-scrabble-words.js ├── streaming.js └── sublevel.js ├── makemehapi ├── directories.js ├── handling.js ├── hello-hapi.js ├── helpers │ └── helper.js ├── helping.js ├── proxies.js ├── public │ ├── file.html │ └── index.html ├── routes.js ├── stream-text.txt ├── streams.js ├── templates │ ├── helper-template.html │ └── index.html └── views.js ├── nodebot-workshop └── 01-blink-blink.js ├── promise-it-wont-hurt ├── always-async.js ├── an-important-rule.js ├── do-some-work.js ├── fetch-json.js ├── fulfill-a-promise.js ├── more-functional.js ├── multiple-promises.js ├── reject-a-promise.js ├── throw-an-error.js ├── to-reject-or-not-to-reject.js ├── using-qfcall.js └── values-and-promises.js └── stream-adventure ├── beep-boop.js ├── combiner.js ├── concat.js ├── crypt.js ├── duplexer-redux.js ├── duplexer.js ├── html-stream.js ├── http-client.js ├── http-server.js ├── input-output.js ├── lines.js ├── meet-pipe.js ├── secretz.js ├── transform.js └── websockets.js /.gitignore: -------------------------------------------------------------------------------- 1 | git-it/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #learning node with nodeschool 2 | 3 | My solutions for [Node School][nodeschool] classes. 4 | 5 | Each level has its own folder. 6 | 7 | [nodeschool]: http://nodeschool.io/ 8 | -------------------------------------------------------------------------------- /async-you/each.js: -------------------------------------------------------------------------------- 1 | var http = require('http'), 2 | async = require('async'); 3 | 4 | async.each([process.argv[2], process.argv[3]], function (item, done) { 5 | http.get(item, function (res) { 6 | res.on('data', function (chunk) { 7 | }); 8 | 9 | res.on('end', function () { 10 | return done(); 11 | }); 12 | }).on('error', function (err) { 13 | return console.log(err); 14 | }); 15 | }, function (err) { 16 | if (err) { 17 | console.log(err); 18 | } 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /async-you/map.js: -------------------------------------------------------------------------------- 1 | var http = require('http'), 2 | async = require('async'); 3 | 4 | async.map(process.argv.slice(2, 4), function (item, done) { 5 | http.get(item, function (res) { 6 | var body = ''; 7 | res.on('data', function (chunk) { 8 | body += chunk.toString(); 9 | }); 10 | 11 | res.on('end', function () { 12 | done(null, body); 13 | }); 14 | }).on('error', function (err) { 15 | done(err); 16 | }); 17 | }, function (err, results) { 18 | if (err) { 19 | return console.error(err); 20 | } 21 | 22 | console.log(results); 23 | }); 24 | 25 | -------------------------------------------------------------------------------- /async-you/reduce.js: -------------------------------------------------------------------------------- 1 | var http = require('http'), 2 | async = require('async'); 3 | 4 | var url = process.argv[2]; 5 | 6 | async.reduce(['one', 'two', 'three'], 0, function (memo, item, cb) { 7 | http.get(url + '?number=' + item, function (res) { 8 | var body = ''; 9 | res.on('data', function (chunk) { 10 | body += chunk.toString(); 11 | }); 12 | 13 | res.on('end', function () { 14 | cb(null, memo + parseInt(body, 10)); 15 | }); 16 | }).on('error', function (err) { 17 | return console.error(err); 18 | }); 19 | }, function (err, result) { 20 | if (err) { 21 | return console.error(err); 22 | } 23 | 24 | console.log(result); 25 | }); 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /async-you/series-object.js: -------------------------------------------------------------------------------- 1 | var http = require('http'), 2 | async = require('async'); 3 | 4 | async.series({ 5 | requestOne: function (cb) { 6 | http.get(process.argv[2], function (res) { 7 | var body = ''; 8 | res.on('data', function (chunk) { 9 | body += chunk.toString(); 10 | }).on('end', function () { 11 | cb(null, body); 12 | }); 13 | }).on('error', function (err) { 14 | return cb(err); 15 | }); 16 | }, 17 | 18 | requestTwo: function (cb) { 19 | http.get(process.argv[3], function (res) { 20 | var body = ''; 21 | res.on('data', function (chunk) { 22 | body += chunk.toString(); 23 | }).on('end', function () { 24 | cb(null, body); 25 | }); 26 | }).on('error', function (err) { 27 | return cb(err); 28 | }); 29 | } 30 | }, function (err, result) { 31 | if (err) { 32 | return console.error(err); 33 | } 34 | 35 | console.log(result); 36 | }); 37 | 38 | 39 | -------------------------------------------------------------------------------- /async-you/times.js: -------------------------------------------------------------------------------- 1 | var http = require('http'), 2 | async = require('async'); 3 | 4 | var hostname = process.argv[2]; 5 | var port = process.argv[3]; 6 | 7 | async.series({ 8 | post: function (done) { 9 | 10 | var opts = { 11 | hostname: hostname, 12 | port: port, 13 | method: 'POST', 14 | path: '/users/create' 15 | }; 16 | 17 | async.times(5, function (i, timesDone) { 18 | var req = http.request(opts, function (res) { 19 | 20 | res.on('data', function (chunk) { 21 | }); 22 | 23 | res.on('end', function () { 24 | timesDone(null); 25 | }); 26 | }).on('error', function (err) { 27 | return console.error(err); 28 | }); 29 | 30 | var data = JSON.stringify({ user_id : i + 1 }); 31 | req.write(data); 32 | req.end(); 33 | }, function (err) { 34 | if (err) { 35 | return console.error(err); 36 | } 37 | 38 | done(null); 39 | }); 40 | 41 | }, 42 | 43 | get: function (done) { 44 | http.get('http://' + process.argv.slice(2).join(':') + '/users', function (res) { 45 | var body = ''; 46 | 47 | res.on('data', function (chunk) { 48 | body += chunk.toString(); 49 | }); 50 | 51 | res.on('end', function () { 52 | done(null, body); 53 | }); 54 | }) 55 | } 56 | }, function (err, results) { 57 | if (err) { 58 | return console.error(err); 59 | } 60 | console.log(results.get); 61 | }); 62 | 63 | -------------------------------------------------------------------------------- /async-you/waterfall.js: -------------------------------------------------------------------------------- 1 | var http = require('http'), 2 | fs = require('fs'), 3 | async = require('async'); 4 | 5 | var filename = process.argv[2]; 6 | 7 | async.waterfall([ 8 | function (cb) { 9 | fs.readFile(filename, 'utf-8', function (err, data) { 10 | if (err) { 11 | return cb(err); 12 | } 13 | 14 | cb(null, data); 15 | }); 16 | }, 17 | 18 | function (data, cb) { 19 | var body = ''; 20 | 21 | http.get(data, function (res) { 22 | res.on('data', function (chunk) { 23 | body += chunk.toString(); 24 | }) 25 | .on('end', function () { 26 | cb(null, body); 27 | }); 28 | }) 29 | .on('error', function (err) { 30 | cb(err); 31 | }); 32 | } 33 | ], function (err, result) { 34 | 35 | if (err) { 36 | return console.error(err); 37 | } 38 | 39 | console.log(result); 40 | }); 41 | 42 | 43 | -------------------------------------------------------------------------------- /async-you/whilst.js: -------------------------------------------------------------------------------- 1 | var async = require('async'), 2 | http = require('http'); 3 | 4 | var lastResponse = '', 5 | totalRequests = 0, 6 | url = process.argv[2]; 7 | 8 | async.whilst(function () { return lastResponse !== 'meerkat'; }, 9 | function (callback) { 10 | http.get(url, function (res) { 11 | totalRequests++; 12 | 13 | var body = ''; 14 | res.on('data', function (chunk) { 15 | body += chunk.toString(); 16 | }); 17 | 18 | res.on('end', function () { 19 | lastResponse = body.trim(); 20 | callback(); 21 | }); 22 | 23 | }).on('error', function (err) { 24 | return console.error(err); 25 | }); 26 | }, 27 | 28 | function (err) { 29 | console.log(totalRequests); 30 | } 31 | ); 32 | 33 | -------------------------------------------------------------------------------- /browserify-adventure/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | 4 | -------------------------------------------------------------------------------- /browserify-adventure/beep-boop.js: -------------------------------------------------------------------------------- 1 | console.log('BEEP BOOP'); 2 | -------------------------------------------------------------------------------- /browserify-adventure/build-a-widget.js: -------------------------------------------------------------------------------- 1 | var domify = require('domify'); 2 | 3 | module.exports = function () { 4 | var name = ''; 5 | 6 | function getHtml() { 7 | return '
Hello ' + name + '!
'; 8 | } 9 | 10 | return { 11 | setName: function (newName) { 12 | name = newName; 13 | }, 14 | 15 | appendTo: function (el) { 16 | return el.appendChild(domify(getHtml())); 17 | } 18 | }; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /browserify-adventure/builtins.js: -------------------------------------------------------------------------------- 1 | var url = require('url'), 2 | querystring = require('querystring'); 3 | 4 | var webaddress = prompt(); 5 | 6 | var parsedUrl = url.parse(webaddress), 7 | parsedQuery = querystring.parse(parsedUrl.query); 8 | 9 | console.log(url.resolve(webaddress, parsedQuery.file)); 10 | -------------------------------------------------------------------------------- /browserify-adventure/multi-export.js: -------------------------------------------------------------------------------- 1 | var ndjson = require('./ndjson'); 2 | 3 | console.log(ndjson.parse(prompt())); 4 | console.log(ndjson.stringify(prompt())); 5 | 6 | -------------------------------------------------------------------------------- /browserify-adventure/ndjson.js: -------------------------------------------------------------------------------- 1 | exports.parse = function (str) { 2 | return str.split('\n').map(JSON.parse); 3 | }; 4 | 5 | exports.stringify = function (rows) { 6 | return rows.map(JSON.stringify).join('\n'); 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /browserify-adventure/single-export.js: -------------------------------------------------------------------------------- 1 | var uniquely = require('./uniquely'); 2 | 3 | console.log(uniquely(prompt())); 4 | 5 | -------------------------------------------------------------------------------- /browserify-adventure/uniquely.js: -------------------------------------------------------------------------------- 1 | var uniq = require('uniq'); 2 | 3 | module.exports = function (str) { 4 | return uniq(str.split(',')); 5 | }; 6 | 7 | -------------------------------------------------------------------------------- /browserify-adventure/using-npm-packages.js: -------------------------------------------------------------------------------- 1 | var uniq = require('uniq'); 2 | 3 | var string = prompt(); 4 | 5 | console.log(uniq(string.split(','))); 6 | 7 | -------------------------------------------------------------------------------- /browserify-adventure/using-transforms.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var sprintf = require('sprintf'); 3 | 4 | var src = fs.readFileSync('/usr/local/lib/node_modules/browserify-adventure/problems/using_transforms/wake.txt', 'utf8'); 5 | 6 | src.split('\n').forEach(function (line, index) { 7 | if (index % 5 === 0) { 8 | console.log(sprintf("%3d %s", index, line)); 9 | } 10 | else { 11 | console.log(sprintf(" %s", line)); 12 | } 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /browserify-adventure/wake.txt: -------------------------------------------------------------------------------- 1 | Be that as it may, but for that light phantastic of his gnose's glow as it 2 | slid lucifericiously within an inch of its page (he touch at its from time 3 | to other, the red eye of his fear in saddishness, to ensign the colours by 4 | the beerlitz in his mathness and his educandees to outhue to themselves in 5 | the cries of girl-glee: gember! inkware! chonchambre! cinsero! zinnzabar! 6 | tincture and gin!) Nibs never would have quilled a seriph to sheepskin. By 7 | that rosy lampoon's effluvious burning and with help of the simulchronic 8 | flush in his pann (a ghinee a ghirk he ghets there!) he scrabbled and 9 | scratched and scriobbled and skrevened namelesss shamelessness about 10 | everybody ever he met, even sharing a precipitation under the idlish 11 | tarriers' umbrella of a showerproof wall, while all over up and down the 12 | four margins of this rancid Shem stuff the evilsmeller (who was devoted to 13 | Uldfadar Sardanapalus) used to stipple endlessly inartistic portraits of 14 | himself in the act of reciting old Nichiabilli's monolook interyerear 15 | Hanno, o Nonanno, acce'l brubblemm'as, ser Autore, q.e.d., a 16 | heartbreakingly handsome young paolo with love lyrics for the goyls in his 17 | eyols, a plain-tiff's tanner vuice, a jucal inkome of one hundred and 18 | thirtytwo dranchmas per yard from Broken Hill stranded estate, Camebreech 19 | mannings, cutting a great dash in a brandnew two guinea dress suit and a 20 | burled hogsford hired for a Fursday evenin merry pawty, anna loavely long 21 | pair of inky Italian moostarshes glistering with boric vaseline and 22 | frangipani. Puh! How unwhisperably so! 23 | -------------------------------------------------------------------------------- /browserify-adventure/writing-transforms-main.js: -------------------------------------------------------------------------------- 1 | var txt = require('./wake.txt'); 2 | 3 | console.log(txt); 4 | -------------------------------------------------------------------------------- /browserify-adventure/writing-transforms-tr.js: -------------------------------------------------------------------------------- 1 | var through = require('through2'); 2 | var split = require('split'); 3 | var quote = require('quote-stream'); 4 | var combiner = require('stream-combiner2'); 5 | 6 | var ftr = require('./writing-transforms-transform'); 7 | 8 | module.exports = function (file) { 9 | if (!/\.txt$/.test(file)) return through(); 10 | 11 | var prefix = through(); 12 | prefix.push('module.exports='); 13 | 14 | return combiner([ split(), ftr, quote(), prefix ]); 15 | }; 16 | -------------------------------------------------------------------------------- /browserify-adventure/writing-transforms-transform.js: -------------------------------------------------------------------------------- 1 | var through = require('through2'); 2 | var sprintf = require('sprintf'); 3 | 4 | var lineNumber = 0; 5 | 6 | module.exports = through(function (buf, enc, next) { 7 | if (lineNumber % 5 === 0) { 8 | this.push(sprintf("%3d %s", lineNumber, buf.toString())); 9 | } 10 | else { 11 | this.push(sprintf(" %s", buf.toString())); 12 | } 13 | this.push('\n'); 14 | lineNumber++; 15 | 16 | next(); 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /bytewiser/array-buffers.js: -------------------------------------------------------------------------------- 1 | var num = process.argv[2]; 2 | var u32 = new Uint32Array(1); 3 | 4 | u32[0] = num; 5 | 6 | var u16 = new Uint16Array(u32.buffer); 7 | 8 | console.log(JSON.stringify(u16)); 9 | 10 | -------------------------------------------------------------------------------- /bytewiser/buffer-concat.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var buffers = []; 4 | 5 | process.stdin.on('data', function (buf) { 6 | buffers.push(buf); 7 | }); 8 | 9 | process.stdin.on('end', function () { 10 | console.log(Buffer.concat(buffers)); 11 | }); 12 | -------------------------------------------------------------------------------- /bytewiser/buffer-from-string.js: -------------------------------------------------------------------------------- 1 | console.log(new Buffer("bytewiser")) 2 | -------------------------------------------------------------------------------- /bytewiser/hexadecimal-encoding.js: -------------------------------------------------------------------------------- 1 | var numbers = process.argv.slice(2).map(parseFloat); 2 | 3 | console.log(new Buffer(numbers).toString('hex')); 4 | 5 | -------------------------------------------------------------------------------- /bytewiser/line-splitter.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var filepath = process.argv[2]; 4 | 5 | fs.readFile(filepath, function (err, buf) { 6 | 7 | for (var prev = 0, curr = 0; curr < buf.length; ++curr) { 8 | if (buf[curr] === 0x0a) { 9 | console.log(new Buffer(buf.slice(prev, curr))); 10 | prev = curr + 1; 11 | } 12 | } 13 | // last line 14 | console.log(new Buffer(buf.slice(prev, buf.length - 1))); 15 | }); 16 | 17 | -------------------------------------------------------------------------------- /bytewiser/modifying-buffers.js: -------------------------------------------------------------------------------- 1 | 2 | process.stdin.on('data', function (buf) { 3 | for (var i = 0; i < buf.length; ++i) { 4 | if (buf[i] === 46) { 5 | buf.write("!", i); 6 | } 7 | } 8 | console.log(buf); 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /bytewiser/typed-arrays.js: -------------------------------------------------------------------------------- 1 | 2 | process.stdin.on('data', function (buf) { 3 | var arr = new Uint8Array(buf.length); 4 | for (var i = 0; i < buf.length; ++i) { 5 | arr[i] = buf[i]; 6 | } 7 | 8 | console.log(JSON.stringify(arr)); 9 | 10 | return; 11 | }); 12 | -------------------------------------------------------------------------------- /expressworks/good-old-form.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | 3 | var app = express(); 4 | 5 | app.use(express.urlencoded()); 6 | app.post('/form', (req, res) => { 7 | res.end(req.body.str.split('').reverse().join('')); 8 | }); 9 | app.listen(process.argv[2] || 3000); 10 | -------------------------------------------------------------------------------- /expressworks/hello-world.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | 3 | var app = express(); 4 | app.get('/home', (req, res) => { 5 | res.send('Hello World!'); 6 | }); 7 | app.listen(process.argv[2] || 3000); 8 | 9 | -------------------------------------------------------------------------------- /expressworks/jade.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | path = require('path'); 3 | 4 | var app = express(); 5 | 6 | app.set('view engine', 'jade'); 7 | app.set('views', process.argv[3] || path.join(__dirname, 'templates')); 8 | 9 | app.get('/home', (req, res) => { 10 | res.render('index', { date: new Date().toDateString() }); 11 | }); 12 | app.listen(process.argv[2] || 3000); 13 | -------------------------------------------------------------------------------- /expressworks/json-me.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | var fs = require('fs'); 4 | 5 | app.get('/books', (req, res) => { 6 | fs.readFile(process.argv[3], (err, content) => { 7 | if(err) { 8 | res.send(500); 9 | } 10 | 11 | try { 12 | var books = JSON.parse(content.toString()); 13 | res.json(books); 14 | } catch(error) { 15 | res.send(500); 16 | } 17 | }); 18 | }); 19 | 20 | app.listen(process.argv[2]); -------------------------------------------------------------------------------- /expressworks/static.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var express = require('express'); 3 | 4 | var app = express(); 5 | 6 | app.use(express.static(process.argv[3] || path.join(__dirname, 'public'))); 7 | app.listen(process.argv[2] || 3000); 8 | -------------------------------------------------------------------------------- /expressworks/stylus-css.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.static(process.argv[3])); 5 | app.use(require('stylus').middleware(process.argv[3])); 6 | 7 | app.listen(process.argv[2]); -------------------------------------------------------------------------------- /expressworks/templates/index.jade: -------------------------------------------------------------------------------- 1 | h1 Hello World 2 | p Today is #{date}. 3 | -------------------------------------------------------------------------------- /functional-javascript/async-loop.js: -------------------------------------------------------------------------------- 1 | function loadUsers(userIds, load, done) { 2 | var totalUsers = userIds.length, 3 | usersLoaded = 0, 4 | users = []; 5 | 6 | userIds.map(function(id, index) { 7 | load(id, function(user) { 8 | users[index] = user; 9 | usersLoaded++; 10 | 11 | if (usersLoaded === totalUsers) { 12 | done(users); 13 | } 14 | }); 15 | }); 16 | } 17 | 18 | module.exports = loadUsers; 19 | -------------------------------------------------------------------------------- /functional-javascript/call-duck-typing.js: -------------------------------------------------------------------------------- 1 | function duckCount() { 2 | return Array.prototype.slice.call(arguments).reduce(function(prev, curr) { 3 | return prev + (Object.prototype.hasOwnProperty.call(curr, 'quack') ? 1 : 0); 4 | }, 0); 5 | } 6 | 7 | module.exports = duckCount; 8 | -------------------------------------------------------------------------------- /functional-javascript/curryn.js: -------------------------------------------------------------------------------- 1 | function curryN(fn, n) { 2 | n = typeof n !== 'undefined' ? n : fn.length; 3 | 4 | if (n) { 5 | return function(arg) { 6 | return curryN(fn.bind(null, arg), n - 1); 7 | } 8 | } 9 | else { 10 | return fn(); 11 | } 12 | } 13 | 14 | module.exports = curryN; 15 | -------------------------------------------------------------------------------- /functional-javascript/dependency-tree.js: -------------------------------------------------------------------------------- 1 | function getDependencies(tree, allDeps) { 2 | allDeps = allDeps || {}; 3 | var dependencies = tree.dependencies || []; 4 | 5 | Object.keys(dependencies).forEach(function(dep) { 6 | var fullDepName = [dep, dependencies[dep].version].join('@'); 7 | allDeps[fullDepName] = fullDepName; 8 | getDependencies(dependencies[dep], allDeps); 9 | }); 10 | 11 | return Object.keys(allDeps).sort(); 12 | } 13 | 14 | module.exports = getDependencies; 15 | -------------------------------------------------------------------------------- /functional-javascript/every-some.js: -------------------------------------------------------------------------------- 1 | module.exports = function checkUsersValid(goodUsers) { 2 | return function(testUsers) { 3 | return testUsers.every(function(testUser) { 4 | return goodUsers.some(function(goodUser) { 5 | return testUser.id === goodUser.id; 6 | }); 7 | }); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /functional-javascript/filter.js: -------------------------------------------------------------------------------- 1 | module.exports = function getShortMessages(msgs) { 2 | return msgs.filter(function(msg) { 3 | return msg.message.length < 50; 4 | }).map(function(msg) { 5 | return msg.message; 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /functional-javascript/function-call.js: -------------------------------------------------------------------------------- 1 | module.exports = Function.prototype.call.bind(Array.prototype.slice); 2 | -------------------------------------------------------------------------------- /functional-javascript/hello-world.js: -------------------------------------------------------------------------------- 1 | module.exports = function(str) { 2 | return str.toUpperCase(); 3 | }; 4 | 5 | -------------------------------------------------------------------------------- /functional-javascript/higher-order-function.js: -------------------------------------------------------------------------------- 1 | function repeat(fn, num) { 2 | if (!num) return; 3 | 4 | fn(); 5 | return repeat(fn, num - 1); 6 | } 7 | 8 | module.exports = repeat; 9 | -------------------------------------------------------------------------------- /functional-javascript/map-using-reduce.js: -------------------------------------------------------------------------------- 1 | module.exports = function arrayMap(arr, fn) { 2 | return arr.reduce(function(prev, curr, index, array) { 3 | return prev.concat(fn.call(null, curr, index, array)); 4 | }, []); 5 | } 6 | -------------------------------------------------------------------------------- /functional-javascript/map.js: -------------------------------------------------------------------------------- 1 | function doubleAll(numbers) { 2 | return numbers.map(function(n) { 3 | return n * 2; 4 | }); 5 | } 6 | 7 | module.exports = doubleAll; 8 | -------------------------------------------------------------------------------- /functional-javascript/non-blocking-recursion.js: -------------------------------------------------------------------------------- 1 | function repeat(fn, num) { 2 | if (!num) return; 3 | 4 | fn(); 5 | 6 | if (num % 200 === 0) { 7 | setTimeout(function() { 8 | repeat(fn, --num); 9 | }, 0); 10 | } 11 | else { 12 | repeat(fn, --num); 13 | } 14 | } 15 | 16 | module.exports = repeat; 17 | -------------------------------------------------------------------------------- /functional-javascript/partial-apply-with-bind.js: -------------------------------------------------------------------------------- 1 | function logger(namespace) { 2 | return console.log.bind(console, namespace); 3 | } 4 | 5 | module.exports = logger; 6 | -------------------------------------------------------------------------------- /functional-javascript/partial-apply-without-bind.js: -------------------------------------------------------------------------------- 1 | var slice = Array.prototype.slice; 2 | 3 | function logger(namespace) { 4 | return function() { 5 | console.log.apply(console, [namespace].concat(slice.call(arguments))); 6 | } 7 | } 8 | 9 | module.exports = logger; 10 | -------------------------------------------------------------------------------- /functional-javascript/recursive-reduce.js: -------------------------------------------------------------------------------- 1 | function reduce(array, fn, init) { 2 | var arrayDup = array.slice(), i = 0; 3 | 4 | return (function recursiveReduce(arrayDup, fn, init) { 5 | return arrayDup.length ? recursiveReduce(arrayDup, fn, fn(init, arrayDup.shift()), i++, array) : init; 6 | }(arrayDup, fn, init)); 7 | } 8 | 9 | module.exports = reduce; 10 | -------------------------------------------------------------------------------- /functional-javascript/reduce.js: -------------------------------------------------------------------------------- 1 | module.exports = function countWords(words) { 2 | return words.reduce(function(wordsTotal, word) { 3 | (++wordsTotal[word]) || (wordsTotal[word] = 1); 4 | return wordsTotal; 5 | }, {}); 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /functional-javascript/spies.js: -------------------------------------------------------------------------------- 1 | function Spy(target, method) { 2 | var oldMethod = target[method], 3 | spy = { count: 0 }; 4 | 5 | target[method] = function() { 6 | spy.count++; 7 | return oldMethod.apply(target, arguments); 8 | } 9 | 10 | return spy; 11 | } 12 | 13 | module.exports = Spy; 14 | -------------------------------------------------------------------------------- /functional-javascript/trampoline.js: -------------------------------------------------------------------------------- 1 | function repeat(operation, num) { 2 | if (!num) return; 3 | return function() { 4 | operation(); 5 | return repeat(operation, --num); 6 | } 7 | } 8 | 9 | function trampoline(fn) { 10 | while (fn()); 11 | } 12 | 13 | module.exports = function(operation, num) { 14 | return trampoline(repeat(operation, num)); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /learn-generators/01-run-stop-run.js: -------------------------------------------------------------------------------- 1 | 2 | function *range(from, to) { 3 | while (from <= to) yield from++ 4 | } 5 | 6 | for (var a of range(5, 10)) { 7 | console.log(a) 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /learn-generators/02-generator-iterator.js: -------------------------------------------------------------------------------- 1 | 2 | function *factorial(n) { 3 | let curr = 1 4 | let total = 1 5 | while (n >= curr) yield total = curr++ * total 6 | } 7 | 8 | for (let a of factorial(5)) console.log(a) 9 | -------------------------------------------------------------------------------- /learn-generators/03-delegating-generators.js: -------------------------------------------------------------------------------- 1 | 2 | function *flat(arr) { 3 | for (let i = 0; i < arr.length; i++) { 4 | if (arr[i].constructor === Array) yield *flat(arr[i]) 5 | else yield arr[i] 6 | } 7 | } 8 | 9 | const A = [ 1, [ 2, [ 3, 4 ], 5 ], 6 ] 10 | 11 | for (let a of flat(A)) console.log(a) 12 | -------------------------------------------------------------------------------- /learn-generators/04-catch-error.js: -------------------------------------------------------------------------------- 1 | 2 | function *upper(list) { 3 | for (let i = 0; i < list.length; ++i) { 4 | try { 5 | yield list[i].toUpperCase() 6 | } catch (e) { 7 | yield null 8 | } 9 | } 10 | } 11 | 12 | let items = [ 'a', 'B', 1, 'c' ] 13 | 14 | for (let a of upper(items)) console.log(a) 15 | -------------------------------------------------------------------------------- /learn-generators/05-look-sync-do-async.js: -------------------------------------------------------------------------------- 1 | 2 | var fs = require('fs') 3 | 4 | function run(generator) { 5 | const it = generator(go) 6 | 7 | function go(err, result) { 8 | if (err) return it.throw(err) 9 | it.next(result) 10 | } 11 | 12 | go() 13 | } 14 | 15 | run(function* (done) { 16 | let firstFile 17 | 18 | try { 19 | const files = yield fs.readdir('NoNoNo', done) 20 | firstFile = files[0] 21 | } catch (e) { 22 | firstFile = null 23 | } 24 | 25 | console.log(firstFile) 26 | }) 27 | 28 | -------------------------------------------------------------------------------- /learn-generators/06-look-sync-make-promise.js: -------------------------------------------------------------------------------- 1 | 2 | const askFoo = () => new Promise((resolve) => resolve('foo')) 3 | 4 | const run = generator => { 5 | const it = generator() 6 | 7 | it.next().value 8 | .then(result => it.next(result)) 9 | .catch(err => it.throw(err)) 10 | } 11 | 12 | run(function* () { 13 | try { 14 | const foo = yield askFoo() 15 | console.log(foo) 16 | } catch (e) { 17 | console.log(e) 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /learnyounode/baby-steps.js: -------------------------------------------------------------------------------- 1 | 2 | var numbers = process.argv.slice(2), 3 | sum = numbers.reduce((curr, prev) => { return +curr + +prev; }); 4 | 5 | console.log(sum); 6 | 7 | -------------------------------------------------------------------------------- /learnyounode/filter-dir.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | module.exports = (dirPath, extension, cb) => { 5 | var filteredFiles = []; 6 | 7 | fs.readdir(dirPath, (err, list) => { 8 | if (err) { 9 | return cb(err); 10 | } 11 | 12 | list.forEach((file) => { 13 | if (path.extname(file) === '.' + extension) { 14 | filteredFiles.push(file); 15 | } 16 | }); 17 | 18 | cb(null, filteredFiles); 19 | }); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /learnyounode/filtered-ls.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | fs.readdir(process.argv[2], (err, list) => { 5 | list.forEach((filename) => { 6 | if (path.extname(filename) === '.' + process.argv[3]) { 7 | console.log(filename); 8 | } 9 | }); 10 | }); 11 | 12 | -------------------------------------------------------------------------------- /learnyounode/hello-world.js: -------------------------------------------------------------------------------- 1 | console.log('HELLO WORLD'); 2 | -------------------------------------------------------------------------------- /learnyounode/http-client.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | 3 | var url = process.argv[2]; 4 | 5 | http.get(url, (response) => { 6 | response.setEncoding('utf8'); 7 | 8 | response.on('data', (data) => { 9 | console.log(data); 10 | }); 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /learnyounode/http-collect.js: -------------------------------------------------------------------------------- 1 | var concatStream = require('concat-stream'); 2 | var http = require('http'); 3 | 4 | var url = process.argv[2]; 5 | 6 | http.get(url, (response) => { 7 | response.setEncoding('utf8'); 8 | response.pipe(concatStream((data) => { 9 | console.log(data.length); 10 | console.log(data); 11 | })); 12 | }); 13 | 14 | -------------------------------------------------------------------------------- /learnyounode/http-file-server.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var http = require('http'); 3 | 4 | var port = process.argv[2]; 5 | var file = process.argv[3]; 6 | 7 | http.createServer((req, res) => { 8 | res.writeHead(200, { 'content-type' : 'text/plain' }); 9 | 10 | fs.createReadStream(file).pipe(res); 11 | }).listen(port); 12 | -------------------------------------------------------------------------------- /learnyounode/http-json-api-server.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var url = require('url'); 3 | 4 | http.createServer((req, res) => { 5 | var urlObj = url.parse(req.url, true), 6 | pathname = urlObj.pathname, 7 | strtime = urlObj.query.iso, 8 | result; 9 | 10 | if (pathname === '/api/unixtime') { 11 | result = getUnixTimestamp(strtime); 12 | } 13 | else if (pathname === '/api/parsetime') { 14 | result = getTimeObj(strtime); 15 | } 16 | 17 | if (result) { 18 | res.writeHead(200, { 'Content-Type': 'application/json' }); 19 | res.end(JSON.stringify(result)); 20 | } 21 | else { 22 | res.writeHead(404); 23 | res.end(); 24 | } 25 | 26 | }).listen(process.argv[2]); 27 | 28 | 29 | var getUnixTimestamp = (strtime) => { 30 | return { 31 | unixtime: getTimestamp(strtime) 32 | }; 33 | } 34 | 35 | var getTimestamp = (strtime) => { 36 | return Date.parse(strtime); 37 | } 38 | 39 | var getTimeObj = (strtime) => { 40 | var date = new Date(getTimestamp(strtime)); 41 | 42 | return { 43 | hour: date.getHours(), 44 | minute: date.getMinutes(), 45 | second: date.getSeconds() 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /learnyounode/http-reverserer.js: -------------------------------------------------------------------------------- 1 | var map = require('through2-map'); 2 | var http = require('http'); 3 | 4 | var port = process.argv[2]; 5 | 6 | http.createServer((req, res) => { 7 | if (req.method === 'POST') { 8 | req.pipe(map((chunk) => { 9 | return chunk.toString().toUpperCase(); 10 | })).pipe(res); 11 | } 12 | }).listen(port); 13 | -------------------------------------------------------------------------------- /learnyounode/juggling-async.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var concatStream = require('concat-stream'); 3 | 4 | var urls = process.argv.slice(2), 5 | results = [], 6 | resultsCount = 0; 7 | 8 | urls.forEach((url, i) => { 9 | http.get(url, (response) => { 10 | response.setEncoding('utf8'); 11 | 12 | response.pipe(concatStream((data) => { 13 | results[i] = data; 14 | resultsCount++; 15 | 16 | if (resultsCount === urls.length) { 17 | results.forEach((result) => { 18 | console.log(result); 19 | }); 20 | } 21 | })); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /learnyounode/make-it-modular.js: -------------------------------------------------------------------------------- 1 | var filterDir = require('./filter-dir'); 2 | 3 | var dirPath = process.argv[2]; 4 | var extension = process.argv[3]; 5 | 6 | filterDir(dirPath, extension, (err, list) => { 7 | if (err) { 8 | console.log('An error happened when reading ' + dirPath); 9 | return err; 10 | } 11 | 12 | list.forEach((filename) => { 13 | console.log(filename); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /learnyounode/my-first-async-io.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | fs.readFile(process.argv[2], 'utf8', (err, data) => { 4 | if (err) throw err; 5 | console.log(data.split('\n').length - 1); 6 | }); 7 | -------------------------------------------------------------------------------- /learnyounode/my-first-io.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var text = fs.readFileSync(process.argv[2]); 4 | 5 | console.log(text.toString().split('\n').length - 1); 6 | -------------------------------------------------------------------------------- /learnyounode/time-server.js: -------------------------------------------------------------------------------- 1 | var net = require('net'); 2 | 3 | var server = net.createServer((socket) => { 4 | 5 | socket.end(getFormattedCurrentTime() + "\n"); 6 | 7 | }); 8 | 9 | server.listen(process.argv[2]); 10 | 11 | var getFormattedCurrentTime = () => { 12 | var now = new Date(); 13 | 14 | return [now.getFullYear(), formatNumber(now.getMonth() + 1), formatNumber(now.getDate())].join("-") 15 | + " " + [formatNumber(now.getHours()), formatNumber(now.getMinutes())].join(":"); 16 | } 17 | 18 | var formatNumber = (number) => { 19 | return number < 10 ? "0" + number : number; 20 | } 21 | -------------------------------------------------------------------------------- /learnyoureact/hello-react/app.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var TodoBox = require('./views/index.jsx'); 3 | 4 | var data = JSON.parse(document.getElementById('initial-data').getAttribute('data-json')); 5 | React.render(, document.getElementById('app')); 6 | 7 | -------------------------------------------------------------------------------- /learnyoureact/hello-react/program.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | var React = require('react'); 5 | var DOM = React.DOM; 6 | var body = DOM.body; 7 | var div = DOM.div; 8 | var script = DOM.script; 9 | 10 | var browserify = require('browserify'); 11 | 12 | app.set('port', process.argv[2] || 3000); 13 | app.set('view engine', 'jsx'); 14 | app.set('views', __dirname + '/views'); 15 | app.engine('jsx', require('express-react-views').createEngine()); 16 | 17 | require('node-jsx').install(); 18 | var TodoBox = require('./views/index.jsx'); 19 | 20 | var data = [ 21 | { 22 | title: 'Shopping', 23 | detail: process.argv[3] 24 | }, 25 | { 26 | title: 'Hair cut', 27 | detail: process.argv[4] 28 | } 29 | ]; 30 | 31 | app.use('/bundle.js', function (req, res) { 32 | res.setHeader('Content-Type', 'application/javascript'); 33 | browserify('./app.js') 34 | .transform('reactify') 35 | .bundle() 36 | .pipe(res); 37 | }); 38 | 39 | app.use('/', function (req, res) { 40 | var initialData = JSON.stringify(data); 41 | var markup = React.renderToString(React.createElement(TodoBox, {data: data})); 42 | 43 | res.setHeader('Content-Type', 'text/html'); 44 | 45 | var html = React.renderToStaticMarkup(body(null, 46 | div({ id: 'app', dangerouslySetInnerHTML: { __html: markup }}), 47 | script({ id: 'initial-data', 48 | type: 'text/plain', 49 | 'data-json': initialData 50 | }), 51 | script({ src: '/bundle.js' }) 52 | )); 53 | 54 | res.end(html); 55 | }); 56 | 57 | app.listen(app.get('port'), function () { 58 | console.log('server listening on port %s', app.get('port')); 59 | }); 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /learnyoureact/hello-react/views/index.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | 3 | var TodoBox = React.createClass({ 4 | render: function () { 5 | return ( 6 |
7 |

Todos

8 | 9 | 10 |
11 | ); 12 | } 13 | }); 14 | 15 | var TodoList = React.createClass({ 16 | render: function () { 17 | var todos = this.props.data.map(function (todo) { 18 | return {todo.detail}; 19 | }); 20 | return ( 21 |
22 | 23 | 24 | {todos} 25 | 26 |
27 |
28 | ); 29 | } 30 | }); 31 | 32 | var Todo = React.createClass({ 33 | propTypes: { 34 | title: React.PropTypes.string.isRequired 35 | }, 36 | 37 | getInitialState: function () { 38 | return { checked: false }; 39 | }, 40 | 41 | handleChange: function () { 42 | this.setState({ 43 | checked: !this.state.checked 44 | }); 45 | }, 46 | 47 | render: function () { 48 | var rowStyle = this.state.checked ? style.checkedTodo : style.notCheckedTodo; 49 | 50 | return ( 51 | 52 | 53 | {this.props.title} 54 | {this.props.children} 55 | 56 | ); 57 | } 58 | }); 59 | 60 | var TodoForm = React.createClass({ 61 | render: function () { 62 | return ( 63 |
64 | I am a TodoForm. 65 |
66 | ); 67 | } 68 | }); 69 | 70 | var style = { 71 | checkedTodo: { 72 | textDecoration: 'line-through' 73 | }, 74 | notCheckedTodo: { 75 | textDecoration: 'none' 76 | }, 77 | tableContent: { 78 | border: '1px solid black' 79 | } 80 | }; 81 | 82 | module.exports = TodoBox; 83 | -------------------------------------------------------------------------------- /levelmeup/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /levelmeup/all-you-base.js: -------------------------------------------------------------------------------- 1 | var x = process.argv[2], 2 | y = process.argv[3]; 3 | 4 | console.log("ALL YOUR " + x + " ARE BELONG TO " + y); 5 | 6 | -------------------------------------------------------------------------------- /levelmeup/basics-batch.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var level = require('level'); 3 | var db = level(process.argv[2]); 4 | 5 | var operations = []; 6 | 7 | fs.readFile(process.argv[3], function (err, data) { 8 | if (err) 9 | throw err; 10 | 11 | var lines = data.toString().split('\n'); 12 | 13 | operations = lines.map(function (line) { 14 | var params = line.split(','), 15 | op = { 16 | type: params[0], 17 | key: params[1] 18 | }; 19 | 20 | if (params[2]) { 21 | op.value = params[2]; 22 | } 23 | 24 | return op; 25 | }); 26 | 27 | db.batch(operations, function (err) { 28 | if (err) 29 | console.error(err); 30 | }); 31 | }); 32 | 33 | -------------------------------------------------------------------------------- /levelmeup/basics-get.js: -------------------------------------------------------------------------------- 1 | var level = require('level'); 2 | var db = level(process.argv[2]); 3 | 4 | for (var i = 0; i <= 100; ++i) { 5 | (function (currKey) { 6 | db.get(currKey, function (err, data) { 7 | if (err) { 8 | return; 9 | } 10 | 11 | console.log("%s=%s", currKey, data); 12 | }); 13 | }("key" + i)); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /levelmeup/basics-put.js: -------------------------------------------------------------------------------- 1 | var level = require('level'); 2 | var db = level(process.argv[2]); 3 | 4 | var data = JSON.parse(process.argv[3]); 5 | 6 | Object.keys(data).forEach(function (key) { 7 | db.put(key, data[key], function (err) { 8 | if (err) { 9 | return console.error('Error in put();'); 10 | } 11 | 12 | console.error(key + " = " + data[key]); 13 | }); 14 | }); 15 | 16 | -------------------------------------------------------------------------------- /levelmeup/get-your-level-on.js: -------------------------------------------------------------------------------- 1 | var level = require('level'); 2 | var db = level(process.argv[2]); 3 | 4 | db.get('levelmeup', function (err, data) { 5 | if (err) { 6 | throw err; 7 | } 8 | 9 | console.log(data); 10 | }); 11 | -------------------------------------------------------------------------------- /levelmeup/horse_js-count.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function (db, date, callback) { 3 | var count = 0, 4 | stream = db.createReadStream({ start: date }); 5 | 6 | stream.on('data', function (data) { 7 | count++; 8 | }); 9 | 10 | stream.on('error', function (err) { 11 | db.close(); 12 | callback(err); 13 | }); 14 | 15 | stream.on('end', function () { 16 | callback(null, count); 17 | }); 18 | }; 19 | 20 | 21 | -------------------------------------------------------------------------------- /levelmeup/horse_js-tweets.js: -------------------------------------------------------------------------------- 1 | module.exports = function (db, date, cb) { 2 | var tweets = []; 3 | 4 | db.createReadStream({ 5 | start: date, 6 | 7 | // append last ASCII character to 'end' date to differentiate from 'start' 8 | end: date + '\xff' 9 | }) 10 | .on('data', function (data) { 11 | tweets.push(data.value); 12 | }) 13 | .on('error', function (err) { 14 | cb(err); 15 | }) 16 | .on('end', function () { 17 | cb(null, tweets); 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /levelmeup/keywise.js: -------------------------------------------------------------------------------- 1 | var db = require('level')(process.argv[2], { valueEncoding: 'json' }); 2 | var data = require(process.argv[3]); 3 | 4 | var operations = []; 5 | data.forEach(function (entry) { 6 | var key; 7 | if (entry.type === 'user') { 8 | key = entry.name; 9 | } 10 | else { 11 | key = entry.user + "!" + entry.name; 12 | } 13 | 14 | operations.push({ 15 | type: 'put', 16 | key: key, 17 | value: entry 18 | }); 19 | }); 20 | 21 | db.batch(operations); 22 | 23 | -------------------------------------------------------------------------------- /levelmeup/multilevel.js: -------------------------------------------------------------------------------- 1 | var multilevel = require('multilevel'); 2 | var net = require('net'); 3 | 4 | var db = multilevel.client(); 5 | var connection = net.connect(4545); 6 | 7 | connection.pipe(db.createRpcStream()).pipe(connection); 8 | 9 | db.get('multilevelmeup', function (err, data) { 10 | if (err) { 11 | throw err; 12 | } 13 | 14 | console.log(data); 15 | connection.end(); 16 | }); 17 | -------------------------------------------------------------------------------- /levelmeup/short-scrabble-words.js: -------------------------------------------------------------------------------- 1 | module.exports.init = function (db, words, cb) { 2 | var ops = []; 3 | 4 | words.forEach(function (word) { 5 | var key = word.length + '!' + word; 6 | 7 | ops.push({ type: 'put', key: key, value: word }); 8 | }); 9 | 10 | db.batch(ops, cb); 11 | }; 12 | 13 | module.exports.query = function (db, word, cb) { 14 | var length = word.length, 15 | word = word.replace(/\*/g, ''), 16 | key = length + '!' + word, 17 | words = []; 18 | 19 | db.createReadStream({ start: key, end: key + '\xff' }) 20 | .on('data', function (data) { 21 | words.push(data.value); 22 | }) 23 | .on('error', function (err) { 24 | cb(err); 25 | throw err; 26 | }) 27 | .on('end', function () { 28 | cb(null, words); 29 | }); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /levelmeup/streaming.js: -------------------------------------------------------------------------------- 1 | var level = require('level'); 2 | var db = level(process.argv[2]); 3 | 4 | db.createReadStream().on('data', function (data) { 5 | console.log('%s=%s', data.key, data.value); 6 | }); 7 | 8 | -------------------------------------------------------------------------------- /levelmeup/sublevel.js: -------------------------------------------------------------------------------- 1 | var level = require('level'), 2 | sub = require('level-sublevel'); 3 | 4 | var db = sub(level(process.argv[2])); 5 | 6 | db.sublevel('dinosaurs').put('slogan', 'rawr'); 7 | db.sublevel('robots').put('slogan', 'beep boop'); 8 | 9 | -------------------------------------------------------------------------------- /makemehapi/directories.js: -------------------------------------------------------------------------------- 1 | var Hapi = require('hapi'), 2 | path = require('path'); 3 | 4 | var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080); 5 | 6 | server.route({ 7 | method: 'GET', 8 | path: '/foo/bar/baz/{param}', 9 | handler: { 10 | directory: { 11 | path: path.join(__dirname, '/public') 12 | } 13 | } 14 | }); 15 | 16 | server.start(); 17 | 18 | -------------------------------------------------------------------------------- /makemehapi/handling.js: -------------------------------------------------------------------------------- 1 | var Hapi = require('hapi'); 2 | var path = require('path'); 3 | 4 | var server = Hapi.createServer('localhost', process.argv[2] || 8080); 5 | 6 | server.route({ 7 | method: 'GET', 8 | path: '/', 9 | handler: { 10 | file: path.join(__dirname, 'public/index.html') 11 | } 12 | }); 13 | 14 | server.start(); 15 | 16 | -------------------------------------------------------------------------------- /makemehapi/hello-hapi.js: -------------------------------------------------------------------------------- 1 | var Hapi = require('hapi'); 2 | 3 | var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080); 4 | 5 | server.route({ 6 | method: 'GET', 7 | path: '/', 8 | handler: function (req, reply) { 9 | reply('Hello Hapi'); 10 | } 11 | }); 12 | 13 | server.start(); 14 | 15 | 16 | -------------------------------------------------------------------------------- /makemehapi/helpers/helper.js: -------------------------------------------------------------------------------- 1 | module.exports = function (context) { 2 | return context.data.root.query.name + context.data.root.query.suffix; 3 | }; 4 | 5 | -------------------------------------------------------------------------------- /makemehapi/helping.js: -------------------------------------------------------------------------------- 1 | var Hapi = require('hapi'), 2 | path = require('path'); 3 | 4 | var options = { 5 | views: { 6 | path: path.join(__dirname, '/templates'), 7 | engines: { 8 | html: require('handlebars') 9 | }, 10 | helpersPath: 'helpers' 11 | } 12 | }; 13 | 14 | var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080, options); 15 | 16 | server.route({ 17 | method: 'GET', 18 | path: '/', 19 | handler: { 20 | view: 'helper-template.html' 21 | } 22 | }); 23 | 24 | server.start(); 25 | 26 | -------------------------------------------------------------------------------- /makemehapi/proxies.js: -------------------------------------------------------------------------------- 1 | var Hapi = require('hapi'); 2 | 3 | var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080); 4 | 5 | server.route({ 6 | method: 'GET', 7 | path: '/proxy', 8 | handler: { 9 | proxy: { 10 | host: 'localhost', 11 | port: 65535 12 | } 13 | } 14 | }); 15 | 16 | server.start(); 17 | 18 | -------------------------------------------------------------------------------- /makemehapi/public/file.html: -------------------------------------------------------------------------------- 1 | 2 | Hello Directories 3 | 4 | Hello Directories 5 | 6 | 7 | -------------------------------------------------------------------------------- /makemehapi/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | Hello Handling 3 | 4 | Hello Handling 5 | 6 | 7 | -------------------------------------------------------------------------------- /makemehapi/routes.js: -------------------------------------------------------------------------------- 1 | var Hapi = require('hapi'); 2 | 3 | var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080); 4 | 5 | server.route({ 6 | method: 'GET', 7 | path: '/{name}', 8 | handler: function (req, rep) { 9 | rep('Hello ' + req.params.name); 10 | } 11 | }); 12 | 13 | server.start(); 14 | 15 | -------------------------------------------------------------------------------- /makemehapi/stream-text.txt: -------------------------------------------------------------------------------- 1 | The Pursuit of Hapi-ness 2 | -------------------------------------------------------------------------------- /makemehapi/streams.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | var fs = require('fs'); 3 | var Hapi = require('hapi'); 4 | 5 | var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080); 6 | 7 | server.route({ 8 | method: 'GET', 9 | path: '/', 10 | handler: function (req, rep) { 11 | var data = fs.createReadStream(__dirname + '/stream-text.txt'); 12 | 13 | rep(data.pipe(through(function (buf) { 14 | this.queue(rot13(buf.toString())); 15 | }, function () { 16 | this.queue(null); 17 | }))); 18 | } 19 | }); 20 | 21 | server.start(); 22 | 23 | var alphabet = 'abcdefghijklmnopqrstuvwxyz', 24 | rot13Alphabet = rotate(alphabet, 13); 25 | 26 | // Map rot13 letters 27 | var rot13Map = alphabet.split('').reduce(function (prev, curr, idx, arr) { 28 | prev[alphabet[idx]] = rot13Alphabet[idx]; 29 | prev[alphabet[idx].toUpperCase()] = rot13Alphabet[idx].toUpperCase(); 30 | 31 | return prev; 32 | }, {}); 33 | 34 | function rot13(text) { 35 | return text.split('').map(rot13Char).join(''); 36 | } 37 | 38 | function rot13Char(c) { 39 | return rot13Map[c] || c; 40 | } 41 | 42 | function rotate(text, size) { 43 | text = text.split(''); 44 | 45 | while (size--) { 46 | text.unshift(text.pop()); 47 | } 48 | 49 | return text.join(''); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /makemehapi/templates/helper-template.html: -------------------------------------------------------------------------------- 1 | 2 | Hello {{ helper }} 3 | 4 | Hello {{ helper }} 5 | 6 | 7 | -------------------------------------------------------------------------------- /makemehapi/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | Hello {{ query.name }} 3 | 4 | Hello {{ query.name }} 5 | 6 | 7 | -------------------------------------------------------------------------------- /makemehapi/views.js: -------------------------------------------------------------------------------- 1 | var Hapi = require('hapi'), 2 | path = require('path'); 3 | 4 | var options = { 5 | views: { 6 | path: path.join(__dirname, '/templates'), 7 | engines: { 8 | html: require('handlebars') 9 | } 10 | } 11 | }; 12 | 13 | var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080, options); 14 | 15 | server.route({ 16 | method: 'GET', 17 | path: '/', 18 | handler: { 19 | view: 'index.html' 20 | } 21 | }); 22 | 23 | 24 | server.start(); 25 | 26 | -------------------------------------------------------------------------------- /nodebot-workshop/01-blink-blink.js: -------------------------------------------------------------------------------- 1 | var five = require('johnny-five'); 2 | 3 | var board = new five.Board(); 4 | 5 | board.on('ready', function () { 6 | var led = new five.Led(13); 7 | 8 | led.strobe(1000); 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/always-async.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | var defer = q.defer(); 4 | 5 | defer.promise.then(console.log); 6 | 7 | defer.resolve('SECOND'); 8 | console.log('FIRST'); 9 | 10 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/an-important-rule.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | function throwMyGod() { 4 | throw new Error('OH NOES'); 5 | } 6 | 7 | function iterate(arg) { 8 | console.log(arg); 9 | 10 | return arg + 1; 11 | } 12 | 13 | q.fcall(iterate, 1) 14 | .then(iterate) 15 | .then(iterate) 16 | .then(iterate) 17 | .then(iterate) 18 | .then(throwMyGod) 19 | .then(iterate) 20 | .then(iterate) 21 | .then(iterate) 22 | .then(iterate) 23 | .then(iterate) 24 | .then(null, console.log); 25 | 26 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/do-some-work.js: -------------------------------------------------------------------------------- 1 | var qioHttp = require('q-io/http'); 2 | 3 | qioHttp.read('http://localhost:7000') 4 | .then(function (data) { 5 | return qioHttp.read('http://localhost:7001/' + data); 6 | }) 7 | .then(function (user) { 8 | console.log(JSON.parse(user)); 9 | }) 10 | .then(null, console.error) 11 | .done(); 12 | 13 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/fetch-json.js: -------------------------------------------------------------------------------- 1 | var qioHttp = require('q-io/http'); 2 | 3 | qioHttp.read('http://localhost:1337') 4 | .then(function (data) { 5 | console.log(JSON.parse(data)); 6 | }) 7 | .then(null, console.error) 8 | .done(); 9 | 10 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/fulfill-a-promise.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | var defer = q.defer(); 4 | 5 | defer.promise.then(console.log); 6 | 7 | setTimeout(defer.resolve, 300, 'RESOLVED!'); 8 | 9 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/more-functional.js: -------------------------------------------------------------------------------- 1 | var qioHttp = require('q-io/http'), 2 | _ = require('lodash'); 3 | 4 | 5 | qioHttp.read('http://localhost:7000') 6 | .then(_.compose(qioHttp.read, function (id) { return 'http://localhost:7001/' + id; })) 7 | .then(_.compose(console.log, JSON.parse)) 8 | .then(null, console.error) 9 | .done(); 10 | 11 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/multiple-promises.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | var defer1 = q.defer(), 4 | defer2 = q.defer(); 5 | 6 | function all(prom1, prom2) { 7 | var defer = q.defer(), 8 | results = [undefined, undefined], 9 | counter = 0; 10 | 11 | prom1 12 | .then(function (data) { 13 | counter += 1; 14 | results[0] = data; 15 | 16 | if (counter === 2) { 17 | defer.resolve(results); 18 | } 19 | }) 20 | .then(null, defer.reject); 21 | 22 | prom2 23 | .then(function (data) { 24 | counter += 1; 25 | results[1] = data; 26 | 27 | if (counter === 2) { 28 | defer.resolve(results); 29 | } 30 | }) 31 | .then(null, defer.reject); 32 | 33 | return defer.promise; 34 | } 35 | 36 | all(defer1.promise, defer2.promise) 37 | .then(console.log); 38 | 39 | setTimeout(function () { 40 | defer1.resolve('PROMISES'); 41 | defer2.resolve('FTW'); 42 | }, 200); 43 | 44 | 45 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/reject-a-promise.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | var defer = q.defer(); 4 | 5 | defer.promise.then(null, function (err) { 6 | console.log(err.message); 7 | }); 8 | 9 | setTimeout(defer.reject, 300, new Error('REJECTED!')); 10 | 11 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/throw-an-error.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | function parsePromised(arg) { 4 | var defer = q.defer(); 5 | 6 | try { 7 | defer.resolve(JSON.parse(arg)); 8 | } catch (e) { 9 | defer.reject(e); 10 | } 11 | 12 | return defer.promise; 13 | } 14 | 15 | 16 | parsePromised(process.argv[2]) 17 | .then(null, console.log); 18 | 19 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/to-reject-or-not-to-reject.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | var defer = q.defer(); 4 | 5 | defer.promise.then(console.log, console.log); 6 | 7 | defer.resolve('I FIRED'); 8 | defer.reject('I DID NOT FIRE'); 9 | 10 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/using-qfcall.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | q.fcall(JSON.parse, process.argv[2]) 4 | .then(null, console.log); 5 | 6 | 7 | -------------------------------------------------------------------------------- /promise-it-wont-hurt/values-and-promises.js: -------------------------------------------------------------------------------- 1 | var q = require('q'); 2 | 3 | function attachTitle(arg) { 4 | return 'DR. ' + arg; 5 | } 6 | 7 | var defer = q.defer(); 8 | 9 | defer.promise 10 | .then(attachTitle) 11 | .then(console.log); 12 | 13 | defer.resolve('MANHATTAN'); 14 | 15 | -------------------------------------------------------------------------------- /stream-adventure/beep-boop.js: -------------------------------------------------------------------------------- 1 | console.log('beep boop'); 2 | -------------------------------------------------------------------------------- /stream-adventure/combiner.js: -------------------------------------------------------------------------------- 1 | var combine = require('stream-combiner'); 2 | var split = require('split'); 3 | var through = require('through'); 4 | var zlib = require('zlib'); 5 | 6 | 7 | module.exports = function () { 8 | var genreInfo; 9 | 10 | function write(buf) { 11 | if (buf.length === 0) { 12 | return; 13 | } 14 | 15 | buf = JSON.parse(buf); 16 | if (buf.type === 'genre') { 17 | if (genreInfo) { 18 | this.queue(JSON.stringify(genreInfo) + '\n'); 19 | } 20 | 21 | genreInfo = { 22 | name: buf.name, 23 | books: [] 24 | } 25 | } 26 | else { 27 | genreInfo.books.push(buf.name); 28 | } 29 | } 30 | 31 | function end() { 32 | this.queue(JSON.stringify(genreInfo) + '\n'); 33 | this.queue(null); 34 | }; 35 | 36 | return combine( 37 | split(), 38 | through(write, end), 39 | zlib.createGzip() 40 | ); 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /stream-adventure/concat.js: -------------------------------------------------------------------------------- 1 | var concatStream = require('concat-stream'); 2 | 3 | process.stdin 4 | .pipe(concatStream(function (body) { 5 | process.stdout.write(body.toString().split('').reverse().join('')); 6 | })); 7 | 8 | -------------------------------------------------------------------------------- /stream-adventure/crypt.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto'); 2 | 3 | var stream = crypto.createDecipher('aes256', process.argv[2]); 4 | 5 | process.stdin.pipe(stream).pipe(process.stdout); 6 | 7 | -------------------------------------------------------------------------------- /stream-adventure/duplexer-redux.js: -------------------------------------------------------------------------------- 1 | var duplexer = require('duplexer'); 2 | var through = require('through'); 3 | 4 | module.exports = function (counter) { 5 | var count = {}; 6 | var tr = through(function (buf) { 7 | count[buf.country] = count[buf.country] ? count[buf.country] + 1 : 1; 8 | }, function () { 9 | counter.setCounts(count); 10 | }); 11 | 12 | return duplexer(tr, counter); 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /stream-adventure/duplexer.js: -------------------------------------------------------------------------------- 1 | var spawn = require('child_process').spawn; 2 | var duplexer = require('duplexer'); 3 | 4 | module.exports = function (cmd, args) { 5 | var proc = spawn(cmd, args); 6 | return duplexer(proc.stdin, proc.stdout); 7 | } 8 | -------------------------------------------------------------------------------- /stream-adventure/html-stream.js: -------------------------------------------------------------------------------- 1 | var trumpet = require('trumpet'); 2 | var through = require('through'); 3 | 4 | var tr = trumpet(); 5 | var stream = tr.select('.loud').createStream(); 6 | 7 | process.stdin.pipe(tr).pipe(process.stdout); 8 | stream 9 | .pipe(through(function (buf) { this.queue(buf.toString().toUpperCase()); })) 10 | .pipe(stream) 11 | 12 | 13 | -------------------------------------------------------------------------------- /stream-adventure/http-client.js: -------------------------------------------------------------------------------- 1 | var request = require('request'); 2 | 3 | var r = request.post('http://localhost:8000'); 4 | 5 | process.stdin.pipe(r).pipe(process.stdout); 6 | 7 | -------------------------------------------------------------------------------- /stream-adventure/http-server.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | var http = require('http'); 3 | 4 | var port = process.argv[2]; 5 | 6 | function write(buf) { 7 | this.queue(buf.toString().toUpperCase()); 8 | } 9 | function end() { 10 | this.queue(null); 11 | }; 12 | 13 | http.createServer(function (req, res) { 14 | if (req.method === 'POST') { 15 | req.pipe(through(write, end)).pipe(res); 16 | } 17 | }).listen(port); 18 | 19 | -------------------------------------------------------------------------------- /stream-adventure/input-output.js: -------------------------------------------------------------------------------- 1 | process.stdin.pipe(process.stdout); 2 | -------------------------------------------------------------------------------- /stream-adventure/lines.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | var split = require('split'); 3 | 4 | var even = false; 5 | 6 | var tr = through(function (buf) { 7 | buf = buf.toString(); 8 | if (even) { 9 | buf = buf.toUpperCase(); 10 | } 11 | else { 12 | buf = buf.toLowerCase(); 13 | } 14 | even = !even; 15 | this.queue(buf + "\n"); 16 | }); 17 | 18 | process.stdin 19 | .pipe(split()) 20 | .pipe(tr) 21 | .pipe(process.stdout); 22 | 23 | -------------------------------------------------------------------------------- /stream-adventure/meet-pipe.js: -------------------------------------------------------------------------------- 1 | require('fs').createReadStream(process.argv[2]).pipe(process.stdout); 2 | -------------------------------------------------------------------------------- /stream-adventure/secretz.js: -------------------------------------------------------------------------------- 1 | var tar = require('tar'); 2 | var parser = tar.Parse(); 3 | var crypto = require('crypto'); 4 | var through = require('through'); 5 | 6 | var gunzipStream = require('zlib').createGunzip(); 7 | var cypherStream = crypto.createDecipher(process.argv[2], process.argv[3]); 8 | 9 | parser.on('entry', function (e) { 10 | var md5Stream = crypto.createHash('md5', { encoding: 'hex' }); 11 | 12 | if (e.type !== 'File') { 13 | return; 14 | } 15 | 16 | e.pipe(md5Stream) 17 | .pipe(through(function (buf) { 18 | this.queue(buf.toString()); 19 | }, function () { 20 | this.queue(" " + e.path + "\n"); 21 | this.queue(null); 22 | })) 23 | .pipe(process.stdout); 24 | }); 25 | 26 | process.stdin.pipe(cypherStream).pipe(gunzipStream).pipe(parser); 27 | -------------------------------------------------------------------------------- /stream-adventure/transform.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | 3 | process.stdin.pipe(through(function (buf) { 4 | this.queue(buf.toString().toUpperCase()); 5 | }, function () { 6 | this.queue(null); 7 | })).pipe(process.stdout); 8 | 9 | -------------------------------------------------------------------------------- /stream-adventure/websockets.js: -------------------------------------------------------------------------------- 1 | var ws = require('websocket-stream'); 2 | var stream = ws('ws://localhost:8000'); 3 | 4 | stream.end('hello\n'); 5 | 6 | --------------------------------------------------------------------------------