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.
- package/README.md +11 -0
- package/lib/bson.js +26 -5
- package/lib/bson.js.map +1 -1
- package/lib/change_stream.js +4 -0
- package/lib/change_stream.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +19 -10
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js +1 -3
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/cmap/auth/aws4.js +4 -4
- package/lib/cmap/auth/aws4.js.map +1 -1
- package/lib/cmap/auth/gssapi.js +3 -6
- package/lib/cmap/auth/gssapi.js.map +1 -1
- package/lib/cmap/auth/mongodb_aws.js +3 -2
- package/lib/cmap/auth/mongodb_aws.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +3 -3
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +3 -3
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +3 -3
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +3 -3
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc.js +4 -4
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/auth/plain.js +1 -1
- package/lib/cmap/auth/plain.js.map +1 -1
- package/lib/cmap/auth/scram.js +53 -40
- package/lib/cmap/auth/scram.js.map +1 -1
- package/lib/cmap/commands.js +46 -39
- package/lib/cmap/commands.js.map +1 -1
- package/lib/cmap/connect.js +1 -0
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +5 -2
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +3 -4
- package/lib/cmap/handshake/client_metadata.js.map +1 -1
- package/lib/cmap/wire_protocol/compression.js +8 -7
- package/lib/cmap/wire_protocol/compression.js.map +1 -1
- package/lib/cmap/wire_protocol/on_data.js.map +1 -1
- package/lib/cmap/wire_protocol/on_demand/document.js +9 -9
- package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
- package/lib/connection_string.js +21 -5
- package/lib/connection_string.js.map +1 -1
- package/lib/gridfs/download.js +2 -1
- package/lib/gridfs/download.js.map +1 -1
- package/lib/gridfs/upload.js +7 -7
- package/lib/gridfs/upload.js.map +1 -1
- package/lib/mongo_client.js.map +1 -1
- package/lib/operations/execute_operation.js +114 -41
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/operation.js +1 -0
- package/lib/operations/operation.js.map +1 -1
- package/lib/runtime_adapters.js +32 -0
- package/lib/runtime_adapters.js.map +1 -0
- package/lib/sdam/srv_polling.js +1 -1
- package/lib/sdam/srv_polling.js.map +1 -1
- package/lib/sdam/topology.js +4 -2
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +124 -79
- package/lib/sessions.js.map +1 -1
- package/lib/utils.js +10 -33
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +45 -2
- package/package.json +30 -21
- package/src/bson.ts +28 -5
- package/src/change_stream.ts +5 -0
- package/src/client-side-encryption/auto_encrypter.ts +17 -11
- package/src/client-side-encryption/client_encryption.ts +1 -3
- package/src/cmap/auth/auth_provider.ts +1 -1
- package/src/cmap/auth/aws4.ts +5 -5
- package/src/cmap/auth/gssapi.ts +9 -6
- package/src/cmap/auth/mongodb_aws.ts +2 -2
- package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +1 -1
- package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +1 -1
- package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +1 -1
- package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +1 -1
- package/src/cmap/auth/mongodb_oidc.ts +4 -4
- package/src/cmap/auth/plain.ts +2 -2
- package/src/cmap/auth/scram.ts +82 -55
- package/src/cmap/commands.ts +70 -51
- package/src/cmap/connect.ts +2 -0
- package/src/cmap/connection.ts +11 -4
- package/src/cmap/handshake/client_metadata.ts +6 -6
- package/src/cmap/wire_protocol/compression.ts +18 -14
- package/src/cmap/wire_protocol/on_data.ts +5 -5
- package/src/cmap/wire_protocol/on_demand/document.ts +12 -14
- package/src/connection_string.ts +26 -8
- package/src/deps.ts +4 -4
- package/src/gridfs/download.ts +2 -2
- package/src/gridfs/upload.ts +13 -12
- package/src/index.ts +1 -0
- package/src/mongo_client.ts +24 -0
- package/src/operations/client_bulk_write/command_builder.ts +1 -1
- package/src/operations/execute_operation.ts +146 -45
- package/src/operations/operation.ts +8 -0
- package/src/runtime_adapters.ts +64 -0
- package/src/sdam/srv_polling.ts +1 -1
- package/src/sdam/topology.ts +10 -7
- package/src/sessions.ts +140 -96
- package/src/utils.ts +21 -40
- 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
|
-
|
|
117
|
+
ByteUtils.utf8ByteLength(appName) <= 128
|
|
118
118
|
? appName
|
|
119
|
-
:
|
|
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<
|
|
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<
|
|
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:
|
|
80
|
-
): Promise<
|
|
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(
|
|
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<
|
|
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
|
|
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:
|
|
185
|
+
export async function decompressResponse(message: Uint8Array): Promise<OpMsgResponse | OpReply> {
|
|
182
186
|
const messageHeader: MessageHeader = {
|
|
183
|
-
length:
|
|
184
|
-
requestId:
|
|
185
|
-
responseTo:
|
|
186
|
-
opCode:
|
|
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:
|
|
199
|
-
length:
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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:
|
|
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
|
-
|
|
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
|
}
|
package/src/connection_string.ts
CHANGED
|
@@ -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(
|
|
45
|
-
function retryDNSTimeoutFor(
|
|
45
|
+
function retryDNSTimeoutFor(rrtype: 'SRV'): (lookupAddress: string) => Promise<dns.SrvRecord[]>;
|
|
46
|
+
function retryDNSTimeoutFor(rrtype: 'TXT'): (lookupAddress: string) => Promise<string[][]>;
|
|
46
47
|
function retryDNSTimeoutFor(
|
|
47
|
-
|
|
48
|
-
): (
|
|
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
|
|
56
|
+
return await resolve(lookupAddress);
|
|
52
57
|
} catch (firstDNSError) {
|
|
53
58
|
if (firstDNSError.code === dns.TIMEOUT) {
|
|
54
|
-
return await
|
|
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('
|
|
63
|
-
const resolveTxt = retryDNSTimeoutFor('
|
|
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:
|
|
53
|
+
compress(buf: Uint8Array, level?: number): Promise<Uint8Array>;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Decompress using zstd.
|
|
57
57
|
*/
|
|
58
|
-
decompress(buf:
|
|
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:
|
|
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:
|
|
153
|
+
uncompress(buf: Uint8Array, opt: { asBuffer: true }): Promise<Uint8Array>;
|
|
154
154
|
};
|
|
155
155
|
|
|
156
156
|
export function getSnappy(): SnappyLib | { kModuleError: MongoMissingDependencyError } {
|
package/src/gridfs/download.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Readable } from 'stream';
|
|
2
2
|
|
|
3
|
-
import type
|
|
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 =
|
|
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) {
|
package/src/gridfs/upload.ts
CHANGED
|
@@ -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:
|
|
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 =
|
|
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:
|
|
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:
|
|
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:
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
499
|
-
stream.bufToStore
|
|
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,
|
package/src/mongo_client.ts
CHANGED
|
@@ -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
|
}
|