bson 6.7.0 → 6.9.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/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "vendor"
15
15
  ],
16
16
  "types": "bson.d.ts",
17
- "version": "6.7.0",
17
+ "version": "6.9.0",
18
18
  "author": {
19
19
  "name": "The MongoDB NodeJS Team",
20
20
  "email": "dbx-node@mongodb.com"
@@ -27,42 +27,41 @@
27
27
  },
28
28
  "devDependencies": {
29
29
  "@istanbuljs/nyc-config-typescript": "^1.0.2",
30
- "@microsoft/api-extractor": "^7.43.1",
31
- "@octokit/core": "^6.1.2",
30
+ "@microsoft/api-extractor": "^7.47.5",
32
31
  "@rollup/plugin-node-resolve": "^15.2.3",
33
32
  "@rollup/plugin-typescript": "^11.1.6",
34
- "@types/chai": "^4.3.14",
35
- "@types/mocha": "^10.0.6",
36
- "@types/node": "^20.12.7",
33
+ "@types/chai": "^4.3.17",
34
+ "@types/mocha": "^10.0.7",
35
+ "@types/node": "^22.1.0",
37
36
  "@types/sinon": "^17.0.3",
38
37
  "@types/sinon-chai": "^3.2.12",
39
- "@typescript-eslint/eslint-plugin": "^7.7.0",
40
- "@typescript-eslint/parser": "^7.7.0",
38
+ "@typescript-eslint/eslint-plugin": "^8.0.1",
39
+ "@typescript-eslint/parser": "^8.0.1",
41
40
  "benchmark": "^2.1.4",
42
41
  "chai": "^4.4.1",
43
42
  "chalk": "^5.3.0",
44
43
  "dbx-js-tools": "github:mongodb-js/dbx-js-tools",
45
- "eslint": "^8.57.0",
44
+ "eslint": "^9.8.0",
46
45
  "eslint-config-prettier": "^9.1.0",
47
46
  "eslint-plugin-no-bigint-usage": "file:etc/eslint/no-bigint-usage",
48
- "eslint-plugin-prettier": "^5.1.3",
49
- "eslint-plugin-tsdoc": "^0.2.17",
50
- "magic-string": "^0.30.10",
51
- "mocha": "^10.4.0",
47
+ "eslint-plugin-prettier": "^5.2.1",
48
+ "eslint-plugin-tsdoc": "^0.3.0",
49
+ "magic-string": "^0.30.11",
50
+ "mocha": "^10.7.0",
52
51
  "node-fetch": "^3.3.2",
53
52
  "nyc": "^15.1.0",
54
- "prettier": "^3.2.5",
55
- "rollup": "^4.14.3",
56
- "sinon": "^17.0.1",
53
+ "prettier": "^3.3.3",
54
+ "rollup": "^4.20.0",
55
+ "sinon": "^18.0.0",
57
56
  "sinon-chai": "^3.7.0",
58
57
  "source-map-support": "^0.5.21",
59
58
  "standard-version": "^9.5.0",
60
- "tar": "^7.0.1",
59
+ "tar": "^7.4.3",
61
60
  "ts-node": "^10.9.2",
62
- "tsd": "^0.31.0",
63
- "typescript": "5.3",
61
+ "tsd": "^0.31.1",
62
+ "typescript": "^5.5.4",
64
63
  "typescript-cached-transpile": "0.0.6",
65
- "uuid": "^9.0.1"
64
+ "uuid": "^10.0.0"
66
65
  },
