bson 6.4.0 → 6.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/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;
@@ -140,12 +142,25 @@ declare namespace BSON {
140
142
  BSONRuntimeError,
141
143
  BSONType,
142
144
  EJSON,
145
+ onDemand,
143
146
  Document,
144
147
  CalculateObjectSizeOptions
145
148
  }
146
149
  }
147
150
  export { BSON }
148
151
 
152
+ /**
153
+ * @public
154
+ * @experimental
155
+ */
156
+ declare type BSONElement = [
157
+ type: number,
158
+ nameOffset: number,
159
+ nameLength: number,
160
+ offset: number,
161
+ length: number
162
+ ];
163
+
149
164
  /**
150
165
  * @public
151
166
  * @category Error
@@ -172,6 +187,21 @@ export declare class BSONError extends Error {
172
187
  static isBSONError(value: unknown): value is BSONError;
173
188
  }
174
189
 
190
+ /**
191
+ * @public
192
+ * @category Error
193
+ *
194
+ * @experimental
195
+ *
196
+ * An error generated when BSON bytes are invalid.
197
+ * Reports the offset the parser was able to reach before encountering the error.
198
+ */
199
+ declare class BSONOffsetError extends BSONError {
200
+ get name(): 'BSONOffsetError';
201
+ offset: number;
202
+ constructor(message: string, offset: number);
203
+ }
204
+
175
205
  /**
176
206
  * A class representation of the BSON RegExp type.
177
207
  * @public
@@ -1106,6 +1136,26 @@ export declare interface ObjectIdLike {
1106
1136
  toHexString(): string;
1107
1137
  }
1108
1138
 
1139
+ /**
1140
+ * @experimental
1141
+ * @public
1142
+ *
1143
+ * A new set of BSON APIs that are currently experimental and not intended for production use.
1144
+ */
1145
+ declare type OnDemand = {
1146
+ BSONOffsetError: {
1147
+ new (message: string, offset: number): BSONOffsetError;
1148
+ isBSONError(value: unknown): value is BSONError;
1149
+ };
1150
+ parseToElements: (this: void, bytes: Uint8Array, startOffset?: number) => Iterable<BSONElement>;
1151
+ };
1152
+
1153
+ /**
1154
+ * @experimental
1155
+ * @public
1156
+ */
1157
+ export declare const onDemand: OnDemand;
1158
+
1109
1159
  /**
1110
1160
  * Parse an Extended JSON string, constructing the JavaScript value or object described by that
1111
1161
  * 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) {
135
+ super(`${message}. offset: ${offset}`);
136
+ this.offset = offset;
137
+ }
138
+ }
130
139
 
131
140
  const FIRST_BIT = 0x80;
132
141
  const FIRST_TWO_BITS = 0xc0;
@@ -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,6 +2136,8 @@ 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 = {
2130
2142
  getInt32LE(source, offset) {
2131
2143
  return (source[offset] |
@@ -2150,17 +2162,29 @@ const NumberUtils = {
2150
2162
  const hi = NumberUtils.getUint32LE(source, offset + 4);
2151
2163
  return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2152
2164
  },
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
- },
2165
+ getFloat64LE: isBigEndian
2166
+ ? (source, offset) => {
2167
+ FLOAT_BYTES[7] = source[offset];
2168
+ FLOAT_BYTES[6] = source[offset + 1];
2169
+ FLOAT_BYTES[5] = source[offset + 2];
2170
+ FLOAT_BYTES[4] = source[offset + 3];
2171
+ FLOAT_BYTES[3] = source[offset + 4];
2172
+ FLOAT_BYTES[2] = source[offset + 5];
2173
+ FLOAT_BYTES[1] = source[offset + 6];
2174
+ FLOAT_BYTES[0] = source[offset + 7];
2175
+ return FLOAT[0];
2176
+ }
2177
+ : (source, offset) => {
2178
+ FLOAT_BYTES[0] = source[offset];
2179
+ FLOAT_BYTES[1] = source[offset + 1];
2180
+ FLOAT_BYTES[2] = source[offset + 2];
2181
+ FLOAT_BYTES[3] = source[offset + 3];
2182
+ FLOAT_BYTES[4] = source[offset + 4];
2183
+ FLOAT_BYTES[5] = source[offset + 5];
2184
+ FLOAT_BYTES[6] = source[offset + 6];
2185
+ FLOAT_BYTES[7] = source[offset + 7];
2186
+ return FLOAT[0];
2187
+ },
2164
2188
  setInt32BE(destination, offset, value) {
2165
2189
  destination[offset + 3] = value;
2166
2190
  value >>>= 8;
@@ -2201,18 +2225,31 @@ const NumberUtils = {
2201
2225
  destination[offset + 7] = hi;
2202
2226
  return 8;
2203
2227
  },
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
- }
2228
+ setFloat64LE: isBigEndian
2229
+ ? (destination, offset, value) => {
2230
+ FLOAT[0] = value;
2231
+ destination[offset] = FLOAT_BYTES[7];
2232
+ destination[offset + 1] = FLOAT_BYTES[6];
2233
+ destination[offset + 2] = FLOAT_BYTES[5];
2234
+ destination[offset + 3] = FLOAT_BYTES[4];
2235
+ destination[offset + 4] = FLOAT_BYTES[3];
2236
+ destination[offset + 5] = FLOAT_BYTES[2];
2237
+ destination[offset + 6] = FLOAT_BYTES[1];
2238
+ destination[offset + 7] = FLOAT_BYTES[0];
2239
+ return 8;
2240
+ }
2241
+ : (destination, offset, value) => {
2242
+ FLOAT[0] = value;
2243
+ destination[offset] = FLOAT_BYTES[0];
2244
+ destination[offset + 1] = FLOAT_BYTES[1];
2245
+ destination[offset + 2] = FLOAT_BYTES[2];
2246
+ destination[offset + 3] = FLOAT_BYTES[3];
2247
+ destination[offset + 4] = FLOAT_BYTES[4];
2248
+ destination[offset + 5] = FLOAT_BYTES[5];
2249
+ destination[offset + 6] = FLOAT_BYTES[6];
2250
+ destination[offset + 7] = FLOAT_BYTES[7];
2251
+ return 8;
2252
+ }
2216
2253
  };
2217
2254
 
2218
2255
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
@@ -4090,6 +4127,104 @@ EJSON.serialize = EJSONserialize;
4090
4127
  EJSON.deserialize = EJSONdeserialize;
4091
4128
  Object.freeze(EJSON);
4092
4129
 
4130
+ function getSize(source, offset) {
4131
+ if (source[offset + 3] > 127) {
4132
+ throw new BSONOffsetError('BSON size cannot be negative', offset);
4133
+ }
4134
+ return (source[offset] |
4135
+ (source[offset + 1] << 8) |
4136
+ (source[offset + 2] << 16) |
4137
+ (source[offset + 3] << 24));
4138
+ }
4139
+ function findNull(bytes, offset) {
4140
+ let nullTerminatorOffset = offset;
4141
+ for (; bytes[nullTerminatorOffset] !== 0x00; nullTerminatorOffset++)
4142
+ ;
4143
+ if (nullTerminatorOffset === bytes.length - 1) {
4144
+ throw new BSONOffsetError('Null terminator not found', offset);
4145
+ }
4146
+ return nullTerminatorOffset;
4147
+ }
4148
+ function parseToElements(bytes, startOffset = 0) {
4149
+ if (bytes.length < 5) {
4150
+ throw new BSONOffsetError(`Input must be at least 5 bytes, got ${bytes.length} bytes`, startOffset);
4151
+ }
4152
+ const documentSize = getSize(bytes, startOffset);
4153
+ if (documentSize > bytes.length - startOffset) {
4154
+ throw new BSONOffsetError(`Parsed documentSize (${documentSize} bytes) does not match input length (${bytes.length} bytes)`, startOffset);
4155
+ }
4156
+ if (bytes[startOffset + documentSize - 1] !== 0x00) {
4157
+ throw new BSONOffsetError('BSON documents must end in 0x00', startOffset + documentSize);
4158
+ }
4159
+ const elements = [];
4160
+ let offset = startOffset + 4;
4161
+ while (offset <= documentSize + startOffset) {
4162
+ const type = bytes[offset];
4163
+ offset += 1;
4164
+ if (type === 0) {
4165
+ if (offset - startOffset !== documentSize) {
4166
+ throw new BSONOffsetError(`Invalid 0x00 type byte`, offset);
4167
+ }
4168
+ break;
4169
+ }
4170
+ const nameOffset = offset;
4171
+ const nameLength = findNull(bytes, offset) - nameOffset;
4172
+ offset += nameLength + 1;
4173
+ let length;
4174
+ if (type === 1 || type === 18 || type === 9 || type === 17) {
4175
+ length = 8;
4176
+ }
4177
+ else if (type === 16) {
4178
+ length = 4;
4179
+ }
4180
+ else if (type === 7) {
4181
+ length = 12;
4182
+ }
4183
+ else if (type === 19) {
4184
+ length = 16;
4185
+ }
4186
+ else if (type === 8) {
4187
+ length = 1;
4188
+ }
4189
+ else if (type === 10 || type === 6 || type === 127 || type === 255) {
4190
+ length = 0;
4191
+ }
4192
+ else if (type === 11) {
4193
+ length = findNull(bytes, findNull(bytes, offset) + 1) + 1 - offset;
4194
+ }
4195
+ else if (type === 3 || type === 4 || type === 15) {
4196
+ length = getSize(bytes, offset);
4197
+ }
4198
+ else if (type === 2 ||
4199
+ type === 5 ||
4200
+ type === 12 ||
4201
+ type === 13 ||
4202
+ type === 14) {
4203
+ length = getSize(bytes, offset) + 4;
4204
+ if (type === 5) {
4205
+ length += 1;
4206
+ }
4207
+ if (type === 12) {
4208
+ length += 12;
4209
+ }
4210
+ }
4211
+ else {
4212
+ throw new BSONOffsetError(`Invalid 0x${type.toString(16).padStart(2, '0')} type byte`, offset);
4213
+ }
4214
+ if (length > documentSize) {
4215
+ throw new BSONOffsetError('value reports length larger than document', offset);
4216
+ }
4217
+ elements.push([type, nameOffset, nameLength, offset, length]);
4218
+ offset += length;
4219
+ }
4220
+ return elements;
4221
+ }
4222
+
4223
+ const onDemand = Object.create(null);
4224
+ onDemand.parseToElements = parseToElements;
4225
+ onDemand.BSONOffsetError = BSONOffsetError;
4226
+ Object.freeze(onDemand);
4227
+
4093
4228
  const MAXSIZE = 1024 * 1024 * 17;
4094
4229
  let buffer = ByteUtils.allocate(MAXSIZE);
4095
4230
  function setInternalBufferSize(size) {
@@ -4166,6 +4301,7 @@ UUID: UUID,
4166
4301
  calculateObjectSize: calculateObjectSize,
4167
4302
  deserialize: deserialize,
4168
4303
  deserializeStream: deserializeStream,
4304
+ onDemand: onDemand,
4169
4305
  serialize: serialize,
4170
4306
  serializeWithBufferAndIndex: serializeWithBufferAndIndex,
4171
4307
  setInternalBufferSize: setInternalBufferSize
@@ -4195,6 +4331,7 @@ exports.UUID = UUID;
4195
4331
  exports.calculateObjectSize = calculateObjectSize;
4196
4332
  exports.deserialize = deserialize;
4197
4333
  exports.deserializeStream = deserializeStream;
4334
+ exports.onDemand = onDemand;
4198
4335
  exports.serialize = serialize;
4199
4336
  exports.serializeWithBufferAndIndex = serializeWithBufferAndIndex;
4200
4337
  exports.setInternalBufferSize = setInternalBufferSize;