mongodb 6.7.0 → 6.8.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 (103) hide show
  1. package/README.md +20 -1
  2. package/lib/bson.js.map +1 -1
  3. package/lib/client-side-encryption/auto_encrypter.js +8 -61
  4. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  5. package/lib/client-side-encryption/client_encryption.js +5 -5
  6. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  7. package/lib/client-side-encryption/providers/index.js.map +1 -1
  8. package/lib/client-side-encryption/state_machine.js +15 -11
  9. package/lib/client-side-encryption/state_machine.js.map +1 -1
  10. package/lib/cmap/connection.js +22 -20
  11. package/lib/cmap/connection.js.map +1 -1
  12. package/lib/cmap/wire_protocol/on_demand/document.js +8 -5
  13. package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
  14. package/lib/cmap/wire_protocol/responses.js +116 -40
  15. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  16. package/lib/collection.js +13 -2
  17. package/lib/collection.js.map +1 -1
  18. package/lib/constants.js +9 -1
  19. package/lib/constants.js.map +1 -1
  20. package/lib/cursor/abstract_cursor.js +231 -285
  21. package/lib/cursor/abstract_cursor.js.map +1 -1
  22. package/lib/cursor/aggregation_cursor.js +11 -19
  23. package/lib/cursor/aggregation_cursor.js.map +1 -1
  24. package/lib/cursor/change_stream_cursor.js +12 -14
  25. package/lib/cursor/change_stream_cursor.js.map +1 -1
  26. package/lib/cursor/find_cursor.js +64 -84
  27. package/lib/cursor/find_cursor.js.map +1 -1
  28. package/lib/cursor/list_collections_cursor.js +0 -1
  29. package/lib/cursor/list_collections_cursor.js.map +1 -1
  30. package/lib/cursor/list_indexes_cursor.js +0 -1
  31. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  32. package/lib/cursor/run_command_cursor.js +4 -6
  33. package/lib/cursor/run_command_cursor.js.map +1 -1
  34. package/lib/error.js +10 -23
  35. package/lib/error.js.map +1 -1
  36. package/lib/index.js.map +1 -1
  37. package/lib/operations/aggregate.js +2 -2
  38. package/lib/operations/aggregate.js.map +1 -1
  39. package/lib/operations/bulk_write.js +1 -2
  40. package/lib/operations/bulk_write.js.map +1 -1
  41. package/lib/operations/command.js +2 -3
  42. package/lib/operations/command.js.map +1 -1
  43. package/lib/operations/execute_operation.js.map +1 -1
  44. package/lib/operations/find.js +2 -1
  45. package/lib/operations/find.js.map +1 -1
  46. package/lib/operations/get_more.js +1 -1
  47. package/lib/operations/get_more.js.map +1 -1
  48. package/lib/operations/indexes.js +2 -1
  49. package/lib/operations/indexes.js.map +1 -1
  50. package/lib/operations/list_collections.js +2 -1
  51. package/lib/operations/list_collections.js.map +1 -1
  52. package/lib/operations/run_command.js +1 -1
  53. package/lib/operations/run_command.js.map +1 -1
  54. package/lib/operations/update.js +2 -1
  55. package/lib/operations/update.js.map +1 -1
  56. package/lib/sdam/server.js +7 -2
  57. package/lib/sdam/server.js.map +1 -1
  58. package/lib/sessions.js +1 -1
  59. package/lib/sessions.js.map +1 -1
  60. package/lib/utils.js +45 -1
  61. package/lib/utils.js.map +1 -1
  62. package/lib/write_concern.js +17 -1
  63. package/lib/write_concern.js.map +1 -1
  64. package/mongodb.d.ts +187 -150
  65. package/package.json +2 -2
  66. package/src/bson.ts +1 -0
  67. package/src/client-side-encryption/auto_encrypter.ts +9 -70
  68. package/src/client-side-encryption/client_encryption.ts +33 -19
  69. package/src/client-side-encryption/providers/index.ts +118 -92
  70. package/src/client-side-encryption/state_machine.ts +22 -18
  71. package/src/cmap/connection.ts +46 -50
  72. package/src/cmap/wire_protocol/on_demand/document.ts +13 -6
  73. package/src/cmap/wire_protocol/responses.ts +140 -45
  74. package/src/collection.ts +25 -5
  75. package/src/constants.ts +9 -0
  76. package/src/cursor/abstract_cursor.ts +280 -373
  77. package/src/cursor/aggregation_cursor.ts +24 -33
  78. package/src/cursor/change_stream_cursor.ts +31 -48
  79. package/src/cursor/find_cursor.ts +77 -92
  80. package/src/cursor/list_collections_cursor.ts +3 -4
  81. package/src/cursor/list_indexes_cursor.ts +3 -4
  82. package/src/cursor/run_command_cursor.ts +13 -19
  83. package/src/error.ts +20 -30
  84. package/src/index.ts +19 -10
  85. package/src/operations/aggregate.ts +12 -5
  86. package/src/operations/bulk_write.ts +1 -2
  87. package/src/operations/command.ts +17 -3
  88. package/src/operations/delete.ts +2 -2
  89. package/src/operations/execute_operation.ts +0 -13
  90. package/src/operations/find.ts +7 -3
  91. package/src/operations/find_and_modify.ts +1 -1
  92. package/src/operations/get_more.ts +6 -10
  93. package/src/operations/indexes.ts +7 -3
  94. package/src/operations/list_collections.ts +8 -3
  95. package/src/operations/run_command.ts +16 -6
  96. package/src/operations/update.ts +2 -1
  97. package/src/sdam/server.ts +7 -2
  98. package/src/sessions.ts +1 -1
  99. package/src/utils.ts +52 -2
  100. package/src/write_concern.ts +18 -0
  101. package/lib/operations/count_documents.js +0 -31
  102. package/lib/operations/count_documents.js.map +0 -1
  103. package/src/operations/count_documents.ts +0 -46
