Commit cc048d2d98e1cd95038b14d5816dd19931a7b0fa
merge
Dominic Tarr committed on 5/20/2016, 8:34:35 AMParent: 9624740f4ee88cb0bc96ed4cc1a0c295f6cef895
Parent: 409629c0f5e18d1098c83d9c935db213242c1588
Files changed
index.js | changed |
package.json | changed |
pull.js | changed |
test/compose.js | changed |
sinks.js | deleted |
sinks/collect.js | added |
sinks/concat.js | added |
sinks/drain.js | added |
sinks/find.js | added |
sinks/index.js | added |
sinks/log.js | added |
sinks/on-end.js | added |
sinks/reduce.js | added |
sources.js | deleted |
sources/count.js | added |
sources/empty.js | added |
sources/error.js | added |
sources/index.js | added |
sources/infinite.js | added |
sources/keys.js | added |
sources/once.js | added |
sources/values.js | added |
throughs.js | deleted |
throughs/async-map.js | added |
throughs/filter-not.js | added |
throughs/filter.js | added |
throughs/flatten.js | added |
throughs/index.js | added |
throughs/map.js | added |
throughs/non-unique.js | added |
throughs/take.js | added |
throughs/through.js | added |
throughs/unique.js | added |
util/abort-cb.js | added |
util/keys.js | added |
util/prop.js | added |
util/tester.js | added |
index.js | ||
---|---|---|
@@ -1,4 +1,6 @@ | ||
1 | +'use strict' | |
2 | + | |
1 | 3 | var sources = require('./sources') |
2 | 4 | var sinks = require('./sinks') |
3 | 5 | var throughs = require('./throughs') |
4 | 6 |
package.json | ||
---|---|---|
@@ -1,8 +1,8 @@ | ||
1 | 1 | { |
2 | 2 | "name": "pull-stream", |
3 | 3 | "description": "minimal pull stream", |
4 | - "version": "3.3.3", | |
4 | + "version": "3.4.0", | |
5 | 5 | "homepage": "https://github.com/dominictarr/pull-stream", |
6 | 6 | "repository": { |
7 | 7 | "type": "git", |
8 | 8 | "url": "git://github.com/dominictarr/pull-stream.git" |
@@ -17,4 +17,6 @@ | ||
17 | 17 | }, |
18 | 18 | "author": "Dominic Tarr <dominic.tarr@gmail.com> (http://dominictarr.com)", |
19 | 19 | "license": "MIT" |
20 | 20 | } |
21 | + | |
22 | + |
pull.js | ||
---|---|---|
@@ -1,4 +1,6 @@ | ||
1 | +'use strict' | |
2 | + | |
1 | 3 | module.exports = function pull (a) { |
2 | 4 | var length = arguments.length |
3 | 5 | if (typeof a === 'function' && a.length === 1) { |
4 | 6 | var args = new Array(length) |
test/compose.js | ||
---|---|---|
@@ -32,9 +32,9 @@ | ||
32 | 32 | //the pipeline will become readable! |
33 | 33 | |
34 | 34 | var read = |
35 | 35 | pull( |
36 | - pull.readArray(['billy', 'joe', 'zeke']), | |
36 | + pull.values(['billy', 'joe', 'zeke']), | |
37 | 37 | pipeline |
38 | 38 | ) |
39 | 39 | |
40 | 40 | t.equal('function', typeof read) |
sinks.js | ||
---|---|---|
@@ -1,121 +1,0 @@ | ||
1 | -'use strict' | |
2 | - | |
3 | -function id (item) { return item } | |
4 | - | |
5 | -function prop (key) { | |
6 | - return ( | |
7 | - 'string' == typeof key | |
8 | - ? function (data) { return data[key] } | |
9 | - : key && 'object' === typeof key && 'function' === typeof key.exec //regexp | |
10 | - ? function (data) { var v = map.exec(data); return v && v[0] } | |
11 | - : key || id | |
12 | - ) | |
13 | -} | |
14 | - | |
15 | - | |
16 | -var drain = exports.drain = function (op, done) { | |
17 | - var read, abort | |
18 | - | |
19 | - function sink (_read) { | |
20 | - read = _read | |
21 | - if(abort) return sink.abort() | |
22 | - //this function is much simpler to write if you | |
23 | - //just use recursion, but by using a while loop | |
24 | - //we do not blow the stack if the stream happens to be sync. | |
25 | - ;(function next() { | |
26 | - var loop = true, cbed = false | |
27 | - while(loop) { | |
28 | - cbed = false | |
29 | - read(null, function (end, data) { | |
30 | - cbed = true | |
31 | - if(end = end || abort) { | |
32 | - loop = false | |
33 | - if(done) done(end === true ? null : end) | |
34 | - else if(end && end !== true) | |
35 | - throw end | |
36 | - } | |
37 | - else if(op && false === op(data) || abort) { | |
38 | - loop = false | |
39 | - read(abort || true, done || function () {}) | |
40 | - } | |
41 | - else if(!loop){ | |
42 | - next() | |
43 | - } | |
44 | - }) | |
45 | - if(!cbed) { | |
46 | - loop = false | |
47 | - return | |
48 | - } | |
49 | - } | |
50 | - })() | |
51 | - } | |
52 | - | |
53 | - sink.abort = function (err, cb) { | |
54 | - if('function' == typeof err) | |
55 | - cb = err, err = true | |
56 | - abort = err || true | |
57 | - if(read) return read(abort, cb || function () {}) | |
58 | - } | |
59 | - | |
60 | - return sink | |
61 | -} | |
62 | - | |
63 | -var onEnd = exports.onEnd = function (done) { | |
64 | - return drain(null, done) | |
65 | -} | |
66 | - | |
67 | -var log = exports.log = function (done) { | |
68 | - return drain(function (data) { | |
69 | - console.log(data) | |
70 | - }, done) | |
71 | -} | |
72 | - | |
73 | -var find = | |
74 | -exports.find = function (test, cb) { | |
75 | - var ended = false | |
76 | - if(!cb) | |
77 | - cb = test, test = id | |
78 | - else | |
79 | - test = prop(test) || id | |
80 | - | |
81 | - return drain(function (data) { | |
82 | - if(test(data)) { | |
83 | - ended = true | |
84 | - cb(null, data) | |
85 | - return false | |
86 | - } | |
87 | - }, function (err) { | |
88 | - if(ended) return //already called back | |
89 | - cb(err === true ? null : err, null) | |
90 | - }) | |
91 | -} | |
92 | - | |
93 | -var reduce = exports.reduce = function (reduce, acc, cb) { | |
94 | - | |
95 | - return drain(function (data) { | |
96 | - acc = reduce(acc, data) | |
97 | - }, function (err) { | |
98 | - cb(err, acc) | |
99 | - }) | |
100 | - | |
101 | -} | |
102 | - | |
103 | -var collect = exports.collect = | |
104 | -function (cb) { | |
105 | - return reduce(function (arr, item) { | |
106 | - arr.push(item) | |
107 | - return arr | |
108 | - }, [], cb) | |
109 | -} | |
110 | - | |
111 | -var concat = exports.concat = | |
112 | -function (cb) { | |
113 | - return reduce(function (a, b) { | |
114 | - return a + b | |
115 | - }, '', cb) | |
116 | -} | |
117 | - | |
118 | - | |
119 | - | |
120 | - | |
121 | - |
sinks/collect.js | ||
---|---|---|
@@ -1,0 +1,10 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var reduce = require('./reduce') | |
4 | + | |
5 | +module.exports = function collect (cb) { | |
6 | + return reduce(function (arr, item) { | |
7 | + arr.push(item) | |
8 | + return arr | |
9 | + }, [], cb) | |
10 | +} |
sinks/concat.js | ||
---|---|---|
@@ -1,0 +1,9 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var reduce = require('./reduce') | |
4 | + | |
5 | +module.exports = function concat (cb) { | |
6 | + return reduce(function (a, b) { | |
7 | + return a + b | |
8 | + }, '', cb) | |
9 | +} |
sinks/drain.js | ||
---|---|---|
@@ -1,0 +1,48 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +module.exports = function drain (op, done) { | |
4 | + var read, abort | |
5 | + | |
6 | + function sink (_read) { | |
7 | + read = _read | |
8 | + if(abort) return sink.abort() | |
9 | + //this function is much simpler to write if you | |
10 | + //just use recursion, but by using a while loop | |
11 | + //we do not blow the stack if the stream happens to be sync. | |
12 | + ;(function next() { | |
13 | + var loop = true, cbed = false | |
14 | + while(loop) { | |
15 | + cbed = false | |
16 | + read(null, function (end, data) { | |
17 | + cbed = true | |
18 | + if(end = end || abort) { | |
19 | + loop = false | |
20 | + if(done) done(end === true ? null : end) | |
21 | + else if(end && end !== true) | |
22 | + throw end | |
23 | + } | |
24 | + else if(op && false === op(data) || abort) { | |
25 | + loop = false | |
26 | + read(abort || true, done || function () {}) | |
27 | + } | |
28 | + else if(!loop){ | |
29 | + next() | |
30 | + } | |
31 | + }) | |
32 | + if(!cbed) { | |
33 | + loop = false | |
34 | + return | |
35 | + } | |
36 | + } | |
37 | + })() | |
38 | + } | |
39 | + | |
40 | + sink.abort = function (err, cb) { | |
41 | + if('function' == typeof err) | |
42 | + cb = err, err = true | |
43 | + abort = err || true | |
44 | + if(read) return read(abort, cb || function () {}) | |
45 | + } | |
46 | + | |
47 | + return sink | |
48 | +} |
sinks/find.js | ||
---|---|---|
@@ -1,0 +1,28 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +function id (e) { return e } | |
4 | +var prop = require('../util/prop') | |
5 | +var drain = require('./drain') | |
6 | + | |
7 | +module.exports = function find (test, cb) { | |
8 | + var ended = false | |
9 | + if(!cb) | |
10 | + cb = test, test = id | |
11 | + else | |
12 | + test = prop(test) || id | |
13 | + | |
14 | + return drain(function (data) { | |
15 | + if(test(data)) { | |
16 | + ended = true | |
17 | + cb(null, data) | |
18 | + return false | |
19 | + } | |
20 | + }, function (err) { | |
21 | + if(ended) return //already called back | |
22 | + cb(err === true ? null : err, null) | |
23 | + }) | |
24 | +} | |
25 | + | |
26 | + | |
27 | + | |
28 | + |
sinks/index.js | ||
---|---|---|
@@ -1,0 +1,12 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +module.exports = { | |
4 | + drain: require('./drain'), | |
5 | + onEnd: require('./on-end'), | |
6 | + log: require('./log'), | |
7 | + find: require('./find'), | |
8 | + reduce: require('./reduce'), | |
9 | + collect: require('./collect'), | |
10 | + concat: require('./concat') | |
11 | +} | |
12 | + |
sinks/log.js | ||
---|---|---|
@@ -1,0 +1,9 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var drain = require('./drain') | |
4 | + | |
5 | +module.exports = function log (done) { | |
6 | + return drain(function (data) { | |
7 | + console.log(data) | |
8 | + }, done) | |
9 | +} |
sinks/on-end.js | ||
---|---|---|
@@ -1,0 +1,7 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var drain = require('./drain') | |
4 | + | |
5 | +module.exports = function onEnd (done) { | |
6 | + return drain(null, done) | |
7 | +} |
sinks/reduce.js | ||
---|---|---|
@@ -1,0 +1,12 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var drain = require('./drain') | |
4 | + | |
5 | +module.exports = function reduce (reducer, acc, cb) { | |
6 | + return drain(function (data) { | |
7 | + acc = reducer(acc, data) | |
8 | + }, function (err) { | |
9 | + cb(err, acc) | |
10 | + }) | |
11 | +} | |
12 | + |
sources.js | ||
---|---|---|
@@ -1,79 +1,0 @@ | ||
1 | - | |
2 | -var keys = exports.keys = | |
3 | -function (object) { | |
4 | - return values(Object.keys(object)) | |
5 | -} | |
6 | - | |
7 | -function abortCb(cb, abort, onAbort) { | |
8 | - cb(abort) | |
9 | - onAbort && onAbort(abort === true ? null: abort) | |
10 | - return | |
11 | -} | |
12 | - | |
13 | -var once = exports.once = | |
14 | -function (value, onAbort) { | |
15 | - return function (abort, cb) { | |
16 | - if(abort) | |
17 | - return abortCb(cb, abort, onAbort) | |
18 | - if(value != null) { | |
19 | - var _value = value; value = null | |
20 | - cb(null, _value) | |
21 | - } else | |
22 | - cb(true) | |
23 | - } | |
24 | -} | |
25 | - | |
26 | -var values = exports.values = exports.readArray = | |
27 | -function (array, onAbort) { | |
28 | - if(!array) | |
29 | - return function (abort, cb) { | |
30 | - if(abort) return abortCb(cb, abort, onAbort) | |
31 | - return cb(true) | |
32 | - } | |
33 | - if(!Array.isArray(array)) | |
34 | - array = Object.keys(array).map(function (k) { | |
35 | - return array[k] | |
36 | - }) | |
37 | - var i = 0 | |
38 | - return function (abort, cb) { | |
39 | - if(abort) | |
40 | - return abortCb(cb, abort, onAbort) | |
41 | - cb(i >= array.length || null, array[i++]) | |
42 | - } | |
43 | -} | |
44 | - | |
45 | - | |
46 | -var count = exports.count = | |
47 | -function (max) { | |
48 | - var i = 0; max = max || Infinity | |
49 | - return function (end, cb) { | |
50 | - if(end) return cb && cb(end) | |
51 | - if(i > max) | |
52 | - return cb(true) | |
53 | - cb(null, i++) | |
54 | - } | |
55 | -} | |
56 | - | |
57 | -var infinite = exports.infinite = | |
58 | -function (generate) { | |
59 | - generate = generate || Math.random | |
60 | - return function (end, cb) { | |
61 | - if(end) return cb && cb(end) | |
62 | - return cb(null, generate()) | |
63 | - } | |
64 | -} | |
65 | - | |
66 | -//a stream that ends immediately. | |
67 | -var empty = exports.empty = function () { | |
68 | - return function (abort, cb) { | |
69 | - cb(true) | |
70 | - } | |
71 | -} | |
72 | - | |
73 | -//a stream that errors immediately. | |
74 | -var error = exports.error = function (err) { | |
75 | - return function (abort, cb) { | |
76 | - cb(err) | |
77 | - } | |
78 | -} | |
79 | - |
sources/count.js | ||
---|---|---|
@@ -1,0 +1,13 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +module.exports = function count (max) { | |
4 | + var i = 0; max = max || Infinity | |
5 | + return function (end, cb) { | |
6 | + if(end) return cb && cb(end) | |
7 | + if(i > max) | |
8 | + return cb(true) | |
9 | + cb(null, i++) | |
10 | + } | |
11 | +} | |
12 | + | |
13 | + |
sources/empty.js | ||
---|---|---|
@@ -1,0 +1,7 @@ | ||
1 | +'use strict' | |
2 | +//a stream that ends immediately. | |
3 | +module.exports = function empty () { | |
4 | + return function (abort, cb) { | |
5 | + cb(true) | |
6 | + } | |
7 | +} |
sources/error.js | ||
---|---|---|
@@ -1,0 +1,8 @@ | ||
1 | +'use strict' | |
2 | +//a stream that errors immediately. | |
3 | +module.exports = function error (err) { | |
4 | + return function (abort, cb) { | |
5 | + cb(err) | |
6 | + } | |
7 | +} | |
8 | + |
sources/index.js | ||
---|---|---|
@@ -1,0 +1,10 @@ | ||
1 | +'use strict' | |
2 | +module.exports = { | |
3 | + keys: require('./keys'), | |
4 | + once: require('./once'), | |
5 | + values: require('./values'), | |
6 | + count: require('./count'), | |
7 | + infinite: require('./infinite'), | |
8 | + empty: require('./empty'), | |
9 | + error: require('./error') | |
10 | +} |
sources/infinite.js | ||
---|---|---|
@@ -1,0 +1,10 @@ | ||
1 | +'use strict' | |
2 | +module.exports = function infinite (generate) { | |
3 | + generate = generate || Math.random | |
4 | + return function (end, cb) { | |
5 | + if(end) return cb && cb(end) | |
6 | + return cb(null, generate()) | |
7 | + } | |
8 | +} | |
9 | + | |
10 | + |
sources/keys.js | ||
---|---|---|
@@ -1,0 +1,7 @@ | ||
1 | +'use strict' | |
2 | +var values = require('./values') | |
3 | +module.exports = function (object) { | |
4 | + return values(Object.keys(object)) | |
5 | +} | |
6 | + | |
7 | + |
sources/once.js | ||
---|---|---|
@@ -1,0 +1,16 @@ | ||
1 | +'use strict' | |
2 | +var abortCb = require('../util/abort-cb') | |
3 | + | |
4 | +module.exports = function once (value, onAbort) { | |
5 | + return function (abort, cb) { | |
6 | + if(abort) | |
7 | + return abortCb(cb, abort, onAbort) | |
8 | + if(value != null) { | |
9 | + var _value = value; value = null | |
10 | + cb(null, _value) | |
11 | + } else | |
12 | + cb(true) | |
13 | + } | |
14 | +} | |
15 | + | |
16 | + |
sources/values.js | ||
---|---|---|
@@ -1,0 +1,21 @@ | ||
1 | +'use strict' | |
2 | +var abortCb = require('../util/abort-cb') | |
3 | + | |
4 | +module.exports = function values (array, onAbort) { | |
5 | + if(!array) | |
6 | + return function (abort, cb) { | |
7 | + if(abort) return abortCb(cb, abort, onAbort) | |
8 | + return cb(true) | |
9 | + } | |
10 | + if(!Array.isArray(array)) | |
11 | + array = Object.keys(array).map(function (k) { | |
12 | + return array[k] | |
13 | + }) | |
14 | + var i = 0 | |
15 | + return function (abort, cb) { | |
16 | + if(abort) | |
17 | + return abortCb(cb, abort, onAbort) | |
18 | + cb(i >= array.length || null, array[i++]) | |
19 | + } | |
20 | +} | |
21 | + |
throughs.js | ||
---|---|---|
@@ -1,234 +1,0 @@ | ||
1 | -'use strict'; | |
2 | - | |
3 | -function id (item) { return item } | |
4 | - | |
5 | -function prop (key) { | |
6 | - return ( | |
7 | - 'string' == typeof key | |
8 | - ? function (data) { return data[key] } | |
9 | - : 'object' === typeof key && 'function' === typeof key.exec //regexp | |
10 | - ? function (data) { var v = map.exec(data); return v && v[0] } | |
11 | - : key | |
12 | - ) | |
13 | -} | |
14 | - | |
15 | -function tester (test) { | |
16 | - return ( | |
17 | - 'object' === typeof test && 'function' === typeof test.test //regexp | |
18 | - ? function (data) { return test.test(data) } | |
19 | - : prop (test) || id | |
20 | - ) | |
21 | -} | |
22 | - | |
23 | -var sources = require('./sources') | |
24 | -var sinks = require('./sinks') | |
25 | - | |
26 | -var map = exports.map = | |
27 | - | |
28 | -function (map) { | |
29 | - if(!map) return id | |
30 | - map = prop(map) | |
31 | - return function (read) { | |
32 | - return function (abort, cb) { | |
33 | - read(abort, function (end, data) { | |
34 | - try { | |
35 | - data = !end ? map(data) : null | |
36 | - } catch (err) { | |
37 | - return read(err, function () { | |
38 | - return cb(err) | |
39 | - }) | |
40 | - } | |
41 | - cb(end, data) | |
42 | - }) | |
43 | - } | |
44 | - } | |
45 | -} | |
46 | - | |
47 | -var asyncMap = exports.asyncMap = | |
48 | -function async (map) { | |
49 | - if(!map) return id | |
50 | - map = prop(map) | |
51 | - var busy = false, abortCb, aborted | |
52 | - return function (read) { | |
53 | - return function next (abort, cb) { | |
54 | - if(aborted) return cb(aborted) | |
55 | - if(abort) { | |
56 | - aborted = abort | |
57 | - if(!busy) read(abort, cb) | |
58 | - else read(abort, function () { | |
59 | - //if we are still busy, wait for the mapper to complete. | |
60 | - if(busy) abortCb = cb | |
61 | - else cb(abort) | |
62 | - }) | |
63 | - } | |
64 | - else | |
65 | - read(null, function (end, data) { | |
66 | - if(end) cb(end) | |
67 | - else if(aborted) cb(aborted) | |
68 | - else { | |
69 | - busy = true | |
70 | - map(data, function (err, data) { | |
71 | - busy = false | |
72 | - if(aborted) { | |
73 | - cb(aborted) | |
74 | - abortCb(aborted) | |
75 | - } | |
76 | - else if(err) next (err, cb) | |
77 | - else cb(null, data) | |
78 | - }) | |
79 | - } | |
80 | - }) | |
81 | - } | |
82 | - } | |
83 | -} | |
84 | - | |
85 | -var filter = exports.filter = | |
86 | -function (test) { | |
87 | - //regexp | |
88 | - test = tester(test) | |
89 | - return function (read) { | |
90 | - return function next (end, cb) { | |
91 | - var sync, loop = true | |
92 | - while(loop) { | |
93 | - loop = false | |
94 | - sync = true | |
95 | - read(end, function (end, data) { | |
96 | - if(!end && !test(data)) | |
97 | - return sync ? loop = true : next(end, cb) | |
98 | - cb(end, data) | |
99 | - }) | |
100 | - sync = false | |
101 | - } | |
102 | - } | |
103 | - } | |
104 | -} | |
105 | - | |
106 | -var filterNot = exports.filterNot = | |
107 | -function (test) { | |
108 | - test = tester(test) | |
109 | - return filter(function (data) { return !test(data) }) | |
110 | -} | |
111 | - | |
112 | -//a pass through stream that doesn't change the value. | |
113 | -var through = exports.through = | |
114 | -function (op, onEnd) { | |
115 | - var a = false | |
116 | - | |
117 | - function once (abort) { | |
118 | - if(a || !onEnd) return | |
119 | - a = true | |
120 | - onEnd(abort === true ? null : abort) | |
121 | - } | |
122 | - | |
123 | - return function (read) { | |
124 | - return function (end, cb) { | |
125 | - if(end) once(end) | |
126 | - return read(end, function (end, data) { | |
127 | - if(!end) op && op(data) | |
128 | - else once(end) | |
129 | - cb(end, data) | |
130 | - }) | |
131 | - } | |
132 | - } | |
133 | -} | |
134 | - | |
135 | -//read a number of items and then stop. | |
136 | -var take = exports.take = | |
137 | -function (test, opts) { | |
138 | - opts = opts || {} | |
139 | - var last = opts.last || false // whether the first item for which !test(item) should still pass | |
140 | - var ended = false | |
141 | - if('number' === typeof test) { | |
142 | - last = true | |
143 | - var n = test; test = function () { | |
144 | - return --n | |
145 | - } | |
146 | - } | |
147 | - | |
148 | - return function (read) { | |
149 | - | |
150 | - function terminate (cb) { | |
151 | - read(true, function (err) { | |
152 | - last = false; cb(err || true) | |
153 | - }) | |
154 | - } | |
155 | - | |
156 | - return function (end, cb) { | |
157 | - if(ended) last ? terminate(cb) : cb(ended) | |
158 | - else if(ended = end) read(ended, cb) | |
159 | - else | |
160 | - read(null, function (end, data) { | |
161 | - if(ended = ended || end) { | |
162 | - //last ? terminate(cb) : | |
163 | - cb(ended) | |
164 | - } | |
165 | - else if(!test(data)) { | |
166 | - ended = true | |
167 | - last ? cb(null, data) : terminate(cb) | |
168 | - } | |
169 | - else | |
170 | - cb(null, data) | |
171 | - }) | |
172 | - } | |
173 | - } | |
174 | -} | |
175 | - | |
176 | -//drop items you have already seen. | |
177 | -var unique = exports.unique = function (field, invert) { | |
178 | - field = prop(field) || id | |
179 | - var seen = {} | |
180 | - return filter(function (data) { | |
181 | - var key = field(data) | |
182 | - if(seen[key]) return !!invert //false, by default | |
183 | - else seen[key] = true | |
184 | - return !invert //true by default | |
185 | - }) | |
186 | -} | |
187 | - | |
188 | -//passes an item through when you see it for the second time. | |
189 | -var nonUnique = exports.nonUnique = function (field) { | |
190 | - return unique(field, true) | |
191 | -} | |
192 | - | |
193 | -//convert a stream of arrays or streams into just a stream. | |
194 | -var flatten = exports.flatten = function () { | |
195 | - return function (read) { | |
196 | - var _read | |
197 | - return function (abort, cb) { | |
198 | - if (abort) { //abort the current stream, and then stream of streams. | |
199 | - _read ? _read(abort, function(err) { | |
200 | - read(err || abort, cb) | |
201 | - }) : read(abort, cb) | |
202 | - } | |
203 | - else if(_read) nextChunk() | |
204 | - else nextStream() | |
205 | - | |
206 | - function nextChunk () { | |
207 | - _read(null, function (err, data) { | |
208 | - if (err === true) nextStream() | |
209 | - else if (err) { | |
210 | - read(true, function(abortErr) { | |
211 | - // TODO: what do we do with the abortErr? | |
212 | - cb(err) | |
213 | - }) | |
214 | - } | |
215 | - else cb(null, data) | |
216 | - }) | |
217 | - } | |
218 | - function nextStream () { | |
219 | - _read = null | |
220 | - read(null, function (end, stream) { | |
221 | - if(end) | |
222 | - return cb(end) | |
223 | - if(Array.isArray(stream) || stream && 'object' === typeof stream) | |
224 | - stream = sources.values(stream) | |
225 | - else if('function' != typeof stream) | |
226 | - stream = sources.once(stream) | |
227 | - _read = stream | |
228 | - nextChunk() | |
229 | - }) | |
230 | - } | |
231 | - } | |
232 | - } | |
233 | -} | |
234 | - |
throughs/async-map.js | ||
---|---|---|
@@ -1,0 +1,43 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +function id (e) { return e } | |
4 | +var prop = require('../util/prop') | |
5 | + | |
6 | +module.exports = function asyncMap (map) { | |
7 | + if(!map) return id | |
8 | + map = prop(map) | |
9 | + var busy = false, abortCb, aborted | |
10 | + return function (read) { | |
11 | + return function next (abort, cb) { | |
12 | + if(aborted) return cb(aborted) | |
13 | + if(abort) { | |
14 | + aborted = abort | |
15 | + if(!busy) read(abort, cb) | |
16 | + else read(abort, function () { | |
17 | + //if we are still busy, wait for the mapper to complete. | |
18 | + if(busy) abortCb = cb | |
19 | + else cb(abort) | |
20 | + }) | |
21 | + } | |
22 | + else | |
23 | + read(null, function (end, data) { | |
24 | + if(end) cb(end) | |
25 | + else if(aborted) cb(aborted) | |
26 | + else { | |
27 | + busy = true | |
28 | + map(data, function (err, data) { | |
29 | + busy = false | |
30 | + if(aborted) { | |
31 | + cb(aborted) | |
32 | + abortCb(aborted) | |
33 | + } | |
34 | + else if(err) next (err, cb) | |
35 | + else cb(null, data) | |
36 | + }) | |
37 | + } | |
38 | + }) | |
39 | + } | |
40 | + } | |
41 | +} | |
42 | + | |
43 | + |
throughs/filter-not.js | ||
---|---|---|
@@ -1,0 +1,9 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var tester = require('../util/tester') | |
4 | +var filter = require('./filter') | |
5 | + | |
6 | +module.exports = function filterNot (test) { | |
7 | + test = tester(test) | |
8 | + return filter(function (data) { return !test(data) }) | |
9 | +} |
throughs/filter.js | ||
---|---|---|
@@ -1,0 +1,24 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var tester = require('../util/tester') | |
4 | + | |
5 | +module.exports = function filter (test) { | |
6 | + //regexp | |
7 | + test = tester(test) | |
8 | + return function (read) { | |
9 | + return function next (end, cb) { | |
10 | + var sync, loop = true | |
11 | + while(loop) { | |
12 | + loop = false | |
13 | + sync = true | |
14 | + read(end, function (end, data) { | |
15 | + if(!end && !test(data)) | |
16 | + return sync ? loop = true : next(end, cb) | |
17 | + cb(end, data) | |
18 | + }) | |
19 | + sync = false | |
20 | + } | |
21 | + } | |
22 | + } | |
23 | +} | |
24 | + |
throughs/flatten.js | ||
---|---|---|
@@ -1,0 +1,47 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var values = require('../sources/values') | |
4 | +var once = require('../sources/once') | |
5 | + | |
6 | +//convert a stream of arrays or streams into just a stream. | |
7 | +module.exports = function flatten () { | |
8 | + return function (read) { | |
9 | + var _read | |
10 | + return function (abort, cb) { | |
11 | + if (abort) { //abort the current stream, and then stream of streams. | |
12 | + _read ? _read(abort, function(err) { | |
13 | + read(err || abort, cb) | |
14 | + }) : read(abort, cb) | |
15 | + } | |
16 | + else if(_read) nextChunk() | |
17 | + else nextStream() | |
18 | + | |
19 | + function nextChunk () { | |
20 | + _read(null, function (err, data) { | |
21 | + if (err === true) nextStream() | |
22 | + else if (err) { | |
23 | + read(true, function(abortErr) { | |
24 | + // TODO: what do we do with the abortErr? | |
25 | + cb(err) | |
26 | + }) | |
27 | + } | |
28 | + else cb(null, data) | |
29 | + }) | |
30 | + } | |
31 | + function nextStream () { | |
32 | + _read = null | |
33 | + read(null, function (end, stream) { | |
34 | + if(end) | |
35 | + return cb(end) | |
36 | + if(Array.isArray(stream) || stream && 'object' === typeof stream) | |
37 | + stream = values(stream) | |
38 | + else if('function' != typeof stream) | |
39 | + stream = once(stream) | |
40 | + _read = stream | |
41 | + nextChunk() | |
42 | + }) | |
43 | + } | |
44 | + } | |
45 | + } | |
46 | +} | |
47 | + |
throughs/index.js | ||
---|---|---|
@@ -1,0 +1,16 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +module.exports = { | |
4 | + map: require('./map'), | |
5 | + asyncMap: require('./async-map'), | |
6 | + filter: require('./filter'), | |
7 | + filterNot: require('./filter-not'), | |
8 | + through: require('./through'), | |
9 | + take: require('./take'), | |
10 | + unique: require('./unique'), | |
11 | + nonUnique: require('./non-unique'), | |
12 | + flatten: require('./flatten') | |
13 | +} | |
14 | + | |
15 | + | |
16 | + |
throughs/map.js | ||
---|---|---|
@@ -1,0 +1,23 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +function id (e) { return e } | |
4 | +var prop = require('../util/prop') | |
5 | + | |
6 | +module.exports = function map (mapper) { | |
7 | + if(!mapper) return id | |
8 | + mapper = prop(mapper) | |
9 | + return function (read) { | |
10 | + return function (abort, cb) { | |
11 | + read(abort, function (end, data) { | |
12 | + try { | |
13 | + data = !end ? mapper(data) : null | |
14 | + } catch (err) { | |
15 | + return read(err, function () { | |
16 | + return cb(err) | |
17 | + }) | |
18 | + } | |
19 | + cb(end, data) | |
20 | + }) | |
21 | + } | |
22 | + } | |
23 | +} |
throughs/non-unique.js | ||
---|---|---|
@@ -1,0 +1,8 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +var unique = require('./unique') | |
4 | + | |
5 | +//passes an item through when you see it for the second time. | |
6 | +module.exports = function nonUnique (field) { | |
7 | + return unique(field, true) | |
8 | +} |
throughs/take.js | ||
---|---|---|
@@ -1,0 +1,41 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +//read a number of items and then stop. | |
4 | +module.exports = function take (test, opts) { | |
5 | + opts = opts || {} | |
6 | + var last = opts.last || false // whether the first item for which !test(item) should still pass | |
7 | + var ended = false | |
8 | + if('number' === typeof test) { | |
9 | + last = true | |
10 | + var n = test; test = function () { | |
11 | + return --n | |
12 | + } | |
13 | + } | |
14 | + | |
15 | + return function (read) { | |
16 | + | |
17 | + function terminate (cb) { | |
18 | + read(true, function (err) { | |
19 | + last = false; cb(err || true) | |
20 | + }) | |
21 | + } | |
22 | + | |
23 | + return function (end, cb) { | |
24 | + if(ended) last ? terminate(cb) : cb(ended) | |
25 | + else if(ended = end) read(ended, cb) | |
26 | + else | |
27 | + read(null, function (end, data) { | |
28 | + if(ended = ended || end) { | |
29 | + //last ? terminate(cb) : | |
30 | + cb(ended) | |
31 | + } | |
32 | + else if(!test(data)) { | |
33 | + ended = true | |
34 | + last ? cb(null, data) : terminate(cb) | |
35 | + } | |
36 | + else | |
37 | + cb(null, data) | |
38 | + }) | |
39 | + } | |
40 | + } | |
41 | +} |
throughs/through.js | ||
---|---|---|
@@ -1,0 +1,23 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +//a pass through stream that doesn't change the value. | |
4 | +module.exports = function through (op, onEnd) { | |
5 | + var a = false | |
6 | + | |
7 | + function once (abort) { | |
8 | + if(a || !onEnd) return | |
9 | + a = true | |
10 | + onEnd(abort === true ? null : abort) | |
11 | + } | |
12 | + | |
13 | + return function (read) { | |
14 | + return function (end, cb) { | |
15 | + if(end) once(end) | |
16 | + return read(end, function (end, data) { | |
17 | + if(!end) op && op(data) | |
18 | + else once(end) | |
19 | + cb(end, data) | |
20 | + }) | |
21 | + } | |
22 | + } | |
23 | +} |
throughs/unique.js | ||
---|---|---|
@@ -1,0 +1,18 @@ | ||
1 | +'use strict' | |
2 | + | |
3 | +function id (e) { return e } | |
4 | +var prop = require('../util/prop') | |
5 | +var filter = require('./filter') | |
6 | + | |
7 | +//drop items you have already seen. | |
8 | +module.exports = function unique (field, invert) { | |
9 | + field = prop(field) || id | |
10 | + var seen = {} | |
11 | + return filter(function (data) { | |
12 | + var key = field(data) | |
13 | + if(seen[key]) return !!invert //false, by default | |
14 | + else seen[key] = true | |
15 | + return !invert //true by default | |
16 | + }) | |
17 | +} | |
18 | + |
util/abort-cb.js | ||
---|---|---|
@@ -1,0 +1,6 @@ | ||
1 | +module.exports = function abortCb(cb, abort, onAbort) { | |
2 | + cb(abort) | |
3 | + onAbort && onAbort(abort === true ? null: abort) | |
4 | + return | |
5 | +} | |
6 | + |
util/keys.js | ||
---|---|---|
@@ -1,0 +1,3 @@ | ||
1 | +module.exports = function keys (object) { | |
2 | + return values(Object.keys(object)) | |
3 | +} |
util/prop.js | ||
---|---|---|
@@ -1,0 +1,9 @@ | ||
1 | +module.exports = function prop (key) { | |
2 | + return key && ( | |
3 | + 'string' == typeof key | |
4 | + ? function (data) { return data[key] } | |
5 | + : 'object' === typeof key && 'function' === typeof key.exec //regexp | |
6 | + ? function (data) { var v = key.exec(data); return v && v[0] } | |
7 | + : key | |
8 | + ) | |
9 | +} |
Built with git-ssb-web