mongodb 6.18.0-dev.20250806.sha.e628296a → 6.18.0-dev.20250814.sha.33d340ef

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 (54) hide show
  1. package/lib/collection.js +5 -5
  2. package/lib/collection.js.map +1 -1
  3. package/lib/operations/client_bulk_write/client_bulk_write.js +9 -42
  4. package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -1
  5. package/lib/operations/count.js +8 -4
  6. package/lib/operations/count.js.map +1 -1
  7. package/lib/operations/create_collection.js +17 -20
  8. package/lib/operations/create_collection.js.map +1 -1
  9. package/lib/operations/delete.js +16 -13
  10. package/lib/operations/delete.js.map +1 -1
  11. package/lib/operations/drop.js +13 -6
  12. package/lib/operations/drop.js.map +1 -1
  13. package/lib/operations/estimated_document_count.js +8 -4
  14. package/lib/operations/estimated_document_count.js.map +1 -1
  15. package/lib/operations/execute_operation.js.map +1 -1
  16. package/lib/operations/find_and_modify.js +53 -42
  17. package/lib/operations/find_and_modify.js.map +1 -1
  18. package/lib/operations/indexes.js +16 -11
  19. package/lib/operations/indexes.js.map +1 -1
  20. package/lib/operations/insert.js +0 -13
  21. package/lib/operations/insert.js.map +1 -1
  22. package/lib/operations/list_databases.js +6 -4
  23. package/lib/operations/list_databases.js.map +1 -1
  24. package/lib/operations/rename.js +11 -9
  25. package/lib/operations/rename.js.map +1 -1
  26. package/lib/operations/search_indexes/create.js +12 -9
  27. package/lib/operations/search_indexes/create.js.map +1 -1
  28. package/lib/operations/search_indexes/update.js +12 -5
  29. package/lib/operations/search_indexes/update.js.map +1 -1
  30. package/lib/operations/update.js +23 -20
  31. package/lib/operations/update.js.map +1 -1
  32. package/lib/operations/validate_collection.js +18 -19
  33. package/lib/operations/validate_collection.js.map +1 -1
  34. package/lib/sdam/server.js +25 -15
  35. package/lib/sdam/server.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/collection.ts +7 -22
  38. package/src/operations/client_bulk_write/client_bulk_write.ts +23 -67
  39. package/src/operations/count.ts +11 -11
  40. package/src/operations/create_collection.ts +22 -31
  41. package/src/operations/delete.ts +32 -36
  42. package/src/operations/drop.ts +18 -17
  43. package/src/operations/estimated_document_count.ts +10 -11
  44. package/src/operations/execute_operation.ts +7 -6
  45. package/src/operations/find_and_modify.ts +80 -56
  46. package/src/operations/indexes.ts +17 -26
  47. package/src/operations/insert.ts +0 -20
  48. package/src/operations/list_databases.ts +8 -17
  49. package/src/operations/rename.ts +13 -16
  50. package/src/operations/search_indexes/create.ts +16 -16
  51. package/src/operations/search_indexes/update.ts +16 -11
  52. package/src/operations/update.ts +55 -54
  53. package/src/operations/validate_collection.ts +21 -29
  54. package/src/sdam/server.ts +25 -15
@@ -1,17 +1,13 @@
1
1
  import type { Document } from '../bson';
2
2
  import { type Connection } from '../cmap/connection';
3
- import { CursorResponse } from '../cmap/wire_protocol/responses';
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
6
  import { MongoCompatibilityError } from '../error';
7
7
  import { type OneOrMore } from '../mongo_types';
8
- import type { Server } from '../sdam/server';
9
- import type { ClientSession } from '../sessions';
10
- import { type TimeoutContext } from '../timeout';
11
8
  import { isObject, maxWireVersion, type MongoDBNamespace } from '../utils';
