mongodb 4.4.1 → 4.5.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 (193) 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 +31 -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 +29 -20
  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.map +1 -1
  12. package/lib/cmap/auth/plain.js.map +1 -1
  13. package/lib/cmap/auth/scram.js +1 -0
  14. package/lib/cmap/auth/scram.js.map +1 -1
  15. package/lib/cmap/auth/x509.js.map +1 -1
  16. package/lib/cmap/commands.js.map +1 -1
  17. package/lib/cmap/connect.js.map +1 -1
  18. package/lib/cmap/connection.js +111 -86
  19. package/lib/cmap/connection.js.map +1 -1
  20. package/lib/cmap/errors.js.map +1 -1
  21. package/lib/cmap/message_stream.js.map +1 -1
  22. package/lib/cmap/stream_description.js +3 -0
  23. package/lib/cmap/stream_description.js.map +1 -1
  24. package/lib/collection.js +28 -28
  25. package/lib/collection.js.map +1 -1
  26. package/lib/connection_string.js +3 -0
  27. package/lib/connection_string.js.map +1 -1
  28. package/lib/cursor/abstract_cursor.js +64 -51
  29. package/lib/cursor/abstract_cursor.js.map +1 -1
  30. package/lib/cursor/aggregation_cursor.js +2 -2
  31. package/lib/cursor/aggregation_cursor.js.map +1 -1
  32. package/lib/cursor/find_cursor.js +3 -3
  33. package/lib/cursor/find_cursor.js.map +1 -1
  34. package/lib/db.js +13 -13
  35. package/lib/db.js.map +1 -1
  36. package/lib/encrypter.js +17 -9
  37. package/lib/encrypter.js.map +1 -1
  38. package/lib/error.js +97 -48
  39. package/lib/error.js.map +1 -1
  40. package/lib/gridfs/download.js +2 -0
  41. package/lib/gridfs/download.js.map +1 -1
  42. package/lib/gridfs/index.js +42 -51
  43. package/lib/gridfs/index.js.map +1 -1
  44. package/lib/gridfs/upload.js.map +1 -1
  45. package/lib/index.js +6 -3
  46. package/lib/index.js.map +1 -1
  47. package/lib/mongo_client.js +14 -27
  48. package/lib/mongo_client.js.map +1 -1
  49. package/lib/operations/add_user.js +8 -1
  50. package/lib/operations/add_user.js.map +1 -1
  51. package/lib/operations/aggregate.js +5 -0
  52. package/lib/operations/aggregate.js.map +1 -1
  53. package/lib/operations/bulk_write.js.map +1 -1
  54. package/lib/operations/collections.js.map +1 -1
  55. package/lib/operations/command.js.map +1 -1
  56. package/lib/operations/common_functions.js +8 -1
  57. package/lib/operations/common_functions.js.map +1 -1
  58. package/lib/operations/count.js.map +1 -1
  59. package/lib/operations/count_documents.js.map +1 -1
  60. package/lib/operations/create_collection.js.map +1 -1
  61. package/lib/operations/delete.js +5 -3
  62. package/lib/operations/delete.js.map +1 -1
  63. package/lib/operations/distinct.js.map +1 -1
  64. package/lib/operations/drop.js.map +1 -1
  65. package/lib/operations/estimated_document_count.js.map +1 -1
  66. package/lib/operations/eval.js.map +1 -1
  67. package/lib/operations/execute_operation.js +70 -79
  68. package/lib/operations/execute_operation.js.map +1 -1
  69. package/lib/operations/find.js +3 -1
  70. package/lib/operations/find.js.map +1 -1
  71. package/lib/operations/find_and_modify.js +5 -0
  72. package/lib/operations/find_and_modify.js.map +1 -1
  73. package/lib/operations/get_more.js +5 -0
  74. package/lib/operations/get_more.js.map +1 -1
  75. package/lib/operations/indexes.js +8 -9
  76. package/lib/operations/indexes.js.map +1 -1
  77. package/lib/operations/insert.js +3 -1
  78. package/lib/operations/insert.js.map +1 -1
  79. package/lib/operations/is_capped.js.map +1 -1
  80. package/lib/operations/list_collections.js +10 -42
  81. package/lib/operations/list_collections.js.map +1 -1
  82. package/lib/operations/list_databases.js +5 -0
  83. package/lib/operations/list_databases.js.map +1 -1
  84. package/lib/operations/map_reduce.js +1 -2
  85. package/lib/operations/map_reduce.js.map +1 -1
  86. package/lib/operations/operation.js +1 -3
  87. package/lib/operations/operation.js.map +1 -1
  88. package/lib/operations/options_operation.js.map +1 -1
  89. package/lib/operations/profiling_level.js.map +1 -1
  90. package/lib/operations/remove_user.js.map +1 -1
  91. package/lib/operations/rename.js +1 -1
  92. package/lib/operations/rename.js.map +1 -1
  93. package/lib/operations/run_command.js.map +1 -1
  94. package/lib/operations/set_profiling_level.js.map +1 -1
  95. package/lib/operations/stats.js.map +1 -1
  96. package/lib/operations/update.js +5 -0
  97. package/lib/operations/update.js.map +1 -1
  98. package/lib/operations/validate_collection.js.map +1 -1
  99. package/lib/read_concern.js +1 -0
  100. package/lib/read_concern.js.map +1 -1
  101. package/lib/sdam/common.js +1 -7
  102. package/lib/sdam/common.js.map +1 -1
  103. package/lib/sdam/events.js +1 -1
  104. package/lib/sdam/events.js.map +1 -1
  105. package/lib/sdam/monitor.js +1 -2
  106. package/lib/sdam/monitor.js.map +1 -1
  107. package/lib/sdam/server.js +79 -57
  108. package/lib/sdam/server.js.map +1 -1
  109. package/lib/sdam/topology.js +16 -33
  110. package/lib/sdam/topology.js.map +1 -1
  111. package/lib/sdam/topology_description.js +1 -3
  112. package/lib/sdam/topology_description.js.map +1 -1
  113. package/lib/sessions.js +93 -68
  114. package/lib/sessions.js.map +1 -1
  115. package/lib/utils.js +21 -97
  116. package/lib/utils.js.map +1 -1
  117. package/mongodb.d.ts +110 -26
  118. package/package.json +24 -28
  119. package/src/admin.ts +6 -10
  120. package/src/bulk/common.ts +42 -14
  121. package/src/bulk/unordered.ts +1 -1
  122. package/src/change_stream.ts +57 -41
  123. package/src/cmap/auth/gssapi.ts +1 -1
  124. package/src/cmap/auth/mongocr.ts +1 -1
  125. package/src/cmap/auth/mongodb_aws.ts +1 -1
  126. package/src/cmap/auth/plain.ts +1 -1
  127. package/src/cmap/auth/scram.ts +3 -2
  128. package/src/cmap/auth/x509.ts +6 -2
  129. package/src/cmap/commands.ts +3 -0
  130. package/src/cmap/connect.ts +2 -12
  131. package/src/cmap/connection.ts +162 -111
  132. package/src/cmap/errors.ts +2 -2
  133. package/src/cmap/message_stream.ts +2 -2
  134. package/src/cmap/stream_description.ts +4 -1
  135. package/src/collection.ts +31 -31
  136. package/src/connection_string.ts +7 -4
  137. package/src/cursor/abstract_cursor.ts +85 -63
  138. package/src/cursor/aggregation_cursor.ts +4 -4
  139. package/src/cursor/find_cursor.ts +7 -7
  140. package/src/db.ts +15 -19
  141. package/src/deps.ts +11 -0
  142. package/src/encrypter.ts +18 -10
  143. package/src/error.ts +143 -76
  144. package/src/gridfs/download.ts +3 -1
  145. package/src/gridfs/index.ts +51 -68
  146. package/src/gridfs/upload.ts +12 -12
  147. package/src/index.ts +7 -0
  148. package/src/mongo_client.ts +19 -41
  149. package/src/operations/add_user.ts +14 -3
  150. package/src/operations/aggregate.ts +15 -5
  151. package/src/operations/bulk_write.ts +6 -2
  152. package/src/operations/collections.ts +6 -2
  153. package/src/operations/command.ts +23 -8
  154. package/src/operations/common_functions.ts +8 -1
  155. package/src/operations/count.ts +6 -2
  156. package/src/operations/count_documents.ts +5 -1
  157. package/src/operations/create_collection.ts +6 -2
  158. package/src/operations/delete.ts +19 -13
  159. package/src/operations/distinct.ts +6 -2
  160. package/src/operations/drop.ts +12 -4
  161. package/src/operations/estimated_document_count.ts +11 -3
  162. package/src/operations/eval.ts +6 -2
  163. package/src/operations/execute_operation.ts +102 -101
  164. package/src/operations/find.ts +9 -5
  165. package/src/operations/find_and_modify.ts +21 -2
  166. package/src/operations/get_more.ts +20 -6
  167. package/src/operations/indexes.ts +54 -36
  168. package/src/operations/insert.ts +20 -6
  169. package/src/operations/is_capped.ts +6 -2
  170. package/src/operations/list_collections.ts +24 -59
  171. package/src/operations/list_databases.ts +13 -3
  172. package/src/operations/map_reduce.ts +7 -6
  173. package/src/operations/operation.ts +10 -9
  174. package/src/operations/options_operation.ts +6 -2
  175. package/src/operations/profiling_level.ts +6 -2
  176. package/src/operations/remove_user.ts +6 -2
  177. package/src/operations/rename.ts +7 -3
  178. package/src/operations/run_command.ts +6 -2
  179. package/src/operations/set_profiling_level.ts +6 -2
  180. package/src/operations/stats.ts +12 -4
  181. package/src/operations/update.ts +19 -9
  182. package/src/operations/validate_collection.ts +6 -2
  183. package/src/read_concern.ts +1 -0
  184. package/src/sdam/common.ts +0 -6
  185. package/src/sdam/events.ts +2 -2
  186. package/src/sdam/monitor.ts +4 -5
  187. package/src/sdam/server.ts +95 -90
  188. package/src/sdam/topology.ts +9 -53
  189. package/src/sdam/topology_description.ts +1 -3
  190. package/src/sessions.ts +108 -78
  191. package/src/utils.ts +38 -118
  192. package/tsconfig.json +40 -0
  193. package/mongodb.ts34.d.ts +0 -5720