67
66
  "tsd": {
68
67
  "directory": "test/types",
@@ -106,12 +105,13 @@
106
105
  "check:web-no-bigint": "WEB=true NO_BIGINT=true mocha test/node",
107
106
  "check:granular-bench": "npm run build:bench && node ./test/bench/etc/run_granular_benchmarks.js",
108
107
  "check:spec-bench": "npm run build:bench && node ./test/bench/lib/spec/bsonBench.js",
108
+ "check:custom-bench": "npm run build && node ./test/bench/custom/main.mjs",
109
109
  "build:bench": "cd test/bench && npx tsc",
110
110
  "build:ts": "node ./node_modules/typescript/bin/tsc",
111
111
  "build:dts": "npm run build:ts && api-extractor run --typescript-compiler-folder node_modules/typescript --local && node etc/clean_definition_files.cjs",
112
112
  "build:bundle": "rollup -c rollup.config.mjs",
113
113
  "build": "npm run build:dts && npm run build:bundle",
114
- "check:lint": "eslint -v && eslint --ext '.js,.ts' --max-warnings=0 src test && npm run build:dts && npm run check:tsd",
114
+ "check:lint": "ESLINT_USE_FLAT_CONFIG=false eslint -v && ESLINT_USE_FLAT_CONFIG=false eslint --ext '.js,.ts' --max-warnings=0 src test && npm run build:dts && npm run check:tsd",
115
115
  "format": "eslint --ext '.js,.ts' src test --fix",
116
116
  "check:coverage": "nyc --check-coverage npm run check:node",
117
117
  "prepare": "node etc/prepare.js",
package/src/bson_value.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { BSON_MAJOR_VERSION } from './constants';
2
2
  import { type InspectFn } from './parser/utils';
3
+ import { BSON_VERSION_SYMBOL } from './constants';
3
4
 
4
5
  /** @public */
5
6
  export abstract class BSONValue {
@@ -7,7 +8,7 @@ export abstract class BSONValue {
7
8
  public abstract get _bsontype(): string;
8
9
 
9
10
  /** @internal */
10
- get [Symbol.for('@@mdb.bson.version')](): typeof BSON_MAJOR_VERSION {
11
+ get [BSON_VERSION_SYMBOL](): typeof BSON_MAJOR_VERSION {
11
12
  return BSON_MAJOR_VERSION;
12
13
  }
13
14
 
package/src/constants.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  /** @internal */
2
2
  export const BSON_MAJOR_VERSION = 6;
3
3
 
4
+ /** @internal */
5
+ export const BSON_VERSION_SYMBOL = Symbol.for('@@mdb.bson.version');
6
+
4
7
  /** @internal */
5
8
  export const BSON_INT32_MAX = 0x7fffffff;
6
9
  /** @internal */
package/src/decimal128.ts CHANGED
@@ -142,7 +142,7 @@ export class Decimal128 extends BSONValue {
142
142
  super();
143
143
  if (typeof bytes === 'string') {
144
144
  this.bytes = Decimal128.fromString(bytes).bytes;
145
- } else if (isUint8Array(bytes)) {
145
+ } else if (bytes instanceof Uint8Array || isUint8Array(bytes)) {
146
146
  if (bytes.byteLength !== 16) {
147
147
  throw new BSONError('Decimal128 must take a Buffer of 16 bytes');
148
148
  }
@@ -6,7 +6,8 @@ import {
6
6
  BSON_INT32_MIN,
7
7
  BSON_INT64_MAX,
8
8
  BSON_INT64_MIN,
9
- BSON_MAJOR_VERSION
9
+ BSON_MAJOR_VERSION,
10
+ BSON_VERSION_SYMBOL
10
11
  } from './constants';
11
12
  import { DBRef, isDBRefLike } from './db_ref';
12
13
  import { Decimal128 } from './decimal128';
@@ -358,7 +359,7 @@ function serializeDocument(doc: any, options: EJSONSerializeOptions) {
358
359
  doc != null &&
359
360
  typeof doc === 'object' &&
360
361
  typeof doc._bsontype === 'string' &&
361
- doc[Symbol.for('@@mdb.bson.version')] !== BSON_MAJOR_VERSION
362
+ doc[BSON_VERSION_SYMBOL] !== BSON_MAJOR_VERSION
362
363
  ) {
363
364
  throw new BSONVersionError();
364
365
  } else if (isBSONType(doc)) {
package/src/long.ts CHANGED
@@ -119,42 +119,57 @@ export class Long extends BSONValue {
119
119
  /**
120
120
  * The high 32 bits as a signed value.
121
121
  */
122
- high!: number;
122
+ high: number;
123
123
 
124
124
  /**
125
125
  * The low 32 bits as a signed value.
126
126
  */
127
- low!: number;
127
+ low: number;
128
128
 
129
129
  /**
130
130
  * Whether unsigned or not.
131
131
  */
132
- unsigned!: boolean;
132
+ unsigned: boolean;
133
133
 
134
134
  /**
135
135
  * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
136
- * See the from* functions below for more convenient ways of constructing Longs.
137
- *
138
- * Acceptable signatures are:
139
- * - Long(low, high, unsigned?)
140
- * - Long(bigint, unsigned?)
141
- * - Long(string, unsigned?)
142
136
  *
143
137
  * @param low - The low (signed) 32 bits of the long
144
138
  * @param high - The high (signed) 32 bits of the long
145
139
  * @param unsigned - Whether unsigned or not, defaults to signed
146
140
  */
147
- constructor(low: number | bigint | string = 0, high?: number | boolean, unsigned?: boolean) {
141
+ constructor(low: number, high?: number, unsigned?: boolean);
142
+ /**
143
+ * Constructs a 64 bit two's-complement integer, given a bigint representation.
144
+ *
145
+ * @param value - BigInt representation of the long value
146
+ * @param unsigned - Whether unsigned or not, defaults to signed
147
+ */
148
+ constructor(value: bigint, unsigned?: boolean);
149
+ /**
150
+ * Constructs a 64 bit two's-complement integer, given a string representation.
151
+ *
152
+ * @param value - String representation of the long value
153
+ * @param unsigned - Whether unsigned or not, defaults to signed
154
+ */
155
+ constructor(value: string, unsigned?: boolean);
156
+ constructor(
157
+ lowOrValue: number | bigint | string = 0,
158
+ highOrUnsigned?: number | boolean,
159
+ unsigned?: boolean
160
+ ) {
148
161
  super();
149
- if (typeof low === 'bigint') {
150
- Object.assign(this, Long.fromBigInt(low, !!high));
151
- } else if (typeof low === 'string') {
152
- Object.assign(this, Long.fromString(low, !!high));
153
- } else {
154
- this.low = low | 0;
155
- this.high = (high as number) | 0;
156
- this.unsigned = !!unsigned;
157
- }
162
+ const unsignedBool = typeof highOrUnsigned === 'boolean' ? highOrUnsigned : Boolean(unsigned);
163
+ const high = typeof highOrUnsigned === 'number' ? highOrUnsigned : 0;
164
+ const res =
165
+ typeof lowOrValue === 'string'
166
+ ? Long.fromString(lowOrValue, unsignedBool)
167
+ : typeof lowOrValue === 'bigint'
168
+ ? Long.fromBigInt(lowOrValue, unsignedBool)
169
+ : { low: lowOrValue | 0, high: high | 0, unsigned: unsignedBool };
170
+ this.low = res.low;
171
+ this.high = res.high;
172
+ this.unsigned = res.unsigned;
158
173
  }
159
174
 
160
175
  static TWO_PWR_24 = Long.fromInt(TWO_PWR_24_DBL);
@@ -243,7 +258,15 @@ export class Long extends BSONValue {
243
258
  * @returns The corresponding Long value
244
259
  */
245
260
  static fromBigInt(value: bigint, unsigned?: boolean): Long {
246
- return Long.fromString(value.toString(), unsigned);
261
+ // eslint-disable-next-line no-restricted-globals
262
+ const FROM_BIGINT_BIT_MASK = BigInt(0xffffffff);
263
+ // eslint-disable-next-line no-restricted-globals
264
+ const FROM_BIGINT_BIT_SHIFT = BigInt(32);
265
+ return new Long(
266
+ Number(value & FROM_BIGINT_BIT_MASK),
267
+ Number((value >> FROM_BIGINT_BIT_SHIFT) & FROM_BIGINT_BIT_MASK),
268
+ unsigned
269
+ );
247
270
  }
248
271
 
249
272
  /**
@@ -1140,7 +1163,6 @@ export class Long extends BSONValue {
1140
1163
  // eslint-disable-next-line @typescript-eslint/no-this-alias
1141
1164
  let rem: Long = this;
1142
1165
  let result = '';
1143
- // eslint-disable-next-line no-constant-condition
1144
1166
  while (true) {
1145
1167
  const remDiv = rem.div(radixToPower);
1146
1168
  const intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0;
package/src/objectid.ts CHANGED
@@ -4,9 +4,6 @@ import { type InspectFn, defaultInspect } from './parser/utils';
4
4
  import { ByteUtils } from './utils/byte_utils';
5
5
  import { NumberUtils } from './utils/number_utils';
6
6
 
7
- // Regular expression that checks for hex value
8
- const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
9
-
10
7
  // Unique sequence for the current process (initialized on first use)
11
8
  let PROCESS_UNIQUE: Uint8Array | null = null;
12
9
 
@@ -112,7 +109,7 @@ export class ObjectId extends BSONValue {
112
109
  // If intstanceof matches we can escape calling ensure buffer in Node.js environments
113
110
  this.buffer = ByteUtils.toLocalBufferType(workingId);
114
111
  } else if (typeof workingId === 'string') {
115
- if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
112
+ if (ObjectId.validateHexString(workingId)) {
116
113
  this.buffer = ByteUtils.fromHex(workingId);
117
114
  } else {
118
115
  throw new BSONError(
@@ -143,6 +140,29 @@ export class ObjectId extends BSONValue {
143
140
  }
144
141
  }
145
142
 
143
+ /**
144
+ * @internal
145
+ * Validates the input string is a valid hex representation of an ObjectId.
146
+ */
147
+ private static validateHexString(string: string): boolean {
148
+ if (string?.length !== 24) return false;
149
+ for (let i = 0; i < 24; i++) {
150
+ const char = string.charCodeAt(i);
151
+ if (
152
+ // Check for ASCII 0-9
153
+ (char >= 48 && char <= 57) ||
154
+ // Check for ASCII a-f
155
+ (char >= 97 && char <= 102) ||
156
+ // Check for ASCII A-F
157
+ (char >= 65 && char <= 70)
158
+ ) {
159
+ continue;
160
+ }
161
+ return false;
162
+ }
163
+ return true;
164
+ }
165
+
146
166
  /** Returns the ObjectId id as a 24 lowercase character hex string representation */
147
167
  toHexString(): string {
148
168
  if (ObjectId.cacheHexString && this.__id) {
@@ -329,6 +349,7 @@ export class ObjectId extends BSONValue {
329
349
  */
330
350
  static isValid(id: string | number | ObjectId | ObjectIdLike | Uint8Array): boolean {
331
351
  if (id == null) return false;
352
+ if (typeof id === 'string') return ObjectId.validateHexString(id);
332
353
 
333
354
  try {
334
355
  new ObjectId(id);
@@ -81,7 +81,7 @@ function calculateElement(
81
81
  if (
82
82
  value != null &&
83
83
  typeof value._bsontype === 'string' &&
84
- value[Symbol.for('@@mdb.bson.version')] !== constants.BSON_MAJOR_VERSION
84
+ value[constants.BSON_VERSION_SYMBOL] !== constants.BSON_MAJOR_VERSION
85
85
  ) {
86
86
  throw new BSONVersionError();
87
87
  } else if (value == null || value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {