mongodb 6.18.0-dev.20250802.sha.be7f808c → 6.18.0-dev.20250806.sha.e628296a

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 (62) hide show
  1. package/lib/beta.d.ts +4 -1
  2. package/lib/cmap/connection.js.map +1 -1
  3. package/lib/cursor/aggregation_cursor.js +2 -1
  4. package/lib/cursor/aggregation_cursor.js.map +1 -1
  5. package/lib/cursor/explainable_cursor.js +36 -0
  6. package/lib/cursor/explainable_cursor.js.map +1 -0
  7. package/lib/cursor/find_cursor.js +2 -1
  8. package/lib/cursor/find_cursor.js.map +1 -1
  9. package/lib/explain.js +1 -33
  10. package/lib/explain.js.map +1 -1
  11. package/lib/index.js +6 -6
  12. package/lib/index.js.map +1 -1
  13. package/lib/operations/aggregate.js +10 -8
  14. package/lib/operations/aggregate.js.map +1 -1
  15. package/lib/operations/command.js +68 -6
  16. package/lib/operations/command.js.map +1 -1
  17. package/lib/operations/drop.js +2 -1
  18. package/lib/operations/drop.js.map +1 -1
  19. package/lib/operations/execute_operation.js +15 -2
  20. package/lib/operations/execute_operation.js.map +1 -1
  21. package/lib/operations/find.js +13 -24
  22. package/lib/operations/find.js.map +1 -1
  23. package/lib/operations/get_more.js +11 -12
  24. package/lib/operations/get_more.js.map +1 -1
  25. package/lib/operations/indexes.js +8 -4
  26. package/lib/operations/indexes.js.map +1 -1
  27. package/lib/operations/insert.js +18 -3
  28. package/lib/operations/insert.js.map +1 -1
  29. package/lib/operations/kill_cursors.js +14 -16
  30. package/lib/operations/kill_cursors.js.map +1 -1
  31. package/lib/operations/list_collections.js +8 -7
  32. package/lib/operations/list_collections.js.map +1 -1
  33. package/lib/operations/operation.js +39 -2
  34. package/lib/operations/operation.js.map +1 -1
  35. package/lib/operations/search_indexes/drop.js +17 -10
  36. package/lib/operations/search_indexes/drop.js.map +1 -1
  37. package/lib/sdam/server.js +86 -7
  38. package/lib/sdam/server.js.map +1 -1
  39. package/lib/sdam/topology.js +3 -2
  40. package/lib/sdam/topology.js.map +1 -1
  41. package/mongodb.d.ts +4 -1
  42. package/package.json +1 -1
  43. package/src/cmap/connection.ts +0 -1
  44. package/src/cursor/aggregation_cursor.ts +1 -1
  45. package/src/cursor/explainable_cursor.ts +51 -0
  46. package/src/cursor/find_cursor.ts +1 -1
  47. package/src/explain.ts +0 -49
  48. package/src/index.ts +8 -3
  49. package/src/operations/aggregate.ts +21 -22
  50. package/src/operations/command.ts +90 -9
  51. package/src/operations/drop.ts +2 -1
  52. package/src/operations/execute_operation.ts +20 -3
  53. package/src/operations/find.ts +28 -49
  54. package/src/operations/get_more.ts +18 -20
  55. package/src/operations/indexes.ts +13 -8
  56. package/src/operations/insert.ts +22 -9
  57. package/src/operations/kill_cursors.ts +22 -23
  58. package/src/operations/list_collections.ts +15 -23
  59. package/src/operations/operation.ts +60 -4
  60. package/src/operations/search_indexes/drop.ts +25 -16
  61. package/src/sdam/server.ts +98 -8
  62. package/src/sdam/topology.ts +4 -3
@@ -1,14 +1,16 @@
1
+ import { type Connection } from '..';
1
2
  import type { Document } from '../bson';
2
3
  import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
3
4
  import { type CursorTimeoutMode } from '../cursor/abstract_cursor';
4
5
  import { MongoInvalidArgumentError } from '../error';
5
6
  import { type ExplainOptions } from '../explain';
6
- import type { Server } from '../sdam/server';
7
- import type { ClientSession } from '../sessions';
8
- import { type TimeoutContext } from '../timeout';
9
7
  import { maxWireVersion, type MongoDBNamespace } from '../utils';
