@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/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,10 @@
1
+ {
2
+ "bumped": {
3
+ "stream-chain": {
4
+ "from": "^2.2.5",
5
+ "to": "^3.4.1"
6
+ }
7
+ },
8
+ "timestamp": "2026-03-17T16:39:24.506Z",
9
+ "totalUpdated": 1
10
+ }
@@ -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;
@@ -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;
package/index.js ADDED
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ const Parser = require('./Parser');
4
+ const emit = require('./utils/emit');
5
+
6
+ const make = options => emit(new Parser(options));
7
+
8
+ make.Parser = Parser;
9
+ make.parser = Parser.parser;
10
+
11
+ module.exports = make;