@@ -1,14 +1,16 @@
1
1
  import type { Document } from '../bson';
2
2
  import {
3
- isRetryableError,
3
+ isRetryableReadError,
4
4
  MongoCompatibilityError,
5
5
  MONGODB_ERROR_CODES,
6
6
  MongoError,
7
+ MongoErrorLabel,
7
8
  MongoExpiredSessionError,
8
9
  MongoNetworkError,
9
10
  MongoRuntimeError,
10
11
  MongoServerError,
11
- MongoTransactionError
12
+ MongoTransactionError,
13
+ MongoUnexpectedServerResponseError
12
14
  } from '../error';
13
15
  import { ReadPreference } from '../read_preference';
14
16
  import type { Server } from '../sdam/server';
@@ -19,7 +21,13 @@ import {
19
21
  } from '../sdam/server_selection';
20
22
  import type { Topology } from '../sdam/topology';
21
23
  import type { ClientSession } from '../sessions';
22
- import { Callback, maxWireVersion, maybePromise, supportsRetryableWrites } from '../utils';
24
+ import {
25
+ Callback,
26
+ getTopology,
27
+ maybePromise,
28
+ supportsRetryableWrites,
29
+ TopologyProvider
30
+ } from '../utils';
23
31
  import { AbstractOperation, Aspect } from './operation';