12
9
  import {
13
10
  type CollationOptions,
14
- CommandOperation,
15
11
  type CommandOperationOptions,
16
12
  ModernizedCommandOperation,
17
13
  type OperationParent
@@ -246,7 +242,8 @@ type ResolvedIndexDescription = Omit<IndexDescription, 'key' | 'version'> & {
246
242
  };
247
243
 
248
244
  /** @internal */
249
- export class CreateIndexesOperation extends CommandOperation<string[]> {
245
+ export class CreateIndexesOperation extends ModernizedCommandOperation<string[]> {
246
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
250
247
  override options: CreateIndexesOptions;
251
248
  collectionName: string;
252
249
  indexes: ReadonlyArray<ResolvedIndexDescription>;
@@ -260,6 +257,8 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
260
257
  super(parent, options);
261
258
 
262
259
  this.options = options ?? {};
260
+ // collation is set on each index, it should not be defined at the root
261
+ this.options.collation = undefined;
263
262
  this.collectionName = collectionName;
264
263
  this.indexes = indexes.map((userIndex: IndexDescription): ResolvedIndexDescription => {
265
264
  // Ensure the key is a Map to preserve index key ordering
@@ -273,6 +272,7 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
273
272
  key
274
273
  };
275
274
  });
275
+ this.ns = parent.s.namespace;
276
276
  }
277
277
 
278
278
  static fromIndexDescriptionArray(
@@ -299,15 +299,11 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
299
299
  return 'createIndexes';
300
300
  }
301
301
 
302
- override async execute(
303
- server: Server,
304
- session: ClientSession | undefined,
305
- timeoutContext: TimeoutContext
306
- ): Promise<string[]> {
302
+ override buildCommandDocument(connection: Connection): Document {
307
303
  const options = this.options;
308
304
  const indexes = this.indexes;
309
305
 
310
- const serverWireVersion = maxWireVersion(server);
306
+ const serverWireVersion = maxWireVersion(connection);
311
307
 
312
308
  const cmd: Document = { createIndexes: this.collectionName, indexes };
313
309
 
@@ -319,13 +315,11 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
319
315
  }
320
316
  cmd.commitQuorum = options.commitQuorum;
321
317
  }
318
+ return cmd;
319
+ }
322
320
 
323
- // collation is set on each index, it should not be defined at the root
324
- this.options.collation = undefined;
325
-
326
- await super.executeCommand(server, session, cmd, timeoutContext);
327
-
328
- const indexNames = indexes.map(index => index.name || '');
321
+ override handleOk(_response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): string[] {
322
+ const indexNames = this.indexes.map(index => index.name || '');
329
323
  return indexNames;
330
324
  }
331
325
  }
@@ -334,7 +328,8 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
334
328
  export type DropIndexesOptions = CommandOperationOptions;
335
329
 
336
330
  /** @internal */
