@depup/stream-json 1.9.1-depup.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/Assembler.js +154 -0
- package/Disassembler.js +209 -0
- package/Emitter.js +22 -0
- package/LICENSE +34 -0
- package/Parser.js +545 -0
- package/README.md +31 -0
- package/Stringer.js +153 -0
- package/changes.json +10 -0
- package/filters/Filter.js +130 -0
- package/filters/FilterBase.js +201 -0
- package/filters/Ignore.js +24 -0
- package/filters/Pick.js +58 -0
- package/filters/Replace.js +115 -0
- package/index.js +11 -0
- package/jsonl/Parser.js +131 -0
- package/jsonl/Stringer.js +29 -0
- package/package.json +64 -0
- package/streamers/StreamArray.js +44 -0
- package/streamers/StreamBase.js +101 -0
- package/streamers/StreamObject.js +43 -0
- package/streamers/StreamValues.js +33 -0
- package/utils/Batch.js +44 -0
- package/utils/Utf8Stream.js +53 -0
- package/utils/Verifier.js +485 -0
- package/utils/emit.js +5 -0
- package/utils/withParser.js +10 -0
package/Stringer.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {Transform} = require('stream');
|
|
4
|
+
|
|
5
|
+
const noCommaAfter = {startObject: 1, startArray: 1, endKey: 1, keyValue: 1},
|
|
6
|
+
noSpaceAfter = {endObject: 1, endArray: 1, '': 1},
|
|
7
|
+
noSpaceBefore = {startObject: 1, startArray: 1},
|
|
8
|
+
depthIncrement = {startObject: 1, startArray: 1},
|
|
9
|
+
depthDecrement = {endObject: 1, endArray: 1},
|
|
10
|
+
values = {startKey: 'keyValue', startString: 'stringValue', startNumber: 'numberValue'},
|
|
11
|
+
stopNames = {startKey: 'endKey', startString: 'endString', startNumber: 'endNumber'},
|
|
12
|
+
symbols = {
|
|
13
|
+
startObject: '{',
|
|
14
|
+
endObject: '}',
|
|
15
|
+
startArray: '[',
|
|
16
|
+
endArray: ']',
|
|
17
|
+
startKey: '"',
|
|
18
|
+
endKey: '":',
|
|
19
|
+
startString: '"',
|
|
20
|
+
endString: '"',
|
|
21
|
+
startNumber: '',
|
|
22
|
+
endNumber: '',
|
|
23
|
+
nullValue: 'null',
|
|
24
|
+
trueValue: 'true',
|
|
25
|
+
falseValue: 'false'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const skipValue = endName =>
|
|
29
|
+
function (chunk, encoding, callback) {
|
|
30
|
+
if (chunk.name === endName) {
|
|
31
|
+
this._transform = this._prev_transform;
|
|
32
|
+
}
|
|
33
|
+
callback(null);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const replaceSymbols = {'\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t', '"': '\\"', '\\': '\\\\'};
|
|
37
|
+
const sanitizeString = value =>
|
|
38
|
+
value.replace(/[\b\f\n\r\t\"\\\u0000-\u001F\u007F-\u009F]/g, match =>
|
|
39
|
+
replaceSymbols.hasOwnProperty(match) ? replaceSymbols[match] : '\\u' + ('0000' + match.charCodeAt(0).toString(16)).slice(-4)
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const doNothing = () => {};
|
|
43
|
+
|
|
44
|
+
class Stringer extends Transform {
|
|
45
|
+
static make(options) {
|
|
46
|
+
return new Stringer(options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
constructor(options) {
|
|
50
|
+
super(Object.assign({}, options, {writableObjectMode: true, readableObjectMode: false}));
|
|
51
|
+
|
|
52
|
+
this._values = {};
|
|
53
|
+
if (options) {
|
|
54
|
+
'useValues' in options && (this._values.keyValue = this._values.stringValue = this._values.numberValue = options.useValues);
|
|
55
|
+
'useKeyValues' in options && (this._values.keyValue = options.useKeyValues);
|
|
56
|
+
'useStringValues' in options && (this._values.stringValue = options.useStringValues);
|
|
57
|
+
'useNumberValues' in options && (this._values.numberValue = options.useNumberValues);
|
|
58
|
+
this._makeArray = options.makeArray;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this._prev = '';
|
|
62
|
+
this._depth = 0;
|
|
63
|
+
|
|
64
|
+
if (this._makeArray) {
|
|
65
|
+
this._transform = this._arrayTransform;
|
|
66
|
+
this._flush = this._arrayFlush;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_arrayTransform(chunk, encoding, callback) {
|
|
71
|
+
// it runs once
|
|
72
|
+
delete this._transform;
|
|
73
|
+
this._transform({name: 'startArray'}, encoding, doNothing);
|
|
74
|
+
this._transform(chunk, encoding, callback);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_arrayFlush(callback) {
|
|
78
|
+
if (this._transform === this._arrayTransform) {
|
|
79
|
+
delete this._transform;
|
|
80
|
+
this._transform({name: 'startArray'}, null, doNothing);
|
|
81
|
+
}
|
|
82
|
+
this._transform({name: 'endArray'}, null, callback);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
_transform(chunk, _, callback) {
|
|
86
|
+
if (this._values[chunk.name]) {
|
|
87
|
+
if (this._depth && noCommaAfter[this._prev] !== 1) this.push(',');
|
|
88
|
+
switch (chunk.name) {
|
|
89
|
+
case 'keyValue':
|
|
90
|
+
this.push('"' + sanitizeString(chunk.value) + '":');
|
|
91
|
+
break;
|
|
92
|
+
case 'stringValue':
|
|
93
|
+
this.push('"' + sanitizeString(chunk.value) + '"');
|
|
94
|
+
break;
|
|
95
|
+
case 'numberValue':
|
|
96
|
+
this.push(chunk.value);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
// filter out values
|
|
101
|
+
switch (chunk.name) {
|
|
102
|
+
case 'endObject':
|
|
103
|
+
case 'endArray':
|
|
104
|
+
case 'endKey':
|
|
105
|
+
case 'endString':
|
|
106
|
+
case 'endNumber':
|
|
107
|
+
this.push(symbols[chunk.name]);
|
|
108
|
+
break;
|
|
109
|
+
case 'stringChunk':
|
|
110
|
+
this.push(sanitizeString(chunk.value));
|
|
111
|
+
break;
|
|
112
|
+
case 'numberChunk':
|
|
113
|
+
this.push(chunk.value);
|
|
114
|
+
break;
|
|
115
|
+
case 'keyValue':
|
|
116
|
+
case 'stringValue':
|
|
117
|
+
case 'numberValue':
|
|
118
|
+
// skip completely
|
|
119
|
+
break;
|
|
120
|
+
case 'startKey':
|
|
121
|
+
case 'startString':
|
|
122
|
+
case 'startNumber':
|
|
123
|
+
if (this._values[values[chunk.name]]) {
|
|
124
|
+
this._prev_transform = this._transform;
|
|
125
|
+
this._transform = skipValue(stopNames[chunk.name]);
|
|
126
|
+
return callback(null);
|
|
127
|
+
}
|
|
128
|
+
// intentional fall down
|
|
129
|
+
default:
|
|
130
|
+
// case 'startObject': case 'startArray': case 'startKey': case 'startString':
|
|
131
|
+
// case 'startNumber': case 'nullValue': case 'trueValue': case 'falseValue':
|
|
132
|
+
if (this._depth) {
|
|
133
|
+
if (noCommaAfter[this._prev] !== 1) this.push(',');
|
|
134
|
+
} else {
|
|
135
|
+
if (noSpaceAfter[this._prev] !== 1 && noSpaceBefore[chunk.name] !== 1) this.push(' ');
|
|
136
|
+
}
|
|
137
|
+
this.push(symbols[chunk.name]);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
if (depthIncrement[chunk.name]) {
|
|
141
|
+
++this._depth;
|
|
142
|
+
} else if (depthDecrement[chunk.name]) {
|
|
143
|
+
--this._depth;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
this._prev = chunk.name;
|
|
147
|
+
callback(null);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
Stringer.stringer = Stringer.make;
|
|
151
|
+
Stringer.make.Constructor = Stringer;
|
|
152
|
+
|
|
153
|
+
module.exports = Stringer;
|
package/changes.json
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const FilterBase = require('./FilterBase');
|
|
4
|
+
const withParser = require('../utils/withParser');
|
|
5
|
+
|
|
6
|
+
class Filter extends FilterBase {
|
|
7
|
+
static make(options) {
|
|
8
|
+
return new Filter(options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static withParser(options) {
|
|
12
|
+
return withParser(Filter.make, options);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
constructor(options) {
|
|
16
|
+
super(options);
|
|
17
|
+
this._once = false;
|
|
18
|
+
this._lastStack = [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_flush(callback) {
|
|
22
|
+
this._syncStack();
|
|
23
|
+
callback(null);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
_checkChunk(chunk) {
|
|
27
|
+
switch (chunk.name) {
|
|
28
|
+
case 'startObject':
|
|
29
|
+
if (this._filter(this._stack, chunk)) {
|
|
30
|
+
this._syncStack();
|
|
31
|
+
this.push(chunk);
|
|
32
|
+
this._lastStack.push(null);
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
case 'startArray':
|
|
36
|
+
if (this._filter(this._stack, chunk)) {
|
|
37
|
+
this._syncStack();
|
|
38
|
+
this.push(chunk);
|
|
39
|
+
this._lastStack.push(-1);
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
case 'nullValue':
|
|
43
|
+
case 'trueValue':
|
|
44
|
+
case 'falseValue':
|
|
45
|
+
case 'stringValue':
|
|
46
|
+
case 'numberValue':
|
|
47
|
+
if (this._filter(this._stack, chunk)) {
|
|
48
|
+
this._syncStack();
|
|
49
|
+
this.push(chunk);
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
case 'startString':
|
|
53
|
+
if (this._filter(this._stack, chunk)) {
|
|
54
|
+
this._syncStack();
|
|
55
|
+
this.push(chunk);
|
|
56
|
+
this._transform = this._passString;
|
|
57
|
+
} else {
|
|
58
|
+
this._transform = this._skipString;
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
case 'startNumber':
|
|
62
|
+
if (this._filter(this._stack, chunk)) {
|
|
63
|
+
this._syncStack();
|
|
64
|
+
this.push(chunk);
|
|
65
|
+
this._transform = this._passNumber;
|
|
66
|
+
} else {
|
|
67
|
+
this._transform = this._skipNumber;
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_syncStack() {
|
|
75
|
+
const stack = this._stack,
|
|
76
|
+
last = this._lastStack,
|
|
77
|
+
stackLength = stack.length,
|
|
78
|
+
lastLength = last.length;
|
|
79
|
+
|
|
80
|
+
// find the common part
|
|
81
|
+
let commonLength = 0;
|
|
82
|
+
for (const n = Math.min(stackLength, lastLength); commonLength < n && stack[commonLength] === last[commonLength]; ++commonLength);
|
|
83
|
+
|
|
84
|
+
// close old objects
|
|
85
|
+
for (let i = lastLength - 1; i > commonLength; --i) {
|
|
86
|
+
this.push({name: typeof last[i] == 'number' ? 'endArray' : 'endObject'});
|
|
87
|
+
}
|
|
88
|
+
if (commonLength < lastLength) {
|
|
89
|
+
if (commonLength < stackLength) {
|
|
90
|
+
if (typeof stack[commonLength] == 'string') {
|
|
91
|
+
const key = stack[commonLength];
|
|
92
|
+
if (this._streamKeys) {
|
|
93
|
+
this.push({name: 'startKey'});
|
|
94
|
+
this.push({name: 'stringChunk', value: key});
|
|
95
|
+
this.push({name: 'endKey'});
|
|
96
|
+
}
|
|
97
|
+
this.push({name: 'keyValue', value: key});
|
|
98
|
+
}
|
|
99
|
+
++commonLength;
|
|
100
|
+
} else {
|
|
101
|
+
this.push({name: typeof last[commonLength] == 'number' ? 'endArray' : 'endObject'});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// open new objects
|
|
106
|
+
for (let i = commonLength; i < stackLength; ++i) {
|
|
107
|
+
const key = stack[i];
|
|
108
|
+
if (typeof key == 'number') {
|
|
109
|
+
if (key >= 0) {
|
|
110
|
+
this.push({name: 'startArray'});
|
|
111
|
+
}
|
|
112
|
+
} else if (typeof key == 'string') {
|
|
113
|
+
this.push({name: 'startObject'});
|
|
114
|
+
if (this._streamKeys) {
|
|
115
|
+
this.push({name: 'startKey'});
|
|
116
|
+
this.push({name: 'stringChunk', value: key});
|
|
117
|
+
this.push({name: 'endKey'});
|
|
118
|
+
}
|
|
119
|
+
this.push({name: 'keyValue', value: key});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// update the last stack
|
|
124
|
+
this._lastStack = Array.prototype.concat.call(stack);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
Filter.filter = Filter.make;
|
|
128
|
+
Filter.make.Constructor = Filter;
|
|
129
|
+
|
|
130
|
+
module.exports = Filter;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {Transform} = require('stream');
|
|
4
|
+
|
|
5
|
+
class FilterBase extends Transform {
|
|
6
|
+
static stringFilter(string, separator) {
|
|
7
|
+
return stack => {
|
|
8
|
+
const path = stack.join(separator);
|
|
9
|
+
return (
|
|
10
|
+
(path.length === string.length && path === string) ||
|
|
11
|
+
(path.length > string.length && path.substr(0, string.length) === string && path.substr(string.length, separator.length) === separator)
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static regExpFilter(regExp, separator) {
|
|
17
|
+
return stack => regExp.test(stack.join(separator));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static arrayReplacement(array) {
|
|
21
|
+
return () => array;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
constructor(options) {
|
|
25
|
+
super(Object.assign({}, options, {writableObjectMode: true, readableObjectMode: true}));
|
|
26
|
+
this._transform = this._check;
|
|
27
|
+
this._stack = [];
|
|
28
|
+
|
|
29
|
+
const filter = options && options.filter,
|
|
30
|
+
separator = (options && options.pathSeparator) || '.';
|
|
31
|
+
if (typeof filter == 'string') {
|
|
32
|
+
this._filter = FilterBase.stringFilter(filter, separator);
|
|
33
|
+
} else if (typeof filter == 'function') {
|
|
34
|
+
this._filter = filter;
|
|
35
|
+
} else if (filter instanceof RegExp) {
|
|
36
|
+
this._filter = FilterBase.regExpFilter(filter, separator);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const replacement = options && options.replacement;
|
|
40
|
+
if (typeof replacement == 'function') {
|
|
41
|
+
this._replacement = replacement;
|
|
42
|
+
} else {
|
|
43
|
+
this._replacement = FilterBase.arrayReplacement(replacement || FilterBase.defaultReplacement);
|
|
44
|
+
}
|
|
45
|
+
this._allowEmptyReplacement = options && options.allowEmptyReplacement;
|
|
46
|
+
|
|
47
|
+
this._streamKeys = true;
|
|
48
|
+
if (options) {
|
|
49
|
+
'streamValues' in options && (this._streamKeys = options.streamValues);
|
|
50
|
+
'streamKeys' in options && (this._streamKeys = options.streamKeys);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this._once = options && options.once;
|
|
54
|
+
this._previousToken = '';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_check(chunk, _, callback) {
|
|
58
|
+
// update the last stack key
|
|
59
|
+
switch (chunk.name) {
|
|
60
|
+
case 'startObject':
|
|
61
|
+
case 'startArray':
|
|
62
|
+
case 'startString':
|
|
63
|
+
case 'startNumber':
|
|
64
|
+
case 'nullValue':
|
|
65
|
+
case 'trueValue':
|
|
66
|
+
case 'falseValue':
|
|
67
|
+
if (typeof this._stack[this._stack.length - 1] == 'number') {
|
|
68
|
+
// array
|
|
69
|
+
++this._stack[this._stack.length - 1];
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case 'keyValue':
|
|
73
|
+
this._stack[this._stack.length - 1] = chunk.value;
|
|
74
|
+
break;
|
|
75
|
+
case 'numberValue':
|
|
76
|
+
if (this._previousToken !== 'endNumber' && typeof this._stack[this._stack.length - 1] == 'number') {
|
|
77
|
+
// array
|
|
78
|
+
++this._stack[this._stack.length - 1];
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
case 'stringValue':
|
|
82
|
+
if (this._previousToken !== 'endString' && typeof this._stack[this._stack.length - 1] == 'number') {
|
|
83
|
+
// array
|
|
84
|
+
++this._stack[this._stack.length - 1];
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
this._previousToken = chunk.name;
|
|
89
|
+
// check, if we allow a chunk
|
|
90
|
+
if (this._checkChunk(chunk)) {
|
|
91
|
+
return callback(null);
|
|
92
|
+
}
|
|
93
|
+
// update the stack
|
|
94
|
+
switch (chunk.name) {
|
|
95
|
+
case 'startObject':
|
|
96
|
+
this._stack.push(null);
|
|
97
|
+
break;
|
|
98
|
+
case 'startArray':
|
|
99
|
+
this._stack.push(-1);
|
|
100
|
+
break;
|
|
101
|
+
case 'endObject':
|
|
102
|
+
case 'endArray':
|
|
103
|
+
this._stack.pop();
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
callback(null);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_passObject(chunk, _, callback) {
|
|
110
|
+
this.push(chunk);
|
|
111
|
+
switch (chunk.name) {
|
|
112
|
+
case 'startObject':
|
|
113
|
+
case 'startArray':
|
|
114
|
+
++this._depth;
|
|
115
|
+
break;
|
|
116
|
+
case 'endObject':
|
|
117
|
+
case 'endArray':
|
|
118
|
+
--this._depth;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (!this._depth) {
|
|
122
|
+
this._transform = this._once ? this._skip : this._check;
|
|
123
|
+
}
|
|
124
|
+
callback(null);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_pass(chunk, _, callback) {
|
|
128
|
+
this.push(chunk);
|
|
129
|
+
callback(null);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
_skipObject(chunk, _, callback) {
|
|
133
|
+
switch (chunk.name) {
|
|
134
|
+
case 'startObject':
|
|
135
|
+
case 'startArray':
|
|
136
|
+
++this._depth;
|
|
137
|
+
break;
|
|
138
|
+
case 'endObject':
|
|
139
|
+
case 'endArray':
|
|
140
|
+
--this._depth;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
if (!this._depth) {
|
|
144
|
+
this._transform = this._once ? this._pass : this._check;
|
|
145
|
+
}
|
|
146
|
+
callback(null);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
_skip(chunk, _, callback) {
|
|
150
|
+
callback(null);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
FilterBase.defaultReplacement = [{name: 'nullValue', value: null}];
|
|
155
|
+
|
|
156
|
+
const passValue = (last, post) =>
|
|
157
|
+
function(chunk, _, callback) {
|
|
158
|
+
if (this._expected) {
|
|
159
|
+
const expected = this._expected;
|
|
160
|
+
this._expected = '';
|
|
161
|
+
this._transform = this._once ? this._skip : this._check;
|
|
162
|
+
if (expected === chunk.name) {
|
|
163
|
+
this.push(chunk);
|
|
164
|
+
} else {
|
|
165
|
+
return this._transform(chunk, _, callback);
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
this.push(chunk);
|
|
169
|
+
if (chunk.name === last) {
|
|
170
|
+
this._expected = post;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
callback(null);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
FilterBase.prototype._passNumber = passValue('endNumber', 'numberValue');
|
|
177
|
+
FilterBase.prototype._passString = passValue('endString', 'stringValue');
|
|
178
|
+
FilterBase.prototype._passKey = passValue('endKey', 'keyValue');
|
|
179
|
+
|
|
180
|
+
const skipValue = (last, post) =>
|
|
181
|
+
function(chunk, _, callback) {
|
|
182
|
+
if (this._expected) {
|
|
183
|
+
const expected = this._expected;
|
|
184
|
+
this._expected = '';
|
|
185
|
+
this._transform = this._once ? this._pass : this._check;
|
|
186
|
+
if (expected !== chunk.name) {
|
|
187
|
+
return this._transform(chunk, _, callback);
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
if (chunk.name === last) {
|
|
191
|
+
this._expected = post;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
callback(null);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
FilterBase.prototype._skipNumber = skipValue('endNumber', 'numberValue');
|
|
198
|
+
FilterBase.prototype._skipString = skipValue('endString', 'stringValue');
|
|
199
|
+
FilterBase.prototype._skipKey = skipValue('endKey', 'keyValue');
|
|
200
|
+
|
|
201
|
+
module.exports = FilterBase;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Replace = require('./Replace');
|
|
4
|
+
const withParser = require('../utils/withParser');
|
|
5
|
+
|
|
6
|
+
class Ignore extends Replace {
|
|
7
|
+
static make(options) {
|
|
8
|
+
return new Ignore(options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static withParser(options) {
|
|
12
|
+
return withParser(Ignore.make, options);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
constructor(options) {
|
|
16
|
+
super(options);
|
|
17
|
+
this._replacement = Replace.arrayReplacement([]);
|
|
18
|
+
this._allowEmptyReplacement = true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
Ignore.ignore = Ignore.make;
|
|
22
|
+
Ignore.make.Constructor = Ignore;
|
|
23
|
+
|
|
24
|
+
module.exports = Ignore;
|
package/filters/Pick.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const FilterBase = require('./FilterBase');
|
|
4
|
+
const withParser = require('../utils/withParser');
|
|
5
|
+
|
|
6
|
+
class Pick extends FilterBase {
|
|
7
|
+
static make(options) {
|
|
8
|
+
return new Pick(options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static withParser(options) {
|
|
12
|
+
return withParser(Pick.make, options);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_checkChunk(chunk) {
|
|
16
|
+
switch (chunk.name) {
|
|
17
|
+
case 'startObject':
|
|
18
|
+
case 'startArray':
|
|
19
|
+
if (this._filter(this._stack, chunk)) {
|
|
20
|
+
this.push(chunk);
|
|
21
|
+
this._transform = this._passObject;
|
|
22
|
+
this._depth = 1;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
break;
|
|
26
|
+
case 'startString':
|
|
27
|
+
if (this._filter(this._stack, chunk)) {
|
|
28
|
+
this.push(chunk);
|
|
29
|
+
this._transform = this._passString;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
break;
|
|
33
|
+
case 'startNumber':
|
|
34
|
+
if (this._filter(this._stack, chunk)) {
|
|
35
|
+
this.push(chunk);
|
|
36
|
+
this._transform = this._passNumber;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
case 'nullValue':
|
|
41
|
+
case 'trueValue':
|
|
42
|
+
case 'falseValue':
|
|
43
|
+
case 'stringValue':
|
|
44
|
+
case 'numberValue':
|
|
45
|
+
if (this._filter(this._stack, chunk)) {
|
|
46
|
+
this.push(chunk);
|
|
47
|
+
this._transform = this._once ? this._skip : this._check;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
Pick.pick = Pick.make;
|
|
56
|
+
Pick.make.Constructor = Pick;
|
|
57
|
+
|
|
58
|
+
module.exports = Pick;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const FilterBase = require('./FilterBase');
|
|
4
|
+
const withParser = require('../utils/withParser');
|
|
5
|
+
|
|
6
|
+
class Replace extends FilterBase {
|
|
7
|
+
static make(options) {
|
|
8
|
+
return new Replace(options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static withParser(options) {
|
|
12
|
+
return withParser(Replace.make, options);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_checkChunk(chunk) {
|
|
16
|
+
switch (chunk.name) {
|
|
17
|
+
case 'startKey':
|
|
18
|
+
if (this._allowEmptyReplacement) {
|
|
19
|
+
this._transform = this._skipKeyChunks;
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
break;
|
|
23
|
+
case 'keyValue':
|
|
24
|
+
if (this._allowEmptyReplacement) return true;
|
|
25
|
+
break;
|
|
26
|
+
case 'startObject':
|
|
27
|
+
case 'startArray':
|
|
28
|
+
case 'startString':
|
|
29
|
+
case 'startNumber':
|
|
30
|
+
case 'nullValue':
|
|
31
|
+
case 'trueValue':
|
|
32
|
+
case 'falseValue':
|
|
33
|
+
case 'stringValue':
|
|
34
|
+
case 'numberValue':
|
|
35
|
+
if (this._filter(this._stack, chunk)) {
|
|
36
|
+
let replacement = this._replacement(this._stack, chunk);
|
|
37
|
+
if (this._allowEmptyReplacement) {
|
|
38
|
+
if (replacement.length) {
|
|
39
|
+
const key = this._stack[this._stack.length - 1];
|
|
40
|
+
if (typeof key == 'string') {
|
|
41
|
+
if (this._streamKeys) {
|
|
42
|
+
this.push({name: 'startKey'});
|
|
43
|
+
this.push({name: 'stringChunk', value: key});
|
|
44
|
+
this.push({name: 'endKey'});
|
|
45
|
+
}
|
|
46
|
+
this.push({name: 'keyValue', value: key});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
if (!replacement.length) replacement = FilterBase.defaultReplacement;
|
|
51
|
+
}
|
|
52
|
+
replacement.forEach(value => this.push(value));
|
|
53
|
+
switch (chunk.name) {
|
|
54
|
+
case 'startObject':
|
|
55
|
+
case 'startArray':
|
|
56
|
+
this._transform = this._skipObject;
|
|
57
|
+
this._depth = 1;
|
|
58
|
+
break;
|
|
59
|
+
case 'startString':
|
|
60
|
+
this._transform = this._skipString;
|
|
61
|
+
break;
|
|
62
|
+
case 'startNumber':
|
|
63
|
+
this._transform = this._skipNumber;
|
|
64
|
+
break;
|
|
65
|
+
case 'nullValue':
|
|
66
|
+
case 'trueValue':
|
|
67
|
+
case 'falseValue':
|
|
68
|
+
case 'stringValue':
|
|
69
|
+
case 'numberValue':
|
|
70
|
+
this._transform = this._once ? this._pass : this._check;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
// issue a key, if needed
|
|
78
|
+
if (this._allowEmptyReplacement) {
|
|
79
|
+
const key = this._stack[this._stack.length - 1];
|
|
80
|
+
if (typeof key == 'string') {
|
|
81
|
+
switch (chunk.name) {
|
|
82
|
+
case 'startObject':
|
|
83
|
+
case 'startArray':
|
|
84
|
+
case 'startString':
|
|
85
|
+
case 'startNumber':
|
|
86
|
+
case 'nullValue':
|
|
87
|
+
case 'trueValue':
|
|
88
|
+
case 'falseValue':
|
|
89
|
+
case 'stringValue':
|
|
90
|
+
case 'numberValue':
|
|
91
|
+
if (this._streamKeys) {
|
|
92
|
+
this.push({name: 'startKey'});
|
|
93
|
+
this.push({name: 'stringChunk', value: key});
|
|
94
|
+
this.push({name: 'endKey'});
|
|
95
|
+
}
|
|
96
|
+
this.push({name: 'keyValue', value: key});
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
this.push(chunk);
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_skipKeyChunks(chunk, _, callback) {
|
|
106
|
+
if (chunk.name === 'endKey') {
|
|
107
|
+
this._transform = this._check;
|
|
108
|
+
}
|
|
109
|
+
callback(null);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
Replace.replace = Replace.make;
|
|
113
|
+
Replace.make.Constructor = Replace;
|
|
114
|
+
|
|
115
|
+
module.exports = Replace;
|