mongodb 4.4.1 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +3 -2
  2. package/lib/admin.js +5 -6
  3. package/lib/admin.js.map +1 -1
  4. package/lib/bulk/common.js +34 -7
  5. package/lib/bulk/common.js.map +1 -1
  6. package/lib/bulk/unordered.js.map +1 -1
  7. package/lib/change_stream.js +251 -245
  8. package/lib/change_stream.js.map +1 -1
  9. package/lib/cmap/auth/gssapi.js.map +1 -1
  10. package/lib/cmap/auth/mongocr.js.map +1 -1
  11. package/lib/cmap/auth/mongodb_aws.js +3 -0
  12. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  13. package/lib/cmap/auth/plain.js.map +1 -1
  14. package/lib/cmap/auth/scram.js +1 -0
  15. package/lib/cmap/auth/scram.js.map +1 -1
  16. package/lib/cmap/auth/x509.js.map +1 -1
  17. package/lib/cmap/commands.js +12 -11
  18. package/lib/cmap/commands.js.map +1 -1
  19. package/lib/cmap/connect.js +8 -1
  20. package/lib/cmap/connect.js.map +1 -1
  21. package/lib/cmap/connection.js +111 -145
  22. package/lib/cmap/connection.js.map +1 -1
  23. package/lib/cmap/errors.js.map +1 -1
  24. package/lib/cmap/message_stream.js.map +1 -1
  25. package/lib/cmap/stream_description.js +3 -0
  26. package/lib/cmap/stream_description.js.map +1 -1
  27. package/lib/collection.js +60 -29
  28. package/lib/collection.js.map +1 -1
  29. package/lib/connection_string.js +32 -11
  30. package/lib/connection_string.js.map +1 -1
  31. package/lib/constants.js +8 -1
  32. package/lib/constants.js.map +1 -1
  33. package/lib/cursor/abstract_cursor.js +64 -51
  34. package/lib/cursor/abstract_cursor.js.map +1 -1
  35. package/lib/cursor/aggregation_cursor.js +2 -2
  36. package/lib/cursor/aggregation_cursor.js.map +1 -1
  37. package/lib/cursor/find_cursor.js +9 -4
  38. package/lib/cursor/find_cursor.js.map +1 -1
  39. package/lib/db.js +20 -13
  40. package/lib/db.js.map +1 -1
  41. package/lib/encrypter.js +21 -10
  42. package/lib/encrypter.js.map +1 -1
  43. package/lib/error.js +121 -59
  44. package/lib/error.js.map +1 -1
  45. package/lib/gridfs/download.js +2 -0
  46. package/lib/gridfs/download.js.map +1 -1
  47. package/lib/gridfs/index.js +42 -51
  48. package/lib/gridfs/index.js.map +1 -1
  49. package/lib/gridfs/upload.js +1 -1
  50. package/lib/gridfs/upload.js.map +1 -1
  51. package/lib/index.js +7 -3
  52. package/lib/index.js.map +1 -1
  53. package/lib/mongo_client.js +21 -27
  54. package/lib/mongo_client.js.map +1 -1
  55. package/lib/operations/add_user.js +8 -1
  56. package/lib/operations/add_user.js.map +1 -1
  57. package/lib/operations/aggregate.js +5 -0
  58. package/lib/operations/aggregate.js.map +1 -1
  59. package/lib/operations/bulk_write.js.map +1 -1
  60. package/lib/operations/collections.js.map +1 -1
  61. package/lib/operations/command.js +0 -3
  62. package/lib/operations/command.js.map +1 -1
  63. package/lib/operations/common_functions.js +8 -1
  64. package/lib/operations/common_functions.js.map +1 -1
  65. package/lib/operations/count.js.map +1 -1
  66. package/lib/operations/count_documents.js.map +1 -1
  67. package/lib/operations/create_collection.js +51 -17
  68. package/lib/operations/create_collection.js.map +1 -1
  69. package/lib/operations/delete.js +5 -3
  70. package/lib/operations/delete.js.map +1 -1
  71. package/lib/operations/distinct.js.map +1 -1
  72. package/lib/operations/drop.js +67 -7
  73. package/lib/operations/drop.js.map +1 -1
  74. package/lib/operations/estimated_document_count.js.map +1 -1
  75. package/lib/operations/eval.js.map +1 -1
  76. package/lib/operations/execute_operation.js +71 -79
  77. package/lib/operations/execute_operation.js.map +1 -1
  78. package/lib/operations/find.js +3 -52
  79. package/lib/operations/find.js.map +1 -1
  80. package/lib/operations/find_and_modify.js +5 -0
  81. package/lib/operations/find_and_modify.js.map +1 -1
  82. package/lib/operations/get_more.js +5 -0
  83. package/lib/operations/get_more.js.map +1 -1
  84. package/lib/operations/indexes.js +8 -9
  85. package/lib/operations/indexes.js.map +1 -1
  86. package/lib/operations/insert.js +8 -2
  87. package/lib/operations/insert.js.map +1 -1
  88. package/lib/operations/is_capped.js.map +1 -1
  89. package/lib/operations/list_collections.js +10 -42
  90. package/lib/operations/list_collections.js.map +1 -1
  91. package/lib/operations/list_databases.js +5 -0
  92. package/lib/operations/list_databases.js.map +1 -1
  93. package/lib/operations/map_reduce.js +1 -2
  94. package/lib/operations/map_reduce.js.map +1 -1
  95. package/lib/operations/operation.js +1 -3
  96. package/lib/operations/operation.js.map +1 -1
  97. package/lib/operations/options_operation.js.map +1 -1
  98. package/lib/operations/profiling_level.js.map +1 -1
  99. package/lib/operations/remove_user.js.map +1 -1
  100. package/lib/operations/rename.js +1 -1
  101. package/lib/operations/rename.js.map +1 -1
  102. package/lib/operations/run_command.js.map +1 -1
  103. package/lib/operations/set_profiling_level.js.map +1 -1
  104. package/lib/operations/stats.js.map +1 -1
  105. package/lib/operations/update.js +5 -0
  106. package/lib/operations/update.js.map +1 -1
  107. package/lib/operations/validate_collection.js.map +1 -1
  108. package/lib/read_concern.js +1 -0
  109. package/lib/read_concern.js.map +1 -1
  110. package/lib/sdam/common.js +1 -7
  111. package/lib/sdam/common.js.map +1 -1
  112. package/lib/sdam/events.js +1 -1
  113. package/lib/sdam/events.js.map +1 -1
  114. package/lib/sdam/monitor.js +1 -2
  115. package/lib/sdam/monitor.js.map +1 -1
  116. package/lib/sdam/server.js +108 -78
  117. package/lib/sdam/server.js.map +1 -1
  118. package/lib/sdam/topology.js +38 -55
  119. package/lib/sdam/topology.js.map +1 -1
  120. package/lib/sdam/topology_description.js +3 -4
  121. package/lib/sdam/topology_description.js.map +1 -1
  122. package/lib/sessions.js +93 -68
  123. package/lib/sessions.js.map +1 -1
  124. package/lib/utils.js +21 -97
  125. package/lib/utils.js.map +1 -1
  126. package/mongodb.d.ts +417 -92
  127. package/package.json +25 -29
  128. package/src/admin.ts +6 -10
  129. package/src/bulk/common.ts +45 -14
  130. package/src/bulk/unordered.ts +1 -1
  131. package/src/change_stream.ts +559 -425
  132. package/src/cmap/auth/gssapi.ts +1 -1
  133. package/src/cmap/auth/mongocr.ts +1 -1
  134. package/src/cmap/auth/mongodb_aws.ts +6 -1
  135. package/src/cmap/auth/plain.ts +1 -1
  136. package/src/cmap/auth/scram.ts +3 -2
  137. package/src/cmap/auth/x509.ts +6 -2
  138. package/src/cmap/commands.ts +26 -22
  139. package/src/cmap/connect.ts +15 -14
  140. package/src/cmap/connection.ts +163 -185
  141. package/src/cmap/errors.ts +2 -2
  142. package/src/cmap/message_stream.ts +2 -2
  143. package/src/cmap/stream_description.ts +4 -1
  144. package/src/collection.ts +66 -35
  145. package/src/connection_string.ts +46 -18
  146. package/src/constants.ts +6 -0
  147. package/src/cursor/abstract_cursor.ts +87 -65
  148. package/src/cursor/aggregation_cursor.ts +4 -4
  149. package/src/cursor/find_cursor.ts +16 -8
  150. package/src/db.ts +27 -24
  151. package/src/deps.ts +40 -0
  152. package/src/encrypter.ts +22 -11
  153. package/src/error.ts +170 -89
  154. package/src/gridfs/download.ts +3 -1
  155. package/src/gridfs/index.ts +51 -68
  156. package/src/gridfs/upload.ts +13 -13
  157. package/src/index.ts +21 -0
  158. package/src/mongo_client.ts +36 -50
  159. package/src/mongo_types.ts +1 -1
  160. package/src/operations/add_user.ts +14 -3
  161. package/src/operations/aggregate.ts +15 -5
  162. package/src/operations/bulk_write.ts +6 -2
  163. package/src/operations/collections.ts +6 -2
  164. package/src/operations/command.ts +23 -12
  165. package/src/operations/common_functions.ts +8 -1
  166. package/src/operations/count.ts +6 -2
  167. package/src/operations/count_documents.ts +5 -1
  168. package/src/operations/create_collection.ts +91 -23
  169. package/src/operations/delete.ts +19 -13
  170. package/src/operations/distinct.ts +6 -2
  171. package/src/operations/drop.ts +100 -10
  172. package/src/operations/estimated_document_count.ts +11 -3
  173. package/src/operations/eval.ts +6 -2
  174. package/src/operations/execute_operation.ts +103 -101
  175. package/src/operations/find.ts +9 -85
  176. package/src/operations/find_and_modify.ts +21 -2
  177. package/src/operations/get_more.ts +20 -6
  178. package/src/operations/indexes.ts +54 -36
  179. package/src/operations/insert.ts +28 -7
  180. package/src/operations/is_capped.ts +6 -2
  181. package/src/operations/list_collections.ts +24 -59
  182. package/src/operations/list_databases.ts +13 -3
  183. package/src/operations/map_reduce.ts +7 -6
  184. package/src/operations/operation.ts +10 -9
  185. package/src/operations/options_operation.ts +6 -2
  186. package/src/operations/profiling_level.ts +6 -2
  187. package/src/operations/remove_user.ts +6 -2
  188. package/src/operations/rename.ts +7 -3
  189. package/src/operations/run_command.ts +6 -2
  190. package/src/operations/set_profiling_level.ts +6 -2
  191. package/src/operations/stats.ts +12 -4
  192. package/src/operations/update.ts +19 -9
  193. package/src/operations/validate_collection.ts +6 -2
  194. package/src/read_concern.ts +1 -0
  195. package/src/sdam/common.ts +0 -6
  196. package/src/sdam/events.ts +2 -2
  197. package/src/sdam/monitor.ts +4 -5
  198. package/src/sdam/server.ts +125 -117
  199. package/src/sdam/topology.ts +39 -78
  200. package/src/sdam/topology_description.ts +3 -4
  201. package/src/sessions.ts +108 -78
  202. package/src/utils.ts +39 -119
  203. package/tsconfig.json +40 -0
  204. package/mongodb.ts34.d.ts +0 -5720