337
- export class DropIndexOperation extends CommandOperation<Document> {
331
+ export class DropIndexOperation extends ModernizedCommandOperation<Document> {
332
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
338
333
  override options: DropIndexesOptions;
339
334
  collection: Collection;
340
335
  indexName: string;
@@ -345,19 +340,15 @@ export class DropIndexOperation extends CommandOperation<Document> {
345
340
  this.options = options ?? {};
346
341
  this.collection = collection;
347
342
  this.indexName = indexName;
343
+ this.ns = collection.fullNamespace;
348
344
  }
349
345
 
350
346
  override get commandName() {
351
347
  return 'dropIndexes' as const;
352
348
  }
353
349
 
354
- override async execute(
355
- server: Server,
356
- session: ClientSession | undefined,
357
- timeoutContext: TimeoutContext
358
- ): Promise<Document> {
359
- const cmd = { dropIndexes: this.collection.collectionName, index: this.indexName };
360
- return await super.executeCommand(server, session, cmd, timeoutContext);
350
+ override buildCommandDocument(_connection: Connection): Document {
351
+ return { dropIndexes: this.collection.collectionName, index: this.indexName };
361
352
  }
362
353
  }
363
354
 
@@ -5,9 +5,7 @@ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
5
5
  import type { Collection } from '../collection';
6
6
  import { MongoServerError } from '../error';
7
7
  import type { InferIdType } from '../mongo_types';
8
- import type { Server } from '../sdam/server';
9
8
  import type { ClientSession } from '../sessions';
10
- import { type TimeoutContext } from '../timeout';
11
9
  import { maybeAddIdToDocuments, type MongoDBNamespace } from '../utils';
12
10
  import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
13
11
  import { Aspect, defineAspects } from './operation';
@@ -73,24 +71,6 @@ export class InsertOneOperation extends InsertOperation {
73
71
  super(collection.s.namespace, [maybeAddIdToDocuments(collection, doc, options)], options);
74
72
  }
75
73
 
76
- override async execute(
77
- server: Server,
78
- session: ClientSession | undefined,
79
- timeoutContext: TimeoutContext
80
- ): Promise<InsertOneResult> {
81
- const res = await super.execute(server, session, timeoutContext);
82
- if (res.code) throw new MongoServerError(res);
83
- if (res.writeErrors) {
84
- // This should be a WriteError but we can't change it now because of error hierarchy
85
- throw new MongoServerError(res.writeErrors[0]);
86
- }
87
-
88
- return {
89
- acknowledged: this.writeConcern?.w !== 0,
90
- insertedId: this.documents[0]._id
91
- };
92
- }
93
-
94
74
  override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): Document {
95
75
  const res = super.handleOk(response);
96
76
  if (res.code) throw new MongoServerError(res);
@@ -1,11 +1,10 @@
1
+ import { type Connection } from '..';
1
2
  import type { Document } from '../bson';
3
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
2
4
  import type { Db } from '../db';
3
- import { type TODO_NODE_3286 } from '../mongo_types';
4
- import type { Server } from '../sdam/server';
5
5
  import type { ClientSession } from '../sessions';
6
- import { type TimeoutContext } from '../timeout';
7
6
  import { maxWireVersion, MongoDBNamespace } from '../utils';
8
- import { CommandOperation, type CommandOperationOptions } from './command';
7
+ import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
9
8
  import { Aspect, defineAspects } from './operation';
10
9
 
11
10
  /** @public */
@@ -27,7 +26,8 @@ export interface ListDatabasesOptions extends CommandOperationOptions {
27
26
  }
28
27
 
29
28
  /** @internal */
30
- export class ListDatabasesOperation extends CommandOperation<ListDatabasesResult> {
29
+ export class ListDatabasesOperation extends ModernizedCommandOperation<ListDatabasesResult> {
30
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
31
31
  override options: ListDatabasesOptions;
32
32
 
33
33
  constructor(db: Db, options?: ListDatabasesOptions) {
@@ -40,11 +40,7 @@ export class ListDatabasesOperation extends CommandOperation<ListDatabasesResult
40
40
  return 'listDatabases' as const;
41
41
  }
42
42
 
43
- override async execute(
44
- server: Server,
45
- session: ClientSession | undefined,
46
- timeoutContext: TimeoutContext
47
- ): Promise<ListDatabasesResult> {
43
+ override buildCommandDocument(connection: Connection, _session?: ClientSession): Document {
48
44
  const cmd: Document = { listDatabases: 1 };
49
45
 
50
46
  if (typeof this.options.nameOnly === 'boolean') {
@@ -61,16 +57,11 @@ export class ListDatabasesOperation extends CommandOperation<ListDatabasesResult
61
57
 
62
58
  // we check for undefined specifically here to allow falsy values
63
59
  // eslint-disable-next-line no-restricted-syntax
64
- if (maxWireVersion(server) >= 9 && this.options.comment !== undefined) {
60
+ if (maxWireVersion(connection) >= 9 && this.options.comment !== undefined) {
65
61
  cmd.comment = this.options.comment;
66
62
  }
67
63
 
68
- return await (super.executeCommand(
69
- server,
70
- session,
71
- cmd,
72
- timeoutContext
73
- ) as Promise<TODO_NODE_3286>);
64
+ return cmd;
74
65
  }
75
66
  }
76
67
 
@@ -1,10 +1,10 @@
1
+ import { type Connection } from '..';
1
2
  import type { Document } from '../bson';
3
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
2
4
  import { Collection } from '../collection';
3
- import type { Server } from '../sdam/server';
4
5
  import type { ClientSession } from '../sessions';
5
- import { type TimeoutContext } from '../timeout';
6
6
  import { MongoDBNamespace } from '../utils';
7
- import { CommandOperation, type CommandOperationOptions } from './command';
7
+ import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
8
8
  import { Aspect, defineAspects } from './operation';
9
9
 
10
10
  /** @public */
@@ -16,7 +16,8 @@ export interface RenameOptions extends CommandOperationOptions {
16
16
  }
17
17
 
18
18
  /** @internal */
19
- export class RenameOperation extends CommandOperation<Document> {
19
+ export class RenameOperation extends ModernizedCommandOperation<Document> {
20
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
20
21
  collection: Collection;
21
22
  newName: string;
22
23
  override options: RenameOptions;
@@ -33,24 +34,20 @@ export class RenameOperation extends CommandOperation<Document> {
33
34
  return 'renameCollection' as const;
34
35
  }
35
36
 
36
- override async execute(
37
- server: Server,
38
- session: ClientSession | undefined,
39
- timeoutContext: TimeoutContext
40
- ): Promise<Collection> {
41
- // Build the command
37
+ override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
42
38
  const renameCollection = this.collection.namespace;
43
- const toCollection = this.collection.s.namespace.withCollection(this.newName).toString();
39
+ const to = this.collection.s.namespace.withCollection(this.newName).toString();
44
40
  const dropTarget =
45
41
  typeof this.options.dropTarget === 'boolean' ? this.options.dropTarget : false;
46
42
 
47
- const command = {
48
- renameCollection: renameCollection,
49
- to: toCollection,
50
- dropTarget: dropTarget
43
+ return {
44
+ renameCollection,
45
+ to,
46
+ dropTarget
51
47
  };
48
+ }
52
49
 
53
- await super.executeCommand(server, session, command, timeoutContext);
50
+ override handleOk(_response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): Document {
54
51
  return new Collection(this.collection.s.db, this.newName, this.collection.s.options);
55
52
  }
56
53
  }
@@ -1,9 +1,11 @@
1
- import type { Document } from '../../bson';
1
+ import { type Document } from '../../bson';
2
+ import { type Connection } from '../../cmap/connection';
3
+ import { MongoDBResponse } from '../../cmap/wire_protocol/responses';
2
4
  import type { Collection } from '../../collection';
3
- import type { Server } from '../../sdam/server';
5
+ import type { ServerCommandOptions } from '../../sdam/server';
4
6
  import type { ClientSession } from '../../sessions';
5
7
  import { type TimeoutContext } from '../../timeout';
6
- import { AbstractOperation } from '../operation';
8
+ import { ModernizedOperation } from '../operation';
7
9
 
8
10
  /**
9
11
  * @public
@@ -20,7 +22,8 @@ export interface SearchIndexDescription extends Document {
20
22
  }
21
23
 
22
24
  /** @internal */
23
- export class CreateSearchIndexesOperation extends AbstractOperation<string[]> {
25
+ export class CreateSearchIndexesOperation extends ModernizedOperation<Document> {
26
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
24
27
  private readonly collection: Collection;
25
28
  private readonly descriptions: ReadonlyArray<SearchIndexDescription>;
26
29
 
@@ -28,29 +31,26 @@ export class CreateSearchIndexesOperation extends AbstractOperation<string[]> {
28
31
  super();
29
32
  this.collection = collection;
30
33
  this.descriptions = descriptions;
34
+ this.ns = collection.fullNamespace;
31
35
  }
32
36
 
33
37
  override get commandName() {
34
38
  return 'createSearchIndexes' as const;
35
39
  }
36
40
 
37
- override async execute(
38
- server: Server,
39
- session: ClientSession | undefined,
40
- timeoutContext: TimeoutContext
41
- ): Promise<string[]> {
41
+ override buildCommand(_connection: Connection, _session?: ClientSession): Document {
42
42
  const namespace = this.collection.fullNamespace;
43
- const command = {
43
+ return {
44
44
  createSearchIndexes: namespace.collection,
45
45
  indexes: this.descriptions
46
46
  };
47
+ }
47
48
 
48
- const res = await server.command(namespace, command, {
49
- session,
50
- timeoutContext
51
- });
49
+ override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): string[] {
50
+ return super.handleOk(response).indexesCreated.map((val: { name: string }) => val.name);
51
+ }
52
52
 
53
- const indexesCreated: Array<{ name: string }> = res?.indexesCreated ?? [];
54
- return indexesCreated.map(({ name }) => name);
53
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
54
+ return { session: this.session, timeoutContext };
55
55
  }
56
56
  }
@@ -1,12 +1,15 @@
1
1
  import type { Document } from '../../bson';
2
+ import { type Connection } from '../../cmap/connection';
3
+ import { MongoDBResponse } from '../../cmap/wire_protocol/responses';
2
4
  import type { Collection } from '../../collection';
3
- import type { Server } from '../../sdam/server';
5
+ import type { ServerCommandOptions } from '../../sdam/server';
4
6
  import type { ClientSession } from '../../sessions';
5
7
  import { type TimeoutContext } from '../../timeout';
6
- import { AbstractOperation } from '../operation';
8
+ import { ModernizedOperation } from '../operation';
7
9
 
8
10
  /** @internal */
9
- export class UpdateSearchIndexOperation extends AbstractOperation<void> {
11
+ export class UpdateSearchIndexOperation extends ModernizedOperation<void> {
12
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
10
13
  private readonly collection: Collection;
11
14
  private readonly name: string;
12
15
  private readonly definition: Document;
@@ -16,25 +19,27 @@ export class UpdateSearchIndexOperation extends AbstractOperation<void> {
16
19
  this.collection = collection;
17
20
  this.name = name;
18
21
  this.definition = definition;
22
+ this.ns = collection.fullNamespace;
19
23
  }
20
24
 
21
25
  override get commandName() {
22
26
  return 'updateSearchIndex' as const;
23
27
  }
24
28
 
25
- override async execute(
26
- server: Server,
27
- session: ClientSession | undefined,
28
- timeoutContext: TimeoutContext
29
- ): Promise<void> {
29
+ override buildCommand(_connection: Connection, _session?: ClientSession): Document {
30
30
  const namespace = this.collection.fullNamespace;
31
- const command = {
31
+ return {
32
32
  updateSearchIndex: namespace.collection,
33
33
  name: this.name,
34
34
  definition: this.definition
35
35
  };
36
+ }
37
+
38
+ override handleOk(_response: MongoDBResponse): void {
39
+ // no response.
40
+ }
36
41
 
37
- await server.command(namespace, command, { session, timeoutContext });
38
- return;
42
+ override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
43
+ return { session: this.session, timeoutContext };
39
44
  }
40
45
  }
@@ -1,13 +1,20 @@
1
1
  import type { Document } from '../bson';
2
- import type { Collection } from '../collection';
2
+ import { type Connection } from '../cmap/connection';
3
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
3
4
  import { MongoCompatibilityError, MongoInvalidArgumentError, MongoServerError } from '../error';
4
- import type { InferIdType, TODO_NODE_3286 } from '../mongo_types';
5
- import type { Server } from '../sdam/server';
5
+ import type { InferIdType } from '../mongo_types';
6
6
  import type { ClientSession } from '../sessions';
7
7
  import { formatSort, type Sort, type SortForCmd } from '../sort';
8
- import { type TimeoutContext } from '../timeout';
9
- import { hasAtomicOperators, type MongoDBNamespace } from '../utils';
10
- import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
8
+ import {
9
+ hasAtomicOperators,
10
+ type MongoDBCollectionNamespace,
11
+ type MongoDBNamespace
12
+ } from '../utils';
13
+ import {
14
+ type CollationOptions,
15
+ type CommandOperationOptions,
16
+ ModernizedCommandOperation
17
+ } from './command';
11
18
  import { Aspect, defineAspects, type Hint } from './operation';
12
19
 
13
20
  /** @public */
@@ -67,7 +74,8 @@ export interface UpdateStatement {
67
74
  * @internal
68
75
  * UpdateOperation is used in bulk write, while UpdateOneOperation and UpdateManyOperation are only used in the collections API
69
76
  */
70
- export class UpdateOperation extends CommandOperation<Document> {
77
+ export class UpdateOperation extends ModernizedCommandOperation<Document> {
78
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
71
79
  override options: UpdateOptions & { ordered?: boolean };
72
80
  statements: UpdateStatement[];
73
81
 
@@ -95,17 +103,12 @@ export class UpdateOperation extends CommandOperation<Document> {
95
103
  return this.statements.every(op => op.multi == null || op.multi === false);
96
104
  }
97
105
 
98
- override async execute(
99
- server: Server,
100
- session: ClientSession | undefined,
101
- timeoutContext: TimeoutContext
102
- ): Promise<Document> {
103
- const options = this.options ?? {};
104
- const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
106
+ override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
107
+ const options = this.options;
105
108
  const command: Document = {
106
109
  update: this.ns.collection,
107
110
  updates: this.statements,
108
- ordered
111
+ ordered: options.ordered ?? true
109
112
  };
110
113
 
111
114
  if (typeof options.bypassDocumentValidation === 'boolean') {
@@ -122,7 +125,7 @@ export class UpdateOperation extends CommandOperation<Document> {
122
125
  command.comment = options.comment;
123
126
  }
124
127
 
125
- const unacknowledgedWrite = this.writeConcern && this.writeConcern.w === 0;
128
+ const unacknowledgedWrite = this.writeConcern?.w === 0;
126
129
  if (unacknowledgedWrite) {
127
130
  if (this.statements.find((o: Document) => o.hint)) {
128
131
  // TODO(NODE-3541): fix error for hint with unacknowledged writes
@@ -130,32 +133,33 @@ export class UpdateOperation extends CommandOperation<Document> {
130
133
  }
131
134
  }
132
135
 
133
- const res = await super.executeCommand(server, session, command, timeoutContext);
134
- return res;
136
+ return command;
135
137
  }
136
138
  }
137
139
 
138
140
  /** @internal */
139
141
  export class UpdateOneOperation extends UpdateOperation {
140
- constructor(collection: Collection, filter: Document, update: Document, options: UpdateOptions) {
141
- super(
142
- collection.s.namespace,
143
- [makeUpdateStatement(filter, update, { ...options, multi: false })],
144
- options
145
- );
142
+ constructor(
143
+ ns: MongoDBCollectionNamespace,
144
+ filter: Document,
145
+ update: Document,
146
+ options: UpdateOptions
147
+ ) {
148
+ super(ns, [makeUpdateStatement(filter, update, { ...options, multi: false })], options);
146
149
 
147
150
  if (!hasAtomicOperators(update, options)) {
148
151
  throw new MongoInvalidArgumentError('Update document requires atomic operators');
149
152
  }
150
153
  }
151
154
 
152
- override async execute(
153
- server: Server,
154
- session: ClientSession | undefined,
155
- timeoutContext: TimeoutContext
156
- ): Promise<UpdateResult> {
157
- const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
155
+ override handleOk(
156
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
157
+ ): UpdateResult {
158
+ const res = super.handleOk(response);
159
+
160
+ // @ts-expect-error Explain typing is broken
158
161
  if (this.explain != null) return res;
162
+
159
163
  if (res.code) throw new MongoServerError(res);
160
164
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
161
165
 
@@ -172,24 +176,25 @@ export class UpdateOneOperation extends UpdateOperation {
172
176
 
173
177
  /** @internal */
174
178
  export class UpdateManyOperation extends UpdateOperation {
175
- constructor(collection: Collection, filter: Document, update: Document, options: UpdateOptions) {
176
- super(
177
- collection.s.namespace,
178
- [makeUpdateStatement(filter, update, { ...options, multi: true })],
179
- options
180
- );
179
+ constructor(
180
+ ns: MongoDBCollectionNamespace,
181
+ filter: Document,
182
+ update: Document,
183
+ options: UpdateOptions
184
+ ) {
185
+ super(ns, [makeUpdateStatement(filter, update, { ...options, multi: true })], options);
181
186
 
182
187
  if (!hasAtomicOperators(update, options)) {
183
188
  throw new MongoInvalidArgumentError('Update document requires atomic operators');
184
189
  }
185
190
  }
186
191
 
187
- override async execute(
188
- server: Server,
189
- session: ClientSession | undefined,
190
- timeoutContext: TimeoutContext
191
- ): Promise<UpdateResult> {
192
- const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
192
+ override handleOk(
193
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
194
+ ): UpdateResult {
195
+ const res = super.handleOk(response);
196
+
197
+ // @ts-expect-error Explain typing is broken
193
198
  if (this.explain != null) return res;
194
199
  if (res.code) throw new MongoServerError(res);
195
200
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
@@ -224,28 +229,24 @@ export interface ReplaceOptions extends CommandOperationOptions {
224
229
  /** @internal */
225
230
  export class ReplaceOneOperation extends UpdateOperation {
226
231
  constructor(
227
- collection: Collection,
232
+ ns: MongoDBCollectionNamespace,
228
233
  filter: Document,
229
234
  replacement: Document,
230
235
  options: ReplaceOptions
231
236
  ) {
232
- super(
233
- collection.s.namespace,
234
- [makeUpdateStatement(filter, replacement, { ...options, multi: false })],
235
- options
236
- );
237
+ super(ns, [makeUpdateStatement(filter, replacement, { ...options, multi: false })], options);
237
238
 
238
239
  if (hasAtomicOperators(replacement)) {
239
240
  throw new MongoInvalidArgumentError('Replacement document must not contain atomic operators');
240
241
  }
241
242
  }
242
243
 
243
- override async execute(
244
- server: Server,
245
- session: ClientSession | undefined,
246
- timeoutContext: TimeoutContext
247
- ): Promise<UpdateResult> {
248
- const res: TODO_NODE_3286 = await super.execute(server, session, timeoutContext);
244
+ override handleOk(
245
+ response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
246
+ ): UpdateResult {
247
+ const res = super.handleOk(response);
248
+
249
+ // @ts-expect-error Explain typing is broken
249
250
  if (this.explain != null) return res;
250
251
  if (res.code) throw new MongoServerError(res);
251
252
  if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
@@ -1,10 +1,10 @@
1
+ import { type Connection } from '..';
1
2
  import type { Admin } from '../admin';
2
- import type { Document } from '../bson';
3
+ import { type Document } from '../bson';
4
+ import { MongoDBResponse } from '../cmap/wire_protocol/responses';
3
5
  import { MongoUnexpectedServerResponseError } from '../error';
4
- import type { Server } from '../sdam/server';
5
6
  import type { ClientSession } from '../sessions';
6
- import { type TimeoutContext } from '../timeout';
7
- import { CommandOperation, type CommandOperationOptions } from './command';
7
+ import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
8
8
 
9
9
  /** @public */
10
10
  export interface ValidateCollectionOptions extends CommandOperationOptions {
@@ -13,24 +13,14 @@ export interface ValidateCollectionOptions extends CommandOperationOptions {
13
13
  }
14
14
 
15
15
  /** @internal */
16
- export class ValidateCollectionOperation extends CommandOperation<Document> {
16
+ export class ValidateCollectionOperation extends ModernizedCommandOperation<Document> {
17
+ override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
17
18
  override options: ValidateCollectionOptions;
18
19
  collectionName: string;
19
- command: Document;
20
20
 
21
21
  constructor(admin: Admin, collectionName: string, options: ValidateCollectionOptions) {
22
- // Decorate command with extra options
23
- const command: Document = { validate: collectionName };
24
- const keys = Object.keys(options);
25
- for (let i = 0; i < keys.length; i++) {
26
- if (Object.prototype.hasOwnProperty.call(options, keys[i]) && keys[i] !== 'session') {
27
- command[keys[i]] = (options as Document)[keys[i]];
28
- }
29
- }
30
-
31
22
  super(admin.s.db, options);
32
23
  this.options = options;
33
- this.command = command;
34
24
  this.collectionName = collectionName;
35
25
  }
36
26
 
@@ -38,21 +28,23 @@ export class ValidateCollectionOperation extends CommandOperation<Document> {
38
28
  return 'validate' as const;
39
29
  }
40
30
 
41
- override async execute(
42
- server: Server,
43
- session: ClientSession | undefined,
44
- timeoutContext: TimeoutContext
45
- ): Promise<Document> {
46
- const collectionName = this.collectionName;
31
+ override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
32
+ // Decorate command with extra options
33
+ return {
34
+ validate: this.collectionName,
35
+ ...Object.fromEntries(Object.entries(this.options).filter(entry => entry[0] !== 'session'))
36
+ };
37
+ }
47
38
 
48
- const doc = await super.executeCommand(server, session, this.command, timeoutContext);
49
- if (doc.result != null && typeof doc.result !== 'string')
39
+ override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): Document {
40
+ const result = super.handleOk(response);
41
+ if (result.result != null && typeof result.result !== 'string')
50
42
  throw new MongoUnexpectedServerResponseError('Error with validation data');
51
- if (doc.result != null && doc.result.match(/exception|corrupt/) != null)
52
- throw new MongoUnexpectedServerResponseError(`Invalid collection ${collectionName}`);
53
- if (doc.valid != null && !doc.valid)
54
- throw new MongoUnexpectedServerResponseError(`Invalid collection ${collectionName}`);
43
+ if (result.result != null && result.result.match(/exception|corrupt/) != null)
44
+ throw new MongoUnexpectedServerResponseError(`Invalid collection ${this.collectionName}`);
45
+ if (result.valid != null && !result.valid)
46
+ throw new MongoUnexpectedServerResponseError(`Invalid collection ${this.collectionName}`);
55
47
 
56
- return doc;
48
+ return response;
57
49
  }
58
50
  }