[Pkg-javascript-commits] [node-jstream] 01/02: Imported Upstream version 0.2.7
Andrew Kelley
andrewrk-guest at moszumanska.debian.org
Thu Jul 3 22:36:11 UTC 2014
This is an automated email from the git hooks/post-receive script.
andrewrk-guest pushed a commit to branch master
in repository node-jstream.
commit de834459512a1cbcbf80730864e7fbb1957862ef
Author: Andrew Kelley <superjoe30 at gmail.com>
Date: Thu Jul 3 22:31:21 2014 +0000
Imported Upstream version 0.2.7
---
.gitignore | 1 +
.travis.yml | 4 ++
LICENSE | 19 +++++
README.md | 54 ++++++++++++++
lib/index.js | 176 ++++++++++++++++++++++++++++++++++++++++++++++
package.json | 29 ++++++++
test/assets/array.json | 6 ++
test/assets/arrayKey.json | 6 ++
test/assets/data.json | 19 +++++
test/assets/function.json | 14 ++++
test/assets/many.json | 18 +++++
test/assets/propName.json | 7 ++
test/assets/regexp.json | 7 ++
test/main-test.js | 31 ++++++++
test/path-test.js | 45 ++++++++++++
test/run.js | 35 +++++++++
16 files changed, 471 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..09d3ef3
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - 0.8
+ - 0.10
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..809ab08
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2012 by Roly Fentanes
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e34476b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,54 @@
+# node-jstream [](http://travis-ci.org/fent/node-jstream)
+
+Continuously reads in JSON and outputs Javascript objects. Meant to be used with keep-alive connections that send back JSON on updates.
+
+# Usage
+
+```js
+var JStream = require('jstream');
+var request = require('request');
+
+request('http://api.myhost.com/updates.json')
+ .pipe(new JStream()).on('data', function(obj) {
+ console.log('new js object');
+ console.log(obj);
+ });
+```
+
+# API
+### new JStream([path])
+Creates an instance of JStream. Inherits from `Stream`. Can be written to and emits `data` events with Javascript objects.
+
+`path` can be an array of property names, `RegExp`'s, booleans, and/or functions. Objects that match will be emitted in `data` events. Passing no `path` means emitting whole Javascript objects as they come in. For example, given the `path` `['results', true, 'name']` and the following JSON gets written into JStream
+
+```js
+{ "results": [
+ {"seq":99230
+ ,"id":"newsemitter"
+ ,"changes":[{"rev":"5-aca7782ab6beeaef30c36b888f817d2e"}]}
+, {"seq":99235
+ ,"id":"chain-tiny"
+ ,"changes":[{"rev":"19-82224279a743d2744f10d52697cdaea9"}]}
+, {"seq":99238
+ ,"id":"Hanzi"
+ ,"changes":[{"rev":"4-5ed20f975bd563ae5d1c8c1d574fe24c"}],"deleted":true}
+] }
+```
+
+JStream will emit `newsemitter`, `chain-tiny`, and `Hanzi` in its `data` event.
+
+
+# Install
+
+ npm install jstream
+
+
+# Tests
+Tests are written with [mocha](http://visionmedia.github.com/mocha/)
+
+```bash
+npm test
+```
+
+# License
+MIT
diff --git a/lib/index.js b/lib/index.js
new file mode 100644
index 0000000..f3eb480
--- /dev/null
+++ b/lib/index.js
@@ -0,0 +1,176 @@
+var Transform = require('readable-stream').Transform;
+var util = require('util');
+var clarinet = require('clarinet');
+
+
+/**
+ * @constructor
+ * @extends {Transform}
+ */
+var JStream = module.exports = function(path) {
+ Transform.call(this, { objectMode: true });
+
+ var parser = this.parser = new clarinet.createStream()
+ , self = this
+ , stack = []
+ , currObj = {}
+ , currKey = 'root'
+ , inArray
+ , pathMatch = true
+ , parentPathMatch = true
+ , comparator
+ ;
+
+ if (path) {
+ // add some listeners only if path is given
+ var onvaluepath = function onvaluepath(value) {
+ if (pathMatch && stack.length === path.length &&
+ match(currKey, comparator)) {
+ self.push(value);
+ }
+ };
+
+ var onopenpath = function onopenpath() {
+ if (stack.length) {
+ parentPathMatch = pathMatch = parentPathMatch &&
+ comparator !== undefined &&
+ match(currKey, comparator);
+ }
+
+ comparator = path[stack.length];
+ };
+
+ parser.on('value', onvaluepath);
+ parser.on('openobject', onopenpath);
+ parser.on('openarray', onopenpath);
+ }
+
+
+ parser.on('value', function onvalue(value) {
+ currObj[currKey] = value;
+ if (inArray) {
+ currKey++;
+ }
+ });
+
+ parser.on('key', function onkey(key) {
+ currKey = key;
+ });
+
+ function onopen(key) {
+ var obj, openArray;
+
+ if (key === undefined) {
+ // openarray
+ obj = currObj[currKey] = [];
+ openArray = true;
+ key = 0;
+
+ } else {
+ // openobject
+ obj = currObj[currKey] = {};
+ openArray = false;
+ }
+
+ stack.push({
+ obj: currObj
+ , key: currKey + (inArray ? 1 : '')
+ , arr: inArray
+ , path: pathMatch
+ });
+
+ currObj = obj;
+ currKey = key;
+ inArray = openArray;
+ }
+
+ function onclose() {
+ var current = stack.pop();
+ currObj = current.obj;
+ currKey = current.key;
+ inArray = current.arr;
+ parentPathMatch = stack.length ? stack[stack.length - 1].path : true;
+ }
+
+ parser.on('openobject', onopen);
+ parser.on('closeobject', onclose);
+ parser.on('openarray', onopen);
+ parser.on('closearray', onclose);
+
+ parser.on('error', function onerror(err) {
+ self.readable = false;
+ self.writable = false;
+ parser.emit = function() {};
+ self.emit('error', err);
+ });
+
+ parser.on('end', self.push.bind(self, null));
+
+ if (path) {
+ var onclosepath = function onclosepath() {
+ if (pathMatch && stack.length === path.length) {
+ self.push(currObj[currKey]);
+ }
+ comparator = path[stack.length - 1];
+ };
+
+ parser.on('closeobject', onclosepath);
+ parser.on('closearray', onclosepath);
+
+ } else {
+ // if `path` is not given, emit `data` event whenever a full
+ // objectd on the root is parsed
+ parser.on('closeobject', function onobjectavailable() {
+ if (!stack.length || stack.length === 1 && inArray) {
+ var key = inArray ? currKey - 1 : currKey;
+ self.push(currObj[key]);
+ }
+ });
+ }
+
+};
+util.inherits(JStream, Transform);
+
+
+/**
+ * Writes to the parser.
+ *
+ * @param {Buffer|String} chunk
+ * @param {String} encoding
+ * @param {Function(!Error)} callback
+ */
+JStream.prototype._transform = function(chunk, encoding, callback) {
+ this.parser.write(chunk);
+ callback(null);
+};
+
+
+/**
+ * Compare a key against a string, number, RegExp, boolean, or function.
+ *
+ * @param {String} key
+ * @param {String|Number|RegExp|Boolean|Function} comparator
+ * @return {Boolean}
+ */
+function match(key, comparator) {
+ switch (typeof comparator) {
+ case 'string':
+ case 'number':
+ return key === comparator;
+
+ case 'boolean':
+ return comparator;
+
+ case 'function':
+ return comparator(key);
+
+ case 'object':
+ if (comparator instanceof RegExp) {
+ return comparator.test(key);
+ }
+ break;
+
+ }
+
+ throw new TypeError('Path object not supported.');
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..a6cacfb
--- /dev/null
+++ b/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "jstream",
+ "description": "Continously reads in JSON and outputs Javascript objects.",
+ "keywords": ["stream", "json", "parse", "api"],
+ "version": "0.2.7",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/fent/node-jstream.git"
+ },
+ "author": "Roly Fentanes (https://github.com/fent)",
+ "main": "./lib/index.js",
+ "scripts": {
+ "test": "mocha -R spec --ignore-leaks test/*-test.js"
+ },
+ "directories": {
+ "lib": "./lib"
+ },
+ "dependencies": {
+ "clarinet": "~0.8.1",
+ "readable-stream": "~1.1.9"
+ },
+ "devDependencies": {
+ "mocha": "*"
+ },
+ "licenses": [ {
+ "type": "MIT",
+ "url" : "http://github.com/fent/node-jstream/raw/master/LICENSE"
+ }]
+}
diff --git a/test/assets/array.json b/test/assets/array.json
new file mode 100644
index 0000000..f781cf5
--- /dev/null
+++ b/test/assets/array.json
@@ -0,0 +1,6 @@
+[
+ { "id": "one" },
+ { "id": "two" },
+ { "id": "three" },
+ { "id": "four" }
+]
diff --git a/test/assets/arrayKey.json b/test/assets/arrayKey.json
new file mode 100644
index 0000000..61d190b
--- /dev/null
+++ b/test/assets/arrayKey.json
@@ -0,0 +1,6 @@
+{ "results": [
+ [42, 74, 83, 2]
+, [11, 6, 5, 74]
+, [92, 7, 64, 12]
+, ["hi", "there", "grandma", 4]
+] }
diff --git a/test/assets/data.json b/test/assets/data.json
new file mode 100644
index 0000000..6b49255
--- /dev/null
+++ b/test/assets/data.json
@@ -0,0 +1,19 @@
+{ "hello": "world" }
+{ "0": "a"
+, "1": "b"
+, "2": "c" }
+
+
+{
+
+ "list": ["mr", "plow"]}
+
+{ "foo": [
+ "bar"
+ , "baz"
+ , 2
+ , { "one": "two" }
+ , ["a", "b", "c"]
+ ]
+, "yes": "no"
+}
diff --git a/test/assets/function.json b/test/assets/function.json
new file mode 100644
index 0000000..452510d
--- /dev/null
+++ b/test/assets/function.json
@@ -0,0 +1,14 @@
+{ "statusCode": "200"
+, "same": { "helo": "dawg" }
+, "results": [42, { "more": "results" }, 23]
+, "a": { "b": 2 }
+, "c": []
+, "something": "long"
+}
+{ "statusCode": "200"
+, "same": { "helo": "dawg" }
+, "results": [42, { "more": "results" }, 23]
+, "a": { "b": 2 }
+, "c": []
+, "something": "long"
+}
diff --git a/test/assets/many.json b/test/assets/many.json
new file mode 100644
index 0000000..2db3c60
--- /dev/null
+++ b/test/assets/many.json
@@ -0,0 +1,18 @@
+{"total_rows":129,"offset":0,"rows":[
+ { "id":"change1_0.6995461115147918"
+ , "key":"change1_0.6995461115147918"
+ , "value":{"rev":"1-e240bae28c7bb3667f02760f6398d508"}
+ , "doc":{
+ "_id": "change1_0.6995461115147918"
+ , "_rev": "1-e240bae28c7bb3667f02760f6398d508","hello":1}
+ },
+ { "id":"change2_0.6995461115147918"
+ , "key":"change2_0.6995461115147918"
+ , "value":{"rev":"1-13677d36b98c0c075145bb8975105153"}
+ , "doc":{
+ "_id":"change2_0.6995461115147918"
+ , "_rev":"1-13677d36b98c0c075145bb8975105153"
+ , "hello":2
+ }
+ }
+]}
diff --git a/test/assets/propName.json b/test/assets/propName.json
new file mode 100644
index 0000000..b008adf
--- /dev/null
+++ b/test/assets/propName.json
@@ -0,0 +1,7 @@
+{ "date": "today"
+, "name": "foo"
+, "value": "hi there" }
+
+{ "date": "tomorrow"
+, "name": "bar"
+, "value": "hello world"}
diff --git a/test/assets/regexp.json b/test/assets/regexp.json
new file mode 100644
index 0000000..0286816
--- /dev/null
+++ b/test/assets/regexp.json
@@ -0,0 +1,7 @@
+{ "name": "energy sword"
+, "type": "melee"
+, "color": "white"
+, "_attack": 500
+, "_cooldown": 2000
+, "_lunge": true
+}
diff --git a/test/main-test.js b/test/main-test.js
new file mode 100644
index 0000000..5409fe1
--- /dev/null
+++ b/test/main-test.js
@@ -0,0 +1,31 @@
+var run = require('./run');
+var path = require('path');
+
+
+/*jshint quotmark:false */
+var file1 = path.join(__dirname, 'assets', 'data.json');
+var expected1 = [
+ { "hello": "world" }
+, { "0": "a", "1": "b", "2": "c" }
+, { "list": ["mr", "plow"] }
+, { "foo": [
+ "bar"
+ , "baz"
+ , 2
+ , { "one": "two" }
+ , ["a", "b", "c"]
+ ]
+ , "yes": "no"
+ }
+];
+
+var file2 = path.join(__dirname, 'assets', 'array.json');
+var expected2 = [
+ { "id": "one" }
+, { "id": "two" }
+, { "id": "three" }
+, { "id": "four" }
+];
+
+run('Read a file with JSON strings', file1, expected1);
+run('Read a file with JSON objects in an array', file2, expected2);
diff --git a/test/path-test.js b/test/path-test.js
new file mode 100644
index 0000000..8539395
--- /dev/null
+++ b/test/path-test.js
@@ -0,0 +1,45 @@
+var run = require('./run');
+var path = require('path');
+
+
+/*jshint quotmark:false */
+var file1 = path.join(__dirname, 'assets', 'propName.json');
+var expected1 = ['foo', 'bar'];
+
+var file2 = path.join(__dirname, 'assets', 'arrayKey.json');
+var expected2 = [83, 5, 64, 'grandma'];
+
+var file3 = path.join(__dirname, 'assets', 'regexp.json');
+var expected3 = [500, 2000, true];
+
+var file4 = path.join(__dirname, 'assets', 'function.json');
+var expected4 = [
+ "200"
+, [42, { "more": "results" }, 23]
+, "long"
+, "200"
+, [42, { "more": "results" }, 23]
+, "long"
+];
+
+var file5 = path.join(__dirname, 'assets', 'many.json');
+var expected5 = [
+ { "_id": "change1_0.6995461115147918"
+ , "_rev": "1-e240bae28c7bb3667f02760f6398d508"
+ , "hello": 1 }
+, { "_id":"change2_0.6995461115147918"
+ , "_rev":"1-13677d36b98c0c075145bb8975105153"
+ , "hello": 2 }
+];
+
+
+describe('Parse JSON with a path that contains', function() {
+ run('a property name', file1, expected1, ['name']);
+ run('a boolean and array key', file2, expected2, [true, true, 2]);
+ run('a RegExp', file3, expected3, [/^_/]);
+ run('a function', file4, expected4, [function(key) {
+ return key.length > 5;
+ }]);
+
+ run('many of the above', file5, expected5, ['rows', true, 'doc']);
+});
diff --git a/test/run.js b/test/run.js
new file mode 100644
index 0000000..8ffbdd0
--- /dev/null
+++ b/test/run.js
@@ -0,0 +1,35 @@
+var JStream = require('..');
+var assert = require('assert');
+var fs = require('fs');
+
+
+/**
+ * Tests that a `file` emits `expected` results given a `path`
+ *
+ * @param (string) description
+ * @param (string) file
+ * @param (Array.Object) expected
+ * @param (Array.Object) path
+ */
+module.exports = function runTest(description, file, expected, path) {
+ describe(description, function() {
+ it('JStream emits expected Javascript objects', function(done) {
+ var rs = fs.createReadStream(file);
+ var jstream = new JStream(path);
+ rs.pipe(jstream);
+
+ var dataEmitted = false;
+ var n = 0;
+
+ jstream.on('data', function(obj) {
+ dataEmitted = true;
+ assert.deepEqual(obj, expected[n++]);
+ });
+
+ jstream.on('end', function() {
+ assert.ok(dataEmitted);
+ done();
+ });
+ });
+ });
+};
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-jstream.git
More information about the Pkg-javascript-commits
mailing list