mongodb 6.17.0 → 6.18.0-dev.20250723.sha.d92acfc1
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 +1 -3
- package/lib/beta.d.ts +68 -22
- package/lib/bulk/common.js.map +1 -1
- package/lib/change_stream.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/state_machine.js +1 -5
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/command_monitoring_events.js +2 -0
- package/lib/cmap/command_monitoring_events.js.map +1 -1
- package/lib/cmap/commands.js +10 -8
- package/lib/cmap/commands.js.map +1 -1
- package/lib/cmap/connection_pool.js +6 -2
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +18 -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/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/connection_string.js +4 -5
- package/lib/connection_string.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +45 -33
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/run_command_cursor.js +3 -0
- package/lib/cursor/run_command_cursor.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +12 -0
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_types.js +4 -1
- package/lib/mongo_types.js.map +1 -1
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/distinct.js +1 -0
- package/lib/operations/distinct.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/sessions.js.map +1 -1
- package/lib/transactions.js +9 -1
- package/lib/transactions.js.map +1 -1
- package/lib/utils.js +0 -1
- 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 +68 -22
- package/package.json +3 -3
- package/src/bulk/common.ts +3 -5
- package/src/change_stream.ts +38 -13
- package/src/client-side-encryption/auto_encrypter.ts +0 -1
- package/src/client-side-encryption/state_machine.ts +8 -10
- package/src/cmap/command_monitoring_events.ts +4 -0
- package/src/cmap/commands.ts +31 -16
- package/src/cmap/connection_pool.ts +6 -2
- package/src/cmap/handshake/client_metadata.ts +37 -4
- package/src/cmap/wire_protocol/compression.ts +2 -1
- package/src/cmap/wire_protocol/on_data.ts +5 -0
- package/src/cmap/wire_protocol/on_demand/document.ts +19 -14
- package/src/cmap/wire_protocol/responses.ts +8 -8
- package/src/connection_string.ts +5 -5
- package/src/cursor/abstract_cursor.ts +67 -44
- package/src/cursor/run_command_cursor.ts +7 -1
- package/src/index.ts +2 -0
- package/src/mongo_client.ts +48 -5
- package/src/mongo_types.ts +4 -1
- package/src/operations/command.ts +4 -0
- package/src/operations/distinct.ts +1 -0
- 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/sessions.ts +1 -0
- package/src/transactions.ts +10 -1
- package/src/utils.ts +8 -8
- package/src/write_concern.ts +2 -4
- package/tsconfig.json +2 -1
|
@@ -610,13 +610,17 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
|
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
private createConnection(callback: Callback<Connection>) {
|
|
613
|
+
// Note that metadata and extendedMetadata may have changed on the client but have
|
|
614
|
+
// been frozen here, so we pull the extendedMetadata promise always from the client
|
|
615
|
+
// no mattter what options were set at the construction of the pool.
|
|
613
616
|
const connectOptions: ConnectionOptions = {
|
|
614
617
|
...this.options,
|
|
615
618
|
id: this.connectionCounter.next().value,
|
|
616
619
|
generation: this.generation,
|
|
617
620
|
cancellationToken: this.cancellationToken,
|
|
618
621
|
mongoLogger: this.mongoLogger,
|
|
619
|
-
authProviders: this.server.topology.client.s.authProviders
|
|
622
|
+
authProviders: this.server.topology.client.s.authProviders,
|
|
623
|
+
extendedMetadata: this.server.topology.client.options.extendedMetadata
|
|
620
624
|
};
|
|
621
625
|
|
|
622
626
|
this.pending++;
|
|
@@ -691,7 +695,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
|
|
|
691
695
|
|
|
692
696
|
private ensureMinPoolSize() {
|
|
693
697
|
const minPoolSize = this.options.minPoolSize;
|
|
694
|
-
if (this.poolState !== PoolState.ready
|
|
698
|
+
if (this.poolState !== PoolState.ready) {
|
|
695
699
|
return;
|
|
696
700
|
}
|
|
697
701
|
|
|
@@ -2,7 +2,7 @@ import * as os from 'os';
|
|
|
2
2
|
import * as process from 'process';
|
|
3
3
|
|
|
4
4
|
import { BSON, type Document, Int32 } from '../../bson';
|
|
5
|
-
import { MongoInvalidArgumentError } from '../../error';
|
|
5
|
+
import { MongoInvalidArgumentError, MongoRuntimeError } from '../../error';
|
|
6
6
|
import type { MongoOptions } from '../../mongo_client';
|
|
7
7
|
import { fileIsAccessible } from '../../utils';
|
|
8
8
|
|
|
@@ -11,6 +11,7 @@ const NODE_DRIVER_VERSION = require('../../../package.json').version;
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @public
|
|
14
|
+
* @deprecated This interface will be made internal in the next major release.
|
|
14
15
|
* @see https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.md#hello-command
|
|
15
16
|
*/
|
|
16
17
|
export interface ClientMetadata {
|
|
@@ -38,7 +39,10 @@ export interface ClientMetadata {
|
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* @public
|
|
44
|
+
* @deprecated This interface will be made internal in the next major release.
|
|
45
|
+
*/
|
|
42
46
|
export interface ClientMetadataOptions {
|
|
43
47
|
driverInfo?: {
|
|
44
48
|
name?: string;
|
|
@@ -53,7 +57,11 @@ export class LimitedSizeDocument {
|
|
|
53
57
|
private document = new Map();
|
|
54
58
|
/** BSON overhead: Int32 + Null byte */
|
|
55
59
|
private documentSize = 5;
|
|
56
|
-
|
|
60
|
+
private maxSize: number;
|
|
61
|
+
|
|
62
|
+
constructor(maxSize: number) {
|
|
63
|
+
this.maxSize = maxSize;
|
|
64
|
+
}
|
|
57
65
|
|
|
58
66
|
/** Only adds key/value if the bsonByteLength is less than MAX_SIZE */
|
|
59
67
|
public ifItFitsItSits(key: string, value: Record<string, any> | string): boolean {
|
|
@@ -82,7 +90,10 @@ export class LimitedSizeDocument {
|
|
|
82
90
|
}
|
|
83
91
|
}
|
|
84
92
|
|
|
85
|
-
type MakeClientMetadataOptions = Pick<
|
|
93
|
+
type MakeClientMetadataOptions = Pick<
|
|
94
|
+
MongoOptions,
|
|
95
|
+
'appName' | 'driverInfo' | 'additionalDriverInfo'
|
|
96
|
+
>;
|
|
86
97
|
/**
|
|
87
98
|
* From the specs:
|
|
88
99
|
* Implementors SHOULD cumulatively update fields in the following order until the document is under the size limit:
|
|
@@ -111,6 +122,22 @@ export function makeClientMetadata(options: MakeClientMetadataOptions): ClientMe
|
|
|
111
122
|
version: version.length > 0 ? `${NODE_DRIVER_VERSION}|${version}` : NODE_DRIVER_VERSION
|
|
112
123
|
};
|
|
113
124
|
|
|
125
|
+
if (options.additionalDriverInfo == null) {
|
|
126
|
+
throw new MongoRuntimeError(
|
|
127
|
+
'Client options `additionalDriverInfo` must always default to an empty array'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// This is where we handle additional driver info added after client construction.
|
|
132
|
+
for (const { name: n = '', version: v = '' } of options.additionalDriverInfo) {
|
|
133
|
+
if (n.length > 0) {
|
|
134
|
+
driverInfo.name = `${driverInfo.name}|${n}`;
|
|
135
|
+
}
|
|
136
|
+
if (v.length > 0) {
|
|
137
|
+
driverInfo.version = `${driverInfo.version}|${v}`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
114
141
|
if (!metadataDocument.ifItFitsItSits('driver', driverInfo)) {
|
|
115
142
|
throw new MongoInvalidArgumentError(
|
|
116
143
|
'Unable to include driverInfo name and version, metadata cannot exceed 512 bytes'
|
|
@@ -122,6 +149,12 @@ export function makeClientMetadata(options: MakeClientMetadataOptions): ClientMe
|
|
|
122
149
|
runtimeInfo = `${runtimeInfo}|${platform}`;
|
|
123
150
|
}
|
|
124
151
|
|
|
152
|
+
for (const { platform: p = '' } of options.additionalDriverInfo) {
|
|
153
|
+
if (p.length > 0) {
|
|
154
|
+
runtimeInfo = `${runtimeInfo}|${p}`;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
125
158
|
if (!metadataDocument.ifItFitsItSits('platform', runtimeInfo)) {
|
|
126
159
|
throw new MongoInvalidArgumentError(
|
|
127
160
|
'Unable to include driverInfo platform, metadata cannot exceed 512 bytes'
|
|
@@ -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;
|
|
@@ -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
|
|
|
@@ -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
|
package/src/connection_string.ts
CHANGED
|
@@ -172,11 +172,6 @@ function checkTLSOptions(allOptions: CaseInsensitiveMap): void {
|
|
|
172
172
|
};
|
|
173
173
|
check('tlsInsecure', 'tlsAllowInvalidCertificates');
|
|
174
174
|
check('tlsInsecure', 'tlsAllowInvalidHostnames');
|
|
175
|
-
check('tlsInsecure', 'tlsDisableCertificateRevocationCheck');
|
|
176
|
-
check('tlsInsecure', 'tlsDisableOCSPEndpointCheck');
|
|
177
|
-
check('tlsAllowInvalidCertificates', 'tlsDisableCertificateRevocationCheck');
|
|
178
|
-
check('tlsAllowInvalidCertificates', 'tlsDisableOCSPEndpointCheck');
|
|
179
|
-
check('tlsDisableCertificateRevocationCheck', 'tlsDisableOCSPEndpointCheck');
|
|
180
175
|
}
|
|
181
176
|
function getBoolean(name: string, value: unknown): boolean {
|
|
182
177
|
if (typeof value === 'boolean') return value;
|
|
@@ -540,6 +535,9 @@ export function parseOptions(
|
|
|
540
535
|
}
|
|
541
536
|
);
|
|
542
537
|
|
|
538
|
+
// Set the default for the additional driver info.
|
|
539
|
+
mongoOptions.additionalDriverInfo = [];
|
|
540
|
+
|
|
543
541
|
mongoOptions.metadata = makeClientMetadata(mongoOptions);
|
|
544
542
|
|
|
545
543
|
mongoOptions.extendedMetadata = addContainerMetadata(mongoOptions.metadata).then(
|
|
@@ -605,6 +603,8 @@ function setOption(
|
|
|
605
603
|
if (values[0] == null) {
|
|
606
604
|
break;
|
|
607
605
|
}
|
|
606
|
+
// The value should always be a string here, but since the array is typed as unknown
|
|
607
|
+
// there still needs to be an explicit cast.
|
|
608
608
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
609
609
|
mongoOptions[name] = String(values[0]);
|
|
610
610
|
break;
|
|
@@ -20,7 +20,7 @@ import { ReadConcern, type ReadConcernLike } from '../read_concern';
|
|
|
20
20
|
import { ReadPreference, type ReadPreferenceLike } from '../read_preference';
|
|
21
21
|
import { type AsyncDisposable, configureResourceManagement } from '../resource_management';
|
|
22
22
|
import type { Server } from '../sdam/server';
|
|
23
|
-
import { ClientSession, maybeClearPinnedConnection } from '../sessions';
|
|
23
|
+
import { type ClientSession, maybeClearPinnedConnection } from '../sessions';
|
|
24
24
|
import { type CSOTTimeoutContext, type Timeout, TimeoutContext } from '../timeout';
|
|
25
25
|
import {
|
|
26
26
|
addAbortListener,
|
|
@@ -227,7 +227,7 @@ export abstract class AbstractCursor<
|
|
|
227
227
|
/** @internal */
|
|
228
228
|
private cursorId: Long | null;
|
|
229
229
|
/** @internal */
|
|
230
|
-
private cursorSession: ClientSession;
|
|
230
|
+
private cursorSession: ClientSession | null;
|
|
231
231
|
/** @internal */
|
|
232
232
|
private selectedServer?: Server;
|
|
233
233
|
/** @internal */
|
|
@@ -352,11 +352,7 @@ export abstract class AbstractCursor<
|
|
|
352
352
|
this.cursorOptions.maxAwaitTimeMS = options.maxAwaitTimeMS;
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
|
|
356
|
-
this.cursorSession = options.session;
|
|
357
|
-
} else {
|
|
358
|
-
this.cursorSession = this.cursorClient.startSession({ owner: this, explicit: false });
|
|
359
|
-
}
|
|
355
|
+
this.cursorSession = options.session ?? null;
|
|
360
356
|
|
|
361
357
|
this.deserializationOptions = {
|
|
362
358
|
...this.cursorOptions,
|
|
@@ -413,7 +409,7 @@ export abstract class AbstractCursor<
|
|
|
413
409
|
}
|
|
414
410
|
|
|
415
411
|
/** @internal */
|
|
416
|
-
get session(): ClientSession {
|
|
412
|
+
get session(): ClientSession | null {
|
|
417
413
|
return this.cursorSession;
|
|
418
414
|
}
|
|
419
415
|
|
|
@@ -877,11 +873,12 @@ export abstract class AbstractCursor<
|
|
|
877
873
|
this.trackCursor();
|
|
878
874
|
|
|
879
875
|
// We only want to end this session if we created it, and it hasn't ended yet
|
|
880
|
-
if (this.cursorSession
|
|
876
|
+
if (this.cursorSession?.explicit === false) {
|
|
881
877
|
if (!this.cursorSession.hasEnded) {
|
|
882
878
|
this.cursorSession.endSession().then(undefined, squashError);
|
|
883
879
|
}
|
|
884
|
-
|
|
880
|
+
|
|
881
|
+
this.cursorSession = null;
|
|
885
882
|
}
|
|
886
883
|
}
|
|
887
884
|
|
|
@@ -907,6 +904,13 @@ export abstract class AbstractCursor<
|
|
|
907
904
|
'Unexpected null selectedServer. A cursor creating command should have set this'
|
|
908
905
|
);
|
|
909
906
|
}
|
|
907
|
+
|
|
908
|
+
if (this.cursorSession == null) {
|
|
909
|
+
throw new MongoRuntimeError(
|
|
910
|
+
'Unexpected null session. A cursor creating command should have set this'
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
|
|
910
914
|
const getMoreOptions = {
|
|
911
915
|
...this.cursorOptions,
|
|
912
916
|
session: this.cursorSession,
|
|
@@ -941,6 +945,7 @@ export abstract class AbstractCursor<
|
|
|
941
945
|
);
|
|
942
946
|
}
|
|
943
947
|
try {
|
|
948
|
+
this.cursorSession ??= this.cursorClient.startSession({ owner: this, explicit: false });
|
|
944
949
|
const state = await this._initialize(this.cursorSession);
|
|
945
950
|
// Set omitMaxTimeMS to the value needed for subsequent getMore calls
|
|
946
951
|
this.cursorOptions.omitMaxTimeMS = this.cursorOptions.timeoutMS != null;
|
|
@@ -1032,41 +1037,57 @@ export abstract class AbstractCursor<
|
|
|
1032
1037
|
return this.timeoutContext?.refreshed();
|
|
1033
1038
|
}
|
|
1034
1039
|
};
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
this.
|
|
1041
|
-
this.selectedServer &&
|
|
1042
|
-
!this.cursorSession.hasEnded
|
|
1043
|
-
) {
|
|
1044
|
-
this.isKilled = true;
|
|
1045
|
-
const cursorId = this.cursorId;
|
|
1046
|
-
this.cursorId = Long.ZERO;
|
|
1047
|
-
|
|
1048
|
-
await executeOperation(
|
|
1049
|
-
this.cursorClient,
|
|
1050
|
-
new KillCursorsOperation(cursorId, this.cursorNamespace, this.selectedServer, {
|
|
1051
|
-
session: this.cursorSession
|
|
1052
|
-
}),
|
|
1053
|
-
timeoutContextForKillCursors()
|
|
1054
|
-
);
|
|
1040
|
+
|
|
1041
|
+
const withEmitClose = async (fn: () => Promise<void>) => {
|
|
1042
|
+
try {
|
|
1043
|
+
await fn();
|
|
1044
|
+
} finally {
|
|
1045
|
+
this.emitClose();
|
|
1055
1046
|
}
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
const close = async () => {
|
|
1050
|
+
// if no session has been defined on the cursor, the cursor was never initialized
|
|
1051
|
+
// or the cursor was re-wound and never re-iterated. In either case, we
|
|
1052
|
+
// 1. do not need to end the session (there is no session after all)
|
|
1053
|
+
// 2. do not need to kill the cursor server-side
|
|
1054
|
+
const session = this.cursorSession;
|
|
1055
|
+
if (!session) return;
|
|
1056
|
+
|
|
1059
1057
|
try {
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1058
|
+
if (
|
|
1059
|
+
!this.isKilled &&
|
|
1060
|
+
this.cursorId &&
|
|
1061
|
+
!this.cursorId.isZero() &&
|
|
1062
|
+
this.cursorNamespace &&
|
|
1063
|
+
this.selectedServer &&
|
|
1064
|
+
!session.hasEnded
|
|
1065
|
+
) {
|
|
1066
|
+
this.isKilled = true;
|
|
1067
|
+
const cursorId = this.cursorId;
|
|
1068
|
+
this.cursorId = Long.ZERO;
|
|
1069
|
+
|
|
1070
|
+
await executeOperation(
|
|
1071
|
+
this.cursorClient,
|
|
1072
|
+
new KillCursorsOperation(cursorId, this.cursorNamespace, this.selectedServer, {
|
|
1073
|
+
session
|
|
1074
|
+
}),
|
|
1075
|
+
timeoutContextForKillCursors()
|
|
1076
|
+
);
|
|
1065
1077
|
}
|
|
1078
|
+
} catch (error) {
|
|
1079
|
+
squashError(error);
|
|
1066
1080
|
} finally {
|
|
1067
|
-
this
|
|
1081
|
+
if (session.owner === this) {
|
|
1082
|
+
await session.endSession({ error });
|
|
1083
|
+
}
|
|
1084
|
+
if (!session.inTransaction()) {
|
|
1085
|
+
maybeClearPinnedConnection(session, { error });
|
|
1086
|
+
}
|
|
1068
1087
|
}
|
|
1069
|
-
}
|
|
1088
|
+
};
|
|
1089
|
+
|
|
1090
|
+
await withEmitClose(close);
|
|
1070
1091
|
}
|
|
1071
1092
|
|
|
1072
1093
|
/** @internal */
|
|
@@ -1213,11 +1234,13 @@ configureResourceManagement(AbstractCursor.prototype);
|
|
|
1213
1234
|
* All timeout behavior is exactly the same as the wrapped timeout context's.
|
|
1214
1235
|
*/
|
|
1215
1236
|
export class CursorTimeoutContext extends TimeoutContext {
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
) {
|
|
1237
|
+
timeoutContext: TimeoutContext;
|
|
1238
|
+
owner: symbol | AbstractCursor;
|
|
1239
|
+
|
|
1240
|
+
constructor(timeoutContext: TimeoutContext, owner: symbol | AbstractCursor) {
|
|
1220
1241
|
super();
|
|
1242
|
+
this.timeoutContext = timeoutContext;
|
|
1243
|
+
this.owner = owner;
|
|
1221
1244
|
}
|
|
1222
1245
|
override get serverSelectionTimeout(): Timeout | null {
|
|
1223
1246
|
return this.timeoutContext.serverSelectionTimeout;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BSONSerializeOptions, Document } from '../bson';
|
|
2
2
|
import { CursorResponse } from '../cmap/wire_protocol/responses';
|
|
3
3
|
import type { Db } from '../db';
|
|
4
|
-
import { MongoAPIError } from '../error';
|
|
4
|
+
import { MongoAPIError, MongoRuntimeError } from '../error';
|
|
5
5
|
import { executeOperation } from '../operations/execute_operation';
|
|
6
6
|
import { GetMoreOperation } from '../operations/get_more';
|
|
7
7
|
import { RunCommandOperation } from '../operations/run_command';
|
|
@@ -161,6 +161,12 @@ export class RunCommandCursor extends AbstractCursor {
|
|
|
161
161
|
|
|
162
162
|
/** @internal */
|
|
163
163
|
override async getMore(_batchSize: number): Promise<CursorResponse> {
|
|
164
|
+
if (!this.session) {
|
|
165
|
+
throw new MongoRuntimeError(
|
|
166
|
+
'Unexpected null session. A cursor creating command should have set this'
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
164
170
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
165
171
|
const getMoreOperation = new GetMoreOperation(this.namespace, this.id!, this.server!, {
|
|
166
172
|
...this.cursorOptions,
|
package/src/index.ts
CHANGED
|
@@ -208,6 +208,7 @@ export type {
|
|
|
208
208
|
ChangeStreamDocumentCommon,
|
|
209
209
|
ChangeStreamDocumentKey,
|
|
210
210
|
ChangeStreamDocumentOperationDescription,
|
|
211
|
+
ChangeStreamDocumentWallTime,
|
|
211
212
|
ChangeStreamDropDatabaseDocument,
|
|
212
213
|
ChangeStreamDropDocument,
|
|
213
214
|
ChangeStreamDropIndexDocument,
|
|
@@ -287,6 +288,7 @@ export type { TokenCache } from './cmap/auth/mongodb_oidc/token_cache';
|
|
|
287
288
|
export type {
|
|
288
289
|
MessageHeader,
|
|
289
290
|
OpCompressedRequest,
|
|
291
|
+
OpCompressesRequestOptions,
|
|
290
292
|
OpMsgOptions,
|
|
291
293
|
OpMsgRequest,
|
|
292
294
|
OpMsgResponse,
|
package/src/mongo_client.ts
CHANGED
|
@@ -14,7 +14,11 @@ import { type TokenCache } from './cmap/auth/mongodb_oidc/token_cache';
|
|
|
14
14
|
import { AuthMechanism } from './cmap/auth/providers';
|
|
15
15
|
import type { LEGAL_TCP_SOCKET_OPTIONS, LEGAL_TLS_SOCKET_OPTIONS } from './cmap/connect';
|
|
16
16
|
import type { Connection } from './cmap/connection';
|
|
17
|
-
import
|
|
17
|
+
import {
|
|
18
|
+
addContainerMetadata,
|
|
19
|
+
type ClientMetadata,
|
|
20
|
+
makeClientMetadata
|
|
21
|
+
} from './cmap/handshake/client_metadata';
|
|
18
22
|
import type { CompressorName } from './cmap/wire_protocol/compression';
|
|
19
23
|
import { parseOptions, resolveSRVRecord } from './connection_string';
|
|
20
24
|
import { MONGO_CLIENT_EVENTS } from './constants';
|
|
@@ -184,7 +188,11 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
|
|
|
184
188
|
minPoolSize?: number;
|
|
185
189
|
/** The maximum number of connections that may be in the process of being established concurrently by the connection pool. */
|
|
186
190
|
maxConnecting?: number;
|
|
187
|
-
/**
|
|
191
|
+
/**
|
|
192
|
+
* The maximum amount of time a connection should remain idle in the connection pool before being marked idle, in milliseconds.
|
|
193
|
+
* If specified, this must be a number greater than or equal to 0, where 0 means there is no limit. Defaults to 0. After this
|
|
194
|
+
* time passes, the idle collection can be automatically cleaned up in the background.
|
|
195
|
+
*/
|
|
188
196
|
maxIdleTimeMS?: number;
|
|
189
197
|
/** The maximum time in milliseconds that a thread can wait for a connection to become available. */
|
|
190
198
|
waitQueueTimeoutMS?: number;
|
|
@@ -394,9 +402,31 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
|
|
|
394
402
|
* The consolidate, parsed, transformed and merged options.
|
|
395
403
|
*/
|
|
396
404
|
public readonly options: Readonly<
|
|
397
|
-
Omit<
|
|
405
|
+
Omit<
|
|
406
|
+
MongoOptions,
|
|
407
|
+
| 'monitorCommands'
|
|
408
|
+
| 'ca'
|
|
409
|
+
| 'crl'
|
|
410
|
+
| 'key'
|
|
411
|
+
| 'cert'
|
|
412
|
+
| 'driverInfo'
|
|
413
|
+
| 'additionalDriverInfo'
|
|
414
|
+
| 'metadata'
|
|
415
|
+
| 'extendedMetadata'
|
|
416
|
+
>
|
|
398
417
|
> &
|
|
399
|
-
Pick<
|
|
418
|
+
Pick<
|
|
419
|
+
MongoOptions,
|
|
420
|
+
| 'monitorCommands'
|
|
421
|
+
| 'ca'
|
|
422
|
+
| 'crl'
|
|
423
|
+
| 'key'
|
|
424
|
+
| 'cert'
|
|
425
|
+
| 'driverInfo'
|
|
426
|
+
| 'additionalDriverInfo'
|
|
427
|
+
| 'metadata'
|
|
428
|
+
| 'extendedMetadata'
|
|
429
|
+
>;
|
|
400
430
|
|
|
401
431
|
constructor(url: string, options?: MongoClientOptions) {
|
|
402
432
|
super();
|
|
@@ -455,6 +485,18 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
|
|
|
455
485
|
await this.close();
|
|
456
486
|
}
|
|
457
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Append metadata to the client metadata after instantiation.
|
|
490
|
+
* @param driverInfo - Information about the application or library.
|
|
491
|
+
*/
|
|
492
|
+
appendMetadata(driverInfo: DriverInfo) {
|
|
493
|
+
this.options.additionalDriverInfo.push(driverInfo);
|
|
494
|
+
this.options.metadata = makeClientMetadata(this.options);
|
|
495
|
+
this.options.extendedMetadata = addContainerMetadata(this.options.metadata)
|
|
496
|
+
.then(undefined, squashError)
|
|
497
|
+
.then(result => result ?? {}); // ensure Promise<Document>
|
|
498
|
+
}
|
|
499
|
+
|
|
458
500
|
/** @internal */
|
|
459
501
|
private checkForNonGenuineHosts() {
|
|
460
502
|
const documentDBHostnames = this.options.hosts.filter((hostAddress: HostAddress) =>
|
|
@@ -1035,9 +1077,10 @@ export interface MongoOptions
|
|
|
1035
1077
|
compressors: CompressorName[];
|
|
1036
1078
|
writeConcern: WriteConcern;
|
|
1037
1079
|
dbName: string;
|
|
1080
|
+
/** @deprecated - Will be made internal in a future major release. */
|
|
1038
1081
|
metadata: ClientMetadata;
|
|
1039
|
-
/** @internal */
|
|
1040
1082
|
extendedMetadata: Promise<Document>;
|
|
1083
|
+
additionalDriverInfo: DriverInfo[];
|
|
1041
1084
|
/** @internal */
|
|
1042
1085
|
autoEncrypter?: AutoEncrypter;
|
|
1043
1086
|
/** @internal */
|
package/src/mongo_types.ts
CHANGED
|
@@ -472,7 +472,10 @@ export class TypedEventEmitter<Events extends EventsDescription> extends EventEm
|
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
/**
|
|
475
|
+
/**
|
|
476
|
+
* @public
|
|
477
|
+
* @deprecated Will be removed in favor of `AbortSignal` in the next major release.
|
|
478
|
+
*/
|
|
476
479
|
export class CancellationToken extends TypedEventEmitter<{ cancel(): void }> {
|
|
477
480
|
constructor(...args: any[]) {
|
|
478
481
|
super(...args);
|
|
@@ -59,6 +59,10 @@ export interface CommandOperationOptions
|
|
|
59
59
|
// Admin command overrides.
|
|
60
60
|
dbName?: string;
|
|
61
61
|
authdb?: string;
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated
|
|
64
|
+
* This option is deprecated and will be removed in an upcoming major version.
|
|
65
|
+
*/
|
|
62
66
|
noResponse?: boolean;
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -96,6 +96,7 @@ export class DistinctOperation extends CommandOperation<any[]> {
|
|
|
96
96
|
|
|
97
97
|
const result = await super.executeCommand(server, session, cmd, timeoutContext);
|
|
98
98
|
|
|
99
|
+
// @ts-expect-error: Explain always returns a document
|
|
99
100
|
return this.explain ? result : result.values;
|
|
100
101
|
}
|
|
101
102
|
}
|
package/src/operations/rename.ts
CHANGED
|
@@ -17,12 +17,15 @@ export interface RenameOptions extends CommandOperationOptions {
|
|
|
17
17
|
|
|
18
18
|
/** @internal */
|
|
19
19
|
export class RenameOperation extends CommandOperation<Document> {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
) {
|
|
20
|
+
collection: Collection;
|
|
21
|
+
newName: string;
|
|
22
|
+
override options: RenameOptions;
|
|
23
|
+
|
|
24
|
+
constructor(collection: Collection, newName: string, options: RenameOptions) {
|
|
25
25
|
super(collection, options);
|
|
26
|
+
this.collection = collection;
|
|
27
|
+
this.newName = newName;
|
|
28
|
+
this.options = options;
|
|
26
29
|
this.ns = new MongoDBNamespace('admin', '$cmd');
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -26,12 +26,17 @@ export type RunCommandOptions = {
|
|
|
26
26
|
|
|
27
27
|
/** @internal */
|
|
28
28
|
export class RunCommandOperation<T = Document> extends AbstractOperation<T> {
|
|
29
|
+
command: Document;
|
|
30
|
+
override options: RunCommandOptions & { responseType?: MongoDBResponseConstructor };
|
|
31
|
+
|
|
29
32
|
constructor(
|
|
30
33
|
parent: Db,
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
command: Document,
|
|
35
|
+
options: RunCommandOptions & { responseType?: MongoDBResponseConstructor }
|
|
33
36
|
) {
|
|
34
37
|
super(options);
|
|
38
|
+
this.command = command;
|
|
39
|
+
this.options = options;
|
|
35
40
|
this.ns = parent.s.namespace.withCollection('$cmd');
|
|
36
41
|
}
|
|
37
42
|
|
|
@@ -62,14 +67,22 @@ export class RunCommandOperation<T = Document> extends AbstractOperation<T> {
|
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
export class RunAdminCommandOperation<T = Document> extends AbstractOperation<T> {
|
|
70
|
+
command: Document;
|
|
71
|
+
override options: RunCommandOptions & {
|
|
72
|
+
noResponse?: boolean;
|
|
73
|
+
bypassPinningCheck?: boolean;
|
|
74
|
+
};
|
|
75
|
+
|
|
65
76
|
constructor(
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
command: Document,
|
|
78
|
+
options: RunCommandOptions & {
|
|
68
79
|
noResponse?: boolean;
|
|
69
80
|
bypassPinningCheck?: boolean;
|
|
70
81
|
}
|
|
71
82
|
) {
|
|
72
83
|
super(options);
|
|
84
|
+
this.command = command;
|
|
85
|
+
this.options = options;
|
|
73
86
|
this.ns = new MongoDBNamespace('admin', '$cmd');
|
|
74
87
|
}
|
|
75
88
|
|