Skip to content

Instantly share code, notes, and snippets.

@Anna-Myzukina
Last active September 10, 2018 16:24
Show Gist options
  • Save Anna-Myzukina/74fb53082bef2daf4cdf1df6f1fa7752 to your computer and use it in GitHub Desktop.
Save Anna-Myzukina/74fb53082bef2daf4cdf1df6f1fa7752 to your computer and use it in GitHub Desktop.
stream-adventure
//Exercise 1
/**
* Make a new directory for your stream-adventure solutions (mkdir stream-adventure and enter it cd ./stream-adventure)
Create a new file called beep_boop.js that uses console.log to output "beep boop".
*/
console.log("beep boop");
//Exercise 14
/**
* Create a module in a new file named combiner.js, it should return a readable/writable stream using the
`stream-combiner` module.
*/
var combine = require('stream-combiner');
var through = require('through');
var split = require('split');
var zlib = require('zlib');
module.exports = function () {
var grouper = through(write, end);
var current;
function write (line) {
if (line.length === 0) return;
var row = JSON.parse(line);
if (row.type === 'genre') {
if (current) {
this.queue(JSON.stringify(current) + '\n');
}
current = { name: row.name, books: [] };
}
else if (row.type === 'book') {
current.books.push(row.name);
}
}
function end () {
if (current) {
this.queue(JSON.stringify(current) + '\n');
}
this.queue(null);
}
return combine(split(), grouper, zlib.createGzip());
};
//Exercise 6
/**
* Create a new file called concat.js.
You will be given text on process.stdin. Buffer the text and reverse it using
the `concat-stream` module before writing it to stdout.`concat-stream` is a write stream that you can pass a callback to get the
complete contents of a stream as a single buffer.In your adventure you'll only need to buffer input with `concat()` from
process.stdin.
`npm install concat-stream` in the directory where your solution
file is located.
*/
var concat = require('concat-stream');
process.stdin.pipe(concat(function (buffer) {
process.stdout.write(buffer.toString().split('').reverse().join(''))
process.stdout.write('\n')
}));
//Exercise 15
/**
* Your program will be given a passphrase on `process.argv[2]` and 'aes256'
encrypted data will be written to stdin.
Simply decrypt the data and stream the result to process.stdout.
You can use the `crypto.createDecipher()` api from node core to solve this
challenge. Here's an example:
var crypto = require('crypto');
var stream = crypto.createDecipher('RC4', 'robots');
stream.pipe(process.stdout);
stream.write(Buffer([ 135, 197, 164, 92, 129, 90, 215, 63, 92 ]));
stream.end();
Instead of calling `.write()` yourself, just pipe stdin into your decrypter.
*/
var crypto = require('crypto');
var passphrase = process.argv[2];
var stream = crypto.createDecipher('aes256', passphrase);
process.stdin.pipe(stream).pipe(process.stdout);
//Exercise 13
/**
* In this example, you will be given a readable stream, `counter`, as the first
argument to your exported function:
module.exports = function (counter) {
// return a duplex stream to count countries on the writable side
// and pass through `counter` on the readable side
};
Return a duplex stream with the `counter` as the readable side. You will be
written objects with a 2-character `country` field as input, such as these:
{"short":"OH","name":"Ohio","country":"US"}
{"name":"West Lothian","country":"GB","region":"Scotland"}
{"short":"NSW","name":"New South Wales","country":"AU"}
Create an object to track the number of occurrences of each unique country code.
`npm install duplexer2` in the directory where your solution file is located.
*/
var duplexer = require('duplexer2');
var through = require('through2').obj;
module.exports = function (counter) {
var counts = {};
var input = through(write, end);
return duplexer({ objectMode: true }, input, counter);
function write(row, _, next) {
counts[row.country] = (counts[row.country] || 0) + 1;
next();
}
function end(done) {
counter.setCounts(counts);
done();
}
};
//Exercise 12
/**
* Write a program that exports a function that spawns a process from a `cmd`
string and an `args` array and returns a single duplex stream joining together
the stdin and stdout of the spawned process:
var spawn = require('child_process').spawn;
module.exports = function (cmd, args) {
// spawn the process and return a single stream
// joining together the stdin and stdout here
};
`npm install duplexer2` in the directory where your solution file is located.
*/
var spawn = require('child_process').spawn;
var duplexer2 = require('duplexer2');
module.exports = function(cmd, args) {
var spawnProcess = spawn(cmd, args);
return duplexer2(spawnProcess.stdin, spawnProcess.stdout);
};
//Exercise 10
/**
* Your program will get some html written to stdin. Convert all the inner html to
upper-case for elements with a class name of "loud",
and pipe all the html to stdout.
You can use `trumpet` and `through2` to solve this adventure.
*/
var trumpet = require('trumpet');
var through = require('through2');
var stream = through(write, end);
var tr = trumpet();
var loud = tr.select('.loud').createStream();
loud.pipe(stream).pipe(loud);
function write(chunk, encoding, next) {
this.push(chunk.toString().toUpperCase());
next();
}
function end(done) {
done();
}
process.stdin.pipe(tr).pipe(process.stdout);
//Exercise 8
/**
* Send an HTTP POST request to http://localhost:8099 and pipe process.stdin into it. Pipe the response stream to process.stdout.
*/
var request = require('request');
var postRequest = request.post('http://localhost:8099');
process.stdin.pipe(postRequest).pipe(process.stdout);
//Exercise 7
/*In this challenge, write an http server that uses a through stream to write
back the request stream as upper-cased response data for POST requests.*/
var http = require('http');
var fs = require('fs');
var through = require('through');
// from transform challenge
var to_upper = function (buffer) {
this.queue(buffer.toString().toUpperCase())
}
var server = http.createServer(function (req, res) {
if (req.method === 'POST') {
req
.pipe(through(to_upper))
.pipe(res);
}
});
server.listen(process.argv[2]);
//Exercise 3
/**
* Take data from `process.stdin` and pipe it to `process.stdout`.
With `.pipe()`. `process.stdin.pipe()` to be exact.
Don't overthink this
*/
process.stdin.pipe(process.stdout);
//Exercise 5
/**
* convert even-numbered lines to upper-case and odd-numbered
lines to lower-case
1.npm install split through2
*/
var through = require('through2');
var split = require('split');
var lineCount = 0;
var tr = through(function (buf, _, next) {
var line = buf.toString();
this.push(lineCount % 2 === 0
? line.toLowerCase() + '\n'
: line.toUpperCase() + '\n'
);
lineCount++;
next();
});
process.stdin.pipe(split()).pipe(tr).pipe(process.stdout);
//Exercise 2
/**
* You will get a file as the first argument to your program (process.argv[2]).
Use `fs.createReadStream()` to pipe the given file to `process.stdout`.
`fs.createReadStream()` takes a file as an argument and returns a readable
stream that you can call `.pipe()` on. Here's a readable stream that pipes its
data to `process.stderr`:
var fs = require('fs');
fs.createReadStream('data.txt').pipe(process.stderr);
Your program is basically the same idea, but instead of `'data.txt'`, the
filename comes from `process.argv[2]` and you should pipe to stdout, not stderr.
*/
var fs = require('fs')
var filename = process.argv[2]
fs.createReadStream(filename).pipe(process.stdout)
//Exercise 16
/**
* An encrypted, gzipped tar file will be piped in on process.stdin. To beat this
challenge, for each file in the tar input, print a hex-encoded md5 hash of the
file contents followed by a single space followed by the filename, then a
newline.
You will receive the cipher name as process.argv[2] and the cipher passphrase as
process.argv[3]. You can pass these arguments directly through to
`crypto.createDecipher()`.
The built-in zlib library you get when you `require('zlib')` has a
`zlib.createGunzip()` that returns a stream for gunzipping.
The `tar` module from npm has a `tar.Parse()` function that emits `'entry'`
events for each file in the tar input. Each `entry` object is a readable stream
of the file contents from the archive and:
`entry.type` is the kind of file ('File', 'Directory', etc)
`entry.path` is the file path
Using the tar module looks like:
var tar = require('tar');
var parser = tar.Parse();
parser.on('entry', function (e) {
console.dir(e);
});
var fs = require('fs');
fs.createReadStream('file.tar').pipe(parser);
Use `crypto.createHash('md5', { encoding: 'hex' })` to generate a stream that
outputs a hex md5 hash for the content written to it.
`npm install tar through` in the directory where your solution file lives.
var crypto = require('crypto');
var zlib = require('zlib');
var tar = require('tar');
var through = require('through2');
var decrypter = crypto.createDecipher(process.argv[2], process.argv[3]);
var unzipper = zlib.createGunzip();
var parser = tar.Parse();
parser.on('entry', function(e){
var hashStream = crypto.createHash('md5', {encoding: 'hex'});
if (e.type !== 'File') { return; }
e.pipe(hashStream)
.pipe(through(function(buf, _, next){
this.push(buf.toString());
this.push(" " + e.path + '\n');
next();
})).pipe(process.stdout);
})
process.stdin
.pipe(decrypter)
.pipe(unzipper)
.pipe(parser)
;*/
var crypto = require('crypto');
var zlib = require('zlib');
var tar = require('tar');
var through = require('through');
var tarParser = tar.Parse().on('entry', function (file) {
if (file.type === 'File') {
var hexmd5Stream = crypto.createHash('md5', {encoding: 'hex'})
file.pipe(hexmd5Stream).pipe(through(write))
}
function write(chunk) {
console.log(chunk.toString() +' '+ file.path);
}
})
var cipherName = process.argv[2]
var passphrase = process.argv[3]
var decryptor = crypto.createDecipher(cipherName, passphrase)
process.stdin.pipe(decryptor).pipe(zlib.createGunzip()).pipe(tarParser)
//Exercise 4
/**
* Convert data from `process.stdin` to upper-case data on `process.stdout`
using the `through2` module.
To get the `through2` module you'll need to do:
npm install through2
A transform stream takes input data and applies an operation to the data to
produce the output data.
Create a through stream with a `write` and `end` function:
var through = require('through2');
var stream = through(write, end);
The `write` function is called for every buffer of available input:
function write (buffer, encoding, next) {
// ...
}
and the `end` function is called when there is no more data:
function end () {
// ...
}
Inside the write function, call `this.push()` to produce output data and call
`next()` when you're ready to receive the next chunk:
function write (buffer, encoding, next) {
this.push('I got some data: ' + buffer + '\n');
next();
}
and call `done()` to finish the output:
function end (done) {
done();
}
`write` and `end` are both optional.
If `write` is not specified, the default implementation passes the input data to
the output unmodified.
If `end` is not specified, the default implementation calls `this.push(null)`
to close the output side when the input side ends.
Make sure to pipe `process.stdin` into your transform stream
and pipe your transform stream into `process.stdout`, like this:
process.stdin.pipe(stream).pipe(process.stdout);
To convert a buffer to a string, call `buffer.toString()`.
*/
var through = require('through2');
var stream = through(function (buffer) {
this.push('I got some data:' + buffer.toString().toUpperCase());
next();
});
process.stdin.pipe(stream).pipe(process.stdout);
//Exercise 9
/**
* In this adventure, write some browser code that uses the websocket-stream module
to print the string "hello\n".
Your solution file will be compiled with browserify and the verify script will
prompt you to open `http://localhost:8099` in a browser to verify your solution
*/
var ws = require('websocket-stream');
var stream = ws('ws://localhost:8099');
stream.write('hello\n');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment