bson 5.2.0 → 5.3.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.
Files changed (57) hide show
  1. package/README.md +3 -126
  2. package/bson.d.ts +71 -22
  3. package/lib/binary.d.ts +182 -0
  4. package/lib/binary.d.ts.map +1 -0
  5. package/lib/bson.bundle.js +68 -86
  6. package/lib/bson.bundle.js.map +1 -1
  7. package/lib/bson.cjs +68 -86
  8. package/lib/bson.cjs.map +1 -1
  9. package/lib/bson.d.ts +97 -0
  10. package/lib/bson.d.ts.map +1 -0
  11. package/lib/bson.mjs +68 -86
  12. package/lib/bson.mjs.map +1 -1
  13. package/lib/bson_value.d.ts +10 -0
  14. package/lib/bson_value.d.ts.map +1 -0
  15. package/lib/code.d.ts +32 -0
  16. package/lib/code.d.ts.map +1 -0
  17. package/lib/constants.d.ts +107 -0
  18. package/lib/constants.d.ts.map +1 -0
  19. package/lib/db_ref.d.ts +40 -0
  20. package/lib/db_ref.d.ts.map +1 -0
  21. package/lib/decimal128.d.ts +34 -0
  22. package/lib/decimal128.d.ts.map +1 -0
  23. package/lib/double.d.ts +35 -0
  24. package/lib/double.d.ts.map +1 -0
  25. package/lib/error.d.ts +50 -0
  26. package/lib/error.d.ts.map +1 -0
  27. package/lib/extended_json.d.ts +82 -0
  28. package/lib/extended_json.d.ts.map +1 -0
  29. package/lib/index.d.ts +4 -0
  30. package/lib/index.d.ts.map +1 -0
  31. package/lib/int_32.d.ts +35 -0
  32. package/lib/int_32.d.ts.map +1 -0
  33. package/lib/long.d.ts +323 -0
  34. package/lib/long.d.ts.map +1 -0
  35. package/lib/max_key.d.ts +19 -0
  36. package/lib/max_key.d.ts.map +1 -0
  37. package/lib/min_key.d.ts +19 -0
  38. package/lib/min_key.d.ts.map +1 -0
  39. package/lib/objectid.d.ts +96 -0
  40. package/lib/objectid.d.ts.map +1 -0
  41. package/lib/regexp.d.ts +36 -0
  42. package/lib/regexp.d.ts.map +1 -0
  43. package/lib/symbol.d.ts +28 -0
  44. package/lib/symbol.d.ts.map +1 -0
  45. package/lib/timestamp.d.ts +66 -0
  46. package/lib/timestamp.d.ts.map +1 -0
  47. package/lib/validate_utf8.d.ts +10 -0
  48. package/lib/validate_utf8.d.ts.map +1 -0
  49. package/package.json +20 -20
  50. package/src/binary.ts +49 -41
  51. package/src/bson.ts +1 -1
  52. package/src/constants.ts +1 -1
  53. package/src/extended_json.ts +11 -3
  54. package/src/parser/deserializer.ts +37 -12
  55. package/src/parser/serializer.ts +17 -4
  56. package/src/timestamp.ts +1 -1
  57. package/src/uuid_utils.ts +0 -33
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "etc/prepare.js"
14
14
  ],
15
15
  "types": "bson.d.ts",
16
- "version": "5.2.0",
16
+ "version": "5.3.0",
17
17
  "author": {
18
18
  "name": "The MongoDB NodeJS Team",
19
19
  "email": "dbx-node@mongodb.com"
@@ -26,37 +26,37 @@
26
26
  },