10
8
  import { WriteConcern } from '../write_concern';
11
- import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
9
+ import {
10
+ type CollationOptions,
11
+ type CommandOperationOptions,
12
+ ModernizedCommandOperation
13
+ } from './command';
12
14
  import { Aspect, defineAspects, type Hint } from './operation';
13
15
 
14
16
  /** @internal */
@@ -51,7 +53,8 @@ export interface AggregateOptions extends Omit<CommandOperationOptions, 'explain
51
53
  }
52
54
 
53
55
  /** @internal */
54
- export class AggregateOperation extends CommandOperation<CursorResponse> {
56
+ export class AggregateOperation extends ModernizedCommandOperation<CursorResponse> {
57
+ override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;
55
58
  override options: AggregateOptions;
56
59
  target: string | typeof DB_AGGREGATE_COLLECTION;
57
60
  pipeline: Document[];
@@ -79,9 +82,7 @@ export class AggregateOperation extends CommandOperation<CursorResponse> {
79
82
  }
80
83
  }
81
84
 
82
- if (this.hasWriteStage) {
83
- this.trySecondaryWrite = true;
84
- } else {
85
+ if (!this.hasWriteStage) {
85
86
  delete this.options.writeConcern;
86
87
  }
87
88
 
@@ -94,6 +95,8 @@ export class AggregateOperation extends CommandOperation<CursorResponse> {
94
95
  if (options?.cursor != null && typeof options.cursor !== 'object') {
95
96
  throw new MongoInvalidArgumentError('Cursor options must be an object');
96
97
  }
98
+
99
+ this.SERVER_COMMAND_RESPONSE_TYPE = this.explain ? ExplainedCursorResponse : CursorResponse;
97
100
  }
98
101
 
99
102
  override get commandName() {
@@ -108,13 +111,9 @@ export class AggregateOperation extends CommandOperation<CursorResponse> {
108
111
  this.pipeline.push(stage);
109
112
  }
110
113
 
111
- override async execute(
112
- server: Server,
113
- session: ClientSession | undefined,
114
- timeoutContext: TimeoutContext
115
- ): Promise<CursorResponse> {
116
- const options: AggregateOptions = this.options;
117
- const serverWireVersion = maxWireVersion(server);
114
+ override buildCommandDocument(connection: Connection): Document {
115
+ const options = this.options;
116
+ const serverWireVersion = maxWireVersion(connection);
118
117
  const command: Document = { aggregate: this.target, pipeline: this.pipeline };
119
118
 
120
119
  if (this.hasWriteStage && serverWireVersion < MIN_WIRE_VERSION_$OUT_READ_CONCERN_SUPPORT) {
@@ -152,13 +151,13 @@ export class AggregateOperation extends CommandOperation<CursorResponse> {
152
151
  command.cursor.batchSize = options.batchSize;
153
152
  }
154
153
 
155
- return await super.executeCommand(
156
- server,
157
- session,
158
- command,
159
- timeoutContext,
160
- this.explain ? ExplainedCursorResponse : CursorResponse
161
- );
154
+ return command;
155
+ }
156
+
157
+ override handleOk(
158
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
159
+ ): CursorResponse {
160
+ return response;
162
161
  }
163
162
  }
164
163
 
@@ -1,3 +1,4 @@
1
+ import { type Connection } from '..';
1
2
  import type { BSONSerializeOptions, Document } from '../bson';
2
3
  import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
3
4
  import { MongoInvalidArgumentError } from '../error';
@@ -9,14 +10,13 @@ import {
9
10
  } from '../explain';
10
11
  import { ReadConcern } from '../read_concern';
11
12
  import type { ReadPreference } from '../read_preference';
12
- import type { Server } from '../sdam/server';
13
- import { MIN_SECONDARY_WRITE_WIRE_VERSION } from '../sdam/server_selection';
13
+ import type { Server, ServerCommandOptions } from '../sdam/server';
14
14
  import type { ClientSession } from '../sessions';
15
15
  import { type TimeoutContext } from '../timeout';
16
- import { commandSupportsReadConcern, maxWireVersion, MongoDBNamespace } from '../utils';
16
+ import { commandSupportsReadConcern, MongoDBNamespace } from '../utils';
17
17
  import { WriteConcern, type WriteConcernOptions } from '../write_concern';
18
18
  import type { ReadConcernLike } from './../read_concern';
19
- import { AbstractOperation, Aspect, type OperationOptions } from './operation';
19
+ import { AbstractOperation, Aspect, ModernizedOperation, type OperationOptions } from './operation';
20
20
 
21
21
  /** @public */
22
22
  export interface CollationOptions {
@@ -149,17 +149,12 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
149
149
  session
150
150
  };
151
151
 
152
- const serverWireVersion = maxWireVersion(server);
153
152
  const inTransaction = this.session && this.session.inTransaction();
154
153
 
155
154
  if (this.readConcern && commandSupportsReadConcern(cmd) && !inTransaction) {
156
155
  Object.assign(cmd, { readConcern: this.readConcern });
157
156
  }
158
157
 
159
- if (this.trySecondaryWrite && serverWireVersion < MIN_SECONDARY_WRITE_WIRE_VERSION) {
160
- options.omitReadPreference = true;
161
- }
162
-
163
158
  if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION) && !inTransaction) {
164
159
  WriteConcern.apply(cmd, this.writeConcern);
165
160
  }
@@ -183,3 +178,89 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
183
178
  return await server.command(this.ns, cmd, options, responseType);
184
179
  }
185
180
  }
