@jsonjoy.com/json-pack 1.3.0 → 1.5.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 CHANGED
@@ -2,18 +2,49 @@
2
2
 
3
3
  High performance JSON serialization and deserialization library for JavaScript, Node.js, browser.
4
4
 
5
- `json-pack` contains implementations of various JSON codecs into binary,
6
- formats, such as MessagePack, CBOR and other formats.
5
+ ## Supported Formats
7
6
 
8
- - [__MessagePack__](./src/msgpack/README.md)
9
- - [__CBOR__](./src/cbor/README.md)
10
- - DAG-CBOR
11
- - JSON
12
- - DAG-JSON
13
- - UBJSON
14
- - Amazon Ion
15
- - RESP3
16
- - Bencode
7
+ This library implements the following serialization formats:
8
+
9
+ - **[MessagePack](./src/msgpack/README.md)** - Fast and lean implementation of MessagePack codec
10
+ - **[CBOR](./src/cbor/README.md)** - Concise Binary Object Representation codec
11
+ - **[UBJSON](./src/ubjson/README.md)** - Universal Binary JSON codec
12
+ - **[JSON](./src/json/README.md)** - Enhanced JSON encoder/decoder with additional features
13
+ - **[JSON Binary](./src/json-binary/README.md)** - JSON with binary data support using Uint8Array
14
+ - **[Amazon Ion](./src/ion/README.md)** - Amazon's Ion data serialization format
15
+ - **[BSON](./src/bson/README.md)** - Binary JSON format used by MongoDB
16
+ - **[RESP](./src/resp/README.md)** - Redis Serialization Protocol (v2 and v3)
17
+ - **[Bencode](./src/bencode/README.md)** - BitTorrent's encoding format
18
+
19
+ Each format comes with optimized encoders and decoders designed for maximum performance.
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @jsonjoy.com/json-pack
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```ts
30
+ import {MessagePackEncoder, MessagePackDecoder} from '@jsonjoy.com/json-pack/lib/msgpack';
31
+
32
+ const encoder = new MessagePackEncoder();
33
+ const decoder = new MessagePackDecoder();
34
+
35
+ const data = {hello: 'world', numbers: [1, 2, 3]};
36
+ const binary = encoder.encode(data);
37
+ const restored = decoder.decode(binary);
38
+
39
+ console.log(restored); // {hello: 'world', numbers: [1, 2, 3]}
40
+ ```
41
+
42
+ ## Documentation
43
+
44
+ For detailed documentation on each codec, refer to the individual README files in their respective folders:
45
+
46
+ - Individual codec documentation is available in each `src/<codec>/README.md` file
47
+ - Each codec includes comprehensive usage examples, API documentation, and performance benchmarks
17
48
 
18
49
 
19
50
  ## Benchmarks
