@sergdudko/objectstream 3.2.25 → 4.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/README.md +320 -63
- package/dist/cjs/index.js +29 -0
- package/dist/esm/classes/Parser.js +231 -0
- package/dist/esm/classes/Stringifer.js +154 -0
- package/{lib → dist/esm}/index.js +10 -7
- package/dist/esm/utils/genericFunction.js +2 -0
- package/dist/esm/utils/global.js +36 -0
- package/{lib → dist/types}/index.d.ts +3 -2
- package/package.json +44 -17
- package/CHANGELOG.md +0 -317
- package/FUNDING.yml +0 -2
- package/ignoreUpdatesModules.json +0 -4
- package/lib/classes/Parser.js.map +0 -1
- package/lib/classes/Stringifer.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/utils/genericFunction.js.map +0 -1
- package/lib/utils/global.js.map +0 -1
- /package/{lib → dist/cjs}/classes/Parser.js +0 -0
- /package/{lib → dist/cjs}/classes/Stringifer.js +0 -0
- /package/{lib → dist/cjs}/utils/genericFunction.js +0 -0
- /package/{lib → dist/cjs}/utils/global.js +0 -0
- /package/{lib → dist/types}/classes/Parser.d.ts +0 -0
- /package/{lib → dist/types}/classes/Stringifer.d.ts +0 -0
- /package/{lib → dist/types}/utils/genericFunction.d.ts +0 -0
- /package/{lib → dist/types}/utils/global.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @sergdudko/objectstream
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A powerful and efficient Node.js library for streaming JSON processing. Transform JSON strings to objects and objects to JSON strings with support for custom separators, multiple encodings, and high-performance streaming operations.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@sergdudko/objectstream)
|
|
6
6
|
[](https://www.npmjs.com/package/@sergdudko/objectstream)
|
|
@@ -8,101 +8,358 @@ Revolutionize Your JSON Handling with Streamlined Efficiency: Seamlessly Convert
|
|
|
8
8
|

|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## ✨ Features
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- **Dual Package**: Full ES Modules (ESM) and CommonJS (CJS) support
|
|
14
|
+
- **TypeScript**: Complete type definitions included
|
|
15
|
+
- **High Performance**: Based on native Node.js stream methods
|
|
16
|
+
- **Multiple Encodings**: Support for utf8, base64, latin1, binary, and hex
|
|
17
|
+
- **Custom Separators**: Configure start, middle, and end separators
|
|
18
|
+
- **Memory Efficient**: Streaming approach for large JSON datasets
|
|
19
|
+
- **Zero Dependencies**: No external dependencies
|
|
20
|
+
|
|
21
|
+
## 📦 Installation
|
|
14
22
|
|
|
15
23
|
```bash
|
|
16
|
-
|
|
24
|
+
npm install @sergdudko/objectstream
|
|
17
25
|
```
|
|
18
26
|
|
|
19
|
-
##
|
|
27
|
+
## 🚀 Quick Start
|
|
28
|
+
|
|
29
|
+
### ESM (ES Modules)
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
```javascript
|
|
32
|
+
import { Parser, Stringifer } from '@sergdudko/objectstream';
|
|
22
33
|
|
|
23
|
-
|
|
34
|
+
// String to Object conversion
|
|
35
|
+
const parser = new Parser();
|
|
36
|
+
parser.on('data', (obj) => {
|
|
37
|
+
console.log('Parsed object:', obj);
|
|
38
|
+
});
|
|
39
|
+
parser.write('{"name":"John","age":30}');
|
|
40
|
+
parser.end();
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
// Object to String conversion
|
|
43
|
+
const stringifer = new Stringifer();
|
|
44
|
+
stringifer.on('data', (jsonString) => {
|
|
45
|
+
console.log('JSON string:', jsonString.toString());
|
|
46
|
+
});
|
|
47
|
+
stringifer.write({ name: 'John', age: 30 });
|
|
48
|
+
stringifer.end();
|
|
49
|
+
```
|
|
29
50
|
|
|
30
|
-
|
|
51
|
+
### CommonJS
|
|
31
52
|
|
|
32
|
-
```
|
|
33
|
-
|
|
53
|
+
```javascript
|
|
54
|
+
const { Parser, Stringifer } = require('@sergdudko/objectstream');
|
|
34
55
|
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
// Or using default export
|
|
57
|
+
const objectstream = require('@sergdudko/objectstream');
|
|
58
|
+
const { Parser, Stringifer } = objectstream.default;
|
|
59
|
+
```
|
|
39
60
|
|
|
40
|
-
|
|
61
|
+
### TypeScript
|
|
41
62
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const endSeparator = "]";
|
|
45
|
-
const stringToObject = new Parser(
|
|
46
|
-
firstSeparator,
|
|
47
|
-
middleSeparator,
|
|
48
|
-
endSeparator
|
|
49
|
-
);
|
|
50
|
-
const objectToString = new Stringifer(
|
|
51
|
-
firstSeparator,
|
|
52
|
-
middleSeparator,
|
|
53
|
-
endSeparator
|
|
54
|
-
);
|
|
63
|
+
```typescript
|
|
64
|
+
import { Parser, Stringifer } from '@sergdudko/objectstream';
|
|
55
65
|
|
|
56
|
-
|
|
66
|
+
interface User {
|
|
67
|
+
name: string;
|
|
68
|
+
age: number;
|
|
69
|
+
}
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
const parser = new Parser();
|
|
72
|
+
parser.on('data', (user: User) => {
|
|
73
|
+
console.log(`User: ${user.name}, Age: ${user.age}`);
|
|
60
74
|
});
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 📚 API Reference
|
|
78
|
+
|
|
79
|
+
### Parser Class
|
|
80
|
+
|
|
81
|
+
Transform stream that converts JSON strings to JavaScript objects.
|
|
82
|
+
|
|
83
|
+
#### Constructor
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
new Parser(start?: string, middle?: string, end?: string)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### Parameters
|
|
90
|
+
|
|
91
|
+
- `start` (optional): First separator character (default: none)
|
|
92
|
+
- `middle` (optional): Middle separator character (default: none)
|
|
93
|
+
- `end` (optional): End separator character (default: none)
|
|
94
|
+
|
|
95
|
+
#### Methods
|
|
96
|
+
|
|
97
|
+
- `setEncoding(encoding)`: Set input encoding (`utf8`, `utf-8`, `base64`, `latin1`, `binary`, `hex`)
|
|
98
|
+
|
|
99
|
+
#### Events
|
|
100
|
+
|
|
101
|
+
- `data`: Emitted when an object is parsed
|
|
102
|
+
- `error`: Emitted when parsing fails
|
|
103
|
+
- `end`: Emitted when stream ends
|
|
104
|
+
- `finish`: Emitted when stream finishes
|
|
105
|
+
|
|
106
|
+
### Stringifer Class
|
|
107
|
+
|
|
108
|
+
Transform stream that converts JavaScript objects to JSON strings.
|
|
109
|
+
|
|
110
|
+
#### Constructor
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
new Stringifer(start?: string, middle?: string, end?: string)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Parameters
|
|
117
|
+
|
|
118
|
+
- `start` (optional): First separator character (default: none)
|
|
119
|
+
- `middle` (optional): Middle separator character (default: none)
|
|
120
|
+
- `end` (optional): End separator character (default: none)
|
|
121
|
+
|
|
122
|
+
#### Methods
|
|
123
|
+
|
|
124
|
+
- `setEncoding(encoding)`: Set output encoding (`utf8`, `utf-8`, `base64`, `latin1`, `binary`, `hex`)
|
|
125
|
+
|
|
126
|
+
#### Events
|
|
127
|
+
|
|
128
|
+
- `data`: Emitted when JSON string is generated
|
|
129
|
+
- `error`: Emitted when stringification fails
|
|
130
|
+
- `end`: Emitted when stream ends
|
|
131
|
+
- `finish`: Emitted when stream finishes
|
|
132
|
+
|
|
133
|
+
## 💡 Usage Examples
|
|
134
|
+
|
|
135
|
+
### Basic JSON Processing
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
import { Parser, Stringifer } from '@sergdudko/objectstream';
|
|
139
|
+
|
|
140
|
+
const parser = new Parser();
|
|
141
|
+
const stringifer = new Stringifer();
|
|
142
|
+
|
|
143
|
+
// Parse JSON string
|
|
144
|
+
parser.on('data', (obj) => {
|
|
145
|
+
console.log('Parsed:', obj);
|
|
63
146
|
});
|
|
64
|
-
|
|
65
|
-
|
|
147
|
+
|
|
148
|
+
parser.write('{"message":"Hello World"}');
|
|
149
|
+
parser.end();
|
|
150
|
+
|
|
151
|
+
// Stringify object
|
|
152
|
+
stringifer.on('data', (data) => {
|
|
153
|
+
console.log('Stringified:', data.toString());
|
|
66
154
|
});
|
|
67
|
-
|
|
68
|
-
|
|
155
|
+
|
|
156
|
+
stringifer.write({ message: 'Hello World' });
|
|
157
|
+
stringifer.end();
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Custom Separators for JSON Arrays
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
import { Parser, Stringifer } from '@sergdudko/objectstream';
|
|
164
|
+
|
|
165
|
+
// Process JSON array with custom separators
|
|
166
|
+
const parser = new Parser('[', ',', ']');
|
|
167
|
+
const stringifer = new Stringifer('[', ',', ']');
|
|
168
|
+
|
|
169
|
+
stringifer.on('data', (data) => {
|
|
170
|
+
console.log('JSON Array chunk:', data.toString());
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Write multiple objects
|
|
174
|
+
stringifer.write({ id: 1, name: 'Alice' });
|
|
175
|
+
stringifer.write({ id: 2, name: 'Bob' });
|
|
176
|
+
stringifer.write({ id: 3, name: 'Charlie' });
|
|
177
|
+
stringifer.end(); // Output: [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"},{"id":3,"name":"Charlie"}]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Different Encodings
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
import { Parser, Stringifer } from '@sergdudko/objectstream';
|
|
184
|
+
|
|
185
|
+
// Base64 encoding
|
|
186
|
+
const stringifer = new Stringifer();
|
|
187
|
+
stringifer.setEncoding('base64');
|
|
188
|
+
|
|
189
|
+
stringifer.on('data', (data) => {
|
|
190
|
+
console.log('Base64 JSON:', data); // Base64 encoded JSON string
|
|
69
191
|
});
|
|
70
|
-
|
|
71
|
-
|
|
192
|
+
|
|
193
|
+
stringifer.write({ encoded: true });
|
|
194
|
+
stringifer.end();
|
|
195
|
+
|
|
196
|
+
// Parse Base64 encoded JSON
|
|
197
|
+
const parser = new Parser();
|
|
198
|
+
parser.setEncoding('base64');
|
|
199
|
+
|
|
200
|
+
parser.on('data', (obj) => {
|
|
201
|
+
console.log('Decoded object:', obj);
|
|
72
202
|
});
|
|
73
|
-
|
|
74
|
-
|
|
203
|
+
|
|
204
|
+
// Write base64 encoded JSON
|
|
205
|
+
parser.write(Buffer.from('{"decoded":true}').toString('base64'));
|
|
206
|
+
parser.end();
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Stream Piping
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
import { Parser, Stringifer } from '@sergdudko/objectstream';
|
|
213
|
+
import { Transform } from 'stream';
|
|
214
|
+
|
|
215
|
+
// Create a processing pipeline
|
|
216
|
+
const parser = new Parser();
|
|
217
|
+
const processor = new Transform({
|
|
218
|
+
objectMode: true,
|
|
219
|
+
transform(obj, encoding, callback) {
|
|
220
|
+
// Process each object
|
|
221
|
+
obj.processed = true;
|
|
222
|
+
obj.timestamp = Date.now();
|
|
223
|
+
callback(null, obj);
|
|
224
|
+
}
|
|
75
225
|
});
|
|
76
|
-
|
|
77
|
-
|
|
226
|
+
const stringifer = new Stringifer();
|
|
227
|
+
|
|
228
|
+
// Pipe the streams together
|
|
229
|
+
parser
|
|
230
|
+
.pipe(processor)
|
|
231
|
+
.pipe(stringifer)
|
|
232
|
+
.on('data', (data) => {
|
|
233
|
+
console.log('Processed JSON:', data.toString());
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Input data
|
|
237
|
+
parser.write('{"name":"test"}');
|
|
238
|
+
parser.end();
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Error Handling
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
import { Parser, Stringifer } from '@sergdudko/objectstream';
|
|
245
|
+
|
|
246
|
+
const parser = new Parser();
|
|
247
|
+
|
|
248
|
+
parser.on('data', (obj) => {
|
|
249
|
+
console.log('Valid object:', obj);
|
|
78
250
|
});
|
|
79
|
-
|
|
80
|
-
|
|
251
|
+
|
|
252
|
+
parser.on('error', (errors) => {
|
|
253
|
+
console.error('Parsing errors:', errors);
|
|
81
254
|
});
|
|
82
255
|
|
|
83
|
-
//
|
|
256
|
+
// Valid JSON
|
|
257
|
+
parser.write('{"valid":true}');
|
|
258
|
+
|
|
259
|
+
// Invalid JSON
|
|
260
|
+
parser.write('{"invalid":}');
|
|
261
|
+
|
|
262
|
+
parser.end();
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## 🎯 Supported Encodings
|
|
266
|
+
|
|
267
|
+
| Encoding | Input | Output | Description |
|
|
268
|
+
|----------|-------|--------|-------------|
|
|
269
|
+
| `utf8` (default) | ✅ | ✅ | Standard UTF-8 text |
|
|
270
|
+
| `utf-8` | ✅ | ✅ | Alias for utf8 |
|
|
271
|
+
| `base64` | ✅ | ✅ | Base64 encoded data |
|
|
272
|
+
| `latin1` | ✅ | ✅ | Latin-1 encoding |
|
|
273
|
+
| `binary` | ✅ | ✅ | Binary data encoding |
|
|
274
|
+
| `hex` | ✅ | ✅ | Hexadecimal encoding |
|
|
84
275
|
|
|
85
|
-
|
|
86
|
-
objectToString.setEncoding("latin1");
|
|
276
|
+
## ⚡ Performance
|
|
87
277
|
|
|
88
|
-
|
|
278
|
+
ObjectStream is optimized for high-performance streaming operations:
|
|
89
279
|
|
|
90
|
-
|
|
91
|
-
|
|
280
|
+
- **Memory Efficient**: Processes data in chunks, suitable for large JSON files
|
|
281
|
+
- **Zero-Copy Operations**: Minimizes memory copying where possible
|
|
282
|
+
- **Stream-Based**: Non-blocking operations using Node.js streams
|
|
283
|
+
- **Optimized Parsing**: Efficient JSON parsing with error recovery
|
|
92
284
|
|
|
93
|
-
|
|
285
|
+
## 🧪 Testing
|
|
94
286
|
|
|
95
|
-
|
|
287
|
+
The library includes comprehensive TypeScript tests:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
npm test
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Test coverage includes:
|
|
294
|
+
|
|
295
|
+
- ✅ Parser functionality with various data types
|
|
296
|
+
- ✅ Stringifer functionality with validation
|
|
297
|
+
- ✅ Custom separators and encodings
|
|
298
|
+
- ✅ Stream piping and event handling
|
|
299
|
+
- ✅ Error handling and edge cases
|
|
300
|
+
- ✅ Performance benchmarks
|
|
301
|
+
- ✅ ESM/CJS compatibility
|
|
302
|
+
|
|
303
|
+
## 🏗️ Development
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# Install dependencies
|
|
307
|
+
npm install
|
|
308
|
+
|
|
309
|
+
# Run tests
|
|
310
|
+
npm test
|
|
311
|
+
|
|
312
|
+
# Build dual package (ESM + CJS)
|
|
313
|
+
npm run build
|
|
314
|
+
|
|
315
|
+
# Lint code
|
|
316
|
+
npm run lint
|
|
96
317
|
```
|
|
97
318
|
|
|
98
|
-
##
|
|
319
|
+
## 📄 Package Structure
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
dist/
|
|
323
|
+
├── esm/ # ES Modules build
|
|
324
|
+
├── cjs/ # CommonJS build
|
|
325
|
+
└── types/ # Shared TypeScript definitions
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## 🤝 Contributing
|
|
329
|
+
|
|
330
|
+
1. Fork the repository
|
|
331
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
332
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
333
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
334
|
+
5. Open a Pull Request
|
|
335
|
+
|
|
336
|
+
## 🎯 Version History
|
|
337
|
+
|
|
338
|
+
- **v3.x**: TypeScript rewrite, dual package support, modern Node.js features
|
|
339
|
+
- **v2.x**: Enhanced performance and encoding support
|
|
340
|
+
- **v1.x**: Initial release with basic streaming functionality
|
|
341
|
+
|
|
342
|
+
## 📄 License
|
|
343
|
+
|
|
344
|
+
MIT License - see [LICENSE](./LICENSE) file for details.
|
|
345
|
+
|
|
346
|
+
## 🆘 Support
|
|
347
|
+
|
|
348
|
+
- 📝 **Issues**: [GitHub Issues](https://github.com/siarheidudko/objectstream/issues)
|
|
349
|
+
- 💬 **Discussions**: [GitHub Discussions](https://github.com/siarheidudko/objectstream/discussions)
|
|
350
|
+
- 📧 **Email**: [siarhei@dudko.dev](mailto:siarhei@dudko.dev)
|
|
351
|
+
|
|
352
|
+
## 💝 Support This Project
|
|
99
353
|
|
|
100
|
-
|
|
354
|
+
If Redux Cluster helps you build amazing applications, consider supporting its development:
|
|
101
355
|
|
|
102
|
-
|
|
356
|
+
- ☕ **[Buy me a coffee](https://www.buymeacoffee.com/dudko.dev)**
|
|
357
|
+
- 💳 **[PayPal](https://paypal.me/dudkodev)**
|
|
358
|
+
- 🎯 **[Patreon](https://patreon.com/dudko_dev)**
|
|
359
|
+
- 🌐 **[More options](http://dudko.dev/donate)**
|
|
103
360
|
|
|
104
|
-
|
|
361
|
+
Your support helps maintain and improve Redux Cluster for the entire community!
|
|
105
362
|
|
|
106
|
-
|
|
363
|
+
---
|
|
107
364
|
|
|
108
|
-
|
|
365
|
+
**Made with ❤️ by [Siarhei Dudko](https://github.com/siarheidudko)**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Module for stream conversion Json to String and String to Json
|
|
4
|
+
* @module sergdudko/objectstream
|
|
5
|
+
* @author Siarhei Dudko <slavianich@gmail.com>
|
|
6
|
+
* @copyright 2020
|
|
7
|
+
* @license MIT
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
* @requires stream
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.Stringifer = exports.Parser = void 0;
|
|
13
|
+
const Parser_1 = require("./classes/Parser");
|
|
14
|
+
Object.defineProperty(exports, "Parser", { enumerable: true, get: function () { return Parser_1.Parser; } });
|
|
15
|
+
const Stringifer_1 = require("./classes/Stringifer");
|
|
16
|
+
Object.defineProperty(exports, "Stringifer", { enumerable: true, get: function () { return Stringifer_1.Stringifer; } });
|
|
17
|
+
// Default export for CommonJS compatibility
|
|
18
|
+
const objectstream = {
|
|
19
|
+
/**
|
|
20
|
+
* Object to String stream
|
|
21
|
+
*/
|
|
22
|
+
Stringifer: Stringifer_1.Stringifer,
|
|
23
|
+
/**
|
|
24
|
+
* String to Object stream
|
|
25
|
+
*/
|
|
26
|
+
Parser: Parser_1.Parser,
|
|
27
|
+
};
|
|
28
|
+
exports.default = objectstream;
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { Transform } from "stream";
|
|
2
|
+
import { validator } from "../utils/global";
|
|
3
|
+
/**
|
|
4
|
+
* @class Parser
|
|
5
|
+
*
|
|
6
|
+
* Сreates an instance of Parser (String to Json conversion stream)
|
|
7
|
+
*/
|
|
8
|
+
export class Parser extends Transform {
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param start - first separator
|
|
12
|
+
* @param middle - middle separator
|
|
13
|
+
* @param end - end separator
|
|
14
|
+
*/
|
|
15
|
+
constructor(start, middle, end) {
|
|
16
|
+
super({ highWaterMark: 64 * 1024, objectMode: true });
|
|
17
|
+
if (typeof start !== "undefined" &&
|
|
18
|
+
(typeof start !== "string" ||
|
|
19
|
+
Buffer.byteLength(start) > 1 ||
|
|
20
|
+
start.match(/["{}]/)))
|
|
21
|
+
throw new Error("Argument start require one byte String!");
|
|
22
|
+
if (typeof middle !== "undefined" &&
|
|
23
|
+
(typeof middle !== "string" ||
|
|
24
|
+
Buffer.byteLength(middle) > 1 ||
|
|
25
|
+
middle.match(/["{}]/)))
|
|
26
|
+
throw new Error("Argument separator require one byte String!");
|
|
27
|
+
if (typeof end !== "undefined" &&
|
|
28
|
+
(typeof end !== "string" ||
|
|
29
|
+
Buffer.byteLength(end) > 1 ||
|
|
30
|
+
end.match(/["{}]/)))
|
|
31
|
+
throw new Error("Argument end require one byte String!");
|
|
32
|
+
this.__separators = {
|
|
33
|
+
start: Buffer.from(start ? start : "", "utf8")[0],
|
|
34
|
+
middle: Buffer.from(middle ? middle : "", "utf8")[0],
|
|
35
|
+
end: Buffer.from(end ? end : "", "utf8")[0],
|
|
36
|
+
};
|
|
37
|
+
this.__clear();
|
|
38
|
+
this.__bytesRead = 0;
|
|
39
|
+
this.__encoding = "utf8";
|
|
40
|
+
this.setDefaultEncoding(this.__encoding);
|
|
41
|
+
this.__buffers = [];
|
|
42
|
+
this.__leftBrace = 0;
|
|
43
|
+
this.__rightBrace = 0;
|
|
44
|
+
this.__openQuotes = false;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* clear buffer and reset counters
|
|
48
|
+
*
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
__clear() {
|
|
52
|
+
this.__buffers = [];
|
|
53
|
+
this.__leftBrace = 0;
|
|
54
|
+
this.__rightBrace = 0;
|
|
55
|
+
this.__openQuotes = false;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* basic stream handler
|
|
59
|
+
*/
|
|
60
|
+
__handler(buffer, s, errors) {
|
|
61
|
+
if (this.__buffers.length > 65536) {
|
|
62
|
+
const _nbuffer = Buffer.concat(this.__buffers);
|
|
63
|
+
this.__buffers = [];
|
|
64
|
+
this.__buffers.push(_nbuffer);
|
|
65
|
+
}
|
|
66
|
+
if (this.__leftBrace !== 0) {
|
|
67
|
+
this.__buffers.push(buffer.slice(s, s + 1));
|
|
68
|
+
}
|
|
69
|
+
else if (this.__separators.start !== buffer[s] &&
|
|
70
|
+
this.__separators.end !== buffer[s] &&
|
|
71
|
+
this.__separators.middle !== buffer[s] &&
|
|
72
|
+
0x20 !== buffer[s] &&
|
|
73
|
+
0x0d !== buffer[s] &&
|
|
74
|
+
0x0a !== buffer[s] &&
|
|
75
|
+
0x09 !== buffer[s]) {
|
|
76
|
+
errors.push(new Error("Unexpected token " +
|
|
77
|
+
buffer.slice(s, s + 1).toString(this.__encoding) +
|
|
78
|
+
" in JSON at position " +
|
|
79
|
+
(this.__bytesRead + s)));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Data event handler
|
|
84
|
+
*
|
|
85
|
+
* @private
|
|
86
|
+
* @param string - string or buffer data
|
|
87
|
+
* @param encoding - stream encoding
|
|
88
|
+
* @param callback - callback function
|
|
89
|
+
*/
|
|
90
|
+
_transform(string,
|
|
91
|
+
// eslint-disable-next-line
|
|
92
|
+
encoding = this.__encoding, callback = () => {
|
|
93
|
+
return;
|
|
94
|
+
}) {
|
|
95
|
+
if (typeof string === "undefined") {
|
|
96
|
+
callback();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (string === null) {
|
|
100
|
+
this._final(() => {
|
|
101
|
+
callback();
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const _buffer = typeof string === "string" ? Buffer.from(string, encoding) : string;
|
|
106
|
+
if (!(_buffer instanceof Buffer)) {
|
|
107
|
+
callback([
|
|
108
|
+
new Error("Incoming data type is " +
|
|
109
|
+
typeof _buffer +
|
|
110
|
+
", require data type is String!"),
|
|
111
|
+
]);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (Parser.__empty.equals(_buffer)) {
|
|
115
|
+
callback();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const errors = [];
|
|
119
|
+
for (let s = 0; s < _buffer.length; s++) {
|
|
120
|
+
switch (_buffer[s]) {
|
|
121
|
+
case 0x7b:
|
|
122
|
+
this.__leftBrace += 1;
|
|
123
|
+
this.__handler(_buffer, s, errors);
|
|
124
|
+
break;
|
|
125
|
+
case 0x7d:
|
|
126
|
+
this.__rightBrace += 1;
|
|
127
|
+
this.__handler(_buffer, s, errors);
|
|
128
|
+
break;
|
|
129
|
+
case 0x08:
|
|
130
|
+
case 0x09:
|
|
131
|
+
case 0x0a:
|
|
132
|
+
case 0x0c:
|
|
133
|
+
case 0x0d:
|
|
134
|
+
case 0x00:
|
|
135
|
+
case 0x0b:
|
|
136
|
+
if (this.__openQuotes && this.__leftBrace !== 0)
|
|
137
|
+
this.__buffers.push(Buffer.from("\\u" + ("0000" + _buffer[s].toString(16)).slice(-4), "utf8"));
|
|
138
|
+
break;
|
|
139
|
+
case 0x22:
|
|
140
|
+
if (_buffer[s - 1] !== 0x5c)
|
|
141
|
+
if (this.__openQuotes)
|
|
142
|
+
this.__openQuotes = false;
|
|
143
|
+
else if (this.__leftBrace !== 0)
|
|
144
|
+
this.__openQuotes = true;
|
|
145
|
+
this.__handler(_buffer, s, errors);
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
this.__handler(_buffer, s, errors);
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
if (this.__leftBrace !== 0 && this.__leftBrace === this.__rightBrace) {
|
|
152
|
+
try {
|
|
153
|
+
const _buf = Buffer.concat(this.__buffers);
|
|
154
|
+
const _str = _buf.toString("utf8");
|
|
155
|
+
const _object = JSON.parse(_str);
|
|
156
|
+
if (validator(_object, false)) {
|
|
157
|
+
this.__clear();
|
|
158
|
+
this.push(_object);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
this.__clear();
|
|
162
|
+
errors.push(new Error("Validation failed, incoming data type is not pure Object!"));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
this.__clear();
|
|
167
|
+
errors.push(err);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else if (this.__leftBrace < this.__rightBrace) {
|
|
171
|
+
this.__clear();
|
|
172
|
+
errors.push(new Error("Parsing error, clear buffer!"));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (errors.length > 0)
|
|
176
|
+
callback(errors);
|
|
177
|
+
else
|
|
178
|
+
callback();
|
|
179
|
+
this.__bytesRead += _buffer.byteLength;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Flush event handler
|
|
183
|
+
*
|
|
184
|
+
* @private
|
|
185
|
+
* @param callback - callback function
|
|
186
|
+
*/
|
|
187
|
+
_flush(callback = () => {
|
|
188
|
+
return;
|
|
189
|
+
}) {
|
|
190
|
+
this.__clear();
|
|
191
|
+
callback();
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* End event handler
|
|
195
|
+
*
|
|
196
|
+
* @private
|
|
197
|
+
* @param callback - callback function
|
|
198
|
+
*/
|
|
199
|
+
_final(callback = () => {
|
|
200
|
+
return;
|
|
201
|
+
}) {
|
|
202
|
+
if (this.__buffers.length === 0) {
|
|
203
|
+
callback();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
const _buf = Buffer.concat(this.__buffers);
|
|
208
|
+
const _str = _buf.toString("utf8");
|
|
209
|
+
JSON.parse(_str);
|
|
210
|
+
callback([new Error("Raw object detected!")]);
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
callback([err]);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* set stream encoding
|
|
218
|
+
*/
|
|
219
|
+
setEncoding(encoding) {
|
|
220
|
+
this.__encoding = encoding;
|
|
221
|
+
this.setDefaultEncoding(this.__encoding);
|
|
222
|
+
return this;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* empty buffer
|
|
227
|
+
*
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
Parser.__empty = Buffer.from("");
|
|
231
|
+
//# sourceMappingURL=Parser.js.map
|