mongodb 7.1.1 → 7.2.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 (102) hide show
  1. package/README.md +11 -0
  2. package/lib/bson.js +26 -5
  3. package/lib/bson.js.map +1 -1
  4. package/lib/change_stream.js +4 -0
  5. package/lib/change_stream.js.map +1 -1
  6. package/lib/client-side-encryption/auto_encrypter.js +19 -10
  7. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  8. package/lib/client-side-encryption/client_encryption.js +1 -3
  9. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  10. package/lib/cmap/auth/aws4.js +4 -4
  11. package/lib/cmap/auth/aws4.js.map +1 -1
  12. package/lib/cmap/auth/gssapi.js +3 -6
  13. package/lib/cmap/auth/gssapi.js.map +1 -1
  14. package/lib/cmap/auth/mongodb_aws.js +3 -2
  15. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  16. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +3 -3
  17. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
  18. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +3 -3
  19. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
  20. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +3 -3
  21. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -1
  22. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +3 -3
  23. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
  24. package/lib/cmap/auth/mongodb_oidc.js +4 -4
  25. package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
  26. package/lib/cmap/auth/plain.js +1 -1
  27. package/lib/cmap/auth/plain.js.map +1 -1
  28. package/lib/cmap/auth/scram.js +53 -40
  29. package/lib/cmap/auth/scram.js.map +1 -1
  30. package/lib/cmap/commands.js +46 -39
  31. package/lib/cmap/commands.js.map +1 -1
  32. package/lib/cmap/connect.js +1 -0
  33. package/lib/cmap/connect.js.map +1 -1
  34. package/lib/cmap/connection.js +5 -2
  35. package/lib/cmap/connection.js.map +1 -1
  36. package/lib/cmap/handshake/client_metadata.js +3 -4
  37. package/lib/cmap/handshake/client_metadata.js.map +1 -1
  38. package/lib/cmap/wire_protocol/compression.js +8 -7
  39. package/lib/cmap/wire_protocol/compression.js.map +1 -1
  40. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  41. package/lib/cmap/wire_protocol/on_demand/document.js +9 -9
  42. package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
  43. package/lib/connection_string.js +21 -5
  44. package/lib/connection_string.js.map +1 -1
  45. package/lib/gridfs/download.js +2 -1
  46. package/lib/gridfs/download.js.map +1 -1
  47. package/lib/gridfs/upload.js +7 -7
  48. package/lib/gridfs/upload.js.map +1 -1
  49. package/lib/mongo_client.js.map +1 -1
  50. package/lib/operations/execute_operation.js +114 -41
  51. package/lib/operations/execute_operation.js.map +1 -1
  52. package/lib/operations/operation.js +1 -0
  53. package/lib/operations/operation.js.map +1 -1
  54. package/lib/runtime_adapters.js +32 -0
  55. package/lib/runtime_adapters.js.map +1 -0
  56. package/lib/sdam/srv_polling.js +1 -1
  57. package/lib/sdam/srv_polling.js.map +1 -1
  58. package/lib/sdam/topology.js +4 -2
  59. package/lib/sdam/topology.js.map +1 -1
  60. package/lib/sessions.js +124 -79
  61. package/lib/sessions.js.map +1 -1
  62. package/lib/utils.js +10 -33
  63. package/lib/utils.js.map +1 -1
  64. package/mongodb.d.ts +45 -2
  65. package/package.json +30 -21
  66. package/src/bson.ts +28 -5
  67. package/src/change_stream.ts +5 -0
  68. package/src/client-side-encryption/auto_encrypter.ts +17 -11
  69. package/src/client-side-encryption/client_encryption.ts +1 -3
  70. package/src/cmap/auth/auth_provider.ts +1 -1
  71. package/src/cmap/auth/aws4.ts +5 -5
  72. package/src/cmap/auth/gssapi.ts +9 -6
  73. package/src/cmap/auth/mongodb_aws.ts +2 -2
  74. package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +1 -1
  75. package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +1 -1
  76. package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +1 -1
  77. package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +1 -1
  78. package/src/cmap/auth/mongodb_oidc.ts +4 -4
  79. package/src/cmap/auth/plain.ts +2 -2
  80. package/src/cmap/auth/scram.ts +82 -55
  81. package/src/cmap/commands.ts +70 -51
  82. package/src/cmap/connect.ts +2 -0
  83. package/src/cmap/connection.ts +11 -4
  84. package/src/cmap/handshake/client_metadata.ts +6 -6
  85. package/src/cmap/wire_protocol/compression.ts +18 -14
  86. package/src/cmap/wire_protocol/on_data.ts +5 -5
  87. package/src/cmap/wire_protocol/on_demand/document.ts +12 -14
  88. package/src/connection_string.ts +26 -8
  89. package/src/deps.ts +4 -4
  90. package/src/gridfs/download.ts +2 -2
  91. package/src/gridfs/upload.ts +13 -12
  92. package/src/index.ts +1 -0
  93. package/src/mongo_client.ts +24 -0
  94. package/src/operations/client_bulk_write/command_builder.ts +1 -1
  95. package/src/operations/execute_operation.ts +146 -45
  96. package/src/operations/operation.ts +8 -0
  97. package/src/runtime_adapters.ts +64 -0
  98. package/src/sdam/srv_polling.ts +1 -1
  99. package/src/sdam/topology.ts +10 -7
  100. package/src/sessions.ts +140 -96
  101. package/src/utils.ts +21 -40
  102. package/tsconfig.json +1 -1
