bfj 7.1.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +1 -1
- package/.gitlab-ci.yml +4 -8
- package/HISTORY.md +22 -1
- package/README.md +16 -47
- package/package.json +8 -8
- package/src/eventify.js +121 -113
- package/src/match.js +3 -5
- package/src/parse.js +3 -12
- package/src/read.js +1 -3
- package/src/streamify.js +45 -56
- package/src/stringify.js +2 -6
- package/src/unpipe.js +11 -4
- package/src/walk.js +257 -333
- package/src/write.js +2 -7
- package/test/integration.js +0 -1
- package/test/performance.js +38 -18
- package/test/unit/eventify.js +12 -13
- package/test/unit/parse.js +0 -7
- package/test/unit/stringify.js +0 -1
- package/test/unit/unpipe.js +0 -1
- package/test/unit/walk.js +3 -3
- package/test/unit/write.js +0 -1
- package/src/promise.js +0 -3
package/.eslintrc
CHANGED
package/.gitlab-ci.yml
CHANGED
|
@@ -12,14 +12,10 @@ before_script:
|
|
|
12
12
|
- npm run lint
|
|
13
13
|
- npm test
|
|
14
14
|
|
|
15
|
-
test:
|
|
16
|
-
image: node:
|
|
15
|
+
test:node18:
|
|
16
|
+
image: node:18
|
|
17
17
|
<<: *npm_test
|
|
18
18
|
|
|
19
|
-
test:
|
|
20
|
-
image: node:
|
|
21
|
-
<<: *npm_test
|
|
22
|
-
|
|
23
|
-
test:node12:
|
|
24
|
-
image: node:12
|
|
19
|
+
test:node20:
|
|
20
|
+
image: node:20
|
|
25
21
|
<<: *npm_test
|
package/HISTORY.md
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
# History
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 9.0.0
|
|
4
|
+
|
|
5
|
+
### Breaking changes
|
|
6
|
+
|
|
7
|
+
* options: ditch bluebird promises and the `Promise` option (7b8292977c3ea1ebf0b0abdfb91a428b0159f374)
|
|
8
|
+
|
|
9
|
+
### Other changes
|
|
10
|
+
|
|
11
|
+
* docs: remove some old information from the readme (7665213e6f24c3cf287d361100513288d0f8b1cf)
|
|
12
|
+
* deps: update dev dependencies (d8a1e3c4028d300a4b292efb82b1bb5d02cff62b)
|
|
13
|
+
* tests: add perf test for walk (ac48de9bb613133a62bd6f67b8f7baccc3808609)
|
|
14
|
+
* walk: restrict json buffer length when parsing (59d8f5f17081a8610f94c614929e3665d5ac511d)
|
|
15
|
+
* options: more modest default options (ff8d18d0c57120cc2a16c66de17908ce85a7f028)
|
|
16
|
+
* perf: add test command for match perf testing (2d4c48040fdc43f7838a565913ec577da921938d)
|
|
17
|
+
|
|
18
|
+
## 8.0.0
|
|
19
|
+
|
|
20
|
+
### Breaking changes
|
|
21
|
+
|
|
22
|
+
* platform: only support node 18+ (45062680c52dc5ee09b136babcb3c333e3409409)
|
|
4
23
|
|
|
5
24
|
### New features
|
|
6
25
|
|
|
@@ -8,6 +27,8 @@
|
|
|
8
27
|
|
|
9
28
|
### Other changes
|
|
10
29
|
|
|
30
|
+
* docs: change downloads metric to weekly in readme (869b78f6629cbfcf9f4f6035c8bef52f1efaf0d1)
|
|
31
|
+
* ci: run tests in node 16, 18 and 20 (a688782892f72f554215e181d7925fb19de934ff)
|
|
11
32
|
* deps: upgrade dependencies (f6e8664281931e0eeea26d62059bfbc9e9a8c37d)
|
|
12
33
|
* tests: add perf test for bfj.match (f345bc83e5fbd9204cab02169a2ae9f4c02d1450)
|
|
13
34
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://gitlab.com/philbooth/bfj/pipelines)
|
|
4
4
|
[](https://www.npmjs.com/package/bfj)
|
|
5
|
-
[](https://www.npmjs.com/package/bfj)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
8
|
Big-Friendly JSON. Asynchronous streaming functions for large JSON data sets.
|
|
@@ -25,7 +25,6 @@ Big-Friendly JSON. Asynchronous streaming functions for large JSON data sets.
|
|
|
25
25
|
* [Options for serialisation functions](#options-for-serialisation-functions)
|
|
26
26
|
* [Is it possible to pause parsing or serialisation from calling code?](#is-it-possible-to-pause-parsing-or-serialisation-from-calling-code)
|
|
27
27
|
* [Can it handle newline-delimited JSON (NDJSON)?](#can-it-handle-newline-delimited-json-ndjson)
|
|
28
|
-
* [Why does it default to bluebird promises?](#why-does-it-default-to-bluebird-promises)
|
|
29
28
|
* [Can I specify a different promise implementation?](#can-i-specify-a-different-promise-implementation)
|
|
30
29
|
* [Is there a change log?](#is-there-a-change-log)
|
|
31
30
|
* [How do I set up the dev environment?](#how-do-i-set-up-the-dev-environment)
|
|
@@ -159,7 +158,7 @@ bfj.read(path, options)
|
|
|
159
158
|
});
|
|
160
159
|
```
|
|
161
160
|
|
|
162
|
-
`read` returns a
|
|
161
|
+
`read` returns a promise and
|
|
163
162
|
asynchronously parses
|
|
164
163
|
a JSON file
|
|
165
164
|
from disk.
|
|
@@ -200,7 +199,7 @@ request({ url }).pipe(bfj.unpipe((error, data) => {
|
|
|
200
199
|
}))
|
|
201
200
|
```
|
|
202
201
|
|
|
203
|
-
* `parse` returns a
|
|
202
|
+
* `parse` returns a promise
|
|
204
203
|
and asynchronously parses
|
|
205
204
|
a stream of JSON data.
|
|
206
205
|
|
|
@@ -313,7 +312,7 @@ bfj.write(path, data, options)
|
|
|
313
312
|
});
|
|
314
313
|
```
|
|
315
314
|
|
|
316
|
-
`write` returns a
|
|
315
|
+
`write` returns a promise
|
|
317
316
|
and asynchronously serialises a data structure
|
|
318
317
|
to a JSON file on disk.
|
|
319
318
|
The promise is resolved
|
|
@@ -373,7 +372,7 @@ bfj.stringify(data, options)
|
|
|
373
372
|
});
|
|
374
373
|
```
|
|
375
374
|
|
|
376
|
-
`stringify` returns a
|
|
375
|
+
`stringify` returns a promise and
|
|
377
376
|
asynchronously serialises a data structure
|
|
378
377
|
to a JSON string.
|
|
379
378
|
The promise is resolved
|
|
@@ -680,18 +679,12 @@ of an object,
|
|
|
680
679
|
but the overall parsing time will be slower.
|
|
681
680
|
Larger values yield to the event loop less often,
|
|
682
681
|
meaning slower tick times but faster overall parsing time.
|
|
683
|
-
The default value is `
|
|
682
|
+
The default value is `1024`.
|
|
684
683
|
|
|
685
684
|
* `options.Promise`:
|
|
686
685
|
Promise constructor that will be used
|
|
687
686
|
for promises returned by all methods.
|
|
688
|
-
|
|
689
|
-
please be aware that some promise implementations
|
|
690
|
-
(including native promises)
|
|
691
|
-
may cause your process to die
|
|
692
|
-
with out-of-memory exceptions.
|
|
693
|
-
Defaults to [bluebird's implementation][promise],
|
|
694
|
-
which does not have that problem.
|
|
687
|
+
Defaults to JS builtin `Promise`.
|
|
695
688
|
|
|
696
689
|
* `options.ndjson`:
|
|
697
690
|
If set to `true`,
|
|
@@ -712,7 +705,7 @@ of an object,
|
|
|
712
705
|
the length of the match buffer.
|
|
713
706
|
Smaller values use less memory
|
|
714
707
|
but may result in a slower parse time.
|
|
715
|
-
The default value is `
|
|
708
|
+
The default value is `256`.
|
|
716
709
|
|
|
717
710
|
* `options.highWaterMark`:
|
|
718
711
|
For `bfj.match` only,
|
|
@@ -789,7 +782,7 @@ of an object,
|
|
|
789
782
|
The length of the write buffer.
|
|
790
783
|
Smaller values use less memory
|
|
791
784
|
but may result in a slower serialisation time.
|
|
792
|
-
The default value is `
|
|
785
|
+
The default value is `256`.
|
|
793
786
|
|
|
794
787
|
* `options.highWaterMark`:
|
|
795
788
|
Set this if you would like to
|
|
@@ -804,18 +797,12 @@ of an object,
|
|
|
804
797
|
but the overall serialisation time will be slower.
|
|
805
798
|
Larger values yield to the event loop less often,
|
|
806
799
|
meaning slower tick times but faster overall serialisation time.
|
|
807
|
-
The default value is `
|
|
800
|
+
The default value is `1024`.
|
|
808
801
|
|
|
809
802
|
* `options.Promise`:
|
|
810
803
|
Promise constructor that will be used
|
|
811
804
|
for promises returned by all methods.
|
|
812
|
-
|
|
813
|
-
please be aware that some promise implementations
|
|
814
|
-
(including native promises)
|
|
815
|
-
may cause your process to die
|
|
816
|
-
with out-of-memory exceptions.
|
|
817
|
-
Defaults to [bluebird's implementation][promise],
|
|
818
|
-
which does not have that problem.
|
|
805
|
+
Defaults to JS builtin `Promise`.
|
|
819
806
|
|
|
820
807
|
## Is it possible to pause parsing or serialisation from calling code?
|
|
821
808
|
|
|
@@ -873,31 +860,14 @@ discrete JSON values:
|
|
|
873
860
|
|
|
874
861
|
`bfj.unpipe` and `bfj.read` will not parse NDJSON.
|
|
875
862
|
|
|
876
|
-
## Why does it default to bluebird promises?
|
|
877
|
-
|
|
878
|
-
Until version `4.2.4`,
|
|
879
|
-
native promises were used.
|
|
880
|
-
But they were found
|
|
881
|
-
to cause out-of-memory errors
|
|
882
|
-
when serialising large amounts of data to JSON,
|
|
883
|
-
due to [well-documented problems
|
|
884
|
-
with the native promise implementation](https://alexn.org/blog/2017/10/11/javascript-promise-leaks-memory.html).
|
|
885
|
-
So in version `5.0.0`,
|
|
886
|
-
bluebird promises were used instead.
|
|
887
|
-
In version `5.1.0`,
|
|
888
|
-
an option was added
|
|
889
|
-
that enables callers to specify
|
|
890
|
-
the promise constructor to use.
|
|
891
|
-
Use it at your own risk.
|
|
892
|
-
|
|
893
863
|
## Can I specify a different promise implementation?
|
|
894
864
|
|
|
895
865
|
Yes.
|
|
896
866
|
Just pass the `Promise` option
|
|
897
867
|
to any method.
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
868
|
+
You might want to try this
|
|
869
|
+
if you get any out-of-memory errors
|
|
870
|
+
when parsing huge files.
|
|
901
871
|
|
|
902
872
|
## Is there a change log?
|
|
903
873
|
|
|
@@ -935,8 +905,8 @@ with the command
|
|
|
935
905
|
|
|
936
906
|
## What versions of Node.js does it support?
|
|
937
907
|
|
|
938
|
-
As of [version `
|
|
939
|
-
only Node.js versions
|
|
908
|
+
As of [version `8.0.0`](HISTORY.md#700),
|
|
909
|
+
only Node.js versions 18 or greater
|
|
940
910
|
are supported.
|
|
941
911
|
|
|
942
912
|
Between versions [`3.0.0`](HISTORY.md#300)
|
|
@@ -955,7 +925,6 @@ were supported.
|
|
|
955
925
|
[ci-image]: https://secure.travis-ci.org/philbooth/bfj.png?branch=master
|
|
956
926
|
[ci-status]: http://travis-ci.org/#!/philbooth/bfj
|
|
957
927
|
[sax]: http://en.wikipedia.org/wiki/Simple_API_for_XML
|
|
958
|
-
[promise]: http://bluebirdjs.com/docs/api-reference.html
|
|
959
928
|
[bfj-collections]: https://github.com/hash-bang/bfj-collections
|
|
960
929
|
[eventemitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
|
961
930
|
[readable]: https://nodejs.org/api/stream.html#stream_readable_streams
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bfj",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "Big-friendly JSON. Asynchronous streaming functions for large JSON data sets.",
|
|
5
5
|
"homepage": "https://gitlab.com/philbooth/bfj",
|
|
6
6
|
"bugs": "https://gitlab.com/philbooth/bfj/issues",
|
|
@@ -26,20 +26,19 @@
|
|
|
26
26
|
"url": "https://gitlab.com/philbooth/bfj.git"
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
29
|
-
"node": ">=
|
|
29
|
+
"node": ">= 18.0.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"bluebird": "^3.7.2",
|
|
33
32
|
"check-types": "^11.2.3",
|
|
34
33
|
"hoopy": "^0.1.4",
|
|
35
34
|
"jsonpath": "^1.1.1",
|
|
36
35
|
"tryer": "^1.0.1"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
39
|
-
"axios": "^1.
|
|
40
|
-
"chai": "^4.
|
|
41
|
-
"eslint": "^8.
|
|
42
|
-
"mocha": "^10.
|
|
38
|
+
"axios": "^1.7.7",
|
|
39
|
+
"chai": "^4.5.0",
|
|
40
|
+
"eslint": "^8.57.1",
|
|
41
|
+
"mocha": "^10.7.3",
|
|
43
42
|
"please-release-me": "^2.1.4",
|
|
44
43
|
"proxyquire": "^2.1.3",
|
|
45
44
|
"spooks": "^2.0.0"
|
|
@@ -49,6 +48,7 @@
|
|
|
49
48
|
"test": "npm run unit && npm run integration",
|
|
50
49
|
"unit": "mocha --ui tdd --reporter spec --recursive --colors --slow 120 test/unit",
|
|
51
50
|
"integration": "mocha --ui tdd --reporter spec --colors test/integration",
|
|
52
|
-
"perf": "wget -O test/mtg.json
|
|
51
|
+
"perf": "wget -O test/mtg.json https://mtgjson.com/api/v5/AllPrices.json && node test/performance mtg",
|
|
52
|
+
"perf-match": "wget -O test/mtg.json https://mtgjson.com/api/v5/AllPrices.json && node test/performance mtg currency"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/eventify.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const check = require('check-types')
|
|
4
4
|
const EventEmitter = require('events').EventEmitter
|
|
5
5
|
const events = require('./events')
|
|
6
|
-
const promise = require('./promise')
|
|
7
6
|
|
|
8
7
|
const invalidTypes = {
|
|
9
8
|
undefined: true, // eslint-disable-line no-undefined
|
|
@@ -34,14 +33,11 @@ module.exports = eventify
|
|
|
34
33
|
* @option circular: 'error' or 'ignore', default is 'error'.
|
|
35
34
|
*
|
|
36
35
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
37
|
-
* default is
|
|
38
|
-
*
|
|
39
|
-
* @option Promise: The promise constructor to use, defaults to bluebird.
|
|
36
|
+
* default is 1024.
|
|
40
37
|
**/
|
|
41
38
|
function eventify (data, options = {}) {
|
|
42
39
|
const coercions = {}
|
|
43
40
|
const emitter = new EventEmitter()
|
|
44
|
-
const Promise = promise(options)
|
|
45
41
|
const references = new Map()
|
|
46
42
|
|
|
47
43
|
let count = 0
|
|
@@ -53,7 +49,7 @@ function eventify (data, options = {}) {
|
|
|
53
49
|
|
|
54
50
|
emitter.pause = () => {
|
|
55
51
|
let resolve
|
|
56
|
-
pause = new Promise(res => resolve = res)
|
|
52
|
+
pause = new Promise((res) => resolve = res)
|
|
57
53
|
return () => {
|
|
58
54
|
pause = null
|
|
59
55
|
count = 0
|
|
@@ -80,7 +76,7 @@ function eventify (data, options = {}) {
|
|
|
80
76
|
}
|
|
81
77
|
|
|
82
78
|
check.assert.maybe.positive(options.yieldRate)
|
|
83
|
-
yieldRate = options.yieldRate ||
|
|
79
|
+
yieldRate = options.yieldRate || 1024
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
function parseCoercionOption (key) {
|
|
@@ -89,59 +85,31 @@ function eventify (data, options = {}) {
|
|
|
89
85
|
}
|
|
90
86
|
}
|
|
91
87
|
|
|
92
|
-
function begin () {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
async function begin () {
|
|
89
|
+
try {
|
|
90
|
+
await proceed(data)
|
|
91
|
+
} catch (error) {
|
|
92
|
+
await emit(events.error, error)
|
|
93
|
+
} finally {
|
|
94
|
+
await emit(events.end)
|
|
95
|
+
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
function proceed (datum) {
|
|
98
|
+
async function proceed (datum) {
|
|
99
99
|
if (++count % yieldRate !== 0) {
|
|
100
|
-
return coerce(datum)
|
|
100
|
+
return afterCoercion(await coerce(datum))
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
return new Promise((
|
|
104
|
-
setImmediate(() => {
|
|
105
|
-
coerce(datum)
|
|
106
|
-
.then(after)
|
|
107
|
-
.then(resolve)
|
|
108
|
-
.catch(reject)
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
function after (coerced) {
|
|
113
|
-
if (isInvalid(coerced)) {
|
|
114
|
-
return
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (coerced === false || coerced === true || coerced === null) {
|
|
118
|
-
return literal(coerced)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (Array.isArray(coerced)) {
|
|
122
|
-
return array(coerced)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const type = typeof coerced
|
|
126
|
-
|
|
127
|
-
switch (type) {
|
|
128
|
-
case 'number':
|
|
129
|
-
return value(coerced, type)
|
|
130
|
-
case 'string':
|
|
131
|
-
return value(escapeString(coerced), type)
|
|
132
|
-
default:
|
|
133
|
-
return object(coerced)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
103
|
+
return new Promise(yieldThenProceed.bind(null, datum))
|
|
136
104
|
}
|
|
137
105
|
|
|
138
|
-
function coerce (datum) {
|
|
106
|
+
async function coerce (datum) {
|
|
139
107
|
if (disableCoercions || check.primitive(datum)) {
|
|
140
|
-
return
|
|
108
|
+
return datum
|
|
141
109
|
}
|
|
142
110
|
|
|
143
111
|
if (check.thenable(datum)) {
|
|
144
|
-
return coerceThing(datum, 'promises', coercePromise)
|
|
112
|
+
return coerce(await coerceThing(datum, 'promises', coercePromise))
|
|
145
113
|
}
|
|
146
114
|
|
|
147
115
|
if (check.instanceStrict(datum, Buffer)) {
|
|
@@ -161,10 +129,10 @@ function eventify (data, options = {}) {
|
|
|
161
129
|
}
|
|
162
130
|
|
|
163
131
|
if (check.function(datum.toJSON)) {
|
|
164
|
-
return
|
|
132
|
+
return datum.toJSON()
|
|
165
133
|
}
|
|
166
134
|
|
|
167
|
-
return
|
|
135
|
+
return datum
|
|
168
136
|
}
|
|
169
137
|
|
|
170
138
|
function coerceThing (datum, thing, fn) {
|
|
@@ -186,8 +154,8 @@ function eventify (data, options = {}) {
|
|
|
186
154
|
function coerceMap (map) {
|
|
187
155
|
const result = {}
|
|
188
156
|
|
|
189
|
-
return coerceCollection(map, result, (
|
|
190
|
-
result[key] =
|
|
157
|
+
return coerceCollection(map, result, (val, key) => {
|
|
158
|
+
result[key] = val
|
|
191
159
|
})
|
|
192
160
|
}
|
|
193
161
|
|
|
@@ -200,11 +168,36 @@ function eventify (data, options = {}) {
|
|
|
200
168
|
function coerceIterable (iterable) {
|
|
201
169
|
const result = []
|
|
202
170
|
|
|
203
|
-
return coerceCollection(iterable, result,
|
|
204
|
-
result.push(
|
|
171
|
+
return coerceCollection(iterable, result, (val) => {
|
|
172
|
+
result.push(val)
|
|
205
173
|
})
|
|
206
174
|
}
|
|
207
175
|
|
|
176
|
+
function afterCoercion (coerced) {
|
|
177
|
+
if (isInvalid(coerced)) {
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (coerced === false || coerced === true || coerced === null) {
|
|
182
|
+
return literal(coerced)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (Array.isArray(coerced)) {
|
|
186
|
+
return array(coerced)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const type = typeof coerced
|
|
190
|
+
|
|
191
|
+
switch (type) {
|
|
192
|
+
case 'number':
|
|
193
|
+
return value(coerced, type)
|
|
194
|
+
case 'string':
|
|
195
|
+
return value(escapeString(coerced), type)
|
|
196
|
+
default:
|
|
197
|
+
return object(coerced)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
208
201
|
function isInvalid (datum) {
|
|
209
202
|
const type = typeof datum
|
|
210
203
|
return !! invalidTypes[type] || (
|
|
@@ -216,89 +209,104 @@ function eventify (data, options = {}) {
|
|
|
216
209
|
return datum > Number.NEGATIVE_INFINITY && datum < Number.POSITIVE_INFINITY
|
|
217
210
|
}
|
|
218
211
|
|
|
219
|
-
function
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
212
|
+
async function yieldThenProceed (datum, resolve, reject) {
|
|
213
|
+
setImmediate(async () => {
|
|
214
|
+
try {
|
|
215
|
+
resolve(await afterCoercion(await coerce(datum)))
|
|
216
|
+
} catch (error) {
|
|
217
|
+
reject(error)
|
|
218
|
+
}
|
|
219
|
+
})
|
|
225
220
|
}
|
|
226
221
|
|
|
227
|
-
function
|
|
228
|
-
return (
|
|
229
|
-
.then(() => emitter.emit(event, eventData))
|
|
230
|
-
.catch(err => {
|
|
231
|
-
try {
|
|
232
|
-
emitter.emit(events.error, err)
|
|
233
|
-
} catch (_) {
|
|
234
|
-
// When calling user code, anything is possible
|
|
235
|
-
}
|
|
236
|
-
})
|
|
222
|
+
function literal (datum) {
|
|
223
|
+
return value(datum, 'literal')
|
|
237
224
|
}
|
|
238
225
|
|
|
239
226
|
function array (datum) {
|
|
240
227
|
// For an array, collection:object and collection:array are the same.
|
|
241
|
-
return collection(datum, datum, 'array',
|
|
242
|
-
if (isInvalid(
|
|
243
|
-
|
|
228
|
+
return collection(datum, datum, 'array', async (val) => {
|
|
229
|
+
if (isInvalid(val)) {
|
|
230
|
+
await proceed(null)
|
|
231
|
+
} else {
|
|
232
|
+
await proceed(val)
|
|
244
233
|
}
|
|
245
|
-
|
|
246
|
-
return proceed(item)
|
|
247
234
|
})
|
|
248
235
|
}
|
|
249
236
|
|
|
250
|
-
function collection (obj, arr, type, action) {
|
|
237
|
+
async function collection (obj, arr, type, action) {
|
|
251
238
|
let ignoreThisItem
|
|
252
239
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
240
|
+
if (references.has(obj)) {
|
|
241
|
+
ignoreThisItem = ignoreItems = true
|
|
242
|
+
|
|
243
|
+
if (! ignoreCircularReferences) {
|
|
244
|
+
return emit(events.dataError, new Error('Circular reference.'))
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
references.set(obj, true)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
await emit(events[type])
|
|
251
|
+
|
|
252
|
+
await item(obj, arr, type, action, ignoreThisItem, 0)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function emit (event, eventData) {
|
|
256
|
+
try {
|
|
257
|
+
await pause
|
|
258
|
+
emitter.emit(event, eventData)
|
|
259
|
+
} catch (error) {
|
|
260
|
+
try {
|
|
261
|
+
emitter.emit(events.error, error)
|
|
262
|
+
} catch (_) {
|
|
263
|
+
// When calling user code, anything is possible
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function item (obj, arr, type, action, ignoreThisItem, index) {
|
|
269
|
+
if (index >= arr.length) {
|
|
270
|
+
if (ignoreThisItem) {
|
|
271
|
+
ignoreItems = false
|
|
280
272
|
}
|
|
281
273
|
|
|
282
274
|
if (ignoreItems) {
|
|
283
|
-
return
|
|
275
|
+
return
|
|
284
276
|
}
|
|
285
277
|
|
|
286
|
-
|
|
287
|
-
|
|
278
|
+
await emit(events.endPrefix + events[type])
|
|
279
|
+
|
|
280
|
+
references.delete(obj)
|
|
281
|
+
|
|
282
|
+
return
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (ignoreItems) {
|
|
286
|
+
return item(obj, arr, type, action, ignoreThisItem, index + 1)
|
|
288
287
|
}
|
|
288
|
+
|
|
289
|
+
await action(arr[index])
|
|
290
|
+
|
|
291
|
+
await item(obj, arr, type, action, ignoreThisItem, index + 1)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function value (datum, type) {
|
|
295
|
+
return emit(events[type], datum)
|
|
289
296
|
}
|
|
290
297
|
|
|
291
298
|
function object (datum) {
|
|
292
299
|
// For an object, collection:object and collection:array are different.
|
|
293
|
-
return collection(datum, Object.keys(datum), 'object', key => {
|
|
294
|
-
const
|
|
300
|
+
return collection(datum, Object.keys(datum), 'object', async (key) => {
|
|
301
|
+
const val = datum[key]
|
|
295
302
|
|
|
296
|
-
if (isInvalid(
|
|
297
|
-
return
|
|
303
|
+
if (isInvalid(val)) {
|
|
304
|
+
return
|
|
298
305
|
}
|
|
299
306
|
|
|
300
|
-
|
|
301
|
-
|
|
307
|
+
await emit(events.property, escapeString(key))
|
|
308
|
+
|
|
309
|
+
await proceed(val)
|
|
302
310
|
})
|
|
303
311
|
}
|
|
304
312
|
|
package/src/match.js
CHANGED
|
@@ -7,7 +7,7 @@ const Hoopy = require('hoopy')
|
|
|
7
7
|
const jsonpath = require('jsonpath')
|
|
8
8
|
const walk = require('./walk')
|
|
9
9
|
|
|
10
|
-
const DEFAULT_BUFFER_LENGTH =
|
|
10
|
+
const DEFAULT_BUFFER_LENGTH = 256
|
|
11
11
|
|
|
12
12
|
module.exports = match
|
|
13
13
|
|
|
@@ -40,14 +40,12 @@ module.exports = match
|
|
|
40
40
|
* default is `false`.
|
|
41
41
|
*
|
|
42
42
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
43
|
-
* default is
|
|
43
|
+
* default is 1024.
|
|
44
44
|
*
|
|
45
|
-
* @option bufferLength: The length of the match buffer, default is
|
|
45
|
+
* @option bufferLength: The length of the match buffer, default is 256.
|
|
46
46
|
*
|
|
47
47
|
* @option highWaterMark: If set, will be passed to the readable stream constructor
|
|
48
48
|
* as the value for the highWaterMark option.
|
|
49
|
-
*
|
|
50
|
-
* @option Promise: The promise constructor to use, defaults to bluebird.
|
|
51
49
|
**/
|
|
52
50
|
function match (stream, selector, options = {}) {
|
|
53
51
|
const keys = []
|
package/src/parse.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const check = require('check-types')
|
|
4
4
|
const events = require('./events')
|
|
5
|
-
const promise = require('./promise')
|
|
6
5
|
const walk = require('./walk')
|
|
7
6
|
|
|
8
7
|
module.exports = parse
|
|
@@ -21,9 +20,7 @@ const NDJSON_STATE = new Map()
|
|
|
21
20
|
* @option reviver: Transformation function, invoked depth-first.
|
|
22
21
|
*
|
|
23
22
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
24
|
-
* default is
|
|
25
|
-
*
|
|
26
|
-
* @option Promise: The promise constructor to use, defaults to bluebird.
|
|
23
|
+
* default is 1024.
|
|
27
24
|
*
|
|
28
25
|
* @option ndjson: Set this to true to parse newline-delimited JSON. In
|
|
29
26
|
* this case, each call will be resolved with one value
|
|
@@ -31,14 +28,8 @@ const NDJSON_STATE = new Map()
|
|
|
31
28
|
* should be made sequentially one-at-a-time until the
|
|
32
29
|
* returned promise resolves to `undefined`.
|
|
33
30
|
**/
|
|
34
|
-
function parse (stream, options = {}) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
check.assert.maybe.function(options.reviver, 'Invalid reviver option')
|
|
39
|
-
} catch (err) {
|
|
40
|
-
return Promise.reject(err)
|
|
41
|
-
}
|
|
31
|
+
async function parse (stream, options = {}) {
|
|
32
|
+
check.assert.maybe.function(options.reviver, 'Invalid reviver option')
|
|
42
33
|
|
|
43
34
|
const errors = []
|
|
44
35
|
const scopes = []
|
package/src/read.js
CHANGED
|
@@ -17,9 +17,7 @@ module.exports = read
|
|
|
17
17
|
* @option reviver: Transformation function, invoked depth-first.
|
|
18
18
|
*
|
|
19
19
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
20
|
-
* default is
|
|
21
|
-
*
|
|
22
|
-
* @option Promise: The promise constructor to use, defaults to bluebird.
|
|
20
|
+
* default is 1024.
|
|
23
21
|
**/
|
|
24
22
|
function read (path, options) {
|
|
25
23
|
return parse(fs.createReadStream(path, options), { ...options, ndjson: false })
|