181
+
182
+ /** @internal */
183
+ export abstract class ModernizedCommandOperation<T> extends ModernizedOperation<T> {
184
+ override options: CommandOperationOptions;
185
+ readConcern?: ReadConcern;
186
+ writeConcern?: WriteConcern;
187
+ explain?: Explain;
188
+
189
+ constructor(parent?: OperationParent, options?: CommandOperationOptions) {
190
+ super(options);
191
+ this.options = options ?? {};
192
+
193
+ // NOTE: this was explicitly added for the add/remove user operations, it's likely
194
+ // something we'd want to reconsider. Perhaps those commands can use `Admin`
195
+ // as a parent?
196
+ const dbNameOverride = options?.dbName || options?.authdb;
197
+ if (dbNameOverride) {
198
+ this.ns = new MongoDBNamespace(dbNameOverride, '$cmd');
199
+ } else {
200
+ this.ns = parent
201
+ ? parent.s.namespace.withCollection('$cmd')
202
+ : new MongoDBNamespace('admin', '$cmd');
203
+ }
204
+
205
+ this.readConcern = ReadConcern.fromOptions(options);
206
+ this.writeConcern = WriteConcern.fromOptions(options);
207
+
208
+ if (this.hasAspect(Aspect.EXPLAINABLE)) {
209
+ this.explain = Explain.fromOptions(options);
210
+ if (this.explain) validateExplainTimeoutOptions(this.options, this.explain);
211
+ } else if (options?.explain != null) {
212
+ throw new MongoInvalidArgumentError(`Option "explain" is not supported on this command`);
213
+ }
214
+ }
215
+
216
+ override get canRetryWrite(): boolean {
217
+ if (this.hasAspect(Aspect.EXPLAINABLE)) {
218
+ return this.explain == null;
219
+ }
220
+ return super.canRetryWrite;
221
+ }
222
+
223
+ abstract buildCommandDocument(connection: Connection, session?: ClientSession): Document;
224
+
225
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
226
+ return {
227
+ ...this.options,
228
+ ...this.bsonOptions,
229
+ timeoutContext,
230
+ readPreference: this.readPreference,
231
+ session: this.session
232
+ };
233
+ }
234
+
235
+ override buildCommand(connection: Connection, session?: ClientSession): Document {
236
+ const command = this.buildCommandDocument(connection, session);
237
+
238
+ const inTransaction = this.session && this.session.inTransaction();
239
+
240
+ if (this.readConcern && commandSupportsReadConcern(command) && !inTransaction) {
241
+ Object.assign(command, { readConcern: this.readConcern });
242
+ }
243
+
244
+ if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION) && !inTransaction) {
245
+ WriteConcern.apply(command, this.writeConcern);
246
+ }
247
+
248
+ if (
249
+ this.options.collation &&
250
+ typeof this.options.collation === 'object' &&
251
+ !this.hasAspect(Aspect.SKIP_COLLATION)
252
+ ) {
253
+ Object.assign(command, { collation: this.options.collation });
254
+ }
255
+
256
+ if (typeof this.options.maxTimeMS === 'number') {
257
+ command.maxTimeMS = this.options.maxTimeMS;
258
+ }
259
+
260
+ if (this.hasAspect(Aspect.EXPLAINABLE) && this.explain) {
261
+ return decorateWithExplain(command, this.explain);
262
+ }
263
+
264
+ return command;
265
+ }
266
+ }
@@ -1,7 +1,8 @@
1
+ import { MongoServerError } from '..';
1
2
  import type { Document } from '../bson';
