bson 6.4.0 → 6.6.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/bson.d.ts CHANGED
@@ -24,6 +24,8 @@ export declare class Binary extends BSONValue {
24
24
  static readonly SUBTYPE_ENCRYPTED = 6;
25
25
  /** Column BSON type */
26
26
  static readonly SUBTYPE_COLUMN = 7;
27
+ /** Sensitive BSON type */
28
+ static readonly SUBTYPE_SENSITIVE = 8;
27
29
  /** User BSON type */
28
30
  static readonly SUBTYPE_USER_DEFINED = 128;
29
31
  buffer: Uint8Array;
@@ -138,14 +140,29 @@ declare namespace BSON {
138
140
  BSONError,
139
141
  BSONVersionError,
140
142
  BSONRuntimeError,
143
+ BSONOffsetError,
141
144
  BSONType,
142
145
  EJSON,
146
+ onDemand,
147
+ OnDemand,
143
148
  Document,
144
149
  CalculateObjectSizeOptions
145
150
  }
146
151
  }
147
152
  export { BSON }
148
153
 
154
+ /**
155
+ * @public
156
+ * @experimental
157
+ */
158
+ declare type BSONElement = [
159
+ type: number,
160
+ nameOffset: number,
161
+ nameLength: number,
162
+ offset: number,
163
+ length: number
164
+ ];
165
+
149
166
  /**
150
167
  * @public
151
168
  * @category Error
@@ -172,6 +189,23 @@ export declare class BSONError extends Error {
172
189
  static isBSONError(value: unknown): value is BSONError;
173
190
  }
174
191
 
192
+ /**
193
+ * @public
194
+ * @category Error
195
+ *
196
+ * @experimental
197
+ *
198
+ * An error generated when BSON bytes are invalid.
199
+ * Reports the offset the parser was able to reach before encountering the error.
200
+ */
201
+ export declare class BSONOffsetError extends BSONError {
202
+ get name(): 'BSONOffsetError';
203
+ offset: number;
204
+ constructor(message: string, offset: number, options?: {
205
+ cause?: unknown;
206
+ });
207
+ }
208
+
175
209
  /**
176
210
  * A class representation of the BSON RegExp type.
177
211
  * @public
@@ -295,6 +329,48 @@ export declare class BSONVersionError extends BSONError {
295
329
  constructor();
296
330
  }
297
331
 
332
+ /**
333
+ * @public
334
+ * @experimental
335
+ *
336
+ * A collection of functions that help work with data in a Uint8Array.
337
+ * ByteUtils is configured at load time to use Node.js or Web based APIs for the internal implementations.
338
+ */
339
+ declare type ByteUtils = {
340
+ /** Transforms the input to an instance of Buffer if running on node, otherwise Uint8Array */
341
+ toLocalBufferType: (buffer: Uint8Array | ArrayBufferView | ArrayBuffer) => Uint8Array;
342
+ /** Create empty space of size */
343
+ allocate: (size: number) => Uint8Array;
344
+ /** Create empty space of size, use pooled memory when available */
345
+ allocateUnsafe: (size: number) => Uint8Array;
346
+ /** Check if two Uint8Arrays are deep equal */
347
+ equals: (a: Uint8Array, b: Uint8Array) => boolean;
348
+ /** Check if two Uint8Arrays are deep equal */
349
+ fromNumberArray: (array: number[]) => Uint8Array;
350
+ /** Create a Uint8Array from a base64 string */
351
+ fromBase64: (base64: string) => Uint8Array;
352
+ /** Create a base64 string from bytes */
353
+ toBase64: (buffer: Uint8Array) => string;
354
+ /** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
355
+ fromISO88591: (codePoints: string) => Uint8Array;
356
+ /** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
357
+ toISO88591: (buffer: Uint8Array) => string;
358
+ /** Create a Uint8Array from a hex string */
359
+ fromHex: (hex: string) => Uint8Array;
360
+ /** Create a lowercase hex string from bytes */
361
+ toHex: (buffer: Uint8Array) => string;
362
+ /** Create a string from utf8 code units, fatal=true will throw an error if UTF-8 bytes are invalid, fatal=false will insert replacement characters */
363
+ toUTF8: (buffer: Uint8Array, start: number, end: number, fatal: boolean) => string;
364
+ /** Get the utf8 code unit count from a string if it were to be transformed to utf8 */
365
+ utf8ByteLength: (input: string) => number;
366
+ /** Encode UTF8 bytes generated from `source` string into `destination` at byteOffset. Returns the number of bytes encoded. */
367
+ encodeUTF8Into: (destination: Uint8Array, source: string, byteOffset: number) => number;
368
+ /** Generate a Uint8Array filled with random bytes with byteLength */
369
+ randomBytes: (byteLength: number) => Uint8Array;
370
+ };
371
+
372
+ /* Excluded declaration from this release type: ByteUtils */
373
+
298
374
  /**
299
375
  * Calculate the bson size for a passed in Javascript object.
300
376
  *
@@ -982,6 +1058,36 @@ export declare interface MinKeyExtended {
982
1058
  $minKey: 1;
983
1059
  }
984
1060
 
1061
+ /**
1062
+ * @experimental
1063
+ * @public
1064
+ *
1065
+ * A collection of functions that get or set various numeric types and bit widths from a Uint8Array.
1066
+ */
1067
+ declare type NumberUtils = {
1068
+ /**
1069
+ * Parses a signed int32 at offset. Throws a `RangeError` if value is negative.
1070
+ */
1071
+ getNonnegativeInt32LE: (source: Uint8Array, offset: number) => number;
1072
+ getInt32LE: (source: Uint8Array, offset: number) => number;
1073
+ getUint32LE: (source: Uint8Array, offset: number) => number;
1074
+ getUint32BE: (source: Uint8Array, offset: number) => number;
1075
+ getBigInt64LE: (source: Uint8Array, offset: number) => bigint;
1076
+ getFloat64LE: (source: Uint8Array, offset: number) => number;
1077
+ setInt32BE: (destination: Uint8Array, offset: number, value: number) => 4;
1078
+ setInt32LE: (destination: Uint8Array, offset: number, value: number) => 4;
1079
+ setBigInt64LE: (destination: Uint8Array, offset: number, value: bigint) => 8;
1080
+ setFloat64LE: (destination: Uint8Array, offset: number, value: number) => 8;
1081
+ };
1082
+
1083
+ /**
1084
+ * Number parsing and serializing utilities.
1085
+ *
1086
+ * @experimental
1087
+ * @public
1088
+ */
1089
+ declare const NumberUtils: NumberUtils;
1090
+
985
1091
  /**
986
1092
  * A class representation of the BSON ObjectId type.
987
1093
  * @public
@@ -1106,6 +1212,25 @@ export declare interface ObjectIdLike {
1106
1212
  toHexString(): string;
1107
1213
  }
1108
1214
 
1215
+ /**
1216
+ * @experimental
1217
+ * @public
1218
+ *
1219
+ * A new set of BSON APIs that are currently experimental and not intended for production use.
1220
+ */
1221
+ export declare type OnDemand = {
1222
+ parseToElements: (this: void, bytes: Uint8Array, startOffset?: number) => Iterable<BSONElement>;
1223
+ BSONElement: BSONElement;
1224
+ ByteUtils: ByteUtils;
1225
+ NumberUtils: NumberUtils;
1226
+ };
1227
+
1228
+ /**
1229
+ * @experimental
1230
+ * @public
1231
+ */
1232
+ export declare const onDemand: OnDemand;
1233
+
1109
1234
  /**
1110
1235
  * Parse an Extended JSON string, constructing the JavaScript value or object described by that
1111
1236
  * string.
@@ -127,6 +127,15 @@ class BSONRuntimeError extends BSONError {
127
127
  super(message);
128
128
  }
129
129
  }
130
+ class BSONOffsetError extends BSONError {
131
+ get name() {
132
+ return 'BSONOffsetError';
133
+ }
134
+ constructor(message, offset, options) {
135
+ super(`${message}. offset: ${offset}`, options);
136
+ this.offset = offset;
137
+ }
138
+ }
130
139
 
131
140
  const FIRST_BIT = 0x80;
132
141
  const FIRST_TWO_BITS = 0xc0;
@@ -525,16 +534,16 @@ class Binary extends BSONValue {
525
534
  return this.position;
526
535
  }
527
536
  toJSON() {
528
- return ByteUtils.toBase64(this.buffer);
537
+ return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
529
538
  }
530
539
  toString(encoding) {
531
540
  if (encoding === 'hex')
532
- return ByteUtils.toHex(this.buffer);
541
+ return ByteUtils.toHex(this.buffer.subarray(0, this.position));
533
542
  if (encoding === 'base64')
534
- return ByteUtils.toBase64(this.buffer);
543
+ return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
535
544
  if (encoding === 'utf8' || encoding === 'utf-8')
536
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
537
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
545
+ return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
546
+ return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
538
547
  }
539
548
  toExtendedJSON(options) {
540
549
  options = options || {};
@@ -608,6 +617,7 @@ Binary.SUBTYPE_UUID = 4;
608
617
  Binary.SUBTYPE_MD5 = 5;
609
618
  Binary.SUBTYPE_ENCRYPTED = 6;
610
619
  Binary.SUBTYPE_COLUMN = 7;
620
+ Binary.SUBTYPE_SENSITIVE = 8;
611
621
  Binary.SUBTYPE_USER_DEFINED = 128;
612
622
  const UUID_BYTE_LENGTH = 16;
613
623
  const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
@@ -2126,7 +2136,18 @@ class MinKey extends BSONValue {
2126
2136
 
2127
2137
  const FLOAT = new Float64Array(1);
2128
2138
  const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2139
+ FLOAT[0] = -1;
2140
+ const isBigEndian = FLOAT_BYTES[7] === 0;
2129
2141
  const NumberUtils = {
2142
+ getNonnegativeInt32LE(source, offset) {
2143
+ if (source[offset + 3] > 127) {
2144
+ throw new RangeError(`Size cannot be negative at offset: ${offset}`);
2145
+ }
2146
+ return (source[offset] |
2147
+ (source[offset + 1] << 8) |
2148
+ (source[offset + 2] << 16) |
2149
+ (source[offset + 3] << 24));
2150
+ },
2130
2151
  getInt32LE(source, offset) {
2131
2152
  return (source[offset] |
2132
2153
  (source[offset + 1] << 8) |
@@ -2150,17 +2171,29 @@ const NumberUtils = {
2150
2171
  const hi = NumberUtils.getUint32LE(source, offset + 4);
2151
2172
  return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2152
2173
  },
2153
- getFloat64LE(source, offset) {
2154
- FLOAT_BYTES[0] = source[offset];
2155
- FLOAT_BYTES[1] = source[offset + 1];
2156
- FLOAT_BYTES[2] = source[offset + 2];
2157
- FLOAT_BYTES[3] = source[offset + 3];
2158
- FLOAT_BYTES[4] = source[offset + 4];
2159
- FLOAT_BYTES[5] = source[offset + 5];
2160
- FLOAT_BYTES[6] = source[offset + 6];
2161
- FLOAT_BYTES[7] = source[offset + 7];
2162
- return FLOAT[0];
2163
- },
2174
+ getFloat64LE: isBigEndian
2175
+ ? (source, offset) => {
2176
+ FLOAT_BYTES[7] = source[offset];
2177
+ FLOAT_BYTES[6] = source[offset + 1];
2178
+ FLOAT_BYTES[5] = source[offset + 2];
2179
+ FLOAT_BYTES[4] = source[offset + 3];
2180
+ FLOAT_BYTES[3] = source[offset + 4];
2181
+ FLOAT_BYTES[2] = source[offset + 5];
2182
+ FLOAT_BYTES[1] = source[offset + 6];
2183
+ FLOAT_BYTES[0] = source[offset + 7];
2184
+ return FLOAT[0];
2185
+ }
2186
+ : (source, offset) => {
2187
+ FLOAT_BYTES[0] = source[offset];
2188
+ FLOAT_BYTES[1] = source[offset + 1];
2189
+ FLOAT_BYTES[2] = source[offset + 2];
2190
+ FLOAT_BYTES[3] = source[offset + 3];
2191
+ FLOAT_BYTES[4] = source[offset + 4];
2192
+ FLOAT_BYTES[5] = source[offset + 5];
2193
+ FLOAT_BYTES[6] = source[offset + 6];
2194
+ FLOAT_BYTES[7] = source[offset + 7];
2195
+ return FLOAT[0];
2196
+ },
2164
2197
  setInt32BE(destination, offset, value) {
2165
2198
  destination[offset + 3] = value;
2166
2199
  value >>>= 8;
@@ -2201,18 +2234,31 @@ const NumberUtils = {
2201
2234
  destination[offset + 7] = hi;
2202
2235
  return 8;
2203
2236
  },
2204
- setFloat64LE(destination, offset, value) {
2205
- FLOAT[0] = value;
2206
- destination[offset] = FLOAT_BYTES[0];
2207
- destination[offset + 1] = FLOAT_BYTES[1];
2208
- destination[offset + 2] = FLOAT_BYTES[2];
2209
- destination[offset + 3] = FLOAT_BYTES[3];
2210
- destination[offset + 4] = FLOAT_BYTES[4];
2211
- destination[offset + 5] = FLOAT_BYTES[5];
2212
- destination[offset + 6] = FLOAT_BYTES[6];
2213
- destination[offset + 7] = FLOAT_BYTES[7];
2214
- return 8;
2215
- }
2237
+ setFloat64LE: isBigEndian
2238
+ ? (destination, offset, value) => {
2239
+ FLOAT[0] = value;
2240
+ destination[offset] = FLOAT_BYTES[7];
2241
+ destination[offset + 1] = FLOAT_BYTES[6];
2242
+ destination[offset + 2] = FLOAT_BYTES[5];
2243
+ destination[offset + 3] = FLOAT_BYTES[4];
2244
+ destination[offset + 4] = FLOAT_BYTES[3];
2245
+ destination[offset + 5] = FLOAT_BYTES[2];
2246
+ destination[offset + 6] = FLOAT_BYTES[1];
2247
+ destination[offset + 7] = FLOAT_BYTES[0];
2248
+ return 8;
2249
+ }
2250
+ : (destination, offset, value) => {
2251
+ FLOAT[0] = value;
2252
+ destination[offset] = FLOAT_BYTES[0];
2253
+ destination[offset + 1] = FLOAT_BYTES[1];
2254
+ destination[offset + 2] = FLOAT_BYTES[2];
2255
+ destination[offset + 3] = FLOAT_BYTES[3];
2256
+ destination[offset + 4] = FLOAT_BYTES[4];
2257
+ destination[offset + 5] = FLOAT_BYTES[5];
2258
+ destination[offset + 6] = FLOAT_BYTES[6];
2259
+ destination[offset + 7] = FLOAT_BYTES[7];
2260
+ return 8;
2261
+ }
2216
2262
  };
2217
2263
 
2218
2264
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
@@ -4090,6 +4136,113 @@ EJSON.serialize = EJSONserialize;
4090
4136
  EJSON.deserialize = EJSONdeserialize;
4091
4137
  Object.freeze(EJSON);
4092
4138
 
4139
+ function getSize(source, offset) {
4140
+ try {
4141
+ return NumberUtils.getNonnegativeInt32LE(source, offset);
4142
+ }
4143
+ catch (cause) {
4144
+ throw new BSONOffsetError('BSON size cannot be negative', offset, { cause });
4145
+ }
4146
+ }
4147
+ function findNull(bytes, offset) {
4148
+ let nullTerminatorOffset = offset;
4149
+ for (; bytes[nullTerminatorOffset] !== 0x00; nullTerminatorOffset++)
4150
+ ;
4151
+ if (nullTerminatorOffset === bytes.length - 1) {
4152
+ throw new BSONOffsetError('Null terminator not found', offset);
4153
+ }
4154
+ return nullTerminatorOffset;
4155
+ }
4156
+ function parseToElements(bytes, startOffset = 0) {
4157
+ startOffset ??= 0;
4158
+ if (bytes.length < 5) {
4159
+ throw new BSONOffsetError(`Input must be at least 5 bytes, got ${bytes.length} bytes`, startOffset);
4160
+ }
4161
+ const documentSize = getSize(bytes, startOffset);
4162
+ if (documentSize > bytes.length - startOffset) {
4163
+ throw new BSONOffsetError(`Parsed documentSize (${documentSize} bytes) does not match input length (${bytes.length} bytes)`, startOffset);
4164
+ }
4165
+ if (bytes[startOffset + documentSize - 1] !== 0x00) {
4166
+ throw new BSONOffsetError('BSON documents must end in 0x00', startOffset + documentSize);
4167
+ }
4168
+ const elements = [];
4169
+ let offset = startOffset + 4;
4170
+ while (offset <= documentSize + startOffset) {
4171
+ const type = bytes[offset];
4172
+ offset += 1;
4173
+ if (type === 0) {
4174
+ if (offset - startOffset !== documentSize) {
4175
+ throw new BSONOffsetError(`Invalid 0x00 type byte`, offset);
4176
+ }
4177
+ break;
4178
+ }
4179
+ const nameOffset = offset;
4180
+ const nameLength = findNull(bytes, offset) - nameOffset;
4181
+ offset += nameLength + 1;
4182
+ let length;
4183
+ if (type === 1 ||
4184
+ type === 18 ||
4185
+ type === 9 ||
4186
+ type === 17) {
4187
+ length = 8;
4188
+ }
4189
+ else if (type === 16) {
4190
+ length = 4;
4191
+ }
4192
+ else if (type === 7) {
4193
+ length = 12;
4194
+ }
4195
+ else if (type === 19) {
4196
+ length = 16;
4197
+ }
4198
+ else if (type === 8) {
4199
+ length = 1;
4200
+ }
4201
+ else if (type === 10 ||
4202
+ type === 6 ||
4203
+ type === 127 ||
4204
+ type === 255) {
4205
+ length = 0;
4206
+ }
4207
+ else if (type === 11) {
4208
+ length = findNull(bytes, findNull(bytes, offset) + 1) + 1 - offset;
4209
+ }
4210
+ else if (type === 3 ||
4211
+ type === 4 ||
4212
+ type === 15) {
4213
+ length = getSize(bytes, offset);
4214
+ }
4215
+ else if (type === 2 ||
4216
+ type === 5 ||
4217
+ type === 12 ||
4218
+ type === 13 ||
4219
+ type === 14) {
4220
+ length = getSize(bytes, offset) + 4;
4221
+ if (type === 5) {
4222
+ length += 1;
4223
+ }
4224
+ if (type === 12) {
4225
+ length += 12;
4226
+ }
4227
+ }
4228
+ else {
4229
+ throw new BSONOffsetError(`Invalid 0x${type.toString(16).padStart(2, '0')} type byte`, offset);
4230
+ }
4231
+ if (length > documentSize) {
4232
+ throw new BSONOffsetError('value reports length larger than document', offset);
4233
+ }
4234
+ elements.push([type, nameOffset, nameLength, offset, length]);
4235
+ offset += length;
4236
+ }
4237
+ return elements;
4238
+ }
4239
+
4240
+ const onDemand = Object.create(null);
4241
+ onDemand.parseToElements = parseToElements;
4242
+ onDemand.ByteUtils = ByteUtils;
4243
+ onDemand.NumberUtils = NumberUtils;
4244
+ Object.freeze(onDemand);
4245
+
4093
4246
  const MAXSIZE = 1024 * 1024 * 17;
4094
4247
  let buffer = ByteUtils.allocate(MAXSIZE);
4095
4248
  function setInternalBufferSize(size) {
@@ -4144,6 +4297,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4144
4297
  var bson = /*#__PURE__*/Object.freeze({
4145
4298
  __proto__: null,
4146
4299
  BSONError: BSONError,
4300
+ BSONOffsetError: BSONOffsetError,
4147
4301
  BSONRegExp: BSONRegExp,
4148
4302
  BSONRuntimeError: BSONRuntimeError,
4149
4303
  BSONSymbol: BSONSymbol,
@@ -4166,6 +4320,7 @@ UUID: UUID,
4166
4320
  calculateObjectSize: calculateObjectSize,
4167
4321
  deserialize: deserialize,
4168
4322
  deserializeStream: deserializeStream,
4323
+ onDemand: onDemand,
4169
4324
  serialize: serialize,
4170
4325
  serializeWithBufferAndIndex: serializeWithBufferAndIndex,
4171
4326
  setInternalBufferSize: setInternalBufferSize
@@ -4173,6 +4328,7 @@ setInternalBufferSize: setInternalBufferSize
4173
4328
 
4174
4329
  exports.BSON = bson;
4175
4330
  exports.BSONError = BSONError;
4331
+ exports.BSONOffsetError = BSONOffsetError;
4176
4332
  exports.BSONRegExp = BSONRegExp;
4177
4333
  exports.BSONRuntimeError = BSONRuntimeError;
4178
4334
  exports.BSONSymbol = BSONSymbol;
@@ -4195,6 +4351,7 @@ exports.UUID = UUID;
4195
4351
  exports.calculateObjectSize = calculateObjectSize;
4196
4352
  exports.deserialize = deserialize;
4197
4353
  exports.deserializeStream = deserializeStream;
4354
+ exports.onDemand = onDemand;
4198
4355
  exports.serialize = serialize;
4199
4356
  exports.serializeWithBufferAndIndex = serializeWithBufferAndIndex;
4200
4357
  exports.setInternalBufferSize = setInternalBufferSize;