mongodb 6.16.0 → 6.17.0-dev.20250605.sha.57ef31be
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 +2 -0
- package/lib/beta.d.ts +160 -49
- package/lib/bulk/common.js +4 -4
- package/lib/bulk/common.js.map +1 -1
- package/lib/change_stream.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +5 -2
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/state_machine.js +1 -1
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +6 -0
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +21 -33
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +14 -21
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +19 -26
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +12 -24
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc.js +5 -4
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/commands.js +10 -8
- package/lib/cmap/commands.js.map +1 -1
- package/lib/cmap/connect.js +4 -3
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +8 -3
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +6 -1
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +1 -1
- package/lib/cmap/handshake/client_metadata.js.map +1 -1
- package/lib/cmap/wire_protocol/compression.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +2 -2
- package/lib/cmap/wire_protocol/on_data.js +4 -0
- package/lib/cmap/wire_protocol/on_data.js.map +1 -1
- package/lib/cmap/wire_protocol/on_demand/document.js +16 -15
- package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
- package/lib/cmap/wire_protocol/responses.js +11 -4
- package/lib/cmap/wire_protocol/responses.js.map +1 -1
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +4 -0
- package/lib/connection_string.js.map +1 -1
- package/lib/constants.js +0 -1
- package/lib/constants.js.map +1 -1
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/encrypter.js +3 -7
- package/lib/encrypter.js.map +1 -1
- package/lib/error.js +28 -1
- package/lib/error.js.map +1 -1
- package/lib/index.js +4 -3
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +66 -20
- package/lib/mongo_client.js.map +1 -1
- package/lib/operations/aggregate.js +0 -1
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/client_bulk_write/command_builder.js +20 -13
- package/lib/operations/client_bulk_write/command_builder.js.map +1 -1
- package/lib/operations/distinct.js +1 -0
- package/lib/operations/distinct.js.map +1 -1
- package/lib/operations/find_and_modify.js +1 -1
- package/lib/operations/find_and_modify.js.map +1 -1
- package/lib/operations/rename.js.map +1 -1
- package/lib/operations/run_command.js.map +1 -1
- package/lib/operations/search_indexes/create.js.map +1 -1
- package/lib/operations/search_indexes/drop.js.map +1 -1
- package/lib/operations/search_indexes/update.js.map +1 -1
- package/lib/operations/update.js +6 -2
- package/lib/operations/update.js.map +1 -1
- package/lib/sdam/server.js +4 -1
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/topology.js +9 -4
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sort.js +13 -6
- package/lib/sort.js.map +1 -1
- package/lib/utils.js +15 -2
- package/lib/utils.js.map +1 -1
- package/lib/write_concern.js +2 -4
- package/lib/write_concern.js.map +1 -1
- package/mongodb.d.ts +160 -49
- package/package.json +21 -21
- package/src/bulk/common.ts +14 -11
- package/src/change_stream.ts +38 -13
- package/src/client-side-encryption/auto_encrypter.ts +10 -2
- package/src/client-side-encryption/client_encryption.ts +5 -0
- package/src/client-side-encryption/state_machine.ts +8 -5
- package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +6 -0
- package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +23 -35
- package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +16 -23
- package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +17 -25
- package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +11 -24
- package/src/cmap/auth/mongodb_oidc.ts +13 -8
- package/src/cmap/commands.ts +31 -16
- package/src/cmap/connect.ts +4 -3
- package/src/cmap/connection.ts +11 -4
- package/src/cmap/connection_pool.ts +8 -1
- package/src/cmap/handshake/client_metadata.ts +5 -1
- package/src/cmap/wire_protocol/compression.ts +2 -1
- package/src/cmap/wire_protocol/constants.ts +2 -2
- package/src/cmap/wire_protocol/on_data.ts +5 -0
- package/src/cmap/wire_protocol/on_demand/document.ts +20 -15
- package/src/cmap/wire_protocol/responses.ts +10 -10
- package/src/collection.ts +2 -1
- package/src/connection_string.ts +4 -0
- package/src/constants.ts +0 -1
- package/src/cursor/abstract_cursor.ts +6 -4
- package/src/encrypter.ts +3 -10
- package/src/error.ts +28 -0
- package/src/index.ts +3 -0
- package/src/mongo_client.ts +73 -21
- package/src/operations/aggregate.ts +0 -1
- package/src/operations/client_bulk_write/command_builder.ts +32 -14
- package/src/operations/client_bulk_write/common.ts +5 -0
- package/src/operations/distinct.ts +1 -0
- package/src/operations/find_and_modify.ts +1 -1
- package/src/operations/rename.ts +8 -5
- package/src/operations/run_command.ts +17 -4
- package/src/operations/search_indexes/create.ts +6 -4
- package/src/operations/search_indexes/drop.ts +6 -4
- package/src/operations/search_indexes/update.ts +8 -5
- package/src/operations/update.ts +12 -3
- package/src/sdam/server.ts +5 -1
- package/src/sdam/topology.ts +10 -4
- package/src/sort.ts +32 -23
- package/src/utils.ts +29 -9
- package/src/write_concern.ts +2 -4
- package/tsconfig.json +2 -1
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +0 -110
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +0 -1
- package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +0 -142
package/src/cmap/commands.ts
CHANGED
|
@@ -76,12 +76,10 @@ export class OpQueryRequest {
|
|
|
76
76
|
partial: boolean;
|
|
77
77
|
/** moreToCome is an OP_MSG only concept */
|
|
78
78
|
moreToCome = false;
|
|
79
|
+
databaseName: string;
|
|
80
|
+
query: Document;
|
|
79
81
|
|
|
80
|
-
constructor(
|
|
81
|
-
public databaseName: string,
|
|
82
|
-
public query: Document,
|
|
83
|
-
options: OpQueryOptions
|
|
84
|
-
) {
|
|
82
|
+
constructor(databaseName: string, query: Document, options: OpQueryOptions) {
|
|
85
83
|
// Basic options needed to be passed in
|
|
86
84
|
// TODO(NODE-3483): Replace with MongoCommandError
|
|
87
85
|
const ns = `${databaseName}.$cmd`;
|
|
@@ -97,7 +95,9 @@ export class OpQueryRequest {
|
|
|
97
95
|
throw new MongoRuntimeError('Namespace cannot contain a null character');
|
|
98
96
|
}
|
|
99
97
|
|
|
100
|
-
// Basic
|
|
98
|
+
// Basic optionsa
|
|
99
|
+
this.databaseName = databaseName;
|
|
100
|
+
this.query = query;
|
|
101
101
|
this.ns = ns;
|
|
102
102
|
|
|
103
103
|
// Additional options
|
|
@@ -496,17 +496,18 @@ export class OpMsgRequest {
|
|
|
496
496
|
checksumPresent: boolean;
|
|
497
497
|
moreToCome: boolean;
|
|
498
498
|
exhaustAllowed: boolean;
|
|
499
|
+
databaseName: string;
|
|
500
|
+
command: Document;
|
|
501
|
+
options: OpQueryOptions;
|
|
499
502
|
|
|
500
|
-
constructor(
|
|
501
|
-
public databaseName: string,
|
|
502
|
-
public command: Document,
|
|
503
|
-
public options: OpQueryOptions
|
|
504
|
-
) {
|
|
503
|
+
constructor(databaseName: string, command: Document, options: OpQueryOptions) {
|
|
505
504
|
// Basic options needed to be passed in
|
|
506
505
|
if (command == null)
|
|
507
506
|
throw new MongoInvalidArgumentError('Query document must be specified for query');
|
|
508
507
|
|
|
509
|
-
// Basic
|
|
508
|
+
// Basic optionsa
|
|
509
|
+
this.databaseName = databaseName;
|
|
510
|
+
this.command = command;
|
|
510
511
|
this.command.$db = databaseName;
|
|
511
512
|
|
|
512
513
|
// Ensure empty options
|
|
@@ -724,16 +725,30 @@ export class OpMsgResponse {
|
|
|
724
725
|
const MESSAGE_HEADER_SIZE = 16;
|
|
725
726
|
const COMPRESSION_DETAILS_SIZE = 9; // originalOpcode + uncompressedSize, compressorID
|
|
726
727
|
|
|
728
|
+
/**
|
|
729
|
+
* @internal
|
|
730
|
+
*/
|
|
731
|
+
export interface OpCompressesRequestOptions {
|
|
732
|
+
zlibCompressionLevel: number;
|
|
733
|
+
agreedCompressor: CompressorName;
|
|
734
|
+
}
|
|
735
|
+
|
|
727
736
|
/**
|
|
728
737
|
* @internal
|
|
729
738
|
*
|
|
730
739
|
* An OP_COMPRESSED request wraps either an OP_QUERY or OP_MSG message.
|
|
731
740
|
*/
|
|
732
741
|
export class OpCompressedRequest {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
) {
|
|
742
|
+
private command: WriteProtocolMessageType;
|
|
743
|
+
private options: OpCompressesRequestOptions;
|
|
744
|
+
|
|
745
|
+
constructor(command: WriteProtocolMessageType, options: OpCompressesRequestOptions) {
|
|
746
|
+
this.command = command;
|
|
747
|
+
this.options = {
|
|
748
|
+
zlibCompressionLevel: options.zlibCompressionLevel,
|
|
749
|
+
agreedCompressor: options.agreedCompressor
|
|
750
|
+
};
|
|
751
|
+
}
|
|
737
752
|
|
|
738
753
|
// Return whether a command contains an uncompressible command term
|
|
739
754
|
// Will return true if command contains no uncompressible command terms
|
package/src/cmap/connect.ts
CHANGED
|
@@ -289,6 +289,7 @@ export const LEGAL_TLS_SOCKET_OPTIONS = [
|
|
|
289
289
|
export const LEGAL_TCP_SOCKET_OPTIONS = [
|
|
290
290
|
'autoSelectFamily',
|
|
291
291
|
'autoSelectFamilyAttemptTimeout',
|
|
292
|
+
'keepAliveInitialDelay',
|
|
292
293
|
'family',
|
|
293
294
|
'hints',
|
|
294
295
|
'localAddress',
|
|
@@ -306,6 +307,9 @@ function parseConnectOptions(options: ConnectionOptions): SocketConnectOpts {
|
|
|
306
307
|
(result as Document)[name] = options[name];
|
|
307
308
|
}
|
|
308
309
|
}
|
|
310
|
+
result.keepAliveInitialDelay ??= 120000;
|
|
311
|
+
result.keepAlive = true;
|
|
312
|
+
result.noDelay = options.noDelay ?? true;
|
|
309
313
|
|
|
310
314
|
if (typeof hostAddress.socketPath === 'string') {
|
|
311
315
|
result.path = hostAddress.socketPath;
|
|
@@ -347,7 +351,6 @@ function parseSslOptions(options: MakeConnectionOptions): TLSConnectionOpts {
|
|
|
347
351
|
|
|
348
352
|
export async function makeSocket(options: MakeConnectionOptions): Promise<Stream> {
|
|
349
353
|
const useTLS = options.tls ?? false;
|
|
350
|
-
const noDelay = options.noDelay ?? true;
|
|
351
354
|
const connectTimeoutMS = options.connectTimeoutMS ?? 30000;
|
|
352
355
|
const existingSocket = options.existingSocket;
|
|
353
356
|
|
|
@@ -376,9 +379,7 @@ export async function makeSocket(options: MakeConnectionOptions): Promise<Stream
|
|
|
376
379
|
socket = net.createConnection(parseConnectOptions(options));
|
|
377
380
|
}
|
|
378
381
|
|
|
379
|
-
socket.setKeepAlive(true, 300000);
|
|
380
382
|
socket.setTimeout(connectTimeoutMS);
|
|
381
|
-
socket.setNoDelay(noDelay);
|
|
382
383
|
|
|
383
384
|
let cancellationHandler: ((err: Error) => void) | null = null;
|
|
384
385
|
|
package/src/cmap/connection.ts
CHANGED
|
@@ -247,9 +247,9 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
|
|
|
247
247
|
this.lastUseTime = now();
|
|
248
248
|
|
|
249
249
|
this.messageStream = this.socket
|
|
250
|
-
.on('error', this.
|
|
250
|
+
.on('error', this.onSocketError.bind(this))
|
|
251
251
|
.pipe(new SizedMessageTransform({ connection: this }))
|
|
252
|
-
.on('error', this.
|
|
252
|
+
.on('error', this.onTransformError.bind(this));
|
|
253
253
|
this.socket.on('close', this.onClose.bind(this));
|
|
254
254
|
this.socket.on('timeout', this.onTimeout.bind(this));
|
|
255
255
|
|
|
@@ -304,6 +304,14 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
|
|
|
304
304
|
this.lastUseTime = now();
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
+
private onSocketError(cause: Error) {
|
|
308
|
+
this.onError(new MongoNetworkError(cause.message, { cause }));
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
private onTransformError(error: Error) {
|
|
312
|
+
this.onError(error);
|
|
313
|
+
}
|
|
314
|
+
|
|
307
315
|
public onError(error: Error) {
|
|
308
316
|
this.cleanup(error);
|
|
309
317
|
}
|
|
@@ -769,7 +777,6 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
|
|
|
769
777
|
} finally {
|
|
770
778
|
this.dataEvents = null;
|
|
771
779
|
this.messageStream.pause();
|
|
772
|
-
this.throwIfAborted();
|
|
773
780
|
}
|
|
774
781
|
}
|
|
775
782
|
}
|
|
@@ -857,7 +864,7 @@ export class CryptoConnection extends Connection {
|
|
|
857
864
|
ns: MongoDBNamespace,
|
|
858
865
|
cmd: Document,
|
|
859
866
|
options?: CommandOptions,
|
|
860
|
-
responseType?: T
|
|
867
|
+
responseType?: T
|
|
861
868
|
): Promise<Document> {
|
|
862
869
|
const { autoEncrypter } = this;
|
|
863
870
|
if (!autoEncrypter) {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from '../constants';
|
|
18
18
|
import {
|
|
19
19
|
type AnyError,
|
|
20
|
+
MongoClientClosedError,
|
|
20
21
|
type MongoError,
|
|
21
22
|
MongoInvalidArgumentError,
|
|
22
23
|
MongoMissingCredentialsError,
|
|
@@ -484,11 +485,17 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
|
|
|
484
485
|
for (const connection of this.checkedOut) {
|
|
485
486
|
if (connection.generation <= minGeneration) {
|
|
486
487
|
connection.onError(new PoolClearedOnNetworkError(this));
|
|
487
|
-
this.checkIn(connection);
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
+
/** For MongoClient.close() procedures */
|
|
493
|
+
public closeCheckedOutConnections() {
|
|
494
|
+
for (const conn of this.checkedOut) {
|
|
495
|
+
conn.onError(new MongoClientClosedError());
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
492
499
|
/** Close the pool */
|
|
493
500
|
close(): void {
|
|
494
501
|
if (this.closed) {
|
|
@@ -53,7 +53,11 @@ export class LimitedSizeDocument {
|
|
|
53
53
|
private document = new Map();
|
|
54
54
|
/** BSON overhead: Int32 + Null byte */
|
|
55
55
|
private documentSize = 5;
|
|
56
|
-
|
|
56
|
+
private maxSize: number;
|
|
57
|
+
|
|
58
|
+
constructor(maxSize: number) {
|
|
59
|
+
this.maxSize = maxSize;
|
|
60
|
+
}
|
|
57
61
|
|
|
58
62
|
/** Only adds key/value if the bsonByteLength is less than MAX_SIZE */
|
|
59
63
|
public ifItFitsItSits(key: string, value: Record<string, any> | string): boolean {
|
|
@@ -7,6 +7,7 @@ import { MongoDecompressionError, MongoInvalidArgumentError } from '../../error'
|
|
|
7
7
|
import {
|
|
8
8
|
type MessageHeader,
|
|
9
9
|
OpCompressedRequest,
|
|
10
|
+
type OpCompressesRequestOptions,
|
|
10
11
|
OpMsgResponse,
|
|
11
12
|
OpReply,
|
|
12
13
|
type WriteProtocolMessageType
|
|
@@ -60,7 +61,7 @@ function loadSnappy() {
|
|
|
60
61
|
|
|
61
62
|
// Facilitate compressing a message using an agreed compressor
|
|
62
63
|
export async function compress(
|
|
63
|
-
options:
|
|
64
|
+
options: OpCompressesRequestOptions,
|
|
64
65
|
dataToBeCompressed: Buffer
|
|
65
66
|
): Promise<Buffer> {
|
|
66
67
|
const zlibOptions = {} as zlib.ZlibOptions;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export const MIN_SUPPORTED_SERVER_VERSION = '4.
|
|
1
|
+
export const MIN_SUPPORTED_SERVER_VERSION = '4.2';
|
|
2
2
|
export const MAX_SUPPORTED_SERVER_VERSION = '8.0';
|
|
3
|
-
export const MIN_SUPPORTED_WIRE_VERSION =
|
|
3
|
+
export const MIN_SUPPORTED_WIRE_VERSION = 8;
|
|
4
4
|
export const MAX_SUPPORTED_WIRE_VERSION = 25;
|
|
5
5
|
export const MIN_SUPPORTED_QE_WIRE_VERSION = 21;
|
|
6
6
|
export const MIN_SUPPORTED_QE_SERVER_VERSION = '7.0';
|
|
@@ -14,14 +14,13 @@ import {
|
|
|
14
14
|
toUTF8
|
|
15
15
|
} from '../../../bson';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
17
|
+
const BSONElementOffset = {
|
|
18
|
+
type: 0,
|
|
19
|
+
nameOffset: 1,
|
|
20
|
+
nameLength: 2,
|
|
21
|
+
offset: 3,
|
|
22
|
+
length: 4
|
|
23
|
+
} as const;
|
|
25
24
|
|
|
26
25
|
/** @internal */
|
|
27
26
|
export type JSTypeOf = {
|
|
@@ -67,17 +66,23 @@ export class OnDemandDocument {
|
|
|
67
66
|
|
|
68
67
|
/** All bson elements in this document */
|
|
69
68
|
private readonly elements: ReadonlyArray<BSONElement>;
|
|
69
|
+
/** BSON bytes, this document begins at offset */
|
|
70
|
+
protected readonly bson: Uint8Array;
|
|
71
|
+
/** The start of the document */
|
|
72
|
+
private readonly offset: number;
|
|
73
|
+
/** If this is an embedded document, indicates if this was a BSON array */
|
|
74
|
+
public readonly isArray: boolean;
|
|
70
75
|
|
|
71
76
|
constructor(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
private readonly offset = 0,
|
|
76
|
-
/** If this is an embedded document, indicates if this was a BSON array */
|
|
77
|
-
public readonly isArray = false,
|
|
77
|
+
bson: Uint8Array,
|
|
78
|
+
offset = 0,
|
|
79
|
+
isArray = false,
|
|
78
80
|
/** If elements was already calculated */
|
|
79
81
|
elements?: BSONElement[]
|
|
80
82
|
) {
|
|
83
|
+
this.bson = bson;
|
|
84
|
+
this.offset = offset;
|
|
85
|
+
this.isArray = isArray;
|
|
81
86
|
this.elements = elements ?? parseToElementsToArray(this.bson, offset);
|
|
82
87
|
}
|
|
83
88
|
|
|
@@ -262,7 +267,7 @@ export class OnDemandDocument {
|
|
|
262
267
|
public get<const T extends keyof JSTypeOf>(
|
|
263
268
|
name: string | number,
|
|
264
269
|
as: T,
|
|
265
|
-
required?: boolean
|
|
270
|
+
required?: boolean
|
|
266
271
|
): JSTypeOf[T] | null;
|
|
267
272
|
|
|
268
273
|
/** `required` will make `get` throw if name does not exist or is null/undefined */
|
|
@@ -20,14 +20,14 @@ import {
|
|
|
20
20
|
type OnDemandDocumentDeserializeOptions
|
|
21
21
|
} from './on_demand/document';
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
const BSONElementOffset = {
|
|
24
|
+
type: 0,
|
|
25
|
+
nameOffset: 1,
|
|
26
|
+
nameLength: 2,
|
|
27
|
+
offset: 3,
|
|
28
|
+
length: 4
|
|
29
|
+
} as const;
|
|
30
|
+
|
|
31
31
|
/**
|
|
32
32
|
* Accepts a BSON payload and checks for na "ok: 0" element.
|
|
33
33
|
* This utility is intended to prevent calling response class constructors
|
|
@@ -77,7 +77,7 @@ export class MongoDBResponse extends OnDemandDocument {
|
|
|
77
77
|
public override get<const T extends keyof JSTypeOf>(
|
|
78
78
|
name: string | number,
|
|
79
79
|
as: T,
|
|
80
|
-
required?: false
|
|
80
|
+
required?: false
|
|
81
81
|
): JSTypeOf[T] | null;
|
|
82
82
|
public override get<const T extends keyof JSTypeOf>(
|
|
83
83
|
name: string | number,
|
|
@@ -87,7 +87,7 @@ export class MongoDBResponse extends OnDemandDocument {
|
|
|
87
87
|
public override get<const T extends keyof JSTypeOf>(
|
|
88
88
|
name: string | number,
|
|
89
89
|
as: T,
|
|
90
|
-
required?: boolean
|
|
90
|
+
required?: boolean
|
|
91
91
|
): JSTypeOf[T] | null {
|
|
92
92
|
try {
|
|
93
93
|
return super.get(name, as, required);
|
package/src/collection.ts
CHANGED
|
@@ -87,6 +87,7 @@ import {
|
|
|
87
87
|
} from './operations/update';
|
|
88
88
|
import { ReadConcern, type ReadConcernLike } from './read_concern';
|
|
89
89
|
import { ReadPreference, type ReadPreferenceLike } from './read_preference';
|
|
90
|
+
import { type Sort } from './sort';
|
|
90
91
|
import {
|
|
91
92
|
DEFAULT_PK_FACTORY,
|
|
92
93
|
MongoDBCollectionNamespace,
|
|
@@ -365,7 +366,7 @@ export class Collection<TSchema extends Document = Document> {
|
|
|
365
366
|
async updateOne(
|
|
366
367
|
filter: Filter<TSchema>,
|
|
367
368
|
update: UpdateFilter<TSchema> | Document[],
|
|
368
|
-
options?: UpdateOptions
|
|
369
|
+
options?: UpdateOptions & { sort?: Sort }
|
|
369
370
|
): Promise<UpdateResult<TSchema>> {
|
|
370
371
|
return await executeOperation(
|
|
371
372
|
this.client,
|
package/src/connection_string.ts
CHANGED
|
@@ -605,6 +605,9 @@ function setOption(
|
|
|
605
605
|
if (values[0] == null) {
|
|
606
606
|
break;
|
|
607
607
|
}
|
|
608
|
+
// The value should always be a string here, but since the array is typed as unknown
|
|
609
|
+
// there still needs to be an explicit cast.
|
|
610
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
608
611
|
mongoOptions[name] = String(values[0]);
|
|
609
612
|
break;
|
|
610
613
|
case 'record':
|
|
@@ -1273,6 +1276,7 @@ export const OPTIONS = {
|
|
|
1273
1276
|
requestCert: { type: 'any' },
|
|
1274
1277
|
rejectUnauthorized: { type: 'any' },
|
|
1275
1278
|
checkServerIdentity: { type: 'any' },
|
|
1279
|
+
keepAliveInitialDelay: { type: 'any' },
|
|
1276
1280
|
ALPNProtocols: { type: 'any' },
|
|
1277
1281
|
SNICallback: { type: 'any' },
|
|
1278
1282
|
session: { type: 'any' },
|
package/src/constants.ts
CHANGED
|
@@ -1213,11 +1213,13 @@ configureResourceManagement(AbstractCursor.prototype);
|
|
|
1213
1213
|
* All timeout behavior is exactly the same as the wrapped timeout context's.
|
|
1214
1214
|
*/
|
|
1215
1215
|
export class CursorTimeoutContext extends TimeoutContext {
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
) {
|
|
1216
|
+
timeoutContext: TimeoutContext;
|
|
1217
|
+
owner: symbol | AbstractCursor;
|
|
1218
|
+
|
|
1219
|
+
constructor(timeoutContext: TimeoutContext, owner: symbol | AbstractCursor) {
|
|
1220
1220
|
super();
|
|
1221
|
+
this.timeoutContext = timeoutContext;
|
|
1222
|
+
this.owner = owner;
|
|
1221
1223
|
}
|
|
1222
1224
|
override get serverSelectionTimeout(): Timeout | null {
|
|
1223
1225
|
return this.timeoutContext.serverSelectionTimeout;
|
package/src/encrypter.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { callbackify } from 'util';
|
|
2
|
-
|
|
3
1
|
import { AutoEncrypter, type AutoEncryptionOptions } from './client-side-encryption/auto_encrypter';
|
|
4
2
|
import { MONGO_CLIENT_EVENTS } from './constants';
|
|
5
3
|
import { getMongoDBClientEncryption } from './deps';
|
|
6
4
|
import { MongoInvalidArgumentError, MongoMissingDependencyError } from './error';
|
|
7
5
|
import { MongoClient, type MongoClientOptions } from './mongo_client';
|
|
8
|
-
import { type Callback } from './utils';
|
|
9
6
|
|
|
10
7
|
/** @internal */
|
|
11
8
|
export interface EncrypterOptions {
|
|
@@ -98,20 +95,16 @@ export class Encrypter {
|
|
|
98
95
|
}
|
|
99
96
|
}
|
|
100
97
|
|
|
101
|
-
|
|
102
|
-
callbackify(this.close.bind(this))(client, force, callback);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async close(client: MongoClient, force: boolean): Promise<void> {
|
|
98
|
+
async close(client: MongoClient): Promise<void> {
|
|
106
99
|
let error;
|
|
107
100
|
try {
|
|
108
|
-
await this.autoEncrypter.
|
|
101
|
+
await this.autoEncrypter.close();
|
|
109
102
|
} catch (autoEncrypterError) {
|
|
110
103
|
error = autoEncrypterError;
|
|
111
104
|
}
|
|
112
105
|
const internalClient = this.internalClient;
|
|
113
106
|
if (internalClient != null && client !== internalClient) {
|
|
114
|
-
return await internalClient.close(
|
|
107
|
+
return await internalClient.close();
|
|
115
108
|
}
|
|
116
109
|
if (error != null) {
|
|
117
110
|
throw error;
|
package/src/error.ts
CHANGED
|
@@ -1018,6 +1018,34 @@ export class MongoTopologyClosedError extends MongoAPIError {
|
|
|
1018
1018
|
}
|
|
1019
1019
|
}
|
|
1020
1020
|
|
|
1021
|
+
/**
|
|
1022
|
+
* An error generated when the MongoClient is closed and async
|
|
1023
|
+
* operations are interrupted.
|
|
1024
|
+
*
|
|
1025
|
+
* @public
|
|
1026
|
+
* @category Error
|
|
1027
|
+
*/
|
|
1028
|
+
export class MongoClientClosedError extends MongoAPIError {
|
|
1029
|
+
/**
|
|
1030
|
+
* **Do not use this constructor!**
|
|
1031
|
+
*
|
|
1032
|
+
* Meant for internal use only.
|
|
1033
|
+
*
|
|
1034
|
+
* @remarks
|
|
1035
|
+
* This class is only meant to be constructed within the driver. This constructor is
|
|
1036
|
+
* not subject to semantic versioning compatibility guarantees and may change at any time.
|
|
1037
|
+
*
|
|
1038
|
+
* @public
|
|
1039
|
+
**/
|
|
1040
|
+
constructor() {
|
|
1041
|
+
super('Operation interrupted because client was closed');
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
override get name(): string {
|
|
1045
|
+
return 'MongoClientClosedError';
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1021
1049
|
/** @public */
|
|
1022
1050
|
export interface MongoNetworkErrorOptions {
|
|
1023
1051
|
/** Indicates the timeout happened before a connection handshake completed */
|
package/src/index.ts
CHANGED
|
@@ -53,6 +53,7 @@ export {
|
|
|
53
53
|
MongoClientBulkWriteCursorError,
|
|
54
54
|
MongoClientBulkWriteError,
|
|
55
55
|
MongoClientBulkWriteExecutionError,
|
|
56
|
+
MongoClientClosedError,
|
|
56
57
|
MongoCompatibilityError,
|
|
57
58
|
MongoCursorExhaustedError,
|
|
58
59
|
MongoCursorInUseError,
|
|
@@ -207,6 +208,7 @@ export type {
|
|
|
207
208
|
ChangeStreamDocumentCommon,
|
|
208
209
|
ChangeStreamDocumentKey,
|
|
209
210
|
ChangeStreamDocumentOperationDescription,
|
|
211
|
+
ChangeStreamDocumentWallTime,
|
|
210
212
|
ChangeStreamDropDatabaseDocument,
|
|
211
213
|
ChangeStreamDropDocument,
|
|
212
214
|
ChangeStreamDropIndexDocument,
|
|
@@ -286,6 +288,7 @@ export type { TokenCache } from './cmap/auth/mongodb_oidc/token_cache';
|
|
|
286
288
|
export type {
|
|
287
289
|
MessageHeader,
|
|
288
290
|
OpCompressedRequest,
|
|
291
|
+
OpCompressesRequestOptions,
|
|
289
292
|
OpMsgOptions,
|
|
290
293
|
OpMsgRequest,
|
|
291
294
|
OpMsgResponse,
|
package/src/mongo_client.ts
CHANGED
|
@@ -115,7 +115,12 @@ export type SupportedTLSSocketOptions = Pick<
|
|
|
115
115
|
|
|
116
116
|
/** @public */
|
|
117
117
|
export type SupportedSocketOptions = Pick<
|
|
118
|
-
TcpNetConnectOpts & {
|
|
118
|
+
TcpNetConnectOpts & {
|
|
119
|
+
autoSelectFamily?: boolean;
|
|
120
|
+
autoSelectFamilyAttemptTimeout?: number;
|
|
121
|
+
/** Node.JS socket option to set the time the first keepalive probe is sent on an idle socket. Defaults to 120000ms */
|
|
122
|
+
keepAliveInitialDelay?: number;
|
|
123
|
+
},
|
|
119
124
|
(typeof LEGAL_TCP_SOCKET_OPTIONS)[number]
|
|
120
125
|
>;
|
|
121
126
|
|
|
@@ -342,22 +347,35 @@ export type MongoClientEvents = Pick<TopologyEvents, (typeof MONGO_CLIENT_EVENTS
|
|
|
342
347
|
};
|
|
343
348
|
|
|
344
349
|
/**
|
|
345
|
-
* The **MongoClient** class is a class that allows for making Connections to MongoDB.
|
|
346
350
|
* @public
|
|
347
351
|
*
|
|
352
|
+
* The **MongoClient** class is a class that allows for making Connections to MongoDB.
|
|
353
|
+
*
|
|
354
|
+
* **NOTE:** The programmatically provided options take precedence over the URI options.
|
|
355
|
+
*
|
|
348
356
|
* @remarks
|
|
349
|
-
*
|
|
357
|
+
*
|
|
358
|
+
* A MongoClient is the entry point to connecting to a MongoDB server.
|
|
359
|
+
*
|
|
360
|
+
* It handles a multitude of features on your application's behalf:
|
|
361
|
+
* - **Server Host Connection Configuration**: A MongoClient is responsible for reading TLS cert, ca, and crl files if provided.
|
|
362
|
+
* - **SRV Record Polling**: A "`mongodb+srv`" style connection string is used to have the MongoClient resolve DNS SRV records of all server hostnames which the driver periodically monitors for changes and adjusts its current view of hosts correspondingly.
|
|
363
|
+
* - **Server Monitoring**: The MongoClient automatically keeps monitoring the health of server nodes in your cluster to reach out to the correct and lowest latency one available.
|
|
364
|
+
* - **Connection Pooling**: To avoid paying the cost of rebuilding a connection to the server on every operation the MongoClient keeps idle connections preserved for reuse.
|
|
365
|
+
* - **Session Pooling**: The MongoClient creates logical sessions that enable retryable writes, causal consistency, and transactions. It handles pooling these sessions for reuse in subsequent operations.
|
|
366
|
+
* - **Cursor Operations**: A MongoClient's cursors use the health monitoring system to send the request for more documents to the same server the query began on.
|
|
367
|
+
* - **Mongocryptd process**: When using auto encryption, a MongoClient will launch a `mongocryptd` instance for handling encryption if the mongocrypt shared library isn't in use.
|
|
368
|
+
*
|
|
369
|
+
* There are many more features of a MongoClient that are not listed above.
|
|
370
|
+
*
|
|
371
|
+
* In order to enable these features, a number of asynchronous Node.js resources are established by the driver: Timers, FS Requests, Sockets, etc.
|
|
372
|
+
* For details on cleanup, please refer to the MongoClient `close()` documentation.
|
|
350
373
|
*
|
|
351
374
|
* @example
|
|
352
375
|
* ```ts
|
|
353
376
|
* import { MongoClient } from 'mongodb';
|
|
354
|
-
*
|
|
355
377
|
* // Enable command monitoring for debugging
|
|
356
|
-
* const client = new MongoClient('mongodb://localhost:27017', { monitorCommands: true });
|
|
357
|
-
*
|
|
358
|
-
* client.on('commandStarted', started => console.log(started));
|
|
359
|
-
* client.db().collection('pets');
|
|
360
|
-
* await client.insertOne({ name: 'spot', kind: 'dog' });
|
|
378
|
+
* const client = new MongoClient('mongodb://localhost:27017?appName=mflix', { monitorCommands: true });
|
|
361
379
|
* ```
|
|
362
380
|
*/
|
|
363
381
|
export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements AsyncDisposable {
|
|
@@ -636,25 +654,57 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
|
|
|
636
654
|
}
|
|
637
655
|
|
|
638
656
|
/**
|
|
639
|
-
* Cleans up
|
|
657
|
+
* Cleans up resources managed by the MongoClient.
|
|
658
|
+
*
|
|
659
|
+
* The close method clears and closes all resources whose lifetimes are managed by the MongoClient.
|
|
660
|
+
* Please refer to the `MongoClient` class documentation for a high level overview of the client's key features and responsibilities.
|
|
661
|
+
*
|
|
662
|
+
* **However,** the close method does not handle the cleanup of resources explicitly created by the user.
|
|
663
|
+
* Any user-created driver resource with its own `close()` method should be explicitly closed by the user before calling MongoClient.close().
|
|
664
|
+
* This method is written as a "best effort" attempt to leave behind the least amount of resources server-side when possible.
|
|
640
665
|
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
* - Cleans up any resources being used for auto encryption if auto encryption is enabled.
|
|
666
|
+
* The following list defines ideal preconditions and consequent pitfalls if they are not met.
|
|
667
|
+
* The MongoClient, ClientSession, Cursors and ChangeStreams all support [explicit resource management](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html).
|
|
668
|
+
* By using explicit resource management to manage the lifetime of driver resources instead of manually managing their lifetimes, the pitfalls outlined below can be avoided.
|
|
645
669
|
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
670
|
+
* The close method performs the following in the order listed:
|
|
671
|
+
* - Client-side:
|
|
672
|
+
* - **Close in-use connections**: Any connections that are currently waiting on a response from the server will be closed.
|
|
673
|
+
* This is performed _first_ to avoid reaching the next step (server-side clean up) and having no available connections to check out.
|
|
674
|
+
* - _Ideal_: All operations have been awaited or cancelled, and the outcomes, regardless of success or failure, have been processed before closing the client servicing the operation.
|
|
675
|
+
* - _Pitfall_: When `client.close()` is called and all connections are in use, after closing them, the client must create new connections for cleanup operations, which comes at the cost of new TLS/TCP handshakes and authentication steps.
|
|
676
|
+
* - Server-side:
|
|
677
|
+
* - **Close active cursors**: All cursors that haven't been completed will have a `killCursor` operation sent to the server they were initialized on, freeing the server-side resource.
|
|
678
|
+
* - _Ideal_: Cursors are explicitly closed or completed before `client.close()` is called.
|
|
679
|
+
* - _Pitfall_: `killCursors` may have to build a new connection if the in-use closure ended all pooled connections.
|
|
680
|
+
* - **End active sessions**: In-use sessions created with `client.startSession()` or `client.withSession()` or implicitly by the driver will have their `.endSession()` method called.
|
|
681
|
+
* Contrary to the name of the method, `endSession()` returns the session to the client's pool of sessions rather than end them on the server.
|
|
682
|
+
* - _Ideal_: Transaction outcomes are awaited and their corresponding explicit sessions are ended before `client.close()` is called.
|
|
683
|
+
* - _Pitfall_: **This step aborts in-progress transactions**. It is advisable to observe the outcome of a transaction before closing your client.
|
|
684
|
+
* - **End all pooled sessions**: The `endSessions` command with all session IDs the client has pooled is sent to the server to inform the cluster it can clean them up.
|
|
685
|
+
* - _Ideal_: No user intervention is expected.
|
|
686
|
+
* - _Pitfall_: None.
|
|
648
687
|
*
|
|
649
|
-
*
|
|
688
|
+
* The remaining shutdown is of the MongoClient resources that are intended to be entirely internal but is documented here as their existence relates to the JS event loop.
|
|
689
|
+
*
|
|
690
|
+
* - Client-side (again):
|
|
691
|
+
* - **Stop all server monitoring**: Connections kept live for detecting cluster changes and roundtrip time measurements are shutdown.
|
|
692
|
+
* - **Close all pooled connections**: Each server node in the cluster has a corresponding connection pool and all connections in the pool are closed. Any operations waiting to check out a connection will have an error thrown instead of a connection returned.
|
|
693
|
+
* - **Clear out server selection queue**: Any operations that are in the process of waiting for a server to be selected will have an error thrown instead of a server returned.
|
|
694
|
+
* - **Close encryption-related resources**: An internal MongoClient created for communicating with `mongocryptd` or other encryption purposes is closed. (Using this same method of course!)
|
|
695
|
+
*
|
|
696
|
+
* After the close method completes there should be no MongoClient related resources [ref-ed in Node.js' event loop](https://docs.libuv.org/en/v1.x/handle.html#reference-counting).
|
|
697
|
+
* This should allow Node.js to exit gracefully if MongoClient resources were the only active handles in the event loop.
|
|
698
|
+
*
|
|
699
|
+
* @param _force - currently an unused flag that has no effect. Defaults to `false`.
|
|
650
700
|
*/
|
|
651
|
-
async close(
|
|
701
|
+
async close(_force = false): Promise<void> {
|
|
652
702
|
if (this.closeLock) {
|
|
653
703
|
return await this.closeLock;
|
|
654
704
|
}
|
|
655
705
|
|
|
656
706
|
try {
|
|
657
|
-
this.closeLock = this._close(
|
|
707
|
+
this.closeLock = this._close();
|
|
658
708
|
await this.closeLock;
|
|
659
709
|
} finally {
|
|
660
710
|
// release
|
|
@@ -663,7 +713,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
|
|
|
663
713
|
}
|
|
664
714
|
|
|
665
715
|
/* @internal */
|
|
666
|
-
private async _close(
|
|
716
|
+
private async _close(): Promise<void> {
|
|
667
717
|
// There's no way to set hasBeenClosed back to false
|
|
668
718
|
Object.defineProperty(this.s, 'hasBeenClosed', {
|
|
669
719
|
value: true,
|
|
@@ -672,6 +722,8 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
|
|
|
672
722
|
writable: false
|
|
673
723
|
});
|
|
674
724
|
|
|
725
|
+
this.topology?.closeCheckedOutConnections();
|
|
726
|
+
|
|
675
727
|
const activeCursorCloses = Array.from(this.s.activeCursors, cursor => cursor.close());
|
|
676
728
|
this.s.activeCursors.clear();
|
|
677
729
|
|
|
@@ -717,7 +769,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
|
|
|
717
769
|
|
|
718
770
|
const { encrypter } = this.options;
|
|
719
771
|
if (encrypter) {
|
|
720
|
-
await encrypter.close(this
|
|
772
|
+
await encrypter.close(this);
|
|
721
773
|
}
|
|
722
774
|
}
|
|
723
775
|
|