2
3
  import { CursorTimeoutContext } from '../cursor/abstract_cursor';
3
4
  import type { Db } from '../db';
4
- import { MONGODB_ERROR_CODES, MongoServerError } from '../error';
5
+ import { MONGODB_ERROR_CODES } from '../error';
5
6
  import type { Server } from '../sdam/server';
6
7
  import type { ClientSession } from '../sessions';
7
8
  import { TimeoutContext } from '../timeout';
@@ -26,7 +26,8 @@ import type { Topology } from '../sdam/topology';
26
26
  import type { ClientSession } from '../sessions';
27
27
  import { TimeoutContext } from '../timeout';
28
28
  import { abortable, supportsRetryableWrites } from '../utils';
29
- import { AbstractOperation, Aspect } from './operation';
29
+ import { AggregateOperation } from './aggregate';
30
+ import { AbstractOperation, Aspect, ModernizedOperation } from './operation';
30
31
 
31
32
  const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES.IllegalOperation;
32
33
  const MMAPv1_RETRY_WRITES_ERROR_MESSAGE =
@@ -85,6 +86,8 @@ export async function executeOperation<
85
86
  throw new MongoInvalidArgumentError('ClientSession must be from the same MongoClient');
86
87
  }
87
88
 
89
+ operation.session ??= session;
90
+
88
91
  const readPreference = operation.readPreference ?? ReadPreference.primary;
89
92
  const inTransaction = !!session?.inTransaction();
90
93
 
@@ -190,7 +193,7 @@ async function tryOperation<
190
193
  // server selection to potentially force monitor checks if the server is
191
194
  // in an unknown state.
192
195
  selector = sameServerSelector(operation.server?.description);