@@ -1,7 +1,6 @@
1
- import * as os from 'os';
2
1
  import * as process from 'process';
3
2
 
4
- import { BSON, type Document, Int32, NumberUtils } from '../../bson';
3
+ import { BSON, ByteUtils, type Document, Int32, NumberUtils } from '../../bson';
5
4
  import { MongoInvalidArgumentError } from '../../error';
6
5
  import type { DriverInfo, MongoOptions } from '../../mongo_client';
7
6
  import { fileIsAccessible } from '../../utils';
@@ -96,7 +95,8 @@ export class LimitedSizeDocument {
96
95
  }
97
96
  }
98
97
 
99
- type MakeClientMetadataOptions = Pick<MongoOptions, 'appName'>;
98
+ type MakeClientMetadataOptions = Pick<MongoOptions, 'appName' | 'runtime'>;
99
+
100
100
  /**
101
101
  * From the specs:
102
102
  * Implementors SHOULD cumulatively update fields in the following order until the document is under the size limit:
@@ -107,16 +107,16 @@ type MakeClientMetadataOptions = Pick<MongoOptions, 'appName'>;
107
107
  */
108
108
  export async function makeClientMetadata(
109
109
  driverInfoList: DriverInfo[],
110
- { appName = '' }: MakeClientMetadataOptions
110
+ { appName = '', runtime: { os } }: MakeClientMetadataOptions
111
111
  ): Promise<ClientMetadata> {
112
112
  const metadataDocument = new LimitedSizeDocument(512);
113
113
 
114
114
  // Add app name first, it must be sent
115
115
  if (appName.length > 0) {
116
116
  const name =
117
- Buffer.byteLength(appName, 'utf8') <= 128
117
+ ByteUtils.utf8ByteLength(appName) <= 128
118
118
  ? appName
119
- : Buffer.from(appName, 'utf8').subarray(0, 128).toString('utf8');
119
+ : ByteUtils.toUTF8(ByteUtils.fromUTF8(appName), 0, 128, false);
120
120
  metadataDocument.ifItFitsItSits('application', { name });
121
121
  }
122
122
 
@@ -1,5 +1,6 @@
1
1
  import * as zlib from 'zlib';
2
2
 
3
+ import { ByteUtils, readInt32LE } from '../../bson';
3
4
  import { LEGACY_HELLO_COMMAND } from '../../constants';
4
5
  import { getSnappy, getZstdLibrary, type SnappyLib, type ZStandard } from '../../deps';
5
6
  import { MongoDecompressionError, MongoInvalidArgumentError } from '../../error';
@@ -43,7 +44,7 @@ export const uncompressibleCommands = new Set([
43
44
  const ZSTD_COMPRESSION_LEVEL = 3;
44
45
 
45
46
  const zlibInflate = (buf: zlib.InputType) => {
46
- return new Promise<Buffer>((resolve, reject) => {
47
+ return new Promise<Uint8Array>((resolve, reject) => {
47
48
  zlib.inflate(buf, (error, result) => {
48
49
  if (error) return reject(error);
49
50
  resolve(result);
@@ -52,7 +53,7 @@ const zlibInflate = (buf: zlib.InputType) => {
52
53
  };
53
54
 
54
55
  const zlibDeflate = (buf: zlib.InputType, options: zlib.ZlibOptions) => {
55
- return new Promise<Buffer>((resolve, reject) => {
56
+ return new Promise<Uint8Array>((resolve, reject) => {
56
57
  zlib.deflate(buf, options, (error, result) => {
57
58
  if (error) return reject(error);
58
59
  resolve(result);
@@ -76,8 +77,8 @@ function loadSnappy() {
76
77
  // Facilitate compressing a message using an agreed compressor
77
78
  export async function compress(
78
79
  options: OpCompressesRequestOptions,
79
- dataToBeCompressed: Buffer
80
- ): Promise<Buffer> {
80
+ dataToBeCompressed: Uint8Array
81
+ ): Promise<Uint8Array> {
81
82
  const zlibOptions = {} as zlib.ZlibOptions;
82
83
  switch (options.agreedCompressor) {
83
84
  case 'snappy': {
@@ -106,7 +107,10 @@ export async function compress(
106
107
  }
107
108
 
108
109
  // Decompress a message using the given compressor
109
- export async function decompress(compressorID: number, compressedData: Buffer): Promise<Buffer> {
110
+ export async function decompress(
111
+ compressorID: number,
112
+ compressedData: Uint8Array
113
+ ): Promise<Uint8Array> {
110
114
  if (
111
115
  compressorID !== Compressor.snappy &&
112
116
  compressorID !== Compressor.zstd &&
@@ -159,7 +163,7 @@ const MESSAGE_HEADER_SIZE = 16;
159
163
  export async function compressCommand(
160
164
  command: WriteProtocolMessageType,
161
165
  description: { agreedCompressor?: CompressorName; zlibCompressionLevel?: number }
162
- ): Promise<Buffer> {
166
+ ): Promise<Uint8Array> {
163
167
  const finalCommand =
164
168
  description.agreedCompressor === 'none' || !OpCompressedRequest.canCompress(command)
165
169
  ? command
@@ -168,7 +172,7 @@ export async function compressCommand(
168
172
  zlibCompressionLevel: description.zlibCompressionLevel ?? 0
169
173
  });
170
174
  const data = await finalCommand.toBin();
171
- return Buffer.concat(data);
175
+ return ByteUtils.concat(data);
172
176
  }
173
177
 
174
178
  /**
@@ -178,12 +182,12 @@ export async function compressCommand(
178
182
  *
179
183
  * This method does not parse the response's BSON.
180
184
  */
181
- export async function decompressResponse(message: Buffer): Promise<OpMsgResponse | OpReply> {
185
+ export async function decompressResponse(message: Uint8Array): Promise<OpMsgResponse | OpReply> {
182
186
  const messageHeader: MessageHeader = {
183
- length: message.readInt32LE(0),
184
- requestId: message.readInt32LE(4),
185
- responseTo: message.readInt32LE(8),
186
- opCode: message.readInt32LE(12)
187
+ length: readInt32LE(message, 0),
188
+ requestId: readInt32LE(message, 4),
189
+ responseTo: readInt32LE(message, 8),
190
+ opCode: readInt32LE(message, 12)
187
191
  };
188
192
 
189
193
  if (messageHeader.opCode !== OP_COMPRESSED) {
@@ -195,8 +199,8 @@ export async function decompressResponse(message: Buffer): Promise<OpMsgResponse
195
199
  const header: MessageHeader = {
196
200
  ...messageHeader,
197
201
  fromCompressed: true,
198
- opCode: message.readInt32LE(MESSAGE_HEADER_SIZE),
199
- length: message.readInt32LE(MESSAGE_HEADER_SIZE + 4)
202
+ opCode: readInt32LE(message, MESSAGE_HEADER_SIZE),
203
+ length: readInt32LE(message, MESSAGE_HEADER_SIZE + 4)
200
204
  };
201
205
  const compressorID = message[MESSAGE_HEADER_SIZE + 8];
202
206
  const compressedBuffer = message.slice(MESSAGE_HEADER_SIZE + 9);
@@ -9,7 +9,7 @@ import { addAbortListener, kDispose, List, promiseWithResolvers } from '../../ut
9
9
  * An object holding references to a promise's resolve and reject functions.
10
10
  */
11
11
  type PendingPromises = Omit<
12
- ReturnType<typeof promiseWithResolvers<IteratorResult<Buffer>>>,
12
+ ReturnType<typeof promiseWithResolvers<IteratorResult<Uint8Array>>>,
13
13
  'promise'
14
14
  >;
15
15
 
@@ -32,7 +32,7 @@ export function onData(
32
32
  * value from the event in this list. Next time they call .next()
33
33
  * we pull the first value out of this list and resolve a promise with it.
34
34
  */
35
- const unconsumedEvents = new List<Buffer>();
35
+ const unconsumedEvents = new List<Uint8Array>();
36
36
  /**
37
37
  * When there has not yet been an event, a new promise will be created
38
38
  * and implicitly stored in this list. When an event occurs we take the first
@@ -49,7 +49,7 @@ export function onData(
49
49
  /** Set to true only after event listeners have been removed. */
50
50
  let finished = false;
51
51
 
52
- const iterator: AsyncGenerator<Buffer> & AsyncDisposable = {
52
+ const iterator: AsyncGenerator<Uint8Array> & AsyncDisposable = {
53
53
  next() {
54
54
  // First, we consume all unread events
55
55
  const value = unconsumedEvents.shift();
@@ -71,7 +71,7 @@ export function onData(
71
71
  if (finished) return closeHandler();
72
72
 
73
73
  // Wait until an event happens
74
- const { promise, resolve, reject } = promiseWithResolvers<IteratorResult<Buffer>>();
74
+ const { promise, resolve, reject } = promiseWithResolvers<IteratorResult<Uint8Array>>();
75
75
  unconsumedPromises.push({ resolve, reject });
76
76
  return promise;
77
77
  },
@@ -107,7 +107,7 @@ export function onData(
107
107
 
108
108
  return iterator;
109
109
 
110
- function eventHandler(value: Buffer) {
110
+ function eventHandler(value: Uint8Array) {
111
111
  const promise = unconsumedPromises.shift();
112
112
  if (promise != null) promise.resolve({ value, done: false });
113
113
  else unconsumedEvents.push(value);
@@ -3,15 +3,13 @@ import {
3
3
  type BSONElement,
4
4
  BSONError,
5
5
  BSONType,
6
+ ByteUtils,
6
7
  deserialize,
7
8
  type DeserializeOptions,
8
- getBigInt64LE,
9
- getFloat64LE,
10
- getInt32LE,
9
+ NumberUtils,
11
10
  ObjectId,
12
11
  parseToElementsToArray,
13
- Timestamp,
14
- toUTF8
12
+ Timestamp
15
13
  } from '../../../bson';
16
14
 
17
15
  const BSONElementOffset = {
@@ -183,25 +181,25 @@ export class OnDemandDocument {
183
181
  case BSONType.undefined:
184
182
  return null;
185
183
  case BSONType.double:
186
- return getFloat64LE(this.bson, offset);
184
+ return NumberUtils.getFloat64LE(this.bson, offset);
187
185
  case BSONType.int:
188
- return getInt32LE(this.bson, offset);
186
+ return NumberUtils.getInt32LE(this.bson, offset);
189
187
  case BSONType.long:
190
- return getBigInt64LE(this.bson, offset);
188
+ return NumberUtils.getBigInt64LE(this.bson, offset);
191
189
  case BSONType.bool:
192
190
  return Boolean(this.bson[offset]);
193
191
  case BSONType.objectId:
194
192
  return new ObjectId(this.bson.subarray(offset, offset + 12));
195
193
  case BSONType.timestamp:
196
- return new Timestamp(getBigInt64LE(this.bson, offset));
194
+ return new Timestamp(NumberUtils.getBigInt64LE(this.bson, offset));
197
195
  case BSONType.string:
198
- return toUTF8(this.bson, offset + 4, offset + length - 1, false);
196
+ return ByteUtils.toUTF8(this.bson, offset + 4, offset + length - 1, false);
199
197
  case BSONType.binData: {
200
- const totalBinarySize = getInt32LE(this.bson, offset);
198
+ const totalBinarySize = NumberUtils.getInt32LE(this.bson, offset);
201
199
  const subType = this.bson[offset + 4];
202
200
 
203
201
  if (subType === 2) {
204
- const subType2BinarySize = getInt32LE(this.bson, offset + 1 + 4);
202
+ const subType2BinarySize = NumberUtils.getInt32LE(this.bson, offset + 1 + 4);
205
203
  if (subType2BinarySize < 0)
206
204
  throw new BSONError('Negative binary type element size found for subtype 0x02');
207
205
  if (subType2BinarySize > totalBinarySize - 4)
@@ -221,7 +219,7 @@ export class OnDemandDocument {
221
219
  }
222
220
  case BSONType.date:
223
221
  // Pretend this is correct.
224
- return new Date(Number(getBigInt64LE(this.bson, offset)));
222
+ return new Date(Number(NumberUtils.getBigInt64LE(this.bson, offset)));
225
223
 
226
224
  case BSONType.object:
227
225
  return new OnDemandDocument(this.bson, offset);
@@ -352,7 +350,7 @@ export class OnDemandDocument {
352
350
 
353
351
  /** Returns this document's bytes only */
354
352
  toBytes() {
355
- const size = getInt32LE(this.bson, this.offset);
353
+ const size = NumberUtils.getInt32LE(this.bson, this.offset);
356
354
  return this.bson.subarray(this.offset, this.offset + size);
357
355
  }
358
356
  }
@@ -20,6 +20,7 @@ import {
20
20
  import { MongoLoggableComponent, MongoLogger, SeverityLevel } from './mongo_logger';
21
21
  import { ReadConcern, type ReadConcernLevel } from './read_concern';
22
22
  import { ReadPreference, type ReadPreferenceMode } from './read_preference';
23
+ import { resolveRuntimeAdapters } from './runtime_adapters';
23
24
  import { ServerMonitoringMode } from './sdam/monitor';
24
25
  import type { TagSet } from './sdam/server_description';
25
26
  import {
@@ -41,17 +42,21 @@ const LB_REPLICA_SET_ERROR = 'loadBalanced option not supported with a replicaSe
41
42
  const LB_DIRECT_CONNECTION_ERROR =
42
43
  'loadBalanced option not supported when directConnection is provided';
43
44
 
44
- function retryDNSTimeoutFor(api: 'resolveSrv'): (a: string) => Promise<dns.SrvRecord[]>;
45
- function retryDNSTimeoutFor(api: 'resolveTxt'): (a: string) => Promise<string[][]>;
45
+ function retryDNSTimeoutFor(rrtype: 'SRV'): (lookupAddress: string) => Promise<dns.SrvRecord[]>;
46
+ function retryDNSTimeoutFor(rrtype: 'TXT'): (lookupAddress: string) => Promise<string[][]>;
46
47
  function retryDNSTimeoutFor(
47
- api: 'resolveSrv' | 'resolveTxt'
48
- ): (a: string) => Promise<dns.SrvRecord[] | string[][]> {
48
+ rrtype: 'SRV' | 'TXT'
49
+ ): (lookupAddress: string) => Promise<dns.SrvRecord[] | string[][]> {
50
+ const resolve =
51
+ rrtype === 'SRV'
52
+ ? (address: string) => dns.promises.resolve(address, 'SRV')
53
+ : (address: string) => dns.promises.resolve(address, 'TXT');
49
54
  return async function dnsReqRetryTimeout(lookupAddress: string) {
50
55
  try {
51
- return await dns.promises[api](lookupAddress);
56
+ return await resolve(lookupAddress);
52
57
  } catch (firstDNSError) {
53
58
  if (firstDNSError.code === dns.TIMEOUT) {
54
- return await dns.promises[api](lookupAddress);
59
+ return await resolve(lookupAddress);
55
60
  } else {
56
61
  throw firstDNSError;
57
62
  }
@@ -59,8 +64,8 @@ function retryDNSTimeoutFor(
59
64
  };
60
65
  }
61
66
 
62
- const resolveSrv = retryDNSTimeoutFor('resolveSrv');
63
- const resolveTxt = retryDNSTimeoutFor('resolveTxt');
67
+ const resolveSrv = retryDNSTimeoutFor('SRV');
68
+ const resolveTxt = retryDNSTimeoutFor('TXT');
64
69
 
65
70
  /**
66
71
  * Lookup a `mongodb+srv` connection string, combine the parts and reparse it as a normal
@@ -538,6 +543,8 @@ export function parseOptions(
538
543
  }
539
544
  );
540
545
 
546
+ mongoOptions.runtime = resolveRuntimeAdapters(options);
547
+
541
548
  return mongoOptions;
542
549
  }
543
550
 
@@ -636,6 +643,10 @@ interface OptionDescriptor {
636
643
  }
637
644
 
638
645
  export const OPTIONS = {
646
+ enableOverloadRetargeting: {
647
+ default: false,
648
+ type: 'boolean'
649
+ },
639
650
  appName: {
640
651
  type: 'string'
641
652
  },
@@ -874,6 +885,10 @@ export const OPTIONS = {
874
885
  default: 15,
875
886
  type: 'uint'
876
887
  },
888
+ maxAdaptiveRetries: {
889
+ default: 2,
890
+ type: 'uint'
891
+ },
877
892
  maxConnecting: {
878
893
  default: 2,
879
894
  transform({ name, values: [value] }): number {
@@ -1061,6 +1076,9 @@ export const OPTIONS = {
1061
1076
  default: true,
1062
1077
  type: 'boolean'
1063
1078
  },
1079
+ runtimeAdapters: {
1080
+ type: 'record'
1081
+ },
1064
1082
  serializeFunctions: {
1065
1083
  type: 'boolean'
1066
1084
  },
package/src/deps.ts CHANGED
@@ -50,12 +50,12 @@ type ZStandardLib = {
50
50
  * Compress using zstd.
51
51
  * @param buf - Buffer to be compressed.
52
52
  */
53
- compress(buf: Buffer, level?: number): Promise<Buffer>;
53
+ compress(buf: Uint8Array, level?: number): Promise<Uint8Array>;
54
54
 
55
55
  /**
56
56
  * Decompress using zstd.
57
57
  */
58
- decompress(buf: Buffer): Promise<Buffer>;
58
+ decompress(buf: Uint8Array): Promise<Uint8Array>;
59
59
  };
60
60
 
61
61
  export type ZStandard = ZStandardLib | { kModuleError: MongoMissingDependencyError };
@@ -144,13 +144,13 @@ export type SnappyLib = {
144
144
  * In order to support both we must check the return value of the function
145
145
  * @param buf - Buffer to be compressed
146
146
  */
147
- compress(buf: Buffer): Promise<Buffer>;
147
+ compress(buf: Uint8Array): Promise<Uint8Array>;
148
148
 
149
149
  /**
150
150
  * In order to support both we must check the return value of the function
151
151
  * @param buf - Buffer to be compressed
152
152
  */
153
- uncompress(buf: Buffer, opt: { asBuffer: true }): Promise<Buffer>;
153
+ uncompress(buf: Uint8Array, opt: { asBuffer: true }): Promise<Uint8Array>;
154
154
  };
155
155
 
156
156
  export function getSnappy(): SnappyLib | { kModuleError: MongoMissingDependencyError } {
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'stream';
2
2
 
3
- import type { Document, ObjectId } from '../bson';
3
+ import { ByteUtils, type Document, type ObjectId } from '../bson';
4
4
  import type { Collection } from '../collection';
5
5
  import { CursorTimeoutMode } from '../cursor/abstract_cursor';
6
6
  import type { FindCursor } from '../cursor/find_cursor';
@@ -248,7 +248,7 @@ function doRead(stream: GridFSBucketReadStream): void {
248
248
  );
249
249
  }
250
250
 
251
- let buf = Buffer.isBuffer(doc.data) ? doc.data : doc.data.buffer;
251
+ let buf = ByteUtils.isUint8Array(doc.data) ? doc.data : doc.data.buffer;
252
252
 
253
253
  if (buf.byteLength !== expectedLength) {
254
254
  if (bytesRemaining <= 0) {
@@ -1,6 +1,6 @@
1
1
  import { Writable } from 'stream';
2
2
 
3
- import { type Document, ObjectId } from '../bson';
3
+ import { ByteUtils, type Document, ObjectId } from '../bson';
4
4
  import type { Collection } from '../collection';
5
5
  import { CursorTimeoutMode } from '../cursor/abstract_cursor';
6
6
  import {
@@ -62,7 +62,7 @@ export class GridFSBucketWriteStream extends Writable {
62
62
  /** The number of bytes that each chunk will be limited to */
63
63
  chunkSizeBytes: number;
64
64
  /** Space used to store a chunk currently being inserted */
65
- bufToStore: Buffer;
65
+ bufToStore: Uint8Array;
66
66
  /** Accumulates the number of bytes inserted as the stream uploads chunks */
67
67
  length: number;
68
68
  /** Accumulates the number of chunks inserted as the stream uploads file contents */
@@ -122,7 +122,7 @@ export class GridFSBucketWriteStream extends Writable {
122
122
  this.id = options.id ? options.id : new ObjectId();
123
123
  // properly inherit the default chunksize from parent
124
124
  this.chunkSizeBytes = options.chunkSizeBytes || this.bucket.s.options.chunkSizeBytes;
125
- this.bufToStore = Buffer.alloc(this.chunkSizeBytes);
125
+ this.bufToStore = ByteUtils.allocate(this.chunkSizeBytes);
126
126
  this.length = 0;
127
127
  this.n = 0;
128
128
  this.pos = 0;
@@ -178,7 +178,7 @@ export class GridFSBucketWriteStream extends Writable {
178
178
  * @param callback - Function to call when the chunk was added to the buffer, or if the entire chunk was persisted to MongoDB if this chunk caused a flush.
179
179
  */
180
180
  override _write(
181
- chunk: Buffer | string,
181
+ chunk: Uint8Array | string,
182
182
  encoding: BufferEncoding,
183
183
  callback: Callback<void>
184
184
  ): void {
@@ -227,7 +227,7 @@ function handleError(stream: GridFSBucketWriteStream, error: Error, callback: Ca
227
227
  queueMicrotask(() => callback(error));
228
228
  }
229
229
 
230
- function createChunkDoc(filesId: ObjectId, n: number, data: Buffer): GridFSChunk {
230
+ function createChunkDoc(filesId: ObjectId, n: number, data: Uint8Array): GridFSChunk {
231
231
  return {
232
232
  _id: new ObjectId(),
233
233
  files_id: filesId,
@@ -409,7 +409,7 @@ function createFilesDoc(
409
409
 
410
410
  function doWrite(
411
411
  stream: GridFSBucketWriteStream,
412
- chunk: Buffer | string,
412
+ chunk: Uint8Array | string,
413
413
  encoding: BufferEncoding,
414
414
  callback: Callback<void>
415
415
  ): void {
@@ -417,13 +417,14 @@ function doWrite(
417
417
  return;
418
418
  }
419
419
 
420
- const inputBuf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding);
420
+ const inputBuf =
421
+ typeof chunk === 'string' ? ByteUtils.fromUTF8(chunk) : ByteUtils.toLocalBufferType(chunk);
421
422
 
422
423
  stream.length += inputBuf.length;
423
424
 
424
425
  // Input is small enough to fit in our buffer
425
426
  if (stream.pos + inputBuf.length < stream.chunkSizeBytes) {
426
- inputBuf.copy(stream.bufToStore, stream.pos);
427
+ ByteUtils.copy(inputBuf, stream.bufToStore, stream.pos);
427
428
  stream.pos += inputBuf.length;
428
429
  queueMicrotask(callback);
429
430
  return;
@@ -437,12 +438,12 @@ function doWrite(
437
438
  let outstandingRequests = 0;
438
439
  while (inputBufRemaining > 0) {
439
440
  const inputBufPos = inputBuf.length - inputBufRemaining;
440
- inputBuf.copy(stream.bufToStore, stream.pos, inputBufPos, inputBufPos + numToCopy);
441
+ ByteUtils.copy(inputBuf, stream.bufToStore, stream.pos, inputBufPos, inputBufPos + numToCopy);
441
442
  stream.pos += numToCopy;
442
443
  spaceRemaining -= numToCopy;
443
444
  let doc: GridFSChunk;
444
445
  if (spaceRemaining === 0) {
445
- doc = createChunkDoc(stream.id, stream.n, Buffer.from(stream.bufToStore));
446
+ doc = createChunkDoc(stream.id, stream.n, new Uint8Array(stream.bufToStore));
446
447
 
447
448
  const remainingTimeMS = stream.timeoutContext?.remainingTimeMS;
448
449
  if (remainingTimeMS != null && remainingTimeMS <= 0) {
@@ -495,8 +496,8 @@ function writeRemnant(stream: GridFSBucketWriteStream, callback: Callback): void
495
496
 
496
497
  // Create a new buffer to make sure the buffer isn't bigger than it needs
497
498
  // to be.
498
- const remnant = Buffer.alloc(stream.pos);
499
- stream.bufToStore.copy(remnant, 0, 0, stream.pos);
499
+ const remnant = ByteUtils.allocate(stream.pos);
500
+ ByteUtils.copy(stream.bufToStore, remnant, 0, 0, stream.pos);
500
501
  const doc = createChunkDoc(stream.id, stream.n, remnant);
501
502
 
502
503
  // If the stream was aborted, do not write remnant
package/src/index.ts CHANGED
@@ -562,6 +562,7 @@ export type {
562
562
  ReadPreferenceLikeOptions,
563
563
  ReadPreferenceOptions
564
564
  } from './read_preference';
565
+ export type { OsAdapter, Runtime, RuntimeAdapters } from './runtime_adapters';
565
566
  export type { ClusterTime } from './sdam/common';
566
567
  export type {
567
568
  Monitor,
@@ -46,6 +46,7 @@ import { EndSessionsOperation } from './operations/end_sessions';
46
46
  import { executeOperation } from './operations/execute_operation';
47
47
  import type { ReadConcern, ReadConcernLevel, ReadConcernLike } from './read_concern';
48
48
  import { ReadPreference, type ReadPreferenceMode } from './read_preference';
49
+ import { type Runtime, type RuntimeAdapters } from './runtime_adapters';
49
50
  import type { ServerMonitoringMode } from './sdam/monitor';
50
51
  import type { TagSet } from './sdam/server_description';
51
52
  import { DeprioritizedServers, readPreferenceServerSelector } from './sdam/server_selection';
@@ -228,6 +229,18 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
228
229
  retryReads?: boolean;
229
230
  /** Enable retryable writes. */
230
231
  retryWrites?: boolean;
232
+ /**
233
+ * The maximum number of retries during server overload. Set to 0 to disable overload retries. Defaults to 2.
234
+ * @see https://www.mongodb.com/docs/atlas/overload-errors
235
+ * */
236
+ maxAdaptiveRetries?: number;
237
+ /**
238
+ * Whether or not to enable overload retargeting. Defaults to false.
239
+ * @see https://www.mongodb.com/docs/atlas/overload-errors
240
+ * More information about the overload policy in drivers:
241
+ * @see https://github.com/mongodb/specifications/blob/master/source/client-backpressure/client-backpressure.md#overload-retry-policy
242
+ * */
243
+ enableOverloadRetargeting?: boolean;
231
244
  /** Allow a driver to force a Single topology type with a connection string containing one host */
232
245
  directConnection?: boolean;
233
246
  /** Instruct the driver it is connecting to a load balancer fronting a mongos like service */
@@ -318,6 +331,12 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
318
331
  connectionType?: typeof Connection;
319
332
  /** @internal */
320
333
  __skipPingOnConnect?: boolean;
334
+ /**
335
+ * @experimental
336
+ *
337
+ * If provided, any adapters provided will be used in place of the corresponding Node.js module.
338
+ */
339
+ runtimeAdapters?: RuntimeAdapters;
321
340
  }
322
341
 
323
342
  /** @public */
@@ -1034,6 +1053,8 @@ export interface MongoOptions
1034
1053
  extends Required<
1035
1054
  Pick<
1036
1055
  MongoClientOptions,
1056
+ | 'maxAdaptiveRetries'
1057
+ | 'enableOverloadRetargeting'
1037
1058
  | 'autoEncryption'
1038
1059
  | 'connectTimeoutMS'
1039
1060
  | 'directConnection'
@@ -1152,4 +1173,7 @@ export interface MongoOptions
1152
1173
  timeoutMS?: number;
1153
1174
  /** @internal */
1154
1175
  __skipPingOnConnect?: boolean;
1176
+
1177
+ /** @internal */
1178
+ runtime: Runtime;
1155
1179
  }
@@ -242,7 +242,7 @@ function validateBufferSize(name: string, buffer: Uint8Array, maxBsonObjectSize:
242
242
  }
243
243
 
244
244
  /** @internal */
245
- interface ClientInsertOperation {
245
+ export interface ClientInsertOperation {
246
246
  insert: number;
247
247
  document: OptionalId<Document>;
248
248
  }