package/src/index.ts CHANGED
@@ -160,7 +160,7 @@ export { SrvPollingEvent } from './sdam/srv_polling';
160
160
 
161
161
  // type only exports below, these are removed from emitted JS
162
162
  export type { AdminPrivate } from './admin';
163
- export type { BSONSerializeOptions, Document } from './bson';
163
+ export type { BSONElement, BSONSerializeOptions, Document } from './bson';
164
164
  export type { deserialize, serialize } from './bson';
165
165
  export type {
166
166
  BulkResult,
@@ -225,6 +225,7 @@ export type {
225
225
  ClientEncryptionRewrapManyDataKeyResult,
226
226
  DataKey,
227
227
  GCPEncryptionKeyOptions,
228
+ KMIPEncryptionKeyOptions,
228
229
  RangeOptions
229
230
  } from './client-side-encryption/client_encryption';
230
231
  export {
@@ -237,8 +238,13 @@ export {
237
238
  } from './client-side-encryption/errors';
238
239
  export type { MongocryptdManager } from './client-side-encryption/mongocryptd_manager';
239
240
  export type {
241
+ AWSKMSProviderConfiguration,
242
+ AzureKMSProviderConfiguration,
240
243
  ClientEncryptionDataKeyProvider,
241
- KMSProviders
244
+ GCPKMSProviderConfiguration,
245
+ KMIPKMSProviderConfiguration,
246
+ KMSProviders,
247
+ LocalKMSProviderConfiguration
242
248
  } from './client-side-encryption/providers/index';
243
249
  export type {
244
250
  ClientEncryptionTlsOptions,
@@ -299,7 +305,12 @@ export type {
299
305
  MongoDBResponse,
300
306
  MongoDBResponseConstructor
301
307
  } from './cmap/wire_protocol/responses';
302
- export type { CollectionOptions, CollectionPrivate, ModifyResult } from './collection';
308
+ export type {
309
+ CollectionOptions,
310
+ CollectionPrivate,
311
+ CountDocumentsOptions,
312
+ ModifyResult
313
+ } from './collection';
303
314
  export type {
304
315
  COMMAND_FAILED,
305
316
  COMMAND_STARTED,
@@ -336,12 +347,12 @@ export type {
336
347
  CursorFlag,
337
348
  CursorStreamOptions
338
349
  } from './cursor/abstract_cursor';
339
- export type { InternalAbstractCursorOptions } from './cursor/abstract_cursor';
340
- export type { AggregationCursorOptions } from './cursor/aggregation_cursor';
341
350
  export type {
342
- ChangeStreamAggregateRawResult,
343
- ChangeStreamCursorOptions
344
- } from './cursor/change_stream_cursor';
351
+ InitialCursorResponse,
352
+ InternalAbstractCursorOptions
353
+ } from './cursor/abstract_cursor';
354
+ export type { AggregationCursorOptions } from './cursor/aggregation_cursor';
355
+ export type { ChangeStreamCursorOptions } from './cursor/change_stream_cursor';
345
356
  export type {
346
357
  ListSearchIndexesCursor,
347
358
  ListSearchIndexesOptions
@@ -457,7 +468,6 @@ export type {
457
468
  OperationParent
458
469
  } from './operations/command';
459
470
  export type { CountOptions } from './operations/count';
460
- export type { CountDocumentsOptions } from './operations/count_documents';
461
471
  export type {
462
472
  ClusteredCollectionOptions,
463
473
  CreateCollectionOptions,
@@ -467,7 +477,6 @@ export type { DeleteOptions, DeleteResult, DeleteStatement } from './operations/
467
477
  export type { DistinctOptions } from './operations/distinct';
468
478
  export type { DropCollectionOptions, DropDatabaseOptions } from './operations/drop';
469
479
  export type { EstimatedDocumentCountOptions } from './operations/estimated_document_count';
470
- export type { ExecutionResult } from './operations/execute_operation';
471
480
  export type { FindOptions } from './operations/find';
472
481
  export type {
473
482
  FindOneAndDeleteOptions,
@@ -1,6 +1,6 @@
1
1
  import type { Document } from '../bson';
2
+ import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
2
3
  import { MongoInvalidArgumentError } from '../error';
3
- import { type TODO_NODE_3286 } from '../mongo_types';
4
4
  import type { Server } from '../sdam/server';
5
5
  import type { ClientSession } from '../sessions';
6
6
  import { maxWireVersion, type MongoDBNamespace } from '../utils';
@@ -37,7 +37,7 @@ export interface AggregateOptions extends CommandOperationOptions {
37
37
  }
38
38
 
39
39
  /** @internal */
40
- export class AggregateOperation<T = Document> extends CommandOperation<T> {
40
+ export class AggregateOperation extends CommandOperation<CursorResponse> {
41
41
  override options: AggregateOptions;
42
42
  target: string | typeof DB_AGGREGATE_COLLECTION;
43
43
  pipeline: Document[];
@@ -94,7 +94,10 @@ export class AggregateOperation<T = Document> extends CommandOperation<T> {
94
94
  this.pipeline.push(stage);
95
95
  }
96
96
 
97
- override async execute(server: Server, session: ClientSession | undefined): Promise<T> {
97
+ override async execute(
98
+ server: Server,
99
+ session: ClientSession | undefined
100
+ ): Promise<CursorResponse> {
98
101
  const options: AggregateOptions = this.options;
99
102
  const serverWireVersion = maxWireVersion(server);
100
103
  const command: Document = { aggregate: this.target, pipeline: this.pipeline };
@@ -134,8 +137,12 @@ export class AggregateOperation<T = Document> extends CommandOperation<T> {
134
137
  command.cursor.batchSize = options.batchSize;
135
138
  }
136
139
 
137
- const res: TODO_NODE_3286 = await super.executeCommand(server, session, command);
138
- return res;
140
+ return await super.executeCommand(
141
+ server,
142
+ session,
143
+ command,
144
+ this.explain ? ExplainedCursorResponse : CursorResponse
145
+ );
139
146
  }
140
147
  }
141
148
 
@@ -50,8 +50,7 @@ export class BulkWriteOperation extends AbstractOperation<BulkWriteResult> {
50
50
  }
51
51
 
52
52
  // Execute the bulk
53
- const result = await bulk.execute({ ...options, session });
54
- return result;
53
+ return await bulk.execute({ ...options, session });
55
54
  }
56
55
  }
57
56
 
@@ -1,4 +1,5 @@
1
1
  import type { BSONSerializeOptions, Document } from '../bson';
2
+ import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
2
3
  import { MongoInvalidArgumentError } from '../error';
3
4
  import { Explain, type ExplainOptions } from '../explain';
4
5
  import { ReadConcern } from '../read_concern';
@@ -106,12 +107,25 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
106
107
  return true;
107
108
  }
108
109
 
109
- async executeCommand(
110
+ public async executeCommand<T extends MongoDBResponseConstructor>(
111
+ server: Server,
112
+ session: ClientSession | undefined,
113
+ cmd: Document,
114
+ responseType: T | undefined
115
+ ): Promise<typeof responseType extends undefined ? Document : InstanceType<T>>;
116
+
117
+ public async executeCommand(
110
118
  server: Server,
111
119
  session: ClientSession | undefined,
112
120
  cmd: Document
121
+ ): Promise<Document>;
122
+
123
+ async executeCommand(
124
+ server: Server,
125
+ session: ClientSession | undefined,
126
+ cmd: Document,
127
+ responseType?: MongoDBResponseConstructor
113
128
  ): Promise<Document> {
114
- // TODO: consider making this a non-enumerable property
115
129
  this.server = server;
116
130
 
117
131
  const options = {
@@ -152,6 +166,6 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
152
166
  cmd = decorateWithExplain(cmd, this.explain);
153
167
  }
154
168
 
155
- return await server.command(this.ns, cmd, options);
169
+ return await server.command(this.ns, cmd, options, responseType);
156
170
  }
157
171
  }
@@ -4,8 +4,8 @@ import { MongoCompatibilityError, MongoServerError } from '../error';
4
4
  import { type TODO_NODE_3286 } from '../mongo_types';
5
5
  import type { Server } from '../sdam/server';
6
6
  import type { ClientSession } from '../sessions';
7
- import type { MongoDBNamespace } from '../utils';
8
- import type { WriteConcernOptions } from '../write_concern';
7
+ import { type MongoDBNamespace } from '../utils';
8
+ import { type WriteConcernOptions } from '../write_concern';
9
9
  import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
10
10
  import { Aspect, defineAspects, type Hint } from './operation';
11
11
 
@@ -1,5 +1,3 @@
1
- import type { Document } from '../bson';
2
- import { type CursorResponse } from '../cmap/wire_protocol/responses';
3
1
  import {
4
2
  isRetryableReadError,
5
3
  isRetryableWriteError,
@@ -18,7 +16,6 @@ import {
18
16
  } from '../error';
19
17
  import type { MongoClient } from '../mongo_client';
20
18
  import { ReadPreference } from '../read_preference';
21
- import type { Server } from '../sdam/server';
22
19
  import type { ServerDescription } from '../sdam/server_description';
23
20
  import {
24
21
  sameServerSelector,
@@ -38,16 +35,6 @@ type ResultTypeFromOperation<TOperation> = TOperation extends AbstractOperation<
38
35
  ? K
39
36
  : never;
40
37
 
41
- /** @internal */
42
- export interface ExecutionResult {
43
- /** The server selected for the operation */
44
- server: Server;
45
- /** The session used for this operation, may be implicitly created */
46
- session?: ClientSession;
47
- /** The raw server response for the operation */
48
- response: Document | CursorResponse;
49
- }
50
-
51
38
  /**
52
39
  * Executes the given operation with provided arguments.
53
40
  * @internal
@@ -1,4 +1,5 @@
1
1
  import type { Document } from '../bson';
2
+ import { CursorResponse, ExplainedCursorResponse } from '../cmap/wire_protocol/responses';
2
3
  import { MongoInvalidArgumentError } from '../error';
3
4
  import { ReadConcern } from '../read_concern';
4
5
  import type { Server } from '../sdam/server';
@@ -65,7 +66,7 @@ export interface FindOptions<TSchema extends Document = Document>
65
66
  }
66
67
 
67
68
  /** @internal */
68
- export class FindOperation extends CommandOperation<Document> {
69
+ export class FindOperation extends CommandOperation<CursorResponse> {
69
70
  /**
70
71
  * @remarks WriteConcern can still be present on the options because
71
72
  * we inherit options from the client/db/collection. The
@@ -95,7 +96,10 @@ export class FindOperation extends CommandOperation<Document> {
95
96
  return 'find' as const;
96
97
  }
97
98
 
98
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
99
+ override async execute(
100
+ server: Server,
101
+ session: ClientSession | undefined
102
+ ): Promise<CursorResponse> {
99
103
  this.server = server;
100
104
 
101
105
  const options = this.options;
@@ -114,7 +118,7 @@ export class FindOperation extends CommandOperation<Document> {
114
118
  documentsReturnedIn: 'firstBatch',
115
119
  session
116
120
  },
117
- undefined
121
+ this.explain ? ExplainedCursorResponse : CursorResponse
118
122
  );
119
123
  }
120
124
  }
@@ -6,7 +6,7 @@ import type { Server } from '../sdam/server';
6
6
  import type { ClientSession } from '../sessions';
7
7
  import { formatSort, type Sort, type SortForCmd } from '../sort';
8
8
  import { decorateWithCollation, hasAtomicOperators, maxWireVersion } from '../utils';
9
- import type { WriteConcern, WriteConcernSettings } from '../write_concern';
9
+ import { type WriteConcern, type WriteConcernSettings } from '../write_concern';
10
10
  import { CommandOperation, type CommandOperationOptions } from './command';
11
11
  import { Aspect, defineAspects } from './operation';
12
12
 
@@ -1,4 +1,4 @@
1
- import type { Document, Long } from '../bson';
1
+ import type { Long } from '../bson';
2
2
  import { CursorResponse } from '../cmap/wire_protocol/responses';
3
3
  import { MongoRuntimeError } from '../error';
4
4
  import type { Server } from '../sdam/server';
@@ -20,8 +20,6 @@ export interface GetMoreOptions extends OperationOptions {
20
20
  maxTimeMS?: number;
21
21
  /** TODO(NODE-4413): Address bug with maxAwaitTimeMS not being passed in from the cursor correctly */
22
22
  maxAwaitTimeMS?: number;
23
-
24
- useCursorResponse: boolean;
25
23
  }
26
24
 
27
25
  /**
@@ -58,7 +56,10 @@ export class GetMoreOperation extends AbstractOperation {
58
56
  * Although there is a server already associated with the get more operation, the signature
59
57
  * for execute passes a server so we will just use that one.
60
58
  */
61
- override async execute(server: Server, _session: ClientSession | undefined): Promise<Document> {
59
+ override async execute(
60
+ server: Server,
61
+ _session: ClientSession | undefined
62
+ ): Promise<CursorResponse> {
62
63
  if (server !== this.server) {
63
64
  throw new MongoRuntimeError('Getmore must run on the same server operation began on');
64
65
  }
@@ -99,12 +100,7 @@ export class GetMoreOperation extends AbstractOperation {
99
100
  ...this.options
100
101
  };
101
102
 
102
- return await server.command(
103
- this.ns,
104
- getMoreCmd,
105
- commandOptions,
106
- this.options.useCursorResponse ? CursorResponse : undefined
107
- );
103
+ return await server.command(this.ns, getMoreCmd, commandOptions, CursorResponse);
108
104
  }
109
105
  }
110
106
 
@@ -1,4 +1,5 @@
1
1
  import type { Document } from '../bson';
2
+ import { CursorResponse } from '../cmap/wire_protocol/responses';
2
3
  import type { Collection } from '../collection';
3
4
  import { type AbstractCursorOptions } from '../cursor/abstract_cursor';
4
5
  import { MongoCompatibilityError } from '../error';
@@ -353,7 +354,7 @@ export class DropIndexOperation extends CommandOperation<Document> {
353
354
  export type ListIndexesOptions = AbstractCursorOptions;
354
355
 
355
356
  /** @internal */
356
- export class ListIndexesOperation extends CommandOperation<Document> {
357
+ export class ListIndexesOperation extends CommandOperation<CursorResponse> {
357
358
  /**
358
359
  * @remarks WriteConcern can still be present on the options because
359
360
  * we inherit options from the client/db/collection. The
@@ -376,7 +377,10 @@ export class ListIndexesOperation extends CommandOperation<Document> {
376
377
  return 'listIndexes' as const;
377
378
  }
378
379
 
379
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
380
+ override async execute(
381
+ server: Server,
382
+ session: ClientSession | undefined
383
+ ): Promise<CursorResponse> {
380
384
  const serverWireVersion = maxWireVersion(server);
381
385
 
382
386
  const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {};
@@ -389,7 +393,7 @@ export class ListIndexesOperation extends CommandOperation<Document> {
389
393
  command.comment = this.options.comment;
390
394
  }
391
395
 
392
- return await super.executeCommand(server, session, command);
396
+ return await super.executeCommand(server, session, command, CursorResponse);
393
397
  }
394
398
  }
395
399
 
@@ -1,4 +1,5 @@
1
1
  import type { Binary, Document } from '../bson';
2
+ import { CursorResponse } from '../cmap/wire_protocol/responses';
2
3
  import type { Db } from '../db';
3
4
  import type { Server } from '../sdam/server';
4
5
  import type { ClientSession } from '../sessions';
@@ -17,7 +18,7 @@ export interface ListCollectionsOptions extends Omit<CommandOperationOptions, 'w
17
18
  }
18
19
 
19
20
  /** @internal */
20
- export class ListCollectionsOperation extends CommandOperation<Document> {
21
+ export class ListCollectionsOperation extends CommandOperation<CursorResponse> {
21
22
  /**
22
23
  * @remarks WriteConcern can still be present on the options because
23
24
  * we inherit options from the client/db/collection. The
@@ -51,11 +52,15 @@ export class ListCollectionsOperation extends CommandOperation<Document> {
51
52
  return 'listCollections' as const;
52
53
  }
53
54
 
54
- override async execute(server: Server, session: ClientSession | undefined): Promise<Document> {
55
+ override async execute(
56
+ server: Server,
57
+ session: ClientSession | undefined
58
+ ): Promise<CursorResponse> {
55
59
  return await super.executeCommand(
56
60
  server,
57
61
  session,
58
- this.generateCommand(maxWireVersion(server))
62
+ this.generateCommand(maxWireVersion(server)),
63
+ CursorResponse
59
64
  );
60
65
  }
61
66
 
@@ -1,4 +1,5 @@
1
1
  import type { BSONSerializeOptions, Document } from '../bson';
2
+ import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
2
3
  import { type Db } from '../db';
3
4
  import { type TODO_NODE_3286 } from '../mongo_types';
4
5
  import type { ReadPreferenceLike } from '../read_preference';
@@ -17,7 +18,11 @@ export type RunCommandOptions = {
17
18
 
18
19
  /** @internal */
19
20
  export class RunCommandOperation<T = Document> extends AbstractOperation<T> {
20
- constructor(parent: Db, public command: Document, public override options: RunCommandOptions) {
21
+ constructor(
22
+ parent: Db,
23
+ public command: Document,
24
+ public override options: RunCommandOptions & { responseType?: MongoDBResponseConstructor }
25
+ ) {
21
26
  super(options);
22
27
  this.ns = parent.s.namespace.withCollection('$cmd');
23
28
  }
@@ -28,11 +33,16 @@ export class RunCommandOperation<T = Document> extends AbstractOperation<T> {
28
33
 
29
34
  override async execute(server: Server, session: ClientSession | undefined): Promise<T> {
30
35
  this.server = server;
31
- const res: TODO_NODE_3286 = await server.command(this.ns, this.command, {
32
- ...this.options,
33
- readPreference: this.readPreference,
34
- session
35
- });
36
+ const res: TODO_NODE_3286 = await server.command(
37
+ this.ns,
38
+ this.command,
39
+ {
40
+ ...this.options,
41
+ readPreference: this.readPreference,
42
+ session
43
+ },
44
+ this.options.responseType
45
+ );
36
46
  return res;
37
47
  }
38
48
  }
@@ -122,7 +122,8 @@ export class UpdateOperation extends CommandOperation<Document> {
122
122
  }
123
123
  }
124
124
 
125
- return await super.executeCommand(server, session, command);
125
+ const res = await super.executeCommand(server, session, command);
126
+ return res;
126
127
  }
127
128
  }
128
129
 
@@ -48,6 +48,7 @@ import {
48
48
  type MongoDBNamespace,
49
49
  supportsRetryableWrites
50
50
  } from '../utils';
51
+ import { throwIfWriteConcernError } from '../write_concern';
51
52
  import {
52
53
  type ClusterTime,
53
54
  STATE_CLOSED,
@@ -323,7 +324,9 @@ export class Server extends TypedEventEmitter<ServerEvents> {
323
324
 
324
325
  try {
325
326
  try {
326
- return await conn.command(ns, cmd, finalOptions, responseType);
327
+ const res = await conn.command(ns, cmd, finalOptions, responseType);
328
+ throwIfWriteConcernError(res);
329
+ return res;
327
330
  } catch (commandError) {
328
331
  throw this.decorateCommandError(conn, cmd, finalOptions, commandError);
329
332
  }
@@ -334,7 +337,9 @@ export class Server extends TypedEventEmitter<ServerEvents> {
334
337
  ) {
335
338
  await this.pool.reauthenticate(conn);
336
339
  try {
337
- return await conn.command(ns, cmd, finalOptions, responseType);
340
+ const res = await conn.command(ns, cmd, finalOptions, responseType);
341
+ throwIfWriteConcernError(res);
342
+ return res;
338
343
  } catch (commandError) {
339
344
  throw this.decorateCommandError(conn, cmd, finalOptions, commandError);
340
345
  }
package/src/sessions.ts CHANGED
@@ -174,7 +174,7 @@ export class ClientSession extends TypedEventEmitter<ClientSessionEvents> {
174
174
  this.sessionPool = sessionPool;
175
175
  this.hasEnded = false;
176
176
  this.clientOptions = clientOptions;
177
- this.timeoutMS = options.defaultTimeoutMS ?? client.options?.timeoutMS;
177
+ this.timeoutMS = options.defaultTimeoutMS ?? client.s.options?.timeoutMS;
178
178
 
179
179
  this.explicit = !!options.explicit;
180
180
  this[kServerSession] = this.explicit ? this.sessionPool.acquire() : null;
package/src/utils.ts CHANGED
@@ -8,11 +8,11 @@ import * as url from 'url';
8
8
  import { URL } from 'url';
9
9
  import { promisify } from 'util';
10
10
 
11
- import { type Document, ObjectId, resolveBSONOptions } from './bson';
11
+ import { deserialize, type Document, ObjectId, resolveBSONOptions } from './bson';
12
12
  import type { Connection } from './cmap/connection';
13
13
  import { MAX_SUPPORTED_WIRE_VERSION } from './cmap/wire_protocol/constants';
14
14
  import type { Collection } from './collection';
15
- import { LEGACY_HELLO_COMMAND } from './constants';
15
+ import { kDecoratedKeys, LEGACY_HELLO_COMMAND } from './constants';
16
16
  import type { AbstractCursor } from './cursor/abstract_cursor';
17
17
  import type { FindCursor } from './cursor/find_cursor';
18
18
  import type { Db } from './db';
@@ -1366,3 +1366,53 @@ export async function fileIsAccessible(fileName: string, mode?: number) {
1366
1366
  export function noop() {
1367
1367
  return;
1368
1368
  }
1369
+
1370
+ /**
1371
+ * Recurse through the (identically-shaped) `decrypted` and `original`
1372
+ * objects and attach a `decryptedKeys` property on each sub-object that
1373
+ * contained encrypted fields. Because we only call this on BSON responses,
1374
+ * we do not need to worry about circular references.
1375
+ *
1376
+ * @internal
1377
+ */
1378
+ export function decorateDecryptionResult(
1379
+ decrypted: Document & { [kDecoratedKeys]?: Array<string> },
1380
+ original: Document,
1381
+ isTopLevelDecorateCall = true
1382
+ ): void {
1383
+ if (isTopLevelDecorateCall) {
1384
+ // The original value could have been either a JS object or a BSON buffer
1385
+ if (Buffer.isBuffer(original)) {
1386
+ original = deserialize(original);
1387
+ }
1388
+ if (Buffer.isBuffer(decrypted)) {
1389
+ throw new MongoRuntimeError('Expected result of decryption to be deserialized BSON object');
1390
+ }
1391
+ }
1392
+
1393
+ if (!decrypted || typeof decrypted !== 'object') return;
1394
+ for (const k of Object.keys(decrypted)) {
1395
+ const originalValue = original[k];
1396
+
1397
+ // An object was decrypted by libmongocrypt if and only if it was
1398
+ // a BSON Binary object with subtype 6.
1399
+ if (originalValue && originalValue._bsontype === 'Binary' && originalValue.sub_type === 6) {
1400
+ if (!decrypted[kDecoratedKeys]) {
1401
+ Object.defineProperty(decrypted, kDecoratedKeys, {
1402
+ value: [],
1403
+ configurable: true,
1404
+ enumerable: false,
1405
+ writable: false
1406
+ });
1407
+ }
1408
+ // this is defined in the preceding if-statement
1409
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1410
+ decrypted[kDecoratedKeys]!.push(k);
1411
+ // Do not recurse into this decrypted value. It could be a sub-document/array,
1412
+ // in which case there is no original value associated with its subfields.
1413
+ continue;
1414
+ }
1415
+
1416
+ decorateDecryptionResult(decrypted[k], originalValue, false);
1417
+ }
1418
+ }
@@ -1,4 +1,6 @@
1
1
  import { type Document } from './bson';
2
+ import { MongoDBResponse } from './cmap/wire_protocol/responses';
3
+ import { MongoWriteConcernError } from './error';
2
4
 
3
5
  /** @public */
4
6
  export type W = number | 'majority';
@@ -159,3 +161,19 @@ export class WriteConcern {
159
161
  return undefined;
160
162
  }
161
163
  }
164
+
165
+ /** Called with either a plain object or MongoDBResponse */
166
+ export function throwIfWriteConcernError(response: unknown): void {
167
+ if (typeof response === 'object' && response != null) {
168
+ const writeConcernError: object | null =
169
+ MongoDBResponse.is(response) && response.has('writeConcernError')
170
+ ? response.toObject()
171
+ : !MongoDBResponse.is(response) && 'writeConcernError' in response
172
+ ? response
173
+ : null;
174
+
175
+ if (writeConcernError != null) {
176
+ throw new MongoWriteConcernError(writeConcernError as any);
177
+ }
178
+ }
179
+ }
@@ -1,31 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CountDocumentsOperation = void 0;
4
- const aggregate_1 = require("./aggregate");
5
- /** @internal */
6
- class CountDocumentsOperation extends aggregate_1.AggregateOperation {
7
- constructor(collection, query, options) {
8
- const pipeline = [];
9
- pipeline.push({ $match: query });
10
- if (typeof options.skip === 'number') {
11
- pipeline.push({ $skip: options.skip });
12
- }
13
- if (typeof options.limit === 'number') {
14
- pipeline.push({ $limit: options.limit });
15
- }
16
- pipeline.push({ $group: { _id: 1, n: { $sum: 1 } } });
17
- super(collection.s.namespace, pipeline, options);
18
- }
19
- async execute(server, session) {
20
- const result = await super.execute(server, session);
21
- // NOTE: We're avoiding creating a cursor here to reduce the callstack.
22
- const response = result;
23
- if (response.cursor == null || response.cursor.firstBatch == null) {
24
- return 0;
25
- }
26
- const docs = response.cursor.firstBatch;
27
- return docs.length ? docs[0].n : 0;
28
- }
29
- }
30
- exports.CountDocumentsOperation = CountDocumentsOperation;
31
- //# sourceMappingURL=count_documents.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"count_documents.js","sourceRoot":"","sources":["../../src/operations/count_documents.ts"],"names":[],"mappings":";;;AAIA,2CAAwE;AAUxE,gBAAgB;AAChB,MAAa,uBAAwB,SAAQ,8BAA0B;IACrE,YAAY,UAAsB,EAAE,KAAe,EAAE,OAA8B;QACjF,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAEjC,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE;YACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;SACxC;QAED,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;YACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;SAC1C;QAED,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAEtD,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAEQ,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,OAAkC;QACvE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAEpD,uEAAuE;QACvE,MAAM,QAAQ,GAAG,MAA6B,CAAC;QAC/C,IAAI,QAAQ,CAAC,MAAM,IAAI,IAAI,IAAI,QAAQ,CAAC,MAAM,CAAC,UAAU,IAAI,IAAI,EAAE;YACjE,OAAO,CAAC,CAAC;SACV;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC;QACxC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;CACF;AA9BD,0DA8BC"}
@@ -1,46 +0,0 @@
1
- import type { Document } from '../bson';
2
- import type { Collection } from '../collection';
3
- import type { Server } from '../sdam/server';
4
- import type { ClientSession } from '../sessions';
5
- import { AggregateOperation, type AggregateOptions } from './aggregate';
6
-
7
- /** @public */
8
- export interface CountDocumentsOptions extends AggregateOptions {
9
- /** The number of documents to skip. */
10
- skip?: number;
11
- /** The maximum amounts to count before aborting. */
12
- limit?: number;
13
- }
14
-
15
- /** @internal */
16
- export class CountDocumentsOperation extends AggregateOperation<number> {
17
- constructor(collection: Collection, query: Document, options: CountDocumentsOptions) {
18
- const pipeline = [];
19
- pipeline.push({ $match: query });
20
-
21
- if (typeof options.skip === 'number') {
22
- pipeline.push({ $skip: options.skip });
23
- }
24
-
25
- if (typeof options.limit === 'number') {
26
- pipeline.push({ $limit: options.limit });
27
- }
28
-
29
- pipeline.push({ $group: { _id: 1, n: { $sum: 1 } } });
30
-
31
- super(collection.s.namespace, pipeline, options);
32
- }
33
-
34
- override async execute(server: Server, session: ClientSession | undefined): Promise<number> {
35
- const result = await super.execute(server, session);
36
-
37
- // NOTE: We're avoiding creating a cursor here to reduce the callstack.
38
- const response = result as unknown as Document;
39
- if (response.cursor == null || response.cursor.firstBatch == null) {
40
- return 0;
41
- }
42
-
43
- const docs = response.cursor.firstBatch;
44
- return docs.length ? docs[0].n : 0;
45
- }
46
- }