@@ -21,7 +21,7 @@ import {
21
21
  } from '../error';
22
22
  import type { ServerApi, SupportedNodeConnectionOptions } from '../mongo_client';
23
23
  import { CancellationToken, TypedEventEmitter } from '../mongo_types';
24
- import { ReadPreference, ReadPreferenceLike } from '../read_preference';
24
+ import type { ReadPreference, ReadPreferenceLike } from '../read_preference';
25
25
  import { applySession, ClientSession, updateSessionFromResponse } from '../sessions';
26
26
  import {
27
27
  calculateDurationInMs,
@@ -33,7 +33,7 @@ import {
33
33
  now,
34
34
  uuidV4
35
35
  } from '../utils';
36
- import type { W, WriteConcern, WriteConcernOptions } from '../write_concern';
36
+ import type { WriteConcern } from '../write_concern';
37
37
  import type { MongoCredentials } from './auth/mongo_credentials';
38
38
  import {
39
39
  CommandFailedEvent,
@@ -45,7 +45,6 @@ import {
45
45
  GetMore,
46
46
  KillCursor,
47
47
  Msg,
48
- OpQueryOptions,
49
48
  Query,
50
49
  Response,
51
50
  WriteProtocolMessageType
@@ -75,6 +74,8 @@ const kHello = Symbol('hello');
75
74
  const kAutoEncrypter = Symbol('autoEncrypter');
76
75
  /** @internal */
77
76
  const kFullResult = Symbol('fullResult');
77
+ /** @internal */
78
+ const kDelayedTimeoutId = Symbol('delayedTimeoutId');
78
79
 
79
80
  /** @internal */
80
81
  export interface QueryOptions extends BSONSerializeOptions {
@@ -109,11 +110,14 @@ export interface CommandOptions extends BSONSerializeOptions {
109
110
  noResponse?: boolean;
110
111
  omitReadPreference?: boolean;
111
112
 
112
- // FIXME: NODE-2802
113
+ // TODO(NODE-2802): Currently the CommandOptions take a property willRetryWrite which is a hint
114
+ // from executeOperation that the txnNum should be applied to this command.
115
+ // Applying a session to a command should happen as part of command construction,
116
+ // most likely in the CommandOperation#executeCommand method, where we have access to
117
+ // the details we need to determine if a txnNum should also be applied.
113
118
  willRetryWrite?: boolean;
114
119
 
115
- // FIXME: NODE-2781
116
- writeConcern?: WriteConcernOptions | WriteConcern | W;
120
+ writeConcern?: WriteConcern;
117
121
  }
118
122
 
119
123
  /** @internal */
@@ -121,7 +125,15 @@ export interface GetMoreOptions extends CommandOptions {
121
125
  batchSize?: number;
122
126
  maxTimeMS?: number;
123
127
  maxAwaitTimeMS?: number;
124
- comment?: Document | string;
128
+ /**
129
+ * Comment to apply to the operation.
130
+ *
131
+ * In server versions pre-4.4, 'comment' must be string. A server
132
+ * error will be thrown if any other type is provided.
133
+ *
134
+ * In server versions 4.4 and above, 'comment' can be any valid BSON type.
135
+ */
136
+ comment?: unknown;
125
137
  }
126
138
 
127
139
  /** @public */
@@ -188,6 +200,9 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
188
200
  lastHelloMS?: number;
189
201
  serverApi?: ServerApi;
190
202
  helloOk?: boolean;
203
+
204
+ /**@internal */
205
+ [kDelayedTimeoutId]: NodeJS.Timeout | null;
191
206
  /** @internal */
192
207
  [kDescription]: StreamDescription;
193
208
  /** @internal */
@@ -201,9 +216,9 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
201
216
  /** @internal */
202
217
  [kStream]: Stream;
203
218
  /** @internal */
204
- [kHello]: Document;
219
+ [kHello]: Document | null;
205
220
  /** @internal */
206
- [kClusterTime]: Document;
221
+ [kClusterTime]: Document | null;
207
222
 
208
223
  /** @event */
209
224
  static readonly COMMAND_STARTED = COMMAND_STARTED;
@@ -231,6 +246,8 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
231
246
  this.serverApi = options.serverApi;
232
247
  this.closed = false;
233
248
  this.destroyed = false;
249
+ this[kHello] = null;
250
+ this[kClusterTime] = null;
234
251
 
235
252
  this[kDescription] = new StreamDescription(this.address, options);
236
253
  this[kGeneration] = options.generation;
@@ -242,31 +259,33 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
242
259
  ...options,
243
260
  maxBsonMessageSize: this.hello?.maxBsonMessageSize
244
261
  });
245
- this[kMessageStream].on('message', messageHandler(this));
246
262
  this[kStream] = stream;
247
- stream.on('error', () => {
263
+
264
+ this[kDelayedTimeoutId] = null;
265
+
266
+ this[kMessageStream].on('message', message => this.onMessage(message));
267
+ this[kMessageStream].on('error', error => this.onError(error));
268
+ this[kStream].on('close', () => this.onClose());
269
+ this[kStream].on('timeout', () => this.onTimeout());
270
+ this[kStream].on('error', () => {
248
271
  /* ignore errors, listen to `close` instead */
249
272
  });
250
273
 
251
- this[kMessageStream].on('error', error => this.handleIssue({ destroy: error }));
252
- stream.on('close', () => this.handleIssue({ isClose: true }));
253
- stream.on('timeout', () => this.handleIssue({ isTimeout: true, destroy: true }));
254
-
255
274
  // hook the message stream up to the passed in stream
256
- stream.pipe(this[kMessageStream]);
257
- this[kMessageStream].pipe(stream);
275
+ this[kStream].pipe(this[kMessageStream]);
276
+ this[kMessageStream].pipe(this[kStream]);
258
277
  }
259
278
 
260
279
  get description(): StreamDescription {
261
280
  return this[kDescription];
262
281
  }
263
282
 
264
- get hello(): Document {
283
+ get hello(): Document | null {
265
284
  return this[kHello];
266
285
  }
267
286
 
268
287
  // the `connect` method stores the result of the handshake hello on the connection
269
- set hello(response: Document) {
288
+ set hello(response: Document | null) {
270
289
  this[kDescription].receiveResponse(response);
271
290
  this[kDescription] = Object.freeze(this[kDescription]);
272
291
 
@@ -294,7 +313,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
294
313
  return calculateDurationInMs(this[kLastUseTime]);
295
314
  }
296
315
 
297
- get clusterTime(): Document {
316
+ get clusterTime(): Document | null {
298
317
  return this[kClusterTime];
299
318
  }
300
319
 
@@ -306,40 +325,133 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
306
325
  this[kLastUseTime] = now();
307
326
  }
308
327
 
309
- handleIssue(issue: { isTimeout?: boolean; isClose?: boolean; destroy?: boolean | Error }): void {
328
+ onError(error: Error) {
310
329
  if (this.closed) {
311
330
  return;
312
331
  }
313
332
 
314
- if (issue.destroy) {
315
- this[kStream].destroy(typeof issue.destroy === 'boolean' ? undefined : issue.destroy);
333
+ this[kStream].destroy(error);
334
+
335
+ this.closed = true;
336
+
337
+ for (const op of this[kQueue].values()) {
338
+ op.cb(error);
339
+ }
340
+
341
+ this[kQueue].clear();
342
+ this.emit(Connection.CLOSE);
343
+ }
344
+
345
+ onClose() {
346
+ if (this.closed) {
347
+ return;
316
348
  }
317
349
 
318
350
  this.closed = true;
319
351
 
320
- for (const [, op] of this[kQueue]) {
321
- if (issue.isTimeout) {
322
- op.cb(
323
- new MongoNetworkTimeoutError(`connection ${this.id} to ${this.address} timed out`, {
324
- beforeHandshake: this.hello == null
325
- })
326
- );
327
- } else if (issue.isClose) {
328
- op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} closed`));
329
- } else {
330
- op.cb(typeof issue.destroy === 'boolean' ? undefined : issue.destroy);
331
- }
352
+ const message = `connection ${this.id} to ${this.address} closed`;
353
+ for (const op of this[kQueue].values()) {
354
+ op.cb(new MongoNetworkError(message));
332
355
  }
333
356
 
334
357
  this[kQueue].clear();
335
358
  this.emit(Connection.CLOSE);
336
359
  }
337
360
 
338
- destroy(): void;
339
- destroy(callback: Callback): void;
340
- destroy(options: DestroyOptions): void;
341
- destroy(options: DestroyOptions, callback: Callback): void;
342
- destroy(options?: DestroyOptions | Callback, callback?: Callback): void {
361
+ onTimeout() {
362
+ if (this.closed) {
363
+ return;
364
+ }
365
+
366
+ this[kDelayedTimeoutId] = setTimeout(() => {
367
+ this[kStream].destroy();
368
+
369
+ this.closed = true;
370
+
371
+ const message = `connection ${this.id} to ${this.address} timed out`;
372
+ const beforeHandshake = this.hello == null;
373
+ for (const op of this[kQueue].values()) {
374
+ op.cb(new MongoNetworkTimeoutError(message, { beforeHandshake }));
375
+ }
376
+
377
+ this[kQueue].clear();
378
+ this.emit(Connection.CLOSE);
379
+ }, 1).unref(); // No need for this timer to hold the event loop open
380
+ }
381
+
382
+ onMessage(message: BinMsg | Response) {
383
+ const delayedTimeoutId = this[kDelayedTimeoutId];
384
+ if (delayedTimeoutId != null) {
385
+ clearTimeout(delayedTimeoutId);
386
+ this[kDelayedTimeoutId] = null;
387
+ }
388
+
389
+ // always emit the message, in case we are streaming
390
+ this.emit('message', message);
391
+ const operationDescription = this[kQueue].get(message.responseTo);
392
+ if (!operationDescription) {
393
+ return;
394
+ }
395
+
396
+ const callback = operationDescription.cb;
397
+
398
+ // SERVER-45775: For exhaust responses we should be able to use the same requestId to
399
+ // track response, however the server currently synthetically produces remote requests
400
+ // making the `responseTo` change on each response
401
+ this[kQueue].delete(message.responseTo);
402
+ if ('moreToCome' in message && message.moreToCome) {
403
+ // requeue the callback for next synthetic request
404
+ this[kQueue].set(message.requestId, operationDescription);
405
+ } else if (operationDescription.socketTimeoutOverride) {
406
+ this[kStream].setTimeout(this.socketTimeoutMS);
407
+ }
408
+
409
+ try {
410
+ // Pass in the entire description because it has BSON parsing options
411
+ message.parse(operationDescription);
412
+ } catch (err) {
413
+ // If this error is generated by our own code, it will already have the correct class applied
414
+ // if it is not, then it is coming from a catastrophic data parse failure or the BSON library
415
+ // in either case, it should not be wrapped
416
+ callback(err);
417
+ return;
418
+ }
419
+
420
+ if (message.documents[0]) {
421
+ const document: Document = message.documents[0];
422
+ const session = operationDescription.session;
423
+ if (session) {
424
+ updateSessionFromResponse(session, document);
425
+ }
426
+
427
+ if (document.$clusterTime) {
428
+ this[kClusterTime] = document.$clusterTime;
429
+ this.emit(Connection.CLUSTER_TIME_RECEIVED, document.$clusterTime);
430
+ }
431
+
432
+ if (operationDescription.command) {
433
+ if (document.writeConcernError) {
434
+ callback(new MongoWriteConcernError(document.writeConcernError, document));
435
+ return;
436
+ }
437
+
438
+ if (document.ok === 0 || document.$err || document.errmsg || document.code) {
439
+ callback(new MongoServerError(document));
440
+ return;
441
+ }
442
+ } else {
443
+ // Pre 3.2 support
444
+ if (document.ok === 0 || document.$err || document.errmsg) {
445
+ callback(new MongoServerError(document));
446
+ return;
447
+ }
448
+ }
449
+ }
450
+
451
+ callback(undefined, operationDescription.fullResult ? message : message.documents[0]);
452
+ }
453
+
454
+ destroy(options?: DestroyOptions, callback?: Callback): void {
343
455
  if (typeof options === 'function') {
344
456
  callback = options;
345
457
  options = { force: false };
@@ -376,7 +488,6 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
376
488
  });
377
489
  }
378
490
 
379
- /** @internal */
380
491
  command(
381
492
  ns: MongoDBNamespace,
382
493
  cmd: Document,
@@ -453,80 +564,6 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
453
564
  }
454
565
  }
455
566
 
456
- /** @internal */
457
- query(ns: MongoDBNamespace, cmd: Document, options: QueryOptions, callback: Callback): void {
458
- const isExplain = cmd.$explain != null;
459
- const readPreference = options.readPreference ?? ReadPreference.primary;
460
- const batchSize = options.batchSize || 0;
461
- const limit = options.limit;
462
- const numberToSkip = options.skip || 0;
463
- let numberToReturn = 0;
464
- if (
465
- limit &&
466
- (limit < 0 || (limit !== 0 && limit < batchSize) || (limit > 0 && batchSize === 0))
467
- ) {
468
- numberToReturn = limit;
469
- } else {
470
- numberToReturn = batchSize;
471
- }
472
-
473
- if (isExplain) {
474
- // nToReturn must be 0 (match all) or negative (match N and close cursor)
475
- // nToReturn > 0 will give explain results equivalent to limit(0)
476
- numberToReturn = -Math.abs(limit || 0);
477
- }
478
-
479
- const queryOptions: OpQueryOptions = {
480
- numberToSkip,
481
- numberToReturn,
482
- pre32Limit: typeof limit === 'number' ? limit : undefined,
483
- checkKeys: false,
484
- secondaryOk: readPreference.secondaryOk()
485
- };
486
-
487
- if (options.projection) {
488
- queryOptions.returnFieldSelector = options.projection;
489
- }
490
-
491
- const query = new Query(ns.toString(), cmd, queryOptions);
492
- if (typeof options.tailable === 'boolean') {
493
- query.tailable = options.tailable;
494
- }
495
-
496
- if (typeof options.oplogReplay === 'boolean') {
497
- query.oplogReplay = options.oplogReplay;
498
- }
499
-
500
- if (typeof options.timeout === 'boolean') {
501
- query.noCursorTimeout = !options.timeout;
502
- } else if (typeof options.noCursorTimeout === 'boolean') {
503
- query.noCursorTimeout = options.noCursorTimeout;
504
- }
505
-
506
- if (typeof options.awaitData === 'boolean') {
507
- query.awaitData = options.awaitData;
508
- }
509
-
510
- if (typeof options.partial === 'boolean') {
511
- query.partial = options.partial;
512
- }
513
-
514
- write(
515
- this,
516
- query,
517
- { [kFullResult]: true, ...pluckBSONSerializeOptions(options) },
518
- (err, result) => {
519
- if (err || !result) return callback(err, result);
520
- if (isExplain && result.documents && result.documents[0]) {
521
- return callback(undefined, result.documents[0]);
522
- }
523
-
524
- callback(undefined, result);
525
- }
526
- );
527
- }
528
-
529
- /** @internal */
530
567
  getMore(
531
568
  ns: MongoDBNamespace,
532
569
  cursorId: Long,
@@ -571,6 +608,11 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
571
608
  if (typeof options.maxAwaitTimeMS === 'number') {
572
609
  getMoreCmd.maxTimeMS = options.maxAwaitTimeMS;
573
610
  }
611
+ // we check for undefined specifically here to allow falsy values
612
+ // eslint-disable-next-line no-restricted-syntax
613
+ if (options.comment !== undefined) {
614
+ getMoreCmd.comment = options.comment;
615
+ }
574
616
 
575
617
  const commandOptions = Object.assign(
576
618
  {
@@ -583,7 +625,6 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
583
625
  this.command(ns, getMoreCmd, commandOptions, callback);
584
626
  }
585
627
 
586
- /** @internal */
587
628
  killCursors(
588
629
  ns: MongoDBNamespace,
589
630
  cursorIds: Long[],
@@ -646,7 +687,12 @@ export class CryptoConnection extends Connection {
646
687
  }
647
688
 
648
689
  /** @internal @override */
649
- command(ns: MongoDBNamespace, cmd: Document, options: CommandOptions, callback: Callback): void {
690
+ override command(
691
+ ns: MongoDBNamespace,
692
+ cmd: Document,
693
+ options: CommandOptions,
694
+ callback: Callback
695
+ ): void {
650
696
  const autoEncrypter = this[kAutoEncrypter];
651
697
  if (!autoEncrypter) {
652
698
  return callback(new MongoMissingDependencyError('No AutoEncrypter available for encryption'));
@@ -698,74 +744,6 @@ function supportsOpMsg(conn: Connection) {
698
744
  return maxWireVersion(conn) >= 6 && !description.__nodejs_mock_server__;
699
745
  }
700
746
 
701
- function messageHandler(conn: Connection) {
702
- return function messageHandler(message: BinMsg | Response) {
703
- // always emit the message, in case we are streaming
704
- conn.emit('message', message);
705
- const operationDescription = conn[kQueue].get(message.responseTo);
706
- if (!operationDescription) {
707
- return;
708
- }
709
-
710
- const callback = operationDescription.cb;
711
-
712
- // SERVER-45775: For exhaust responses we should be able to use the same requestId to
713
- // track response, however the server currently synthetically produces remote requests
714
- // making the `responseTo` change on each response
715
- conn[kQueue].delete(message.responseTo);
716
- if ('moreToCome' in message && message.moreToCome) {
717
- // requeue the callback for next synthetic request
718
- conn[kQueue].set(message.requestId, operationDescription);
719
- } else if (operationDescription.socketTimeoutOverride) {
720
- conn[kStream].setTimeout(conn.socketTimeoutMS);
721
- }
722
-
723
- try {
724
- // Pass in the entire description because it has BSON parsing options
725
- message.parse(operationDescription);
726
- } catch (err) {
727
- // If this error is generated by our own code, it will already have the correct class applied
728
- // if it is not, then it is coming from a catastrophic data parse failure or the BSON library
729
- // in either case, it should not be wrapped
730
- callback(err);
731
- return;
732
- }
733
-
734
- if (message.documents[0]) {
735
- const document: Document = message.documents[0];
736
- const session = operationDescription.session;
737
- if (session) {
738
- updateSessionFromResponse(session, document);
739
- }
740
-
741
- if (document.$clusterTime) {
742
- conn[kClusterTime] = document.$clusterTime;
743
- conn.emit(Connection.CLUSTER_TIME_RECEIVED, document.$clusterTime);
744
- }
745
-
746
- if (operationDescription.command) {
747
- if (document.writeConcernError) {
748
- callback(new MongoWriteConcernError(document.writeConcernError, document));
749
- return;
750
- }
751
-
752
- if (document.ok === 0 || document.$err || document.errmsg || document.code) {
753
- callback(new MongoServerError(document));
754
- return;
755
- }
756
- } else {
757
- // Pre 3.2 support
758
- if (document.ok === 0 || document.$err || document.errmsg) {
759
- callback(new MongoServerError(document));
760
- return;
761
- }
762
- }
763
- }
764
-
765
- callback(undefined, operationDescription.fullResult ? message : message.documents[0]);
766
- };
767
- }
768
-
769
747
  function streamIdentifier(stream: Stream, options: ConnectionOptions): string {
770
748
  if (options.proxyHost) {
771
749
  // If proxy options are specified, the properties of `stream` itself
@@ -14,7 +14,7 @@ export class PoolClosedError extends MongoDriverError {
14
14
  this.address = pool.address;
15
15
  }
16
16
 
17
- get name(): string {
17
+ override get name(): string {
18
18
  return 'MongoPoolClosedError';
19
19
  }
20
20
  }
@@ -32,7 +32,7 @@ export class WaitQueueTimeoutError extends MongoDriverError {
32
32
  this.address = address;
33
33
  }
34
34
 
35
- get name(): string {
35
+ override get name(): string {
36
36
  return 'MongoWaitQueueTimeoutError';
37
37
  }
38
38
  }
@@ -60,12 +60,12 @@ export class MessageStream extends Duplex {
60
60
  this[kBuffer] = new BufferPool();
61
61
  }
62
62
 
63
- _write(chunk: Buffer, _: unknown, callback: Callback<Buffer>): void {
63
+ override _write(chunk: Buffer, _: unknown, callback: Callback<Buffer>): void {
64
64
  this[kBuffer].append(chunk);
65
65
  processIncomingData(this, callback);
66
66
  }
67
67
 
68
- _read(/* size */): void {
68
+ override _read(/* size */): void {
69
69
  // NOTE: This implementation is empty because we explicitly push data to be read
70
70
  // when `writeMessage` is called.
71
71
  return;
@@ -53,7 +53,10 @@ export class StreamDescription {
53
53
  : [];
54
54
  }
55
55
 
56
- receiveResponse(response: Document): void {
56
+ receiveResponse(response: Document | null): void {
57
+ if (response == null) {
58
+ return;
59
+ }
57
60
  this.type = parseServerType(response);
58
61
  for (const field of RESPONSE_FIELDS) {
59
62
  if (response[field] != null) {