193
- } else if (operation.trySecondaryWrite) {
196
+ } else if (operation instanceof AggregateOperation && operation.hasWriteStage) {
194
197
  // If operation should try to write to secondary use the custom server selector
195
198
  // otherwise provide the read preference.
196
199
  selector = secondaryWritableServerSelector(topology.commonWireVersion, readPreference);
@@ -231,6 +234,8 @@ async function tryOperation<
231
234
  let previousOperationError: MongoError | undefined;
232
235
  let previousServer: ServerDescription | undefined;
233
236
 
237
+ const isModernOperation = operation instanceof ModernizedOperation;
238
+
234
239
  for (let tries = 0; tries < maxTries; tries++) {
235
240
  if (previousOperationError) {
236
241
  if (hasWriteAspect && previousOperationError.code === MMAPv1_RETRY_WRITES_ERROR_CODE) {
@@ -276,12 +281,24 @@ async function tryOperation<
276
281
  }
277
282
  }
278
283
 
284
+ operation.server = server;
285
+
279
286
  try {
280
287
  // If tries > 0 and we are command batching we need to reset the batch.
281
288
  if (tries > 0 && operation.hasAspect(Aspect.COMMAND_BATCHING)) {
282
289
  operation.resetBatch();
283
290
  }
284
- return await operation.execute(server, session, timeoutContext);
291
+
292
+ if (!isModernOperation) {
293
+ return await operation.execute(server, session, timeoutContext);
294
+ }
295
+
296
+ try {
297
+ const result = await server.modernCommand(operation, timeoutContext);
298
+ return operation.handleOk(result);
299
+ } catch (error) {
300
+ return operation.handleError(error);
301
+ }
285
302
  } catch (operationError) {
286
303
  if (!(operationError instanceof MongoError)) throw operationError;
287
304
  if (
@@ -2,18 +2,16 @@ import type { Document } from '../bson';
2
2
  import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
3
3
  import { type AbstractCursorOptions, type CursorTimeoutMode } from '../cursor/abstract_cursor';
4
4
  import { MongoInvalidArgumentError } from '../error';
5
- import {
6
- decorateWithExplain,
7
- type ExplainOptions,
8
- validateExplainTimeoutOptions
9
- } from '../explain';
10
- import { ReadConcern } from '../read_concern';
11
- import type { Server } from '../sdam/server';
12
- import type { ClientSession } from '../sessions';
5
+ import { type ExplainOptions } from '../explain';
6
+ import type { ServerCommandOptions } from '../sdam/server';
13
7
  import { formatSort, type Sort } from '../sort';
14
8
  import { type TimeoutContext } from '../timeout';
15
9
  import { type MongoDBNamespace, normalizeHintField } from '../utils';
16
- import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
10
+ import {
11
+ type CollationOptions,
12
+ type CommandOperationOptions,
13
+ ModernizedCommandOperation
14
+ } from './command';
17
15
  import { Aspect, defineAspects, type Hint } from './operation';
18
16
 
19
17
  /**
@@ -92,7 +90,9 @@ export interface FindOneOptions extends FindOptions {
92
90
  }
93
91
 
94
92
  /** @internal */
95
- export class FindOperation extends CommandOperation<CursorResponse> {
93
+ export class FindOperation extends ModernizedCommandOperation<CursorResponse> {
94
+ override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;
95
+
96
96
  /**
97
97
  * @remarks WriteConcern can still be present on the options because
98
98
  * we inherit options from the client/db/collection. The
@@ -116,39 +116,32 @@ export class FindOperation extends CommandOperation<CursorResponse> {
116
116
 
117
117
  // special case passing in an ObjectId as a filter
118
118
  this.filter = filter != null && filter._bsontype === 'ObjectId' ? { _id: filter } : filter;
119
+
120
+ this.SERVER_COMMAND_RESPONSE_TYPE = this.explain ? ExplainedCursorResponse : CursorResponse;
119
121
  }
120
122
 
121
123
  override get commandName() {
122
124
  return 'find' as const;
123
125
  }
124
126
 
125
- override async execute(
126
- server: Server,
127
- session: ClientSession | undefined,
128
- timeoutContext: TimeoutContext
129
- ): Promise<CursorResponse> {
130
- this.server = server;
131
-
132
- const options = this.options;
127
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
128
+ return {
129
+ ...this.options,
130
+ ...this.bsonOptions,
131
+ documentsReturnedIn: 'firstBatch',
132
+ session: this.session,
133
+ timeoutContext
134
+ };
135
+ }
133
136
 
134
- let findCommand = makeFindCommand(this.ns, this.filter, options);
135
- if (this.explain) {
136
- validateExplainTimeoutOptions(this.options, this.explain);
137
- findCommand = decorateWithExplain(findCommand, this.explain);
138
- }
137
+ override handleOk(
138
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
139
+ ): CursorResponse {
140
+ return response;
141
+ }
139
142
 
140
- return await server.command(
141
- this.ns,
142
- findCommand,
143
- {
144
- ...this.options,
145
- ...this.bsonOptions,
146
- documentsReturnedIn: 'firstBatch',
147
- session,
148
- timeoutContext
149
- },
150
- this.explain ? ExplainedCursorResponse : CursorResponse
151
- );
143
+ override buildCommandDocument(): Document {
144
+ return makeFindCommand(this.ns, this.filter, this.options);
152
145
  }
153
146
  }
154
147
 
@@ -217,15 +210,6 @@ function makeFindCommand(ns: MongoDBNamespace, filter: Document, options: FindOp
217
210
  findCommand.comment = options.comment;
218
211
  }
219
212
 
220
- if (typeof options.maxTimeMS === 'number') {
221
- findCommand.maxTimeMS = options.maxTimeMS;
222
- }
223
-
224
- const readConcern = ReadConcern.fromOptions(options);
225
- if (readConcern) {
226
- findCommand.readConcern = readConcern.toJSON();
227
- }
228
-
229
213
  if (options.max) {
230
214
  findCommand.max = options.max;
231
215
  }
@@ -263,11 +247,6 @@ function makeFindCommand(ns: MongoDBNamespace, filter: Document, options: FindOp
263
247
  if (typeof options.allowPartialResults === 'boolean') {
264
248
  findCommand.allowPartialResults = options.allowPartialResults;
265
249
  }
266
-
267
- if (options.collation) {
268
- findCommand.collation = options.collation;
269
- }
270
-
271
250
  if (typeof options.allowDiskUse === 'boolean') {
272
251
  findCommand.allowDiskUse = options.allowDiskUse;
273
252
  }
@@ -1,11 +1,11 @@
1
- import type { Long } from '../bson';
1
+ import type { Document, Long } from '../bson';
2
+ import { type Connection } from '../cmap/connection';
2
3
  import { CursorResponse } from '../cmap/wire_protocol/responses';
3
4
  import { MongoRuntimeError } from '../error';
4
- import type { Server } from '../sdam/server';
5
- import type { ClientSession } from '../sessions';
5
+ import type { Server, ServerCommandOptions } from '../sdam/server';
6
6
  import { type TimeoutContext } from '../timeout';
7
7
  import { maxWireVersion, type MongoDBNamespace } from '../utils';
8
- import { AbstractOperation, Aspect, defineAspects, type OperationOptions } from './operation';
8
+ import { Aspect, defineAspects, ModernizedOperation, type OperationOptions } from './operation';
9
9
 
10
10
  /** @internal */
11
11
  export interface GetMoreOptions extends OperationOptions {
@@ -37,7 +37,8 @@ export interface GetMoreCommand {
37
37
  }
38
38
 
39
39
  /** @internal */
40
- export class GetMoreOperation extends AbstractOperation {
40
+ export class GetMoreOperation extends ModernizedOperation<CursorResponse> {
41
+ override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;
41
42
  cursorId: Long;
42
43
  override options: GetMoreOptions;
43
44
 
@@ -53,19 +54,8 @@ export class GetMoreOperation extends AbstractOperation {
53
54
  override get commandName() {
54
55
  return 'getMore' as const;
55
56
  }
56
- /**
57
- * Although there is a server already associated with the get more operation, the signature
58
- * for execute passes a server so we will just use that one.
59
- */
60
- override async execute(
61
- server: Server,
62
- _session: ClientSession | undefined,
63
- timeoutContext: TimeoutContext
64
- ): Promise<CursorResponse> {
65
- if (server !== this.server) {
66
- throw new MongoRuntimeError('Getmore must run on the same server operation began on');
67
- }
68
57
 
58
+ override buildCommand(connection: Connection): Document {
69
59
  if (this.cursorId == null || this.cursorId.isZero()) {
70
60
  throw new MongoRuntimeError('Unable to iterate cursor with no id');
71
61
  }
@@ -92,18 +82,26 @@ export class GetMoreOperation extends AbstractOperation {
92
82
 
93
83
  // we check for undefined specifically here to allow falsy values
94
84
  // eslint-disable-next-line no-restricted-syntax
95
- if (this.options.comment !== undefined && maxWireVersion(server) >= 9) {
85
+ if (this.options.comment !== undefined && maxWireVersion(connection) >= 9) {
96
86
  getMoreCmd.comment = this.options.comment;
97
87
  }
98
88
 
99
- const commandOptions = {
89
+ return getMoreCmd;
90
+ }
91
+
92
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
93
+ return {
100
94
  returnFieldSelector: null,
101
95
  documentsReturnedIn: 'nextBatch',
102
96
  timeoutContext,
103
97
  ...this.options
104
98
  };
99
+ }
105
100
 
106
- return await server.command(this.ns, getMoreCmd, commandOptions, CursorResponse);
101
+ override handleOk(
102
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
103
+ ): CursorResponse {
104
+ return response;
107
105
  }
108
106
  }
109
107
 
@@ -1,4 +1,5 @@
1
1
  import type { Document } from '../bson';
2
+ import { type Connection } from '../cmap/connection';
2
3
  import { CursorResponse } from '../cmap/wire_protocol/responses';
3
4
  import type { Collection } from '../collection';
4
5
  import { type AbstractCursorOptions } from '../cursor/abstract_cursor';
@@ -12,6 +13,7 @@ import {
12
13
  type CollationOptions,
13
14
  CommandOperation,
14
15
  type CommandOperationOptions,
16
+ ModernizedCommandOperation,
15
17
  type OperationParent
16
18
  } from './command';
17
19
  import { Aspect, defineAspects } from './operation';
@@ -366,7 +368,8 @@ export type ListIndexesOptions = AbstractCursorOptions & {
366
368
  };
367
369
 
368
370
  /** @internal */
369
- export class ListIndexesOperation extends CommandOperation<CursorResponse> {
371
+ export class ListIndexesOperation extends ModernizedCommandOperation<CursorResponse> {
372
+ override SERVER_COMMAND_RESPONSE_TYPE = CursorResponse;
370
373
  /**
371
374
  * @remarks WriteConcern can still be present on the options because
372
375
  * we inherit options from the client/db/collection. The
@@ -389,12 +392,8 @@ export class ListIndexesOperation extends CommandOperation<CursorResponse> {
389
392
  return 'listIndexes' as const;
390
393
  }
391
394
 
392
- override async execute(
393
- server: Server,
394
- session: ClientSession | undefined,
395
- timeoutContext: TimeoutContext
396
- ): Promise<CursorResponse> {
397
- const serverWireVersion = maxWireVersion(server);
395
+ override buildCommandDocument(connection: Connection): Document {
396
+ const serverWireVersion = maxWireVersion(connection);
398
397
 
399
398
  const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {};
400
399
 
@@ -406,7 +405,13 @@ export class ListIndexesOperation extends CommandOperation<CursorResponse> {
406
405
  command.comment = this.options.comment;
407
406
  }
408
407
 
409
- return await super.executeCommand(server, session, command, timeoutContext, CursorResponse);
408
+ return command;
409
+ }
410
+
411
+ override handleOk(
412
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
413
+ ): CursorResponse {
414
+ return response;
410
415
  }
411
416
  }
412
417
 
@@ -1,5 +1,7 @@
1
+ import { type Connection } from '..';
1
2
  import type { Document } from '../bson';
2
3
  import type { BulkWriteOptions } from '../bulk/common';
4
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
3
5
  import type { Collection } from '../collection';
4
6
  import { MongoServerError } from '../error';
5
7
  import type { InferIdType } from '../mongo_types';
@@ -7,12 +9,13 @@ import type { Server } from '../sdam/server';
7
9
  import type { ClientSession } from '../sessions';
8
10
  import { type TimeoutContext } from '../timeout';
9
11
  import { maybeAddIdToDocuments, type MongoDBNamespace } from '../utils';
10
- import { CommandOperation, type CommandOperationOptions } from './command';
12
+ import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
11
13
  import { Aspect, defineAspects } from './operation';
12
-
13
14
  /** @internal */
14
- export class InsertOperation extends CommandOperation<Document> {
15
+ export class InsertOperation extends ModernizedCommandOperation<Document> {
16
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
15
17
  override options: BulkWriteOptions;
18
+
16
19
  documents: Document[];
17
20
 
18
21
  constructor(ns: MongoDBNamespace, documents: Document[], options: BulkWriteOptions) {
@@ -26,11 +29,7 @@ export class InsertOperation extends CommandOperation<Document> {
26
29
  return 'insert' as const;
27
30
  }
28
31
 
29
- override async execute(
30
- server: Server,
31
- session: ClientSession | undefined,
32
- timeoutContext: TimeoutContext
33
- ): Promise<Document> {
32
+ override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
34
33
  const options = this.options ?? {};
35
34
  const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
36
35
  const command: Document = {
@@ -49,7 +48,7 @@ export class InsertOperation extends CommandOperation<Document> {
49
48
  command.comment = options.comment;
50
49
  }
51
50
 
52
- return await super.executeCommand(server, session, command, timeoutContext);
51
+ return command;
53
52
  }
54
53
  }
55
54
 
@@ -91,6 +90,20 @@ export class InsertOneOperation extends InsertOperation {
91
90
  insertedId: this.documents[0]._id
92
91
  };
93
92
  }
93
+
94
+ override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): Document {
95
+ const res = super.handleOk(response);
96
+ if (res.code) throw new MongoServerError(res);
97
+ if (res.writeErrors) {
98
+ // This should be a WriteError but we can't change it now because of error hierarchy
99
+ throw new MongoServerError(res.writeErrors[0]);
100
+ }
101
+
102
+ return {
103
+ acknowledged: this.writeConcern?.w !== 0,
104
+ insertedId: this.documents[0]._id
105
+ };
106
+ }
94
107
  }
95
108
 
96
109
  /** @public */