27
27
  "devDependencies": {
28
28
  "@istanbuljs/nyc-config-typescript": "^1.0.2",
29
- "@microsoft/api-extractor": "^7.33.7",
30
- "@rollup/plugin-node-resolve": "^15.0.1",
31
- "@rollup/plugin-typescript": "^10.0.1",
32
- "@types/chai": "^4.3.4",
29
+ "@microsoft/api-extractor": "^7.34.7",
30
+ "@rollup/plugin-node-resolve": "^15.0.2",
31
+ "@rollup/plugin-typescript": "^11.1.0",
32
+ "@types/chai": "^4.3.5",
33
33
  "@types/mocha": "^10.0.1",
34
- "@types/node": "^18.11.12",
35
- "@types/sinon": "^10.0.13",
34
+ "@types/node": "^18.16.3",
35
+ "@types/sinon": "^10.0.14",
36
36
  "@types/sinon-chai": "^3.2.9",
37
- "@typescript-eslint/eslint-plugin": "^5.46.0",
38
- "@typescript-eslint/parser": "^5.46.0",
37
+ "@typescript-eslint/eslint-plugin": "^5.59.2",
38
+ "@typescript-eslint/parser": "^5.59.2",
39
39
  "benchmark": "^2.1.4",
40
40
  "chai": "^4.3.7",
41
- "chalk": "^5.1.2",
42
- "eslint": "^8.29.0",
43
- "eslint-config-prettier": "^8.5.0",
41
+ "chalk": "^5.2.0",
42
+ "eslint": "^8.39.0",
43
+ "eslint-config-prettier": "^8.8.0",
44
44
  "eslint-plugin-no-bigint-usage": "file:./etc/eslint/no-bigint-usage",
45
45
  "eslint-plugin-prettier": "^4.2.1",
46
46
  "eslint-plugin-tsdoc": "^0.2.17",
47
- "magic-string": "^0.27.0",
48
- "mocha": "10.1.0",
49
- "node-fetch": "^3.2.10",
47
+ "magic-string": "^0.30.0",
48
+ "mocha": "10.2.0",
49
+ "node-fetch": "^3.3.1",
50
50
  "nyc": "^15.1.0",
51
- "prettier": "^2.8.1",
52
- "rimraf": "^3.0.2",
53
- "rollup": "^3.7.1",
54
- "sinon": "^15.0.0",
51
+ "prettier": "^2.8.8",
52
+ "rimraf": "^5.0.0",
53
+ "rollup": "^3.21.4",
54
+ "sinon": "^15.0.4",
55
55
  "sinon-chai": "^3.7.0",
56
56
  "source-map-support": "^0.5.21",
57
57
  "standard-version": "^9.5.0",
58
58
  "ts-node": "^10.9.1",
59
- "tsd": "^0.25.0",
59
+ "tsd": "^0.28.1",
60
60
  "typescript": "^4.9.4",
61
61
  "typescript-cached-transpile": "0.0.6",
62
62
  "uuid": "^9.0.0",
package/src/binary.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { bufferToUuidHexString, uuidHexStringToBuffer, uuidValidateString } from './uuid_utils';
2
1
  import { isUint8Array } from './parser/utils';
3
2
  import type { EJSONOptions } from './extended_json';
4
3
  import { BSONError } from './error';
@@ -288,7 +287,7 @@ export class Binary extends BSONValue {
288
287
  }
289
288
  } else if ('$uuid' in doc) {
290
289
  type = 4;
291
- data = uuidHexStringToBuffer(doc.$uuid);
290
+ data = UUID.bytesFromString(doc.$uuid);
292
291
  }