24
32
 
25
33
  const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES.IllegalOperation;
@@ -58,99 +66,101 @@ export interface ExecutionResult {
58
66
  export function executeOperation<
59
67
  T extends AbstractOperation<TResult>,
60
68
  TResult = ResultTypeFromOperation<T>
61
- >(topology: Topology, operation: T): Promise<TResult>;
69
+ >(topologyProvider: TopologyProvider, operation: T): Promise<TResult>;
62
70
  export function executeOperation<
63
71
  T extends AbstractOperation<TResult>,
64
72
  TResult = ResultTypeFromOperation<T>
65
- >(topology: Topology, operation: T, callback: Callback<TResult>): void;
73
+ >(topologyProvider: TopologyProvider, operation: T, callback: Callback<TResult>): void;
66
74
  export function executeOperation<
67
75
  T extends AbstractOperation<TResult>,
68
76
  TResult = ResultTypeFromOperation<T>
69
- >(topology: Topology, operation: T, callback?: Callback<TResult>): Promise<TResult> | void;
77
+ >(
78
+ topologyProvider: TopologyProvider,
79
+ operation: T,
80
+ callback?: Callback<TResult>
81
+ ): Promise<TResult> | void;
70
82
  export function executeOperation<
71
83
  T extends AbstractOperation<TResult>,
72
84
  TResult = ResultTypeFromOperation<T>
73
- >(topology: Topology, operation: T, callback?: Callback<TResult>): Promise<TResult> | void {
85
+ >(
86
+ topologyProvider: TopologyProvider,
87
+ operation: T,
88
+ callback?: Callback<TResult>
89
+ ): Promise<TResult> | void {
74
90
  if (!(operation instanceof AbstractOperation)) {
75
- // TODO(NODE-3483)
91
+ // TODO(NODE-3483): Extend MongoRuntimeError
76
92
  throw new MongoRuntimeError('This method requires a valid operation instance');
77
93
  }
78
94
 
79
- return maybePromise(callback, cb => {
95
+ return maybePromise(callback, callback => {
96
+ let topology: Topology;
97
+ try {
98
+ topology = getTopology(topologyProvider);
99
+ } catch (error) {
100
+ return callback(error);
101
+ }
80
102
  if (topology.shouldCheckForSessionSupport()) {
81
- return topology.selectServer(ReadPreference.primaryPreferred, err => {
82
- if (err) return cb(err);
103
+ return topology.selectServer(ReadPreference.primaryPreferred, {}, err => {
104
+ if (err) return callback(err);
83
105
 
84
- executeOperation<T, TResult>(topology, operation, cb);
106
+ executeOperation<T, TResult>(topologyProvider, operation, callback);
85
107
  });
86
108
  }
87
109
 
88
110
  // The driver sessions spec mandates that we implicitly create sessions for operations
89
111
  // that are not explicitly provided with a session.
90
- let session: ClientSession | undefined = operation.session;
112
+ let session = operation.session;
91
113
  let owner: symbol | undefined;
92
114
  if (topology.hasSessionSupport()) {
93
115
  if (session == null) {
94
116
  owner = Symbol();
95
117
  session = topology.startSession({ owner, explicit: false });
96
118
  } else if (session.hasEnded) {
97
- return cb(new MongoExpiredSessionError('Use of expired sessions is not permitted'));
119
+ return callback(new MongoExpiredSessionError('Use of expired sessions is not permitted'));
98
120
  } else if (session.snapshotEnabled && !topology.capabilities.supportsSnapshotReads) {
99
- return cb(new MongoCompatibilityError('Snapshot reads require MongoDB 5.0 or later'));
121
+ return callback(new MongoCompatibilityError('Snapshot reads require MongoDB 5.0 or later'));
100
122
  }
101
123
  } else if (session) {
102
124
  // If the user passed an explicit session and we are still, after server selection,
103
125
  // trying to run against a topology that doesn't support sessions we error out.
104
- return cb(new MongoCompatibilityError('Current topology does not support sessions'));
126
+ return callback(new MongoCompatibilityError('Current topology does not support sessions'));
105
127
  }
106
128
 
107
129
  try {
108
- executeWithServerSelection(topology, session, operation, (err, result) => {
109
- if (session && session.owner && session.owner === owner) {
110
- return session.endSession(err2 => cb(err2 || err, result));
130
+ executeWithServerSelection<TResult>(topology, session, operation, (error, result) => {
131
+ if (session?.owner != null && session.owner === owner) {
132
+ return session.endSession(endSessionError => callback(endSessionError ?? error, result));
111
133
  }
112
134
 
113
- cb(err, result);
135
+ callback(error, result);
114
136
  });
115
- } catch (e) {
116
- if (session && session.owner && session.owner === owner) {
137
+ } catch (error) {
138
+ if (session?.owner != null && session.owner === owner) {
117
139
  session.endSession();
118
140
  }
119
-
120
- throw e;
141
+ throw error;
121
142
  }
122
143
  });
123
144
  }
124
145
 
125
- function supportsRetryableReads(server: Server) {
126
- return maxWireVersion(server) >= 6;
127
- }
128
-
129
- function executeWithServerSelection(
146
+ function executeWithServerSelection<TResult>(
130
147
  topology: Topology,
131
- session: ClientSession,
148
+ session: ClientSession | undefined,
132
149
  operation: AbstractOperation,
133
- callback: Callback
150
+ callback: Callback<TResult>
134
151
  ) {
135
- const readPreference = operation.readPreference || ReadPreference.primary;
136
- const inTransaction = session && session.inTransaction();
152
+ const readPreference = operation.readPreference ?? ReadPreference.primary;
153
+ const inTransaction = !!session?.inTransaction();
137
154
 
138
155
  if (inTransaction && !readPreference.equals(ReadPreference.primary)) {
139
- callback(
156
+ return callback(
140
157
  new MongoTransactionError(
141
158
  `Read preference in a transaction must be primary, not: ${readPreference.mode}`
142
159
  )
143
160
  );
144
-
145
- return;
146
161
  }
147
162
 
148
- if (
149
- session &&
150
- session.isPinned &&
151
- session.transaction.isCommitted &&
152
- !operation.bypassPinningCheck
153
- ) {
163
+ if (session?.isPinned && session.transaction.isCommitted && !operation.bypassPinningCheck) {
154
164
  session.unpin();
155
165
  }
156
166
 
@@ -170,60 +180,54 @@ function executeWithServerSelection(
170
180
  }
171
181
 
172
182
  const serverSelectionOptions = { session };
173
- function callbackWithRetry(err?: any, result?: any) {
174
- if (err == null) {
175
- return callback(undefined, result);
176
- }
183
+ function retryOperation(originalError: MongoError) {
184
+ const isWriteOperation = operation.hasAspect(Aspect.WRITE_OPERATION);
185
+ const isReadOperation = operation.hasAspect(Aspect.READ_OPERATION);
177
186
 
178
- const hasReadAspect = operation.hasAspect(Aspect.READ_OPERATION);
179
- const hasWriteAspect = operation.hasAspect(Aspect.WRITE_OPERATION);
180
- const itShouldRetryWrite = shouldRetryWrite(err);
181
-
182
- if ((hasReadAspect && !isRetryableError(err)) || (hasWriteAspect && !itShouldRetryWrite)) {
183
- return callback(err);
184
- }
185
-
186
- if (
187
- hasWriteAspect &&
188
- itShouldRetryWrite &&
189
- err.code === MMAPv1_RETRY_WRITES_ERROR_CODE &&
190
- err.errmsg.match(/Transaction numbers/)
191
- ) {
192
- callback(
187
+ if (isWriteOperation && originalError.code === MMAPv1_RETRY_WRITES_ERROR_CODE) {
188
+ return callback(
193
189
  new MongoServerError({
194
190
  message: MMAPv1_RETRY_WRITES_ERROR_MESSAGE,
195
191
  errmsg: MMAPv1_RETRY_WRITES_ERROR_MESSAGE,
196
- originalError: err
192
+ originalError
197
193
  })
198
194
  );
195
+ }
199
196
 
200
- return;
197
+ if (isWriteOperation && !originalError.hasErrorLabel(MongoErrorLabel.RetryableWriteError)) {
198
+ return callback(originalError);
201
199
  }
202
200
 
203
- // select a new server, and attempt to retry the operation
204
- topology.selectServer(selector, serverSelectionOptions, (e?: any, server?: any) => {
205
- if (
206
- e ||
207
- (operation.hasAspect(Aspect.READ_OPERATION) && !supportsRetryableReads(server)) ||
208
- (operation.hasAspect(Aspect.WRITE_OPERATION) && !supportsRetryableWrites(server))
209
- ) {
210
- callback(e);
211
- return;
212
- }
201
+ if (isReadOperation && !isRetryableReadError(originalError)) {
202
+ return callback(originalError);
203
+ }
213
204
 
205
+ if (
206
+ originalError instanceof MongoNetworkError &&
207
+ session?.isPinned &&
208
+ !session.inTransaction() &&
209
+ operation.hasAspect(Aspect.CURSOR_CREATING)
210
+ ) {
214
211
  // If we have a cursor and the initial command fails with a network error,
215
212
  // we can retry it on another connection. So we need to check it back in, clear the
216
213
  // pool for the service id, and retry again.
217
- if (
218
- err &&
219
- err instanceof MongoNetworkError &&
220
- server.loadBalanced &&
221
- session &&
222
- session.isPinned &&
223
- !session.inTransaction() &&
224
- operation.hasAspect(Aspect.CURSOR_CREATING)
225
- ) {
226
- session.unpin({ force: true, forceClear: true });
214
+ session.unpin({ force: true, forceClear: true });
215
+ }
216
+
217
+ // select a new server, and attempt to retry the operation
218
+ topology.selectServer(selector, serverSelectionOptions, (error?: Error, server?: Server) => {
219
+ if (!error && isWriteOperation && !supportsRetryableWrites(server)) {
220
+ return callback(
221
+ new MongoUnexpectedServerResponseError(
222
+ 'Selected server does not support retryable writes'
223
+ )
224
+ );
225
+ }
226
+
227
+ if (error || !server) {
228
+ return callback(
229
+ error ?? new MongoUnexpectedServerResponseError('Server selection failed without error')
230
+ );
227
231
  }
228
232
 
229
233
  operation.execute(server, session, callback);
@@ -233,8 +237,7 @@ function executeWithServerSelection(
233
237
  if (
234
238
  readPreference &&
235
239
  !readPreference.equals(ReadPreference.primary) &&
236
- session &&
237
- session.inTransaction()
240
+ session?.inTransaction()
238
241
  ) {
239
242
  callback(
240
243
  new MongoTransactionError(
@@ -246,21 +249,17 @@ function executeWithServerSelection(
246
249
  }
247
250
 
248
251
  // select a server, and execute the operation against it
249
- topology.selectServer(selector, serverSelectionOptions, (err?: any, server?: any) => {
250
- if (err) {
251
- callback(err);
252
- return;
252
+ topology.selectServer(selector, serverSelectionOptions, (error, server) => {
253
+ if (error || !server) {
254
+ return callback(error);
253
255
  }
254
256
 
255
257
  if (session && operation.hasAspect(Aspect.RETRYABLE)) {
256
258
  const willRetryRead =
257
- topology.s.options.retryReads !== false &&
258
- !inTransaction &&
259
- supportsRetryableReads(server) &&
260
- operation.canRetryRead;
259
+ topology.s.options.retryReads && !inTransaction && operation.canRetryRead;
261
260
 
262
261
  const willRetryWrite =
263
- topology.s.options.retryWrites === true &&
262
+ topology.s.options.retryWrites &&
264
263
  !inTransaction &&
265
264
  supportsRetryableWrites(server) &&
266
265
  operation.canRetryWrite;
@@ -274,15 +273,17 @@ function executeWithServerSelection(
274
273
  session.incrementTransactionNumber();
275
274
  }
276
275
 
277
- operation.execute(server, session, callbackWithRetry);
278
- return;
276
+ return operation.execute(server, session, (error, result) => {
277
+ if (error instanceof MongoError) {
278
+ return retryOperation(error);
279
+ } else if (error) {
280
+ return callback(error);
281
+ }
282
+ callback(undefined, result);
283
+ });
279
284
  }
280
285
  }
281
286
 
282
- operation.execute(server, session, callback);
287
+ return operation.execute(server, session, callback);
283
288
  });
284
289
  }
285
-
286
- function shouldRetryWrite(err: any) {
287
- return err instanceof MongoError && err.hasErrorLabel('RetryableWriteError');
288
- }
@@ -46,8 +46,6 @@ export interface FindOptions<TSchema extends Document = Document> extends Comman
46
46
  min?: Document;
47
47
  /** The exclusive upper bound for a specific index */
48
48
  max?: Document;
49
- /** You can put a $comment field on a query to make looking in the profiler logs simpler. */
50
- comment?: string | Document;
51
49
  /** Number of milliseconds to wait before aborting the query. */
52
50
  maxTimeMS?: number;
53
51
  /** The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query. Requires `tailable` and `awaitData` to be true */
@@ -72,7 +70,7 @@ const SUPPORTS_WRITE_CONCERN_AND_COLLATION = 5;
72
70
 
73
71
  /** @internal */
74
72
  export class FindOperation extends CommandOperation<Document> {
75
- options: FindOptions;
73
+ override options: FindOptions;
76
74
  filter: Document;
77
75
 
78
76
  constructor(
@@ -104,7 +102,11 @@ export class FindOperation extends CommandOperation<Document> {
104
102
  this.filter = filter != null && filter._bsontype === 'ObjectID' ? { _id: filter } : filter;
105
103
  }
106
104
 
107
- execute(server: Server, session: ClientSession, callback: Callback<Document>): void {
105
+ override execute(
106
+ server: Server,
107
+ session: ClientSession | undefined,
108
+ callback: Callback<Document>
109
+ ): void {
108
110
  this.server = server;
109
111
 
110
112
  const serverWireVersion = maxWireVersion(server);
@@ -237,7 +239,9 @@ function makeFindCommand(ns: MongoDBNamespace, filter: Document, options: FindOp
237
239
  findCommand.singleBatch = options.singleBatch;
238
240
  }
239
241
 
240
- if (options.comment) {
242
+ // we check for undefined specifically here to allow falsy values
243
+ // eslint-disable-next-line no-restricted-syntax
244
+ if (options.comment !== undefined) {
241
245
  findCommand.comment = options.comment;
242
246
  }
243
247
 
@@ -82,6 +82,15 @@ interface FindAndModifyCmdBase {
82
82
  maxTimeMS?: number;
83
83
  let?: Document;
84
84
  writeConcern?: WriteConcern | WriteConcernSettings;
85
+ /**
86
+ * Comment to apply to the operation.
87
+ *
88
+ * In server versions pre-4.4, 'comment' must be string. A server
89
+ * error will be thrown if any other type is provided.
90
+ *
91
+ * In server versions 4.4 and above, 'comment' can be any valid BSON type.
92
+ */
93
+ comment?: unknown;
85
94
  }
86
95
 
87
96
  function configureFindAndModifyCmdBaseUpdateOpts(
@@ -99,7 +108,7 @@ function configureFindAndModifyCmdBaseUpdateOpts(
99
108
 
100
109
  /** @internal */
101
110
  class FindAndModifyOperation extends CommandOperation<Document> {
102
- options: FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions;
111
+ override options: FindOneAndReplaceOptions | FindOneAndUpdateOptions | FindOneAndDeleteOptions;
103
112
  cmdBase: FindAndModifyCmdBase;
104
113
  collection: Collection;
105
114
  query: Document;
@@ -140,6 +149,12 @@ class FindAndModifyOperation extends CommandOperation<Document> {
140
149
  this.cmdBase.let = options.let;
141
150
  }
142
151
 
152
+ // we check for undefined specifically here to allow falsy values
153
+ // eslint-disable-next-line no-restricted-syntax
154
+ if (options.comment !== undefined) {
155
+ this.cmdBase.comment = options.comment;
156
+ }
157
+
143
158
  // force primary read preference
144
159
  this.readPreference = ReadPreference.primary;
145
160
 
@@ -147,7 +162,11 @@ class FindAndModifyOperation extends CommandOperation<Document> {
147
162
  this.query = query;
148
163
  }
149
164
 
150
- execute(server: Server, session: ClientSession, callback: Callback<Document>): void {
165
+ override execute(
166
+ server: Server,
167
+ session: ClientSession | undefined,
168
+ callback: Callback<Document>
169
+ ): void {
151
170
  const coll = this.collection;
152
171
  const query = this.query;
153
172
  const options = { ...this.options, ...this.bsonOptions };
@@ -2,7 +2,7 @@ import type { Document, Long } from '../bson';
2
2
  import { MongoRuntimeError } from '../error';
3
3
  import type { Server } from '../sdam/server';
4
4
  import type { ClientSession } from '../sessions';
5
- import type { Callback, MongoDBNamespace } from '../utils';
5
+ import { Callback, maxWireVersion, MongoDBNamespace } from '../utils';
6
6
  import { AbstractOperation, Aspect, defineAspects, OperationOptions } from './operation';
7
7
 
8
8
  /**
@@ -12,8 +12,12 @@ import { AbstractOperation, Aspect, defineAspects, OperationOptions } from './op
12
12
  export interface GetMoreOptions extends OperationOptions {
13
13
  /** Set the batchSize for the getMoreCommand when iterating over the query results. */
14
14
  batchSize?: number;
15
- /** You can put a $comment field on a query to make looking in the profiler logs simpler. */
16
- comment?: string | Document;
15
+ /**
16
+ * Comment to apply to the operation.
17
+ *
18
+ * getMore only supports 'comment' in server versions 4.4 and above.
19
+ */
20
+ comment?: unknown;
17
21
  /** Number of milliseconds to wait before aborting the query. */
18
22
  maxTimeMS?: number;
19
23
  }
@@ -21,12 +25,18 @@ export interface GetMoreOptions extends OperationOptions {
21
25
  /** @internal */
22
26
  export class GetMoreOperation extends AbstractOperation {
23
27
  cursorId: Long;
24
- options: GetMoreOptions;
25
- server: Server;
28
+ override options: GetMoreOptions;
26
29
 
27
30
  constructor(ns: MongoDBNamespace, cursorId: Long, server: Server, options: GetMoreOptions = {}) {
28
31
  super(options);
32
+
29
33
  this.options = options;
34
+
35
+ // comment on getMore is only supported for server versions 4.4 and above
36
+ if (maxWireVersion(server) < 9) {
37
+ delete this.options.comment;
38
+ }
39
+
30
40
  this.ns = ns;
31
41
  this.cursorId = cursorId;
32
42
  this.server = server;
@@ -36,7 +46,11 @@ export class GetMoreOperation extends AbstractOperation {
36
46
  * Although there is a server already associated with the get more operation, the signature
37
47
  * for execute passes a server so we will just use that one.
38
48
  */
39
- execute(server: Server, session: ClientSession, callback: Callback<Document>): void {
49
+ override execute(
50
+ server: Server,
51
+ session: ClientSession | undefined,
52
+ callback: Callback<Document>
53
+ ): void {
40
54
  if (server !== this.server) {
41
55
  return callback(
42
56
  new MongoRuntimeError('Getmore must run on the same server operation began on')