├── .gitignore ├── README.md ├── bytewiser ├── array-buffer.js ├── buffer-concat.js ├── buffer-from-string.js ├── encoding.js ├── line-splitter.js ├── modify-buffer.js └── typed-array.js ├── count-to-6 ├── 01-hello-es6.js ├── 02-template-strings.js ├── 03-arrow-functions.js ├── 04-spread.js ├── 05-rest.js ├── 06-default-arguments-part-1.js ├── 07-default-arguments-part-2.js └── 08-tagged-template-strings.js ├── functional-javascript-workshop ├── async-loop.js ├── basic-recursion.js ├── blocking-event-loop.js ├── call.js ├── currying.js ├── easy-some.js ├── filter.js ├── function-call.js ├── function-spies.js ├── hello-world.js ├── higher-order-function.js ├── implement-map-with-reduce.js ├── map.js ├── partial-application-with-bind.js ├── partial-application-without-bind.js ├── recurison.js ├── reduce.js └── trampoline.js └── stream-adventure ├── 01-beep-boop.js ├── 02-meet-pipe.js ├── 03-input-out.js ├── 04-transform.js ├── 05-lines.js ├── 06-concat.js ├── 07-http-client.js ├── 08-http-client.js ├── 09-websockets.js ├── 10-html-stream.js ├── 11-duplexer.js ├── 12-duplexer-redux.js ├── 13-combiner.js ├── 14-crypt.js ├── 15-secretz.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | */node_modules/* 2 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repo is only my solutions to the nodeschool's exercise. 2 | 3 | 4 | Please visit http://nodeschool.io for more informations. -------------------------------------------------------------------------------- /bytewiser/array-buffer.js: -------------------------------------------------------------------------------- 1 | var num = process.argv[2]; 2 | 3 | var arr32 = new Uint32Array(1); 4 | 5 | arr32[0] = num; 6 | 7 | var arr16 = new Uint16Array(arr32.buffer); 8 | 9 | console.log(JSON.stringify(arr16)); -------------------------------------------------------------------------------- /bytewiser/buffer-concat.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | 3 | var allbuf; 4 | process.stdin.pipe(through(function(buf) { 5 | if(Buffer.isBuffer(allbuf)) { 6 | allbuf = Buffer.concat([allbuf, buf]); 7 | } else { 8 | allbuf = buf; 9 | } 10 | }, function() { 11 | console.log(allbuf); 12 | })); -------------------------------------------------------------------------------- /bytewiser/buffer-from-string.js: -------------------------------------------------------------------------------- 1 | var buf = new Buffer('bytewiser'); 2 | 3 | console.log(buf); -------------------------------------------------------------------------------- /bytewiser/encoding.js: -------------------------------------------------------------------------------- 1 | var data = process.argv.slice(2); 2 | 3 | var buffer = new Buffer(data); 4 | console.log(buffer.toString('hex')); -------------------------------------------------------------------------------- /bytewiser/line-splitter.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var path = process.argv[2]; 4 | 5 | fs.readFile(path, function(err, data) { 6 | var newlinesIdx = []; 7 | for (var i = 0; i < data.length; i++) { 8 | if(data[i] == '10') { 9 | newlinesIdx.push(i); 10 | } 11 | }; 12 | 13 | newlinesIdx.unshift(-1); 14 | for (var i = 0, j = 1; i < newlinesIdx.length; i++, j++) { 15 | console.log(data.slice(newlinesIdx[i] + 1, [newlinesIdx[j]])) 16 | }; 17 | }); -------------------------------------------------------------------------------- /bytewiser/modify-buffer.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | 3 | process.stdin.pipe(through(function(buf) { 4 | for (var i = 0; i < buf.length; i++) { 5 | if(buf[i] === 46) { 6 | buf.write('!', i); 7 | } 8 | }; 9 | console.log(buf); 10 | })) -------------------------------------------------------------------------------- /bytewiser/typed-array.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | 3 | var allbuf; 4 | process.stdin.pipe(through(function(buf) { 5 | var u8a = new Uint8Array(buf); 6 | this.queue(JSON.stringify(u8a)); 7 | this.queue('\n'); 8 | })).pipe(process.stdout); -------------------------------------------------------------------------------- /count-to-6/01-hello-es6.js: -------------------------------------------------------------------------------- 1 | console.log('HELLO ES6'); -------------------------------------------------------------------------------- /count-to-6/02-template-strings.js: -------------------------------------------------------------------------------- 1 | var name = process.argv[2]; 2 | var lowerName = name.toLowerCase(); 3 | 4 | console.log(`Hello, ${name}! 5 | Your name lowercased is "${lowerName}".`); -------------------------------------------------------------------------------- /count-to-6/03-arrow-functions.js: -------------------------------------------------------------------------------- 1 | var inputs = process.argv.slice(2); 2 | var result = inputs.map( x => x[0] ) 3 | .reduce( (memo, x) => memo + x, '' ); 4 | console.log(`[${inputs}] becomes "${result}"`); -------------------------------------------------------------------------------- /count-to-6/04-spread.js: -------------------------------------------------------------------------------- 1 | var numbers = process.argv.slice(2); 2 | 3 | var min = Math.min(...numbers); 4 | 5 | console.log(`The minimum of [${numbers}] is ${min}`); -------------------------------------------------------------------------------- /count-to-6/05-rest.js: -------------------------------------------------------------------------------- 1 | module.exports = function average(...args) { 2 | return args.reduce( (sum, x) => sum + x, 0) / args.length; 3 | }; -------------------------------------------------------------------------------- /count-to-6/06-default-arguments-part-1.js: -------------------------------------------------------------------------------- 1 | module.exports = function midpoint(lower = 0, upper = 1) { 2 | return (lower + upper) / 2; 3 | }; -------------------------------------------------------------------------------- /count-to-6/07-default-arguments-part-2.js: -------------------------------------------------------------------------------- 1 | module.exports = (str, num = str.length) => `${str}${'!'.repeat(num)}`; -------------------------------------------------------------------------------- /count-to-6/08-tagged-template-strings.js: -------------------------------------------------------------------------------- 1 | console.log(html`${process.argv[2]} says: "${process.argv[3]}"`); 2 | 3 | function html(tpls, ...args) { 4 | var str = tpls[0]; 5 | for (var i = 0; i < args.length; i++) { 6 | str = str + escape(args[i]) + tpls[i + 1]; 7 | }; 8 | return str; 9 | } 10 | 11 | function escape(raw) { 12 | return raw.replace(/&/g, "&") 13 | .replace(//g, ">") 15 | .replace(/'/g, "'") 16 | .replace(/"/g, """); 17 | }; -------------------------------------------------------------------------------- /functional-javascript-workshop/async-loop.js: -------------------------------------------------------------------------------- 1 | function loadUsers(userIds, load, done) { 2 | var users = []; 3 | var count = 0; 4 | userIds.forEach(function(id, idx) { 5 | load(id, function(data) { 6 | users[idx] = data; 7 | ++count; 8 | if(count === userIds.length) return done(users); 9 | }) 10 | }) 11 | 12 | } 13 | 14 | module.exports = loadUsers -------------------------------------------------------------------------------- /functional-javascript-workshop/basic-recursion.js: -------------------------------------------------------------------------------- 1 | function reduce(arr, fn, initial) { 2 | 3 | return (function step(idx, value) { 4 | if(idx > arr.length - 1) return value; 5 | return step(idx + 1, fn(value, arr[idx], idx, arr)) 6 | })(0, initial) 7 | } 8 | 9 | module.exports = reduce -------------------------------------------------------------------------------- /functional-javascript-workshop/blocking-event-loop.js: -------------------------------------------------------------------------------- 1 | function repeat(operation, num) { 2 | if (num <= 0) return 3 | 4 | operation() 5 | 6 | // release control every 10 or so 7 | // iterations. 8 | // 10 is arbitrary. 9 | if (num % 10 === 0) { 10 | setTimeout(function() { 11 | repeat(operation, --num) 12 | }) 13 | } else { 14 | repeat(operation, --num) 15 | } 16 | } 17 | 18 | module.exports = repeat 19 | 20 | 21 | // this is not my solutions -------------------------------------------------------------------------------- /functional-javascript-workshop/call.js: -------------------------------------------------------------------------------- 1 | function duckCount() { 2 | return Array.prototype.filter.call(arguments, (function(arg) { 3 | return Object.prototype.hasOwnProperty.call(arg, 'quack'); 4 | })).length; 5 | } 6 | 7 | module.exports = duckCount 8 | -------------------------------------------------------------------------------- /functional-javascript-workshop/currying.js: -------------------------------------------------------------------------------- 1 | function curryN(fn, n) { 2 | if(typeof n !== 'number') n = fn.length; 3 | 4 | function genCurry(prev) { 5 | return function(arg) { 6 | var args = prev.concat(arg); 7 | if(args.length < n) return genCurry(args); 8 | return fn.apply(this, args); 9 | 10 | 11 | } 12 | } 13 | 14 | return genCurry([]); 15 | 16 | 17 | } 18 | 19 | module.exports = curryN 20 | 21 | 22 | // fin. by reference -------------------------------------------------------------------------------- /functional-javascript-workshop/easy-some.js: -------------------------------------------------------------------------------- 1 | function checkUsersValid(goodUsers) { 2 | return function(submittedUsers) { 3 | return submittedUsers.every(function(submit) { 4 | return goodUsers.some(function(good) { 5 | return good.id === submit.id; 6 | }) 7 | }) 8 | }; 9 | } 10 | 11 | module.exports = checkUsersValid -------------------------------------------------------------------------------- /functional-javascript-workshop/filter.js: -------------------------------------------------------------------------------- 1 | function getShortMessages(messages) { 2 | var filtered = messages.filter(function(msg) { 3 | if(msg.message && msg.message.length < 50) { 4 | return true; 5 | } 6 | }); 7 | 8 | 9 | return filtered.map(function(msg) { 10 | return msg.message; 11 | }) 12 | } 13 | 14 | module.exports = getShortMessages -------------------------------------------------------------------------------- /functional-javascript-workshop/function-call.js: -------------------------------------------------------------------------------- 1 | module.exports = Function.prototype.call.bind(Array.prototype.slice); -------------------------------------------------------------------------------- /functional-javascript-workshop/function-spies.js: -------------------------------------------------------------------------------- 1 | function Spy(target, method) { 2 | var reuslt = {count: 0}; 3 | 4 | var fn = target[method]; 5 | 6 | target[method] = function() { 7 | reuslt.count += 1; 8 | return fn.apply(this, arguments); 9 | } 10 | 11 | return reuslt; 12 | } 13 | 14 | module.exports = Spy -------------------------------------------------------------------------------- /functional-javascript-workshop/hello-world.js: -------------------------------------------------------------------------------- 1 | function upperCaser(input) { 2 | return input.toString().toUpperCase(); 3 | } 4 | 5 | module.exports = upperCaser -------------------------------------------------------------------------------- /functional-javascript-workshop/higher-order-function.js: -------------------------------------------------------------------------------- 1 | function repeat(operation, num) { 2 | if(num === 0) return; 3 | operation(); 4 | return repeat(operation, num - 1); 5 | } 6 | 7 | module.exports = repeat -------------------------------------------------------------------------------- /functional-javascript-workshop/implement-map-with-reduce.js: -------------------------------------------------------------------------------- 1 | module.exports = function arrayMap(arr, fn) { 2 | var result = []; 3 | arr.reduce(function(prev, curr, idx, arr) { 4 | result.push(fn(curr)); 5 | }, null); 6 | return result; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /functional-javascript-workshop/map.js: -------------------------------------------------------------------------------- 1 | function doubleAll(numbers) { 2 | var result = [] 3 | numbers.map(function(number) { 4 | result.push(number * 2); 5 | }); 6 | return result 7 | } 8 | 9 | module.exports = doubleAll -------------------------------------------------------------------------------- /functional-javascript-workshop/partial-application-with-bind.js: -------------------------------------------------------------------------------- 1 | module.exports = function(namespace) { 2 | return console.log.bind(null, namespace); 3 | } 4 | -------------------------------------------------------------------------------- /functional-javascript-workshop/partial-application-without-bind.js: -------------------------------------------------------------------------------- 1 | var slice = Array.prototype.slice 2 | 3 | function logger(namespace) { 4 | return function() { 5 | var args = slice.call(arguments); 6 | console.log.apply(null, [namespace].concat(args)); 7 | } 8 | } 9 | 10 | module.exports = logger -------------------------------------------------------------------------------- /functional-javascript-workshop/recurison.js: -------------------------------------------------------------------------------- 1 | function getDependencies(tree, result) { 2 | var result = result || []; 3 | var deps = tree.dependencies || {}; 4 | if(!tree.dependencies) return []; 5 | 6 | Object.keys(deps).forEach(function(dep) { 7 | var depStr = dep + "@" + deps[dep].version; 8 | 9 | if(result.indexOf(depStr) < 0) { 10 | result.push(depStr); 11 | } 12 | 13 | getDependencies(deps[dep], result); 14 | }) 15 | 16 | return result.sort(); 17 | 18 | } 19 | 20 | module.exports = getDependencies 21 | 22 | // by reference -------------------------------------------------------------------------------- /functional-javascript-workshop/reduce.js: -------------------------------------------------------------------------------- 1 | function countWords(inputWords) { 2 | var result = {}; 3 | inputWords.reduce(function(prev, current, idx, arry) { 4 | if(!result[current]) { 5 | result[current] = 1; 6 | } else { 7 | result[current]++; 8 | } 9 | return current; 10 | }, null); 11 | return result; 12 | } 13 | 14 | module.exports = countWords 15 | 16 | -------------------------------------------------------------------------------- /functional-javascript-workshop/trampoline.js: -------------------------------------------------------------------------------- 1 | function repeat(operation, num) { 2 | // Modify this so it doesn't cause a stack overflow! 3 | if (num <= 0) return 4 | 5 | return function() { 6 | operation() 7 | return repeat(operation, --num) 8 | } 9 | } 10 | 11 | function trampoline(fn) { 12 | while (fn && typeof fn === 'function') { 13 | fn = fn(); 14 | } 15 | 16 | return fn; 17 | } 18 | 19 | module.exports = function(operation, num) { 20 | // You probably want to call your trampoline here! 21 | return trampoline(function() { 22 | return repeat(operation, num) 23 | }) 24 | } 25 | 26 | 27 | // by reference -------------------------------------------------------------------------------- /stream-adventure/01-beep-boop.js: -------------------------------------------------------------------------------- 1 | console.log('beep boop'); -------------------------------------------------------------------------------- /stream-adventure/02-meet-pipe.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | fs.createReadStream(process.argv[2]).pipe(process.stdout); -------------------------------------------------------------------------------- /stream-adventure/03-input-out.js: -------------------------------------------------------------------------------- 1 | process.stdin.pipe(process.stdout) -------------------------------------------------------------------------------- /stream-adventure/04-transform.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | 3 | var tr = through(function(buf) { 4 | this.queue(buf.toString().toUpperCase()); 5 | }); 6 | 7 | process.stdin.pipe(tr).pipe(process.stdout) -------------------------------------------------------------------------------- /stream-adventure/05-lines.js: -------------------------------------------------------------------------------- 1 | var through = require('through'); 2 | var split = require('split'); 3 | 4 | var count = 0; 5 | 6 | var tr = through(function(buf) { 7 | if(count%2 === 1) { 8 | this.queue(buf.toString().toUpperCase() + '\n'); 9 | } else { 10 | this.queue(buf.toString().toLowerCase()); 11 | this.queue('\n') 12 | } 13 | count++; 14 | }); 15 | 16 | process.stdin.pipe(split()).pipe(tr).pipe(process.stdout) -------------------------------------------------------------------------------- /stream-adventure/06-concat.js: -------------------------------------------------------------------------------- 1 | var concat = require('concat-stream'); 2 | 3 | process.stdin.pipe(concat(function (src) { 4 | var s = src.toString().split('').reverse().join(''); 5 | console.log(s); 6 | })); -------------------------------------------------------------------------------- /stream-adventure/07-http-client.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var through = require('through'); 3 | 4 | 5 | var srv = http.createServer(function(req, res) { 6 | req.pipe(through(function(buf) { 7 | this.queue(buf.toString().toUpperCase()) 8 | })).pipe(res) 9 | }); 10 | 11 | srv.listen(process.argv[2]); -------------------------------------------------------------------------------- /stream-adventure/08-http-client.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var request = require('request'); 3 | 4 | process.stdin.pipe(request.post('http://localhost:8000')).pipe(process.stdout); -------------------------------------------------------------------------------- /stream-adventure/09-websockets.js: -------------------------------------------------------------------------------- 1 | var ws = require('websocket-stream'); 2 | 3 | var stream = ws('ws://localhost:8000'); 4 | 5 | 6 | stream.end('hello\n'); -------------------------------------------------------------------------------- /stream-adventure/10-html-stream.js: -------------------------------------------------------------------------------- 1 | var trumpet = require('trumpet'); 2 | var through = require('through'); 3 | var fs = require('fs'); 4 | var tr = trumpet(); 5 | 6 | 7 | process.stdin.pipe(tr).pipe(process.stdout); 8 | 9 | var stream = tr.select('.loud').createStream(); 10 | 11 | stream.pipe(through(function(buf) { 12 | this.queue(buf.toString().toUpperCase()) 13 | })).pipe(stream) 14 | -------------------------------------------------------------------------------- /stream-adventure/11-duplexer.js: -------------------------------------------------------------------------------- 1 | var spawn = require('child_process').spawn; 2 | var duplexer = require('duplexer'); 3 | 4 | module.exports = function(cmd, args) { 5 | var exec = spawn(cmd, args); 6 | return duplexer(exec.stdin, exec.stdout); 7 | } -------------------------------------------------------------------------------- /stream-adventure/12-duplexer-redux.js: -------------------------------------------------------------------------------- 1 | var duplexer = require('duplexer'); 2 | var through = require('through'); 3 | 4 | module.exports = function(counter) { 5 | var countries = {}; 6 | return duplexer(through(function(buf) { 7 | if(!countries[buf.country]) { 8 | countries[buf.country] = 1; 9 | } else { 10 | countries[buf.country]++; 11 | } 12 | }, function() { 13 | counter.setCounts(countries); 14 | }), counter) 15 | } -------------------------------------------------------------------------------- /stream-adventure/13-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 | module.exports = function () { 7 | var lib = {}; 8 | var currentGenre = ''; 9 | 10 | return combine( 11 | split(), 12 | through(function(buf) { 13 | 14 | if(buf) { 15 | buf = JSON.parse(buf); 16 | } else { 17 | if(currentGenre) { 18 | this.queue(JSON.stringify(lib[currentGenre]) + '\n'); 19 | } 20 | } 21 | if(buf.type === 'genre') { 22 | if(currentGenre) { 23 | this.queue(JSON.stringify(lib[currentGenre]) + '\n'); 24 | } 25 | 26 | if(!lib[buf.name] ) { 27 | lib[buf.name] = {"name": buf.name, "books": []} 28 | currentGenre = buf.name; 29 | } 30 | } else { 31 | lib[currentGenre].books.push(buf.name) 32 | } 33 | 34 | }), 35 | zlib.createGzip() 36 | 37 | ) 38 | } -------------------------------------------------------------------------------- /stream-adventure/14-crypt.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto'); 2 | var key = process.argv[2]; 3 | 4 | process.stdin.pipe(crypto.createDecipher('aes256', key)).pipe(process.stdout); -------------------------------------------------------------------------------- /stream-adventure/15-secretz.js: -------------------------------------------------------------------------------- 1 | var zlib = require('zlib'); 2 | var crypto = require('crypto'); 3 | var fs = require('fs'); 4 | var tar = require('tar'); 5 | var through = require('through'); 6 | 7 | 8 | 9 | var parser = tar.Parse(); 10 | parser.on('entry', function(e) { 11 | if(e.type === 'Directory') return; 12 | e.pipe(crypto.createHash('md5', { encoding: 'hex' })).pipe(through(function(buf) { 13 | this.queue(buf.toString() + ' ' + e.path + '\n'); 14 | })).pipe(process.stdout); 15 | }) 16 | 17 | process.stdin.pipe(crypto.createDecipher(process.argv[2], process.argv[3])).pipe(zlib.createGunzip()).pipe(parser) 18 | -------------------------------------------------------------------------------- /stream-adventure/README.md: -------------------------------------------------------------------------------- 1 | Please visit http://nodeschool.io/#stream-adventure for more information --------------------------------------------------------------------------------