@depup/mongodb 7.5.0-depup.8 → 7.7.0-depup.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 +5 -6
- package/changes.json +6 -10
- package/lib/bulk/common.js +27 -5
- package/lib/bulk/common.js.map +1 -1
- package/lib/bulk/ordered.js +25 -7
- package/lib/bulk/ordered.js.map +1 -1
- package/lib/bulk/unordered.js +25 -7
- package/lib/bulk/unordered.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +8 -2
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js +12 -4
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/kms_options.js +3 -0
- package/lib/client-side-encryption/kms_options.js.map +1 -0
- package/lib/client-side-encryption/state_machine.js +54 -7
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/auth/gssapi.js +2 -1
- package/lib/cmap/auth/gssapi.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js +0 -1
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongodb_aws.js +0 -3
- package/lib/cmap/auth/mongodb_aws.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +7 -8
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
- package/lib/cmap/command_monitoring_events.js +6 -7
- package/lib/cmap/command_monitoring_events.js.map +1 -1
- package/lib/cmap/commands.js +13 -0
- package/lib/cmap/commands.js.map +1 -1
- package/lib/cmap/connect.js +2 -2
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +3 -1
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +2 -1
- package/lib/cmap/handshake/client_metadata.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +2 -2
- package/lib/connection_string.js +4 -0
- package/lib/connection_string.js.map +1 -1
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/error.js +7 -11
- package/lib/error.js.map +1 -1
- package/lib/gridfs/download.js +1 -1
- package/lib/gridfs/download.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/delete.js +7 -10
- package/lib/operations/delete.js.map +1 -1
- package/lib/operations/execute_operation.js +29 -2
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find_and_modify.js +1 -5
- package/lib/operations/find_and_modify.js.map +1 -1
- package/lib/operations/get_more.js +2 -3
- package/lib/operations/get_more.js.map +1 -1
- package/lib/operations/indexes.js +3 -9
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/insert.js +6 -2
- package/lib/operations/insert.js.map +1 -1
- package/lib/operations/list_collections.js +2 -3
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/operations/list_databases.js +2 -2
- package/lib/operations/list_databases.js.map +1 -1
- package/lib/operations/update.js +6 -2
- package/lib/operations/update.js.map +1 -1
- package/lib/runtime_adapters.js +15 -16
- package/lib/runtime_adapters.js.map +1 -1
- package/lib/sdam/server.js +1 -1
- package/lib/sdam/server.js.map +1 -1
- package/lib/sessions.js +2 -2
- package/lib/sessions.js.map +1 -1
- package/lib/utils.js +1 -3
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +77 -20
- package/package.json +30 -33
- package/src/bulk/common.ts +37 -5
- package/src/bulk/ordered.ts +23 -7
- package/src/bulk/unordered.ts +23 -8
- package/src/client-side-encryption/auto_encrypter.ts +19 -3
- package/src/client-side-encryption/client_encryption.ts +29 -9
- package/src/client-side-encryption/kms_options.ts +93 -0
- package/src/client-side-encryption/state_machine.ts +68 -47
- package/src/cmap/auth/gssapi.ts +3 -4
- package/src/cmap/auth/mongo_credentials.ts +0 -1
- package/src/cmap/auth/mongodb_aws.ts +2 -12
- package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +17 -17
- package/src/cmap/command_monitoring_events.ts +9 -10
- package/src/cmap/commands.ts +17 -0
- package/src/cmap/connect.ts +3 -3
- package/src/cmap/connection.ts +4 -2
- package/src/cmap/handshake/client_metadata.ts +2 -1
- package/src/cmap/wire_protocol/constants.ts +2 -2
- package/src/connection_string.ts +4 -0
- package/src/cursor/abstract_cursor.ts +0 -5
- package/src/error.ts +7 -19
- package/src/gridfs/download.ts +1 -1
- package/src/index.ts +7 -6
- package/src/mongo_client.ts +1 -1
- package/src/operations/command.ts +0 -5
- package/src/operations/delete.ts +17 -15
- package/src/operations/execute_operation.ts +29 -2
- package/src/operations/find_and_modify.ts +3 -15
- package/src/operations/get_more.ts +3 -5
- package/src/operations/indexes.ts +6 -16
- package/src/operations/insert.ts +13 -2
- package/src/operations/list_collections.ts +5 -6
- package/src/operations/list_databases.ts +3 -3
- package/src/operations/update.ts +9 -2
- package/src/operations/validate_collection.ts +1 -1
- package/src/runtime_adapters.ts +19 -18
- package/src/sdam/server.ts +1 -1
- package/src/sessions.ts +2 -5
- package/src/utils.ts +1 -3
- package/tsconfig.json +9 -2
package/src/error.ts
CHANGED
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
type ClientBulkWriteError,
|
|
4
4
|
type ClientBulkWriteResult
|
|
5
5
|
} from './operations/client_bulk_write/common';
|
|
6
|
-
import type { ServerType } from './sdam/common';
|
|
7
6
|
import type { TopologyVersion } from './sdam/server_description';
|
|
8
7
|
import type { TopologyDescription } from './sdam/topology_description';
|
|
9
8
|
|
|
@@ -1394,23 +1393,13 @@ const RETRYABLE_READ_ERROR_CODES = new Set<number>([
|
|
|
1394
1393
|
// see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.md#terms
|
|
1395
1394
|
const RETRYABLE_WRITE_ERROR_CODES = RETRYABLE_READ_ERROR_CODES;
|
|
1396
1395
|
|
|
1397
|
-
export function needsRetryableWriteLabel(
|
|
1398
|
-
error: Error,
|
|
1399
|
-
maxWireVersion: number,
|
|
1400
|
-
serverType: ServerType
|
|
1401
|
-
): boolean {
|
|
1402
|
-
// pre-4.4 server, then the driver adds an error label for every valid case
|
|
1403
|
-
// execute operation will only inspect the label, code/message logic is handled here
|
|
1396
|
+
export function needsRetryableWriteLabel(error: Error): boolean {
|
|
1404
1397
|
if (error instanceof MongoNetworkError) {
|
|
1405
1398
|
return true;
|
|
1406
1399
|
}
|
|
1407
|
-
|
|
1408
1400
|
if (error instanceof MongoError) {
|
|
1409
|
-
if (
|
|
1410
|
-
|
|
1411
|
-
!error.hasErrorLabel(MongoErrorLabel.HandshakeError)
|
|
1412
|
-
) {
|
|
1413
|
-
// If we already have the error label no need to add it again. 4.4+ servers add the label.
|
|
1401
|
+
if (!error.hasErrorLabel(MongoErrorLabel.HandshakeError)) {
|
|
1402
|
+
// If we already have the error label no need to add it again. servers add the label.
|
|
1414
1403
|
// In the case where we have a handshake error, need to fall down to the logic checking
|
|
1415
1404
|
// the codes.
|
|
1416
1405
|
return false;
|
|
@@ -1418,10 +1407,6 @@ export function needsRetryableWriteLabel(
|
|
|
1418
1407
|
}
|
|
1419
1408
|
|
|
1420
1409
|
if (error instanceof MongoWriteConcernError) {
|
|
1421
|
-
if (serverType === 'Mongos' && maxWireVersion < 9) {
|
|
1422
|
-
// use original top-level code from server response
|
|
1423
|
-
return RETRYABLE_WRITE_ERROR_CODES.has(error.result.code ?? 0);
|
|
1424
|
-
}
|
|
1425
1410
|
const code = error.result.writeConcernError.code ?? Number(error.code);
|
|
1426
1411
|
return RETRYABLE_WRITE_ERROR_CODES.has(Number.isNaN(code) ? 0 : code);
|
|
1427
1412
|
}
|
|
@@ -1551,8 +1536,11 @@ export function isResumableError(error?: Error, wireVersion?: number): boolean {
|
|
|
1551
1536
|
return true;
|
|
1552
1537
|
}
|
|
1553
1538
|
|
|
1539
|
+
// wireVersion of 0 is possible when the server version is unknown (e.g heartbeat failure), so despite
|
|
1540
|
+
// all supported servers being wire version 9+, the >= 9 bound must stay to route "unknown" to the
|
|
1541
|
+
// code-list fallback below to maintain parity.
|
|
1554
1542
|
if (wireVersion != null && wireVersion >= 9) {
|
|
1555
|
-
// DRIVERS-1308:
|
|
1543
|
+
// DRIVERS-1308: Drivers will add a special case to treat the CursorNotFound error code as resumable
|
|
1556
1544
|
if (error.code === MONGODB_ERROR_CODES.CursorNotFound) {
|
|
1557
1545
|
return true;
|
|
1558
1546
|
}
|
package/src/gridfs/download.ts
CHANGED
|
@@ -351,7 +351,7 @@ function init(stream: GridFSBucketReadStream): void {
|
|
|
351
351
|
|
|
352
352
|
const filter: Document = { files_id: doc._id };
|
|
353
353
|
|
|
354
|
-
// Currently
|
|
354
|
+
// Currently the skip function does not support the index,
|
|
355
355
|
// it needs to retrieve all the documents first and then skip them. (CS-25811)
|
|
356
356
|
// As work around we use $gte on the "n" field.
|
|
357
357
|
if (stream.s.options && stream.s.options.start != null) {
|
package/src/index.ts
CHANGED
|
@@ -252,6 +252,12 @@ export {
|
|
|
252
252
|
MongoCryptInvalidArgumentError,
|
|
253
253
|
MongoCryptKMSRequestNetworkTimeoutError
|
|
254
254
|
} from './client-side-encryption/errors';
|
|
255
|
+
export type {
|
|
256
|
+
ClientEncryptionSocketOptions,
|
|
257
|
+
ClientEncryptionTlsOptions,
|
|
258
|
+
CSFLEKMSTlsOptions,
|
|
259
|
+
KMSConnectCallback
|
|
260
|
+
} from './client-side-encryption/kms_options';
|
|
255
261
|
export type { MongocryptdManager } from './client-side-encryption/mongocryptd_manager';
|
|
256
262
|
export type {
|
|
257
263
|
AWSKMSProviderConfiguration,
|
|
@@ -263,12 +269,7 @@ export type {
|
|
|
263
269
|
KMSProviders,
|
|
264
270
|
LocalKMSProviderConfiguration
|
|
265
271
|
} from './client-side-encryption/providers/index';
|
|
266
|
-
export type {
|
|
267
|
-
ClientEncryptionSocketOptions,
|
|
268
|
-
ClientEncryptionTlsOptions,
|
|
269
|
-
CSFLEKMSTlsOptions,
|
|
270
|
-
StateMachineExecutable
|
|
271
|
-
} from './client-side-encryption/state_machine';
|
|
272
|
+
export type { StateMachineExecutable } from './client-side-encryption/state_machine';
|
|
272
273
|
export type { AuthContext, AuthProvider } from './cmap/auth/auth_provider';
|
|
273
274
|
export type {
|
|
274
275
|
AuthMechanismProperties,
|
package/src/mongo_client.ts
CHANGED
|
@@ -46,11 +46,6 @@ export interface CommandOperationOptions
|
|
|
46
46
|
maxTimeMS?: number;
|
|
47
47
|
/**
|
|
48
48
|
* Comment to apply to the operation.
|
|
49
|
-
*
|
|
50
|
-
* In server versions pre-4.4, 'comment' must be string. A server
|
|
51
|
-
* error will be thrown if any other type is provided.
|
|
52
|
-
*
|
|
53
|
-
* In server versions 4.4 and above, 'comment' can be any valid BSON type.
|
|
54
49
|
*/
|
|
55
50
|
comment?: unknown;
|
|
56
51
|
// Admin command overrides.
|
package/src/operations/delete.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Document } from '../bson';
|
|
2
|
+
import { makeDocumentSequence } from '../cmap/commands';
|
|
2
3
|
import { type Connection } from '../cmap/connection';
|
|
3
4
|
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
4
|
-
import {
|
|
5
|
+
import { MongoServerError } from '../error';
|
|
5
6
|
import type { ClientSession } from '../sessions';
|
|
6
|
-
import {
|
|
7
|
+
import { type MongoDBCollectionNamespace, type MongoDBNamespace } from '../utils';
|
|
7
8
|
import { type WriteConcernOptions } from '../write_concern';
|
|
8
9
|
import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
|
|
9
10
|
import { Aspect, defineAspects, type Hint } from './operation';
|
|
@@ -45,12 +46,20 @@ export class DeleteOperation extends CommandOperation<Document> {
|
|
|
45
46
|
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
46
47
|
override options: DeleteOptions;
|
|
47
48
|
statements: DeleteStatement[];
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
/** @internal */
|
|
50
|
+
serializedOperations?: Uint8Array[];
|
|
51
|
+
|
|
52
|
+
constructor(
|
|
53
|
+
ns: MongoDBNamespace,
|
|
54
|
+
statements: DeleteStatement[],
|
|
55
|
+
options: DeleteOptions,
|
|
56
|
+
serializedOperations?: Uint8Array[]
|
|
57
|
+
) {
|
|
50
58
|
super(undefined, options);
|
|
51
59
|
this.options = options;
|
|
52
60
|
this.ns = ns;
|
|
53
61
|
this.statements = statements;
|
|
62
|
+
this.serializedOperations = serializedOperations;
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
override get commandName() {
|
|
@@ -65,13 +74,15 @@ export class DeleteOperation extends CommandOperation<Document> {
|
|
|
65
74
|
return this.statements.every(op => (op.limit != null ? op.limit > 0 : true));
|
|
66
75
|
}
|
|
67
76
|
|
|
68
|
-
override buildCommandDocument(
|
|
77
|
+
override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
|
|
69
78
|
const options = this.options;
|
|
70
79
|
|
|
71
80
|
const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
|
|
72
81
|
const command: Document = {
|
|
73
82
|
delete: this.ns.collection,
|
|
74
|
-
deletes: this.
|
|
83
|
+
deletes: this.serializedOperations
|
|
84
|
+
? makeDocumentSequence('deletes', this.statements, this.serializedOperations)
|
|
85
|
+
: this.statements,
|
|
75
86
|
ordered
|
|
76
87
|
};
|
|
77
88
|
|
|
@@ -85,15 +96,6 @@ export class DeleteOperation extends CommandOperation<Document> {
|
|
|
85
96
|
command.comment = options.comment;
|
|
86
97
|
}
|
|
87
98
|
|
|
88
|
-
const unacknowledgedWrite = this.writeConcern && this.writeConcern.w === 0;
|
|
89
|
-
if (unacknowledgedWrite && maxWireVersion(connection) < 9) {
|
|
90
|
-
if (this.statements.find((o: Document) => o.hint)) {
|
|
91
|
-
throw new MongoCompatibilityError(
|
|
92
|
-
`hint for the delete command is only supported on MongoDB 4.4+`
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
99
|
return command;
|
|
98
100
|
}
|
|
99
101
|
}
|
|
@@ -170,10 +170,33 @@ type RetryOptions = {
|
|
|
170
170
|
timeoutContext: TimeoutContext;
|
|
171
171
|
};
|
|
172
172
|
/** @internal The base backoff duration in milliseconds */
|
|
173
|
-
const BASE_BACKOFF_MS = 100;
|
|
173
|
+
export const BASE_BACKOFF_MS = 100;
|
|
174
174
|
/** @internal The maximum backoff duration in milliseconds */
|
|
175
175
|
const MAX_BACKOFF_MS = 10_000;
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* @internal
|
|
179
|
+
* The server-supplied base backoff duration in milliseconds, if the error carries a usable one.
|
|
180
|
+
*
|
|
181
|
+
* The server may attach `baseBackoffMS` to an overload error to indicate how long clients should
|
|
182
|
+
* back off in place of the driver's default. Only a positive value is honoured: the server disables
|
|
183
|
+
* the behaviour by reporting `0`, in which case we fall back to `BASE_BACKOFF_MS`.
|
|
184
|
+
*/
|
|
185
|
+
export function calculateBaseBackoffMS(error: MongoError): number {
|
|
186
|
+
if (!(error instanceof MongoServerError)) return BASE_BACKOFF_MS;
|
|
187
|
+
|
|
188
|
+
// The server sends baseBackoffMS as an int64, so its runtime type depends on the client's BSON
|
|
189
|
+
// options: a number by default, a Long under `promoteLongs: false`, a bigint under
|
|
190
|
+
// `useBigInt64: true`. `Number()` handles all three, so coerce rather than check for `number`.
|
|
191
|
+
// `errorResponse` is indexed as `any`; narrow to `unknown` so the checks below are real.
|
|
192
|
+
const raw: unknown = error.errorResponse.baseBackoffMS;
|
|
193
|
+
const isNumeric = typeof raw === 'number' || typeof raw === 'bigint' || typeof raw === 'object';
|
|
194
|
+
const baseBackoffMS = isNumeric ? Number(raw) : NaN;
|
|
195
|
+
const useServerValue = Number.isFinite(baseBackoffMS) && baseBackoffMS > 0;
|
|
196
|
+
const result = useServerValue ? baseBackoffMS : BASE_BACKOFF_MS;
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
|
|
177
200
|
/**
|
|
178
201
|
* Executes an operation and retries as appropriate
|
|
179
202
|
* @internal
|
|
@@ -327,7 +350,11 @@ async function executeOperationWithRetries<
|
|
|
327
350
|
}
|
|
328
351
|
|
|
329
352
|
if (operationError.hasErrorLabel(MongoErrorLabel.SystemOverloadedError)) {
|
|
330
|
-
const
|
|
353
|
+
const baseBackoffMS = calculateBaseBackoffMS(operationError);
|
|
354
|
+
// The spec numbers the first retry as attempt 1, while `attempt` here is the zero-based
|
|
355
|
+
// index of the attempt that just failed -- hence the `+ 1`.
|
|
356
|
+
const backoffMS =
|
|
357
|
+
Math.random() * Math.min(MAX_BACKOFF_MS, baseBackoffMS * 2 ** (attempt + 1));
|
|
331
358
|
|
|
332
359
|
// if the backoff would exhaust the CSOT timeout, short-circuit.
|
|
333
360
|
if (timeoutContext.csotEnabled() && backoffMS > timeoutContext.remainingTimeMS) {
|
|
@@ -2,11 +2,11 @@ import { type Connection } from '..';
|
|
|
2
2
|
import type { Document } from '../bson';
|
|
3
3
|
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
4
4
|
import type { Collection } from '../collection';
|
|
5
|
-
import {
|
|
5
|
+
import { MongoInvalidArgumentError } from '../error';
|
|
6
6
|
import { ReadPreference } from '../read_preference';
|
|
7
7
|
import type { ClientSession } from '../sessions';
|
|
8
8
|
import { formatSort, type Sort, type SortForCmd } from '../sort';
|
|
9
|
-
import { decorateWithCollation, hasAtomicOperators
|
|
9
|
+
import { decorateWithCollation, hasAtomicOperators } from '../utils';
|
|
10
10
|
import { type WriteConcern, type WriteConcernSettings } from '../write_concern';
|
|
11
11
|
import { CommandOperation, type CommandOperationOptions } from './command';
|
|
12
12
|
import { Aspect, defineAspects } from './operation';
|
|
@@ -97,11 +97,6 @@ interface FindAndModifyCmdBase {
|
|
|
97
97
|
writeConcern?: WriteConcern | WriteConcernSettings;
|
|
98
98
|
/**
|
|
99
99
|
* Comment to apply to the operation.
|
|
100
|
-
*
|
|
101
|
-
* In server versions pre-4.4, 'comment' must be string. A server
|
|
102
|
-
* error will be thrown if any other type is provided.
|
|
103
|
-
*
|
|
104
|
-
* In server versions 4.4 and above, 'comment' can be any valid BSON type.
|
|
105
100
|
*/
|
|
106
101
|
comment?: unknown;
|
|
107
102
|
}
|
|
@@ -146,7 +141,7 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
|
|
|
146
141
|
}
|
|
147
142
|
|
|
148
143
|
override buildCommandDocument(
|
|
149
|
-
|
|
144
|
+
_connection: Connection,
|
|
150
145
|
_session?: ClientSession
|
|
151
146
|
): Document & FindAndModifyCmdBase {
|
|
152
147
|
const options = this.options;
|
|
@@ -191,13 +186,6 @@ export class FindAndModifyOperation extends CommandOperation<Document> {
|
|
|
191
186
|
decorateWithCollation(command, options);
|
|
192
187
|
|
|
193
188
|
if (options.hint) {
|
|
194
|
-
const unacknowledgedWrite = this.writeConcern?.w === 0;
|
|
195
|
-
if (unacknowledgedWrite && maxWireVersion(connection) < 9) {
|
|
196
|
-
throw new MongoCompatibilityError(
|
|
197
|
-
'hint for the findAndModify command is only supported on MongoDB 4.4+'
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
189
|
command.hint = options.hint;
|
|
202
190
|
}
|
|
203
191
|
|
|
@@ -4,7 +4,7 @@ import { CursorResponse } from '../cmap/wire_protocol/responses';
|
|
|
4
4
|
import { MongoRuntimeError } from '../error';
|
|
5
5
|
import type { Server, ServerCommandOptions } from '../sdam/server';
|
|
6
6
|
import { type TimeoutContext } from '../timeout';
|
|
7
|
-
import {
|
|
7
|
+
import { type MongoDBNamespace } from '../utils';
|
|
8
8
|
import { AbstractOperation, Aspect, defineAspects, type OperationOptions } from './operation';
|
|
9
9
|
|
|
10
10
|
/** @internal */
|
|
@@ -13,8 +13,6 @@ export interface GetMoreOptions extends OperationOptions {
|
|
|
13
13
|
batchSize?: number;
|
|
14
14
|
/**
|
|
15
15
|
* Comment to apply to the operation.
|
|
16
|
-
*
|
|
17
|
-
* getMore only supports 'comment' in server versions 4.4 and above.
|
|
18
16
|
*/
|
|
19
17
|
comment?: unknown;
|
|
20
18
|
/** Number of milliseconds to wait before aborting the query. */
|
|
@@ -55,7 +53,7 @@ export class GetMoreOperation extends AbstractOperation<CursorResponse> {
|
|
|
55
53
|
return 'getMore' as const;
|
|
56
54
|
}
|
|
57
55
|
|
|
58
|
-
override buildCommand(
|
|
56
|
+
override buildCommand(_connection: Connection): Document {
|
|
59
57
|
if (this.cursorId == null || this.cursorId.isZero()) {
|
|
60
58
|
throw new MongoRuntimeError('Unable to iterate cursor with no id');
|
|
61
59
|
}
|
|
@@ -82,7 +80,7 @@ export class GetMoreOperation extends AbstractOperation<CursorResponse> {
|
|
|
82
80
|
|
|
83
81
|
// we check for undefined specifically here to allow falsy values
|
|
84
82
|
// eslint-disable-next-line no-restricted-syntax
|
|
85
|
-
if (this.options.comment !== undefined
|
|
83
|
+
if (this.options.comment !== undefined) {
|
|
86
84
|
getMoreCmd.comment = this.options.comment;
|
|
87
85
|
}
|
|
88
86
|
|
|
@@ -3,9 +3,8 @@ import { type Connection } from '../cmap/connection';
|
|
|
3
3
|
import { CursorResponse, MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
4
4
|
import type { Collection } from '../collection';
|
|
5
5
|
import { type AbstractCursorOptions } from '../cursor/abstract_cursor';
|
|
6
|
-
import { MongoCompatibilityError } from '../error';
|
|
7
6
|
import { type OneOrMore } from '../mongo_types';
|
|
8
|
-
import { isObject,
|
|
7
|
+
import { isObject, type MongoDBNamespace } from '../utils';
|
|
9
8
|
import {
|
|
10
9
|
type CollationOptions,
|
|
11
10
|
CommandOperation,
|
|
@@ -138,7 +137,7 @@ export interface CreateIndexesOptions extends Omit<CommandOperationOptions, 'wri
|
|
|
138
137
|
expireAfterSeconds?: number;
|
|
139
138
|
/** Allows users to configure the storage engine on a per-index basis when creating an index. (MongoDB 3.0 or higher) */
|
|
140
139
|
storageEngine?: Document;
|
|
141
|
-
/**
|
|
140
|
+
/** Specifies how many data-bearing members of a replica set, including the primary, must complete the index builds successfully before the primary marks the indexes as ready. This option accepts the same values for the "w" field in a write concern plus "votingMembers", which indicates all voting data-bearing nodes. */
|
|
142
141
|
commitQuorum?: number | string;
|
|
143
142
|
/** Specifies the index version number, either 0 or 1. */
|
|
144
143
|
version?: number;
|
|
@@ -159,7 +158,7 @@ export interface CreateIndexesOptions extends Omit<CommandOperationOptions, 'wri
|
|
|
159
158
|
bucketSize?: number;
|
|
160
159
|
// wildcard indexes
|
|
161
160
|
wildcardProjection?: Document;
|
|
162
|
-
/** Specifies that the index should exist on the target collection but should not be used by the query planner when executing operations.
|
|
161
|
+
/** Specifies that the index should exist on the target collection but should not be used by the query planner when executing operations. */
|
|
163
162
|
hidden?: boolean;
|
|
164
163
|
}
|
|
165
164
|
|
|
@@ -299,20 +298,13 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
|
|
|
299
298
|
return 'createIndexes';
|
|
300
299
|
}
|
|
301
300
|
|
|
302
|
-
override buildCommandDocument(
|
|
301
|
+
override buildCommandDocument(_connection: Connection): Document {
|
|
303
302
|
const options = this.options;
|
|
304
303
|
const indexes = this.indexes;
|
|
305
304
|
|
|
306
|
-
const serverWireVersion = maxWireVersion(connection);
|
|
307
|
-
|
|
308
305
|
const cmd: Document = { createIndexes: this.collectionName, indexes };
|
|
309
306
|
|
|
310
307
|
if (options.commitQuorum != null) {
|
|
311
|
-
if (serverWireVersion < 9) {
|
|
312
|
-
throw new MongoCompatibilityError(
|
|
313
|
-
'Option `commitQuorum` for `createIndexes` not supported on servers < 4.4'
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
308
|
cmd.commitQuorum = options.commitQuorum;
|
|
317
309
|
}
|
|
318
310
|
return cmd;
|
|
@@ -385,16 +377,14 @@ export class ListIndexesOperation extends CommandOperation<CursorResponse> {
|
|
|
385
377
|
return 'listIndexes' as const;
|
|
386
378
|
}
|
|
387
379
|
|
|
388
|
-
override buildCommandDocument(
|
|
389
|
-
const serverWireVersion = maxWireVersion(connection);
|
|
390
|
-
|
|
380
|
+
override buildCommandDocument(_connection: Connection): Document {
|
|
391
381
|
const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {};
|
|
392
382
|
|
|
393
383
|
const command: Document = { listIndexes: this.collectionNamespace.collection, cursor };
|
|
394
384
|
|
|
395
385
|
// we check for undefined specifically here to allow falsy values
|
|
396
386
|
// eslint-disable-next-line no-restricted-syntax
|
|
397
|
-
if (
|
|
387
|
+
if (this.options.comment !== undefined) {
|
|
398
388
|
command.comment = this.options.comment;
|
|
399
389
|
}
|
|
400
390
|
|
package/src/operations/insert.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Connection } from '..';
|
|
2
2
|
import type { Document } from '../bson';
|
|
3
3
|
import type { BulkWriteOptions } from '../bulk/common';
|
|
4
|
+
import { makeDocumentSequence } from '../cmap/commands';
|
|
4
5
|
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
5
6
|
import type { Collection } from '../collection';
|
|
6
7
|
import { MongoServerError } from '../error';
|
|
@@ -15,12 +16,20 @@ export class InsertOperation extends CommandOperation<Document> {
|
|
|
15
16
|
override options: BulkWriteOptions;
|
|
16
17
|
|
|
17
18
|
documents: Document[];
|
|
19
|
+
/** @internal Per-operation pre-serialized BSON, reused to build a DocumentSequence. */
|
|
20
|
+
serializedOperations?: Uint8Array[];
|
|
18
21
|
|
|
19
|
-
constructor(
|
|
22
|
+
constructor(
|
|
23
|
+
ns: MongoDBNamespace,
|
|
24
|
+
documents: Document[],
|
|
25
|
+
options: BulkWriteOptions,
|
|
26
|
+
serializedOperations?: Uint8Array[]
|
|
27
|
+
) {
|
|
20
28
|
super(undefined, options);
|
|
21
29
|
this.options = { ...options, checkKeys: options.checkKeys ?? false };
|
|
22
30
|
this.ns = ns;
|
|
23
31
|
this.documents = documents;
|
|
32
|
+
this.serializedOperations = serializedOperations;
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
override get commandName() {
|
|
@@ -32,7 +41,9 @@ export class InsertOperation extends CommandOperation<Document> {
|
|
|
32
41
|
const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
|
|
33
42
|
const command: Document = {
|
|
34
43
|
insert: this.ns.collection,
|
|
35
|
-
documents: this.
|
|
44
|
+
documents: this.serializedOperations
|
|
45
|
+
? makeDocumentSequence('documents', this.documents, this.serializedOperations)
|
|
46
|
+
: this.documents,
|
|
36
47
|
ordered
|
|
37
48
|
};
|
|
38
49
|
|
|
@@ -4,7 +4,6 @@ import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/r
|
|
|
4
4
|
import { type CursorTimeoutContext, type CursorTimeoutMode } from '../cursor/abstract_cursor';
|
|
5
5
|
import type { Db } from '../db';
|
|
6
6
|
import { type Abortable } from '../mongo_types';
|
|
7
|
-
import { maxWireVersion } from '../utils';
|
|
8
7
|
import { CommandOperation, type CommandOperationOptions } from './command';
|
|
9
8
|
import { Aspect, defineAspects } from './operation';
|
|
10
9
|
|
|
@@ -12,11 +11,11 @@ import { Aspect, defineAspects } from './operation';
|
|
|
12
11
|
export interface ListCollectionsOptions
|
|
13
12
|
extends Omit<CommandOperationOptions, 'writeConcern'>,
|
|
14
13
|
Abortable {
|
|
15
|
-
/**
|
|
14
|
+
/** If true, will only return the collection name in the response, and will omit additional info */
|
|
16
15
|
nameOnly?: boolean;
|
|
17
|
-
/**
|
|
16
|
+
/** If true and nameOnly is true, allows a user without the required privilege (i.e. listCollections action on the database) to run the command when access control is enforced. */
|
|
18
17
|
authorizedCollections?: boolean;
|
|
19
|
-
/** The batchSize for the returned command cursor
|
|
18
|
+
/** The batchSize for the returned command cursor */
|
|
20
19
|
batchSize?: number;
|
|
21
20
|
/** @internal */
|
|
22
21
|
timeoutMode?: CursorTimeoutMode;
|
|
@@ -63,7 +62,7 @@ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
|
|
|
63
62
|
return 'listCollections' as const;
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
override buildCommandDocument(
|
|
65
|
+
override buildCommandDocument(_connection: Connection): Document {
|
|
67
66
|
const command: Document = {
|
|
68
67
|
listCollections: 1,
|
|
69
68
|
filter: this.filter,
|
|
@@ -74,7 +73,7 @@ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
|
|
|
74
73
|
|
|
75
74
|
// we check for undefined specifically here to allow falsy values
|
|
76
75
|
// eslint-disable-next-line no-restricted-syntax
|
|
77
|
-
if (
|
|
76
|
+
if (this.options.comment !== undefined) {
|
|
78
77
|
command.comment = this.options.comment;
|
|
79
78
|
}
|
|
80
79
|
|
|
@@ -3,7 +3,7 @@ import type { Document } from '../bson';
|
|
|
3
3
|
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
4
4
|
import type { Db } from '../db';
|
|
5
5
|
import type { ClientSession } from '../sessions';
|
|
6
|
-
import {
|
|
6
|
+
import { MongoDBNamespace } from '../utils';
|
|
7
7
|
import { CommandOperation, type CommandOperationOptions } from './command';
|
|
8
8
|
import { Aspect, defineAspects } from './operation';
|
|
9
9
|
|
|
@@ -40,7 +40,7 @@ export class ListDatabasesOperation extends CommandOperation<ListDatabasesResult
|
|
|
40
40
|
return 'listDatabases' as const;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
override buildCommandDocument(
|
|
43
|
+
override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
|
|
44
44
|
const cmd: Document = { listDatabases: 1 };
|
|
45
45
|
|
|
46
46
|
if (typeof this.options.nameOnly === 'boolean') {
|
|
@@ -57,7 +57,7 @@ export class ListDatabasesOperation extends CommandOperation<ListDatabasesResult
|
|
|
57
57
|
|
|
58
58
|
// we check for undefined specifically here to allow falsy values
|
|
59
59
|
// eslint-disable-next-line no-restricted-syntax
|
|
60
|
-
if (
|
|
60
|
+
if (this.options.comment !== undefined) {
|
|
61
61
|
cmd.comment = this.options.comment;
|
|
62
62
|
}
|
|
63
63
|
|
package/src/operations/update.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Document } from '../bson';
|
|
2
|
+
import { makeDocumentSequence } from '../cmap/commands';
|
|
2
3
|
import { type Connection } from '../cmap/connection';
|
|
3
4
|
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
4
5
|
import { MongoInvalidArgumentError, MongoServerError } from '../error';
|
|
@@ -74,17 +75,21 @@ export class UpdateOperation extends CommandOperation<Document> {
|
|
|
74
75
|
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
75
76
|
override options: UpdateOptions & { ordered?: boolean };
|
|
76
77
|
statements: UpdateStatement[];
|
|
78
|
+
/** @internal */
|
|
79
|
+
serializedOperations?: Uint8Array[];
|
|
77
80
|
|
|
78
81
|
constructor(
|
|
79
82
|
ns: MongoDBNamespace,
|
|
80
83
|
statements: UpdateStatement[],
|
|
81
|
-
options: UpdateOptions & { ordered?: boolean }
|
|
84
|
+
options: UpdateOptions & { ordered?: boolean },
|
|
85
|
+
serializedOperations?: Uint8Array[]
|
|
82
86
|
) {
|
|
83
87
|
super(undefined, options);
|
|
84
88
|
this.options = options;
|
|
85
89
|
this.ns = ns;
|
|
86
90
|
|
|
87
91
|
this.statements = statements;
|
|
92
|
+
this.serializedOperations = serializedOperations;
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
override get commandName() {
|
|
@@ -103,7 +108,9 @@ export class UpdateOperation extends CommandOperation<Document> {
|
|
|
103
108
|
const options = this.options;
|
|
104
109
|
const command: Document = {
|
|
105
110
|
update: this.ns.collection,
|
|
106
|
-
updates: this.
|
|
111
|
+
updates: this.serializedOperations
|
|
112
|
+
? makeDocumentSequence('updates', this.statements, this.serializedOperations)
|
|
113
|
+
: this.statements,
|
|
107
114
|
ordered: options.ordered ?? true
|
|
108
115
|
};
|
|
109
116
|
|
|
@@ -8,7 +8,7 @@ import { CommandOperation, type CommandOperationOptions } from './command';
|
|
|
8
8
|
|
|
9
9
|
/** @public */
|
|
10
10
|
export interface ValidateCollectionOptions extends Omit<CommandOperationOptions, 'rawData'> {
|
|
11
|
-
/** Validates a collection in the background, without interrupting read or write traffic
|
|
11
|
+
/** Validates a collection in the background, without interrupting read or write traffic */
|
|
12
12
|
background?: boolean;
|
|
13
13
|
}
|
|
14
14
|
|
package/src/runtime_adapters.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-restricted-imports*/
|
|
2
2
|
|
|
3
|
-
// We squash the restricted import errors here
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// We squash the restricted import errors here: the module-scope imports are type-only, and the
|
|
4
|
+
// one runtime dependency this file takes — the dynamic `import('os')` fallback in
|
|
5
|
+
// resolveRuntimeAdapters — is deliberate: this file is expected to be the only place that loads
|
|
6
|
+
// restricted Node APIs at runtime.
|
|
6
7
|
|
|
7
8
|
import type * as os from 'os';
|
|
8
9
|
|
|
@@ -11,8 +12,9 @@ import { type MongoClientOptions } from './mongo_client';
|
|
|
11
12
|
/**
|
|
12
13
|
* @internal
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
15
|
+
* Legacy escape hatch for the test sandbox's restricted `require`: the driver no longer sets this
|
|
16
|
+
* property (the os adapter loads via dynamic `import()`), but the vm test harness
|
|
17
|
+
* still checks it. Kept until the sandbox contract is revisited in a follow-up.
|
|
16
18
|
*/
|
|
17
19
|
export const ALLOWED_DRIVER_REQUIRE_PROPERTY_NAME = 'allowedDriverRequire';
|
|
18
20
|
|
|
@@ -47,18 +49,17 @@ export interface Runtime {
|
|
|
47
49
|
/**
|
|
48
50
|
* @internal
|
|
49
51
|
*
|
|
50
|
-
* Given a MongoClientOptions, this function resolves the set of runtime options, providing Nodejs
|
|
51
|
-
* not provided
|
|
52
|
+
* Given a MongoClientOptions, this function resolves the set of runtime options, providing Nodejs
|
|
53
|
+
* implementations if not provided in `options`, and returns a `Runtime`.
|
|
54
|
+
*
|
|
55
|
+
* Resolution is asynchronous because the default `os` adapter is loaded via a dynamic `import()`.
|
|
56
|
+
* Unlike `require`, dynamic import exists in every module system the driver ships into or is
|
|
57
|
+
* bundled into (CJS, ESM, and bundled ESM output), and the literal specifier keeps it
|
|
58
|
+
* statically analyzable for bundlers. The promise is created during synchronous
|
|
59
|
+
* options parsing and awaited later by consumers, so the public constructor stays synchronous.
|
|
52
60
|
*/
|
|
53
|
-
export function resolveRuntimeAdapters(options: MongoClientOptions): Runtime {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
58
|
-
os: options.runtimeAdapters?.os ?? require('os')
|
|
59
|
-
};
|
|
60
|
-
return runtime;
|
|
61
|
-
} finally {
|
|
62
|
-
(globalThis as any)[ALLOWED_DRIVER_REQUIRE_PROPERTY_NAME] = false;
|
|
63
|
-
}
|
|
61
|
+
export async function resolveRuntimeAdapters(options: MongoClientOptions): Promise<Runtime> {
|
|
62
|
+
return {
|
|
63
|
+
os: options.runtimeAdapters?.os ?? (await import('os'))
|
|
64
|
+
};
|
|
64
65
|
}
|
package/src/sdam/server.ts
CHANGED
|
@@ -494,7 +494,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
494
494
|
} else {
|
|
495
495
|
if (
|
|
496
496
|
(isRetryableWritesEnabled(this.topology) || isTransactionCommand(cmd)) &&
|
|
497
|
-
needsRetryableWriteLabel(error
|
|
497
|
+
needsRetryableWriteLabel(error) &&
|
|
498
498
|
!inActiveTransaction(session, cmd)
|
|
499
499
|
) {
|
|
500
500
|
error.addErrorLabel(MongoErrorLabel.RetryableWriteError);
|
package/src/sessions.ts
CHANGED
|
@@ -771,7 +771,7 @@ export class ClientSession
|
|
|
771
771
|
) {
|
|
772
772
|
// 2. If `transactionAttempt` > 0:
|
|
773
773
|
if (isRetry) {
|
|
774
|
-
// 2.1 Calculate backoffMS to be jitter * min(BACKOFF_INITIAL * 1.5 ** (transactionAttempt
|
|
774
|
+
// 2.1 Calculate backoffMS to be jitter * min(BACKOFF_INITIAL * 1.5 ** (transactionAttempt), BACKOFF_MAX).
|
|
775
775
|
// If elapsed time + backoffMS > TIMEOUT_MS, then propagate the previously encountered error to the caller of
|
|
776
776
|
// withTransaction as per timeout error propagation and return immediately. Otherwise, sleep for backoffMS.
|
|
777
777
|
// 2.1.1 jitter is a random float between [0, 1), optionally including 1, depending on what is most natural
|
|
@@ -785,10 +785,7 @@ export class ClientSession
|
|
|
785
785
|
const jitter = Math.random();
|
|
786
786
|
const backoffMS =
|
|
787
787
|
jitter *
|
|
788
|
-
Math.min(
|
|
789
|
-
BACKOFF_INITIAL_MS * BACKOFF_GROWTH ** (transactionAttempt - 1),
|
|
790
|
-
BACKOFF_MAX_MS
|
|
791
|
-
);
|
|
788
|
+
Math.min(BACKOFF_INITIAL_MS * BACKOFF_GROWTH ** transactionAttempt, BACKOFF_MAX_MS);
|
|
792
789
|
|
|
793
790
|
if (processTimeMS() + backoffMS >= deadline) {
|
|
794
791
|
throw makeTimeoutError(
|
package/src/utils.ts
CHANGED
|
@@ -343,9 +343,7 @@ export function maxWireVersion(handshakeAware?: Connection | Topology | Server):
|
|
|
343
343
|
// object being checked will be a connection, and we will have a hello response on
|
|
344
344
|
// it. For other cases, such as retryable writes, the object will be a server or
|
|
345
345
|
// topology, and there will be no hello response on those objects, so we return
|
|
346
|
-
// the max wire version so we support retryability.
|
|
347
|
-
// wire version of 9, then the needsRetryableWriteLabel() check can remove the
|
|
348
|
-
// usage of passing the wire version into it.
|
|
346
|
+
// the max wire version so we support retryability.
|
|
349
347
|
if (handshakeAware.loadBalanced) {
|
|
350
348
|
return MAX_SUPPORTED_WIRE_VERSION;
|
|
351
349
|
}
|