@@ -0,0 +1,109 @@
1
+ export interface AvroBaseSchema {
2
+ type: string;
3
+ doc?: string;
4
+ [key: string]: any;
5
+ }
6
+ export interface AvroNullSchema extends AvroBaseSchema {
7
+ type: 'null';
8
+ }
9
+ export interface AvroBooleanSchema extends AvroBaseSchema {
10
+ type: 'boolean';
11
+ }
12
+ export interface AvroIntSchema extends AvroBaseSchema {
13
+ type: 'int';
14
+ }
15
+ export interface AvroLongSchema extends AvroBaseSchema {
16
+ type: 'long';
17
+ }
18
+ export interface AvroFloatSchema extends AvroBaseSchema {
19
+ type: 'float';
20
+ }
21
+ export interface AvroDoubleSchema extends AvroBaseSchema {
22
+ type: 'double';
23
+ }
24
+ export interface AvroBytesSchema extends AvroBaseSchema {
25
+ type: 'bytes';
26
+ }
27
+ export interface AvroStringSchema extends AvroBaseSchema {
28
+ type: 'string';
29
+ }
30
+ export interface AvroRecordField {
31
+ name: string;
32
+ type: AvroSchema;
33
+ doc?: string;
34
+ default?: any;
35
+ order?: 'ascending' | 'descending' | 'ignore';
36
+ aliases?: string[];
37
+ }
38
+ export interface AvroRecordSchema extends AvroBaseSchema {
39
+ type: 'record';
40
+ name: string;
41
+ namespace?: string;
42
+ fields: AvroRecordField[];
43
+ aliases?: string[];
44
+ }
45
+ export interface AvroEnumSchema extends AvroBaseSchema {
46
+ type: 'enum';
47
+ name: string;
48
+ namespace?: string;
49
+ symbols: string[];
50
+ default?: string;
51
+ aliases?: string[];
52
+ }
53
+ export interface AvroArraySchema extends AvroBaseSchema {
54
+ type: 'array';
55
+ items: AvroSchema;
56
+ }
57
+ export interface AvroMapSchema extends AvroBaseSchema {
58
+ type: 'map';
59
+ values: AvroSchema;
60
+ }
61
+ export interface AvroUnionSchema extends Array<AvroSchema> {
62
+ }
63
+ export interface AvroFixedSchema extends AvroBaseSchema {
64
+ type: 'fixed';
65
+ name: string;
66
+ namespace?: string;
67
+ size: number;
68
+ aliases?: string[];
69
+ }
70
+ export type AvroPrimitiveSchema = AvroNullSchema | AvroBooleanSchema | AvroIntSchema | AvroLongSchema | AvroFloatSchema | AvroDoubleSchema | AvroBytesSchema | AvroStringSchema;
71
+ export type AvroComplexSchema = AvroRecordSchema | AvroEnumSchema | AvroArraySchema | AvroMapSchema | AvroUnionSchema | AvroFixedSchema;
72
+ export type AvroSchema = AvroPrimitiveSchema | AvroComplexSchema | string;
73
+ export type AvroNamedSchema = AvroRecordSchema | AvroEnumSchema | AvroFixedSchema;
74
+ export interface AvroLogicalTypeSchema extends AvroBaseSchema {
75
+ logicalType: string;
76
+ }
77
+ export interface AvroDecimalLogicalType extends AvroLogicalTypeSchema {
78
+ logicalType: 'decimal';
79
+ precision: number;
80
+ scale?: number;
81
+ }
82
+ export interface AvroUuidLogicalType extends AvroStringSchema {
83
+ logicalType: 'uuid';
84
+ }
85
+ export interface AvroDateLogicalType extends AvroIntSchema {
86
+ logicalType: 'date';
87
+ }
88
+ export interface AvroTimeMillisLogicalType extends AvroIntSchema {
89
+ logicalType: 'time-millis';
90
+ }
91
+ export interface AvroTimeMicrosLogicalType extends AvroLongSchema {
92
+ logicalType: 'time-micros';
93
+ }
94
+ export interface AvroTimestampMillisLogicalType extends AvroLongSchema {
95
+ logicalType: 'timestamp-millis';
96
+ }
97
+ export interface AvroTimestampMicrosLogicalType extends AvroLongSchema {
98
+ logicalType: 'timestamp-micros';
99
+ }
100
+ export interface AvroLocalTimestampMillisLogicalType extends AvroLongSchema {
101
+ logicalType: 'local-timestamp-millis';
102
+ }
103
+ export interface AvroLocalTimestampMicrosLogicalType extends AvroLongSchema {
104
+ logicalType: 'local-timestamp-micros';
105
+ }
106
+ export interface AvroDurationLogicalType extends AvroFixedSchema {
107
+ logicalType: 'duration';
108
+ size: 12;
109
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/avro/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import { JsonDecoder } from '../json/JsonDecoder';
2
+ export interface EjsonDecoderOptions {
3
+ legacy?: boolean;
4
+ }
5
+ export declare class EjsonDecoder extends JsonDecoder {
6
+ private options;
7
+ constructor(options?: EjsonDecoderOptions);
8
+ decodeFromString(json: string): unknown;
9
+ readAny(): unknown;
10
+ readArr(): unknown[];
11
+ readObjWithEjsonSupport(): unknown;
12
+ private readValue;
13
+ private readRawObj;
14
+ private transformEjsonObject;
15
+ private parseObjectId;
16
+ private base64ToUint8Array;
17
+ private isValidUuid;
18
+ private uuidToBytes;
19
+ }
@@ -0,0 +1,449 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EjsonDecoder = void 0;
4
+ const values_1 = require("../bson/values");
5
+ const JsonDecoder_1 = require("../json/JsonDecoder");
6
+ const JsonDecoder_2 = require("../json/JsonDecoder");
7
+ class EjsonDecoder extends JsonDecoder_1.JsonDecoder {
8
+ constructor(options = {}) {
9
+ super();
10
+ this.options = options;
11
+ }
12
+ decodeFromString(json) {
13
+ const bytes = new TextEncoder().encode(json);
14
+ return this.decode(bytes);
15
+ }
16
+ readAny() {
17
+ this.skipWhitespace();
18
+ const reader = this.reader;
19
+ const uint8 = reader.uint8;
20
+ const char = uint8[reader.x];
21
+ switch (char) {
22
+ case 34:
23
+ return this.readStr();
24
+ case 91:
25
+ return this.readArr();
26
+ case 102:
27
+ return this.readFalse();
28
+ case 110:
29
+ return this.readNull();
30
+ case 116:
31
+ return this.readTrue();
32
+ case 123:
33
+ return this.readObjWithEjsonSupport();
34
+ default:
35
+ if ((char >= 48 && char <= 57) || char === 45)
36
+ return this.readNum();
37
+ throw new Error('Invalid JSON');
38
+ }
39
+ }
40
+ readArr() {
41
+ const reader = this.reader;
42
+ if (reader.u8() !== 0x5b)
43
+ throw new Error('Invalid JSON');
44
+ const arr = [];
45
+ const uint8 = reader.uint8;
46
+ let first = true;
47
+ while (true) {
48
+ this.skipWhitespace();
49
+ const char = uint8[reader.x];
50
+ if (char === 0x5d)
51
+ return reader.x++, arr;
52
+ if (char === 0x2c)
53
+ reader.x++;
54
+ else if (!first)
55
+ throw new Error('Invalid JSON');
56
+ this.skipWhitespace();
57
+ arr.push(this.readAny());
58
+ first = false;
59
+ }
60
+ }
61
+ readObjWithEjsonSupport() {
62
+ const reader = this.reader;
63
+ if (reader.u8() !== 0x7b)
64
+ throw new Error('Invalid JSON');
65
+ const obj = {};
66
+ const uint8 = reader.uint8;
67
+ let first = true;
68
+ while (true) {
69
+ this.skipWhitespace();
70
+ let char = uint8[reader.x];
71
+ if (char === 0x7d) {
72
+ reader.x++;
73
+ return this.transformEjsonObject(obj);
74
+ }
75
+ if (char === 0x2c)
76
+ reader.x++;
77
+ else if (!first)
78
+ throw new Error('Invalid JSON');
79
+ this.skipWhitespace();
80
+ char = uint8[reader.x++];
81
+ if (char !== 0x22)
82
+ throw new Error('Invalid JSON');
83
+ const key = (0, JsonDecoder_2.readKey)(reader);
84
+ if (key === '__proto__')
85
+ throw new Error('Invalid JSON');
86
+ this.skipWhitespace();
87
+ if (reader.u8() !== 0x3a)
88
+ throw new Error('Invalid JSON');
89
+ this.skipWhitespace();
90
+ obj[key] = this.readValue();
91
+ first = false;
92
+ }
93
+ }
94
+ readValue() {
95
+ this.skipWhitespace();
96
+ const reader = this.reader;
97
+ const uint8 = reader.uint8;
98
+ const char = uint8[reader.x];
99
+ switch (char) {
100
+ case 34:
101
+ return this.readStr();
102
+ case 91:
103
+ return this.readArr();
104
+ case 102:
105
+ return this.readFalse();
106
+ case 110:
107
+ return this.readNull();
108
+ case 116:
109
+ return this.readTrue();
110
+ case 123:
111
+ return this.readRawObj();
112
+ default:
113
+ if ((char >= 48 && char <= 57) || char === 45)
114
+ return this.readNum();
115
+ throw new Error('Invalid JSON');
116
+ }
117
+ }
118
+ readRawObj() {
119
+ const reader = this.reader;
120
+ if (reader.u8() !== 0x7b)
121
+ throw new Error('Invalid JSON');
122
+ const obj = {};
123
+ const uint8 = reader.uint8;
124
+ let first = true;
125
+ while (true) {
126
+ this.skipWhitespace();
127
+ let char = uint8[reader.x];
128
+ if (char === 0x7d) {
129
+ reader.x++;
130
+ return obj;
131
+ }
132
+ if (char === 0x2c)
133
+ reader.x++;
134
+ else if (!first)
135
+ throw new Error('Invalid JSON');
136
+ this.skipWhitespace();
137
+ char = uint8[reader.x++];
138
+ if (char !== 0x22)
139
+ throw new Error('Invalid JSON');
140
+ const key = (0, JsonDecoder_2.readKey)(reader);
141
+ if (key === '__proto__')
142
+ throw new Error('Invalid JSON');
143
+ this.skipWhitespace();
144
+ if (reader.u8() !== 0x3a)
145
+ throw new Error('Invalid JSON');
146
+ this.skipWhitespace();
147
+ obj[key] = this.readValue();
148
+ first = false;
149
+ }
150
+ }
151
+ transformEjsonObject(obj) {
152
+ const keys = Object.keys(obj);
153
+ const hasExactKeys = (expectedKeys) => {
154
+ if (keys.length !== expectedKeys.length)
155
+ return false;
156
+ return expectedKeys.every((key) => keys.includes(key));
157
+ };
158
+ const specialKeys = keys.filter((key) => key.startsWith('$'));
159
+ if (specialKeys.length > 0) {
160
+ if (specialKeys.includes('$oid')) {
161
+ if (!hasExactKeys(['$oid'])) {
162
+ throw new Error('Invalid ObjectId format: extra keys not allowed');
163
+ }
164
+ const oidStr = obj.$oid;
165
+ if (typeof oidStr === 'string' && /^[0-9a-fA-F]{24}$/.test(oidStr)) {
166
+ return this.parseObjectId(oidStr);
167
+ }
168
+ throw new Error('Invalid ObjectId format');
169
+ }
170
+ if (specialKeys.includes('$numberInt')) {
171
+ if (!hasExactKeys(['$numberInt'])) {
172
+ throw new Error('Invalid Int32 format: extra keys not allowed');
173
+ }
174
+ const intStr = obj.$numberInt;
175
+ if (typeof intStr === 'string') {
176
+ const value = parseInt(intStr, 10);
177
+ if (!isNaN(value) && value >= -2147483648 && value <= 2147483647) {
178
+ return new values_1.BsonInt32(value);
179
+ }
180
+ }
181
+ throw new Error('Invalid Int32 format');
182
+ }
183
+ if (specialKeys.includes('$numberLong')) {
184
+ if (!hasExactKeys(['$numberLong'])) {
185
+ throw new Error('Invalid Int64 format: extra keys not allowed');
186
+ }
187
+ const longStr = obj.$numberLong;
188
+ if (typeof longStr === 'string') {
189
+ const value = parseFloat(longStr);
190
+ if (!isNaN(value)) {
191
+ return new values_1.BsonInt64(value);
192
+ }
193
+ }
194
+ throw new Error('Invalid Int64 format');
195
+ }
196
+ if (specialKeys.includes('$numberDouble')) {
197
+ if (!hasExactKeys(['$numberDouble'])) {
198
+ throw new Error('Invalid Double format: extra keys not allowed');
199
+ }
200
+ const doubleStr = obj.$numberDouble;
201
+ if (typeof doubleStr === 'string') {
202
+ if (doubleStr === 'Infinity')
203
+ return new values_1.BsonFloat(Infinity);
204
+ if (doubleStr === '-Infinity')
205
+ return new values_1.BsonFloat(-Infinity);
206
+ if (doubleStr === 'NaN')
207
+ return new values_1.BsonFloat(NaN);
208
+ const value = parseFloat(doubleStr);
209
+ if (!isNaN(value)) {
210
+ return new values_1.BsonFloat(value);
211
+ }
212
+ }
213
+ throw new Error('Invalid Double format');
214
+ }
215
+ if (specialKeys.includes('$numberDecimal')) {
216
+ if (!hasExactKeys(['$numberDecimal'])) {
217
+ throw new Error('Invalid Decimal128 format: extra keys not allowed');
218
+ }
219
+ const decimalStr = obj.$numberDecimal;
220
+ if (typeof decimalStr === 'string') {
221
+ return new values_1.BsonDecimal128(new Uint8Array(16));
222
+ }
223
+ throw new Error('Invalid Decimal128 format');
224
+ }
225
+ if (specialKeys.includes('$binary')) {
226
+ if (!hasExactKeys(['$binary'])) {
227
+ throw new Error('Invalid Binary format: extra keys not allowed');
228
+ }
229
+ const binaryObj = obj.$binary;
230
+ if (typeof binaryObj === 'object' && binaryObj !== null) {
231
+ const binaryKeys = Object.keys(binaryObj);
232
+ if (binaryKeys.length === 2 && binaryKeys.includes('base64') && binaryKeys.includes('subType')) {
233
+ const base64 = binaryObj.base64;
234
+ const subType = binaryObj.subType;
235
+ if (typeof base64 === 'string' && typeof subType === 'string') {
236
+ const data = this.base64ToUint8Array(base64);
237
+ const subtype = parseInt(subType, 16);
238
+ return new values_1.BsonBinary(subtype, data);
239
+ }
240
+ }
241
+ }
242
+ throw new Error('Invalid Binary format');
243
+ }
244
+ if (specialKeys.includes('$uuid')) {
245
+ if (!hasExactKeys(['$uuid'])) {
246
+ throw new Error('Invalid UUID format: extra keys not allowed');
247
+ }
248
+ const uuidStr = obj.$uuid;
249
+ if (typeof uuidStr === 'string' && this.isValidUuid(uuidStr)) {
250
+ const data = this.uuidToBytes(uuidStr);
251
+ return new values_1.BsonBinary(4, data);
252
+ }
253
+ throw new Error('Invalid UUID format');
254
+ }
255
+ if (specialKeys.includes('$code') && !specialKeys.includes('$scope')) {
256
+ if (!hasExactKeys(['$code'])) {
257
+ throw new Error('Invalid Code format: extra keys not allowed');
258
+ }
259
+ const code = obj.$code;
260
+ if (typeof code === 'string') {
261
+ return new values_1.BsonJavascriptCode(code);
262
+ }
263
+ throw new Error('Invalid Code format');
264
+ }
265
+ if (specialKeys.includes('$code') && specialKeys.includes('$scope')) {
266
+ if (!hasExactKeys(['$code', '$scope'])) {
267
+ throw new Error('Invalid CodeWScope format: extra keys not allowed');
268
+ }
269
+ const code = obj.$code;
270
+ const scope = obj.$scope;
271
+ if (typeof code === 'string' && typeof scope === 'object' && scope !== null) {
272
+ return new values_1.BsonJavascriptCodeWithScope(code, this.transformEjsonObject(scope));
273
+ }
274
+ throw new Error('Invalid CodeWScope format');
275
+ }
276
+ if (specialKeys.includes('$symbol')) {
277
+ if (!hasExactKeys(['$symbol'])) {
278
+ throw new Error('Invalid Symbol format: extra keys not allowed');
279
+ }
280
+ const symbol = obj.$symbol;
281
+ if (typeof symbol === 'string') {
282
+ return new values_1.BsonSymbol(symbol);
283
+ }
284
+ throw new Error('Invalid Symbol format');
285
+ }
286
+ if (specialKeys.includes('$timestamp')) {
287
+ if (!hasExactKeys(['$timestamp'])) {
288
+ throw new Error('Invalid Timestamp format: extra keys not allowed');
289
+ }
290
+ const timestampObj = obj.$timestamp;
291
+ if (typeof timestampObj === 'object' && timestampObj !== null) {
292
+ const timestampKeys = Object.keys(timestampObj);
293
+ if (timestampKeys.length === 2 && timestampKeys.includes('t') && timestampKeys.includes('i')) {
294
+ const t = timestampObj.t;
295
+ const i = timestampObj.i;
296
+ if (typeof t === 'number' && typeof i === 'number' && t >= 0 && i >= 0) {
297
+ return new values_1.BsonTimestamp(i, t);
298
+ }
299
+ }
300
+ }
301
+ throw new Error('Invalid Timestamp format');
302
+ }
303
+ if (specialKeys.includes('$regularExpression')) {
304
+ if (!hasExactKeys(['$regularExpression'])) {
305
+ throw new Error('Invalid RegularExpression format: extra keys not allowed');
306
+ }
307
+ const regexObj = obj.$regularExpression;
308
+ if (typeof regexObj === 'object' && regexObj !== null) {
309
+ const regexKeys = Object.keys(regexObj);
310
+ if (regexKeys.length === 2 && regexKeys.includes('pattern') && regexKeys.includes('options')) {
311
+ const pattern = regexObj.pattern;
312
+ const options = regexObj.options;
313
+ if (typeof pattern === 'string' && typeof options === 'string') {
314
+ return new RegExp(pattern, options);
315
+ }
316
+ }
317
+ }
318
+ throw new Error('Invalid RegularExpression format');
319
+ }
320
+ if (specialKeys.includes('$dbPointer')) {
321
+ if (!hasExactKeys(['$dbPointer'])) {
322
+ throw new Error('Invalid DBPointer format: extra keys not allowed');
323
+ }
324
+ const dbPointerObj = obj.$dbPointer;
325
+ if (typeof dbPointerObj === 'object' && dbPointerObj !== null) {
326
+ const dbPointerKeys = Object.keys(dbPointerObj);
327
+ if (dbPointerKeys.length === 2 && dbPointerKeys.includes('$ref') && dbPointerKeys.includes('$id')) {
328
+ const ref = dbPointerObj.$ref;
329
+ const id = dbPointerObj.$id;
330
+ if (typeof ref === 'string' && id !== undefined) {
331
+ const transformedId = this.transformEjsonObject(id);
332
+ if (transformedId instanceof values_1.BsonObjectId) {
333
+ return new values_1.BsonDbPointer(ref, transformedId);
334
+ }
335
+ }
336
+ }
337
+ }
338
+ throw new Error('Invalid DBPointer format');
339
+ }
340
+ if (specialKeys.includes('$date')) {
341
+ if (!hasExactKeys(['$date'])) {
342
+ throw new Error('Invalid Date format: extra keys not allowed');
343
+ }
344
+ const dateValue = obj.$date;
345
+ if (typeof dateValue === 'string') {
346
+ const date = new Date(dateValue);
347
+ if (!isNaN(date.getTime())) {
348
+ return date;
349
+ }
350
+ }
351
+ else if (typeof dateValue === 'object' && dateValue !== null) {
352
+ const longObj = dateValue;
353
+ const longKeys = Object.keys(longObj);
354
+ if (longKeys.length === 1 && longKeys[0] === '$numberLong' && typeof longObj.$numberLong === 'string') {
355
+ const timestamp = parseFloat(longObj.$numberLong);
356
+ if (!isNaN(timestamp)) {
357
+ return new Date(timestamp);
358
+ }
359
+ }
360
+ }
361
+ throw new Error('Invalid Date format');
362
+ }
363
+ if (specialKeys.includes('$minKey')) {
364
+ if (!hasExactKeys(['$minKey'])) {
365
+ throw new Error('Invalid MinKey format: extra keys not allowed');
366
+ }
367
+ if (obj.$minKey === 1) {
368
+ return new values_1.BsonMinKey();
369
+ }
370
+ throw new Error('Invalid MinKey format');
371
+ }
372
+ if (specialKeys.includes('$maxKey')) {
373
+ if (!hasExactKeys(['$maxKey'])) {
374
+ throw new Error('Invalid MaxKey format: extra keys not allowed');
375
+ }
376
+ if (obj.$maxKey === 1) {
377
+ return new values_1.BsonMaxKey();
378
+ }
379
+ throw new Error('Invalid MaxKey format');
380
+ }
381
+ if (specialKeys.includes('$undefined')) {
382
+ if (!hasExactKeys(['$undefined'])) {
383
+ throw new Error('Invalid Undefined format: extra keys not allowed');
384
+ }
385
+ if (obj.$undefined === true) {
386
+ return undefined;
387
+ }
388
+ throw new Error('Invalid Undefined format');
389
+ }
390
+ }
391
+ if (keys.includes('$ref') && keys.includes('$id')) {
392
+ const ref = obj.$ref;
393
+ const id = this.transformEjsonObject(obj.$id);
394
+ const result = { $ref: ref, $id: id };
395
+ if (keys.includes('$db')) {
396
+ result.$db = obj.$db;
397
+ }
398
+ for (const key of keys) {
399
+ if (key !== '$ref' && key !== '$id' && key !== '$db') {
400
+ result[key] = this.transformEjsonObject(obj[key]);
401
+ }
402
+ }
403
+ return result;
404
+ }
405
+ const result = {};
406
+ for (const [key, val] of Object.entries(obj)) {
407
+ if (typeof val === 'object' && val !== null && !Array.isArray(val)) {
408
+ result[key] = this.transformEjsonObject(val);
409
+ }
410
+ else if (Array.isArray(val)) {
411
+ result[key] = val.map((item) => typeof item === 'object' && item !== null && !Array.isArray(item)
412
+ ? this.transformEjsonObject(item)
413
+ : item);
414
+ }
415
+ else {
416
+ result[key] = val;
417
+ }
418
+ }
419
+ return result;
420
+ }
421
+ parseObjectId(hex) {
422
+ const timestamp = parseInt(hex.slice(0, 8), 16);
423
+ const process = parseInt(hex.slice(8, 18), 16);
424
+ const counter = parseInt(hex.slice(18, 24), 16);
425
+ return new values_1.BsonObjectId(timestamp, process, counter);
426
+ }
427
+ base64ToUint8Array(base64) {
428
+ const binary = atob(base64);
429
+ const bytes = new Uint8Array(binary.length);
430
+ for (let i = 0; i < binary.length; i++) {
431
+ bytes[i] = binary.charCodeAt(i);
432
+ }
433
+ return bytes;
434
+ }
435
+ isValidUuid(uuid) {
436
+ const uuidPattern = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
437
+ return uuidPattern.test(uuid);
438
+ }
439
+ uuidToBytes(uuid) {
440
+ const hex = uuid.replace(/-/g, '');
441
+ const bytes = new Uint8Array(16);
442
+ for (let i = 0; i < 16; i++) {
443
+ bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
444
+ }
445
+ return bytes;
446
+ }
447
+ }
448
+ exports.EjsonDecoder = EjsonDecoder;
449
+ //# sourceMappingURL=EjsonDecoder.js.map