293
292
  if (!data) {
294
293
  throw new BSONError(`Unexpected Binary Extended JSON format ${JSON.stringify(doc)}`);
@@ -311,42 +310,41 @@ export class Binary extends BSONValue {
311
310
  export type UUIDExtended = {
312
311
  $uuid: string;
313
312
  };
313
+
314
314
  const UUID_BYTE_LENGTH = 16;
315
+ const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
316
+ const UUID_WITH_DASHES = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;
315
317
 
316
318
  /**
317
319
  * A class representation of the BSON UUID type.
318
320
  * @public
319
321
  */
320
322
  export class UUID extends Binary {
321
- static cacheHexString: boolean;
322
-
323
- /** UUID hexString cache @internal */
324
- private __id?: string;
325
-
323
+ /** @deprecated Hex string is no longer cached, this control will be removed in a future major release */
324
+ static cacheHexString = false;
326
325
  /**
327
- * Create an UUID type
326
+ * Create a UUID type
327
+ *
328
+ * When the argument to the constructor is omitted a random v4 UUID will be generated.
328
329
  *
329
330
  * @param input - Can be a 32 or 36 character hex string (dashes excluded/included) or a 16 byte binary Buffer.
330
331
  */
331
332
  constructor(input?: string | Uint8Array | UUID) {
332
333
  let bytes: Uint8Array;
333
- let hexStr;
334
334
  if (input == null) {
335
335
  bytes = UUID.generate();
336
336
  } else if (input instanceof UUID) {
337
337
  bytes = ByteUtils.toLocalBufferType(new Uint8Array(input.buffer));
338
- hexStr = input.__id;
339
338
  } else if (ArrayBuffer.isView(input) && input.byteLength === UUID_BYTE_LENGTH) {
340
339
  bytes = ByteUtils.toLocalBufferType(input);
341
340
  } else if (typeof input === 'string') {
342
- bytes = uuidHexStringToBuffer(input);
341
+ bytes = UUID.bytesFromString(input);
343
342
  } else {
344
343
  throw new BSONError(
345
344
  'Argument passed in UUID constructor must be a UUID, a 16 byte Buffer or a 32/36 character hex string (dashes excluded/included, format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).'
346
345
  );
347
346
  }
348
347
  super(bytes, BSON_BINARY_SUBTYPE_UUID_NEW);
349
- this.__id = hexStr;
350
348
  }
351
349
 
352
350
  /**
@@ -359,28 +357,23 @@ export class UUID extends Binary {
359
357
 
360
358
  set id(value: Uint8Array) {
361
359
  this.buffer = value;
362
-
363
- if (UUID.cacheHexString) {
364
- this.__id = bufferToUuidHexString(value);
365
- }
366
360
  }
367
361
 
368
362
  /**
369
363
  * Returns the UUID id as a 32 or 36 character hex string representation, excluding/including dashes (defaults to 36 character dash separated)
370
364
  * @param includeDashes - should the string exclude dash-separators.
371
- * */
365
+ */
372
366
  toHexString(includeDashes = true): string {
373
- if (UUID.cacheHexString && this.__id) {
374
- return this.__id;
367
+ if (includeDashes) {
368
+ return [
369
+ ByteUtils.toHex(this.buffer.subarray(0, 4)),
370
+ ByteUtils.toHex(this.buffer.subarray(4, 6)),
371
+ ByteUtils.toHex(this.buffer.subarray(6, 8)),
372
+ ByteUtils.toHex(this.buffer.subarray(8, 10)),
373
+ ByteUtils.toHex(this.buffer.subarray(10, 16))
374
+ ].join('-');
375
375
  }
376
-
377
- const uuidHexString = bufferToUuidHexString(this.id, includeDashes);
378
-
379
- if (UUID.cacheHexString) {
380
- this.__id = uuidHexString;
381
- }
382
-
383
- return uuidHexString;
376
+ return ByteUtils.toHex(this.buffer);
384
377
  }
385
378
 
386
379
  /**
@@ -446,29 +439,24 @@ export class UUID extends Binary {
446
439
  * Checks if a value is a valid bson UUID
447
440
  * @param input - UUID, string or Buffer to validate.
448
441
  */
449
- static isValid(input: string | Uint8Array | UUID): boolean {
442
+ static isValid(input: string | Uint8Array | UUID | Binary): boolean {
450
443
  if (!input) {
451
444
  return false;
452
445
  }
453
446
 
454
- if (input instanceof UUID) {
455
- return true;
456
- }
457
-
458
447
  if (typeof input === 'string') {
459
- return uuidValidateString(input);
448
+ return UUID.isValidUUIDString(input);
460
449
  }
461
450
 
462
451
  if (isUint8Array(input)) {
463
- // check for length & uuid version (https://tools.ietf.org/html/rfc4122#section-4.1.3)
464
- if (input.byteLength !== UUID_BYTE_LENGTH) {
465
- return false;
466
- }
467
-
468
- return (input[6] & 0xf0) === 0x40 && (input[8] & 0x80) === 0x80;
452
+ return input.byteLength === UUID_BYTE_LENGTH;
469
453
  }
470
454
 
471
- return false;
455
+ return (
456
+ input._bsontype === 'Binary' &&
457
+ input.sub_type === this.SUBTYPE_UUID &&
458
+ input.buffer.byteLength === 16
459
+ );
472
460
  }
473
461
 
474
462
  /**
@@ -476,7 +464,7 @@ export class UUID extends Binary {
476
464
  * @param hexString - 32 or 36 character hex string (dashes excluded/included).
477
465
  */
478
466
  static override createFromHexString(hexString: string): UUID {
479
- const buffer = uuidHexStringToBuffer(hexString);
467
+ const buffer = UUID.bytesFromString(hexString);
480
468
  return new UUID(buffer);
481
469
  }
482
470
 
@@ -485,6 +473,26 @@ export class UUID extends Binary {
485
473
  return new UUID(ByteUtils.fromBase64(base64));
486
474
  }
487
475
 
476
+ /** @internal */
477
+ static bytesFromString(representation: string) {
478
+ if (!UUID.isValidUUIDString(representation)) {
479
+ throw new BSONError(
480
+ 'UUID string representation must be 32 hex digits or canonical hyphenated representation'
481
+ );
482
+ }
483
+ return ByteUtils.fromHex(representation.replace(/-/g, ''));
484
+ }
485
+
486
+ /**
487
+ * @internal
488
+ *
489
+ * Validates a string to be a hex digit sequence with or without dashes.
490
+ * The canonical hyphenated representation of a uuid is hex in 8-4-4-4-12 groups.
491
+ */
492
+ static isValidUUIDString(representation: string) {
493
+ return UUID_WITHOUT_DASHES.test(representation) || UUID_WITH_DASHES.test(representation);
494
+ }
495
+
488
496
  /**
489
497
  * Converts to a string representation of this Id.
490
498
  *
package/src/bson.ts CHANGED
@@ -70,7 +70,7 @@ let buffer = ByteUtils.allocate(MAXSIZE);
70
70
  /**
71
71
  * Sets the size of the internal serialization buffer.
72
72
  *
73
- * @param size - The desired size for the internal serialization buffer
73
+ * @param size - The desired size for the internal serialization buffer in bytes
74
74
  * @public
75
75
  */
76
76
  export function setInternalBufferSize(size: number): void {
package/src/constants.ts CHANGED
@@ -138,4 +138,4 @@ export const BSONType = Object.freeze({
138
138
  } as const);
139
139
 
140
140
  /** @public */
141
- export type BSONType = typeof BSONType[keyof typeof BSONType];
141
+ export type BSONType = (typeof BSONType)[keyof typeof BSONType];
@@ -24,11 +24,19 @@ import { Timestamp } from './timestamp';
24
24
 
25
25
  /** @public */
26
26
  export type EJSONOptions = {
27
- /** Output using the Extended JSON v1 spec */
27
+ /**
28
+ * Output using the Extended JSON v1 spec
29
+ * @defaultValue `false`
30
+ */
28
31
  legacy?: boolean;
29
- /** Enable Extended JSON's `relaxed` mode, which attempts to return native JS types where possible, rather than BSON types */
32
+ /**
33
+ * Enable Extended JSON's `relaxed` mode, which attempts to return native JS types where possible, rather than BSON types
34
+ * @defaultValue `false` */
30
35
  relaxed?: boolean;
31
- /** Enable native bigint support */
36
+ /**
37
+ * Enable native bigint support
38
+ * @defaultValue `false`
39
+ */
32
40
  useBigInt64?: boolean;
33
41
  };
34
42
 
@@ -1,4 +1,4 @@
1
- import { Binary } from '../binary';
1
+ import { Binary, UUID } from '../binary';
2
2
  import type { Document } from '../bson';
3
3
  import { Code } from '../code';
4
4
  import * as constants from '../constants';
@@ -19,21 +19,45 @@ import { validateUtf8 } from '../validate_utf8';
19
19
 
20
20
  /** @public */
21
21
  export interface DeserializeOptions {
22
- /** when deserializing a Long will return as a BigInt. */
22
+ /**
23
+ * when deserializing a Long return as a BigInt.
24
+ * @defaultValue `false`
25
+ */
23
26
  useBigInt64?: boolean;
24
- /** when deserializing a Long will fit it into a Number if it's smaller than 53 bits. */
27
+ /**
28
+ * when deserializing a Long will fit it into a Number if it's smaller than 53 bits.
29
+ * @defaultValue `true`
30
+ */
25
31
  promoteLongs?: boolean;
26
- /** when deserializing a Binary will return it as a node.js Buffer instance. */
32
+ /**
33
+ * when deserializing a Binary will return it as a node.js Buffer instance.
34
+ * @defaultValue `false`
35
+ */
27
36
  promoteBuffers?: boolean;
28
- /** when deserializing will promote BSON values to their Node.js closest equivalent types. */
37
+ /**
38
+ * when deserializing will promote BSON values to their Node.js closest equivalent types.
39
+ * @defaultValue `true`
40
+ */
29
41
  promoteValues?: boolean;
30
- /** allow to specify if there what fields we wish to return as unserialized raw buffer. */
42
+ /**
43
+ * allow to specify if there what fields we wish to return as unserialized raw buffer.
44
+ * @defaultValue `null`
45
+ */
31
46
  fieldsAsRaw?: Document;
32
- /** return BSON regular expressions as BSONRegExp instances. */
47
+ /**
48
+ * return BSON regular expressions as BSONRegExp instances.
49
+ * @defaultValue `false`
50
+ */
33
51
  bsonRegExp?: boolean;
34
- /** allows the buffer to be larger than the parsed BSON object. */
52
+ /**
53
+ * allows the buffer to be larger than the parsed BSON object.
54
+ * @defaultValue `false`
55
+ */
35
56
  allowObjectSmallerThanBufferSize?: boolean;
36
- /** Offset into buffer to begin reading document from */
57
+ /**
58
+ * Offset into buffer to begin reading document from
59
+ * @defaultValue `0`
60
+ */
37
61
  index?: number;
38
62
 
39
63
  raw?: boolean;
@@ -404,7 +428,7 @@ function deserializeObject(
404
428
  value = ByteUtils.toLocalBufferType(buffer.slice(index, index + binarySize));
405
429
  } else {
406
430
  value = new Binary(buffer.slice(index, index + binarySize), subType);
407
- if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW) {
431
+ if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
408
432
  value = value.toUUID();
409
433
  }
410
434
  }
@@ -432,10 +456,11 @@ function deserializeObject(
432
456
 
433
457
  if (promoteBuffers && promoteValues) {
434
458
  value = _buffer;
435
- } else if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW) {
436
- value = new Binary(buffer.slice(index, index + binarySize), subType).toUUID();
437
459
  } else {
438
460
  value = new Binary(buffer.slice(index, index + binarySize), subType);
461
+ if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
462
+ value = value.toUUID();
463
+ }
439
464
  }
440
465
  }
441
466
 
@@ -16,15 +16,28 @@ import { isAnyArrayBuffer, isDate, isMap, isRegExp, isUint8Array } from './utils
16
16
 
17
17
  /** @public */
18
18
  export interface SerializeOptions {
19
- /** the serializer will check if keys are valid. */
19
+ /**
20
+ * the serializer will check if keys are valid.
21
+ * @defaultValue `false`
22
+ */
20
23
  checkKeys?: boolean;
21
- /** serialize the javascript functions **(default:false)**. */
24
+ /**
25
+ * serialize the javascript functions
26
+ * @defaultValue `false`
27
+ */
22
28
  serializeFunctions?: boolean;
23
- /** serialize will not emit undefined fields **(default:true)** */
29
+ /**
30
+ * serialize will not emit undefined fields
31
+ * note that the driver sets this to `false`
32
+ * @defaultValue `true`
33
+ */
24
34
  ignoreUndefined?: boolean;
25
35
  /** @internal Resize internal buffer */
26
36
  minInternalBufferSize?: number;
27
- /** the index in the buffer where we wish to start serializing into */
37
+ /**
38
+ * the index in the buffer where we wish to start serializing into
39
+ * @defaultValue `0`
40
+ */
28
41
  index?: number;
29
42
  }
30
43
 
package/src/timestamp.ts CHANGED
@@ -27,7 +27,7 @@ export interface TimestampExtended {
27
27
  /**
28
28
  * @public
29
29
  * @category BSONType
30
- * */
30
+ */
31
31
  export class Timestamp extends LongWithoutOverridesClass {
32
32
  get _bsontype(): 'Timestamp' {
33
33
  return 'Timestamp';
package/src/uuid_utils.ts DELETED
@@ -1,33 +0,0 @@
1
- import { BSONError } from './error';
2
- import { ByteUtils } from './utils/byte_utils';
3
-
4
- // Validation regex for v4 uuid (validates with or without dashes)
5
- const VALIDATION_REGEX =
6
- /^(?:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15})$/i;
7
-
8
- export const uuidValidateString = (str: string): boolean =>
9
- typeof str === 'string' && VALIDATION_REGEX.test(str);
10
-
11
- export const uuidHexStringToBuffer = (hexString: string): Uint8Array => {
12
- if (!uuidValidateString(hexString)) {
13
- throw new BSONError(
14
- 'UUID string representations must be a 32 or 36 character hex string (dashes excluded/included). Format: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" or "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".'
15
- );
16
- }
17
-
18
- const sanitizedHexString = hexString.replace(/-/g, '');
19
- return ByteUtils.fromHex(sanitizedHexString);
20
- };
21
-
22
- export function bufferToUuidHexString(buffer: Uint8Array, includeDashes = true): string {
23
- if (includeDashes) {
24
- return [
25
- ByteUtils.toHex(buffer.subarray(0, 4)),
26
- ByteUtils.toHex(buffer.subarray(4, 6)),
27
- ByteUtils.toHex(buffer.subarray(6, 8)),
28
- ByteUtils.toHex(buffer.subarray(8, 10)),
29
- ByteUtils.toHex(buffer.subarray(10, 16))
30
- ].join('-');
31
- }
32
- return ByteUtils.toHex(buffer);
33
- }