mongodb 6.7.0-dev.20240608.sha.0655c730 → 6.7.0-dev.20240614.sha.3ed6a2ad

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 (96) hide show
  1. package/lib/bson.js.map +1 -1
  2. package/lib/client-side-encryption/auto_encrypter.js +8 -61
  3. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  4. package/lib/client-side-encryption/client_encryption.js +5 -5
  5. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  6. package/lib/client-side-encryption/providers/index.js.map +1 -1
  7. package/lib/client-side-encryption/state_machine.js +15 -11
  8. package/lib/client-side-encryption/state_machine.js.map +1 -1
  9. package/lib/cmap/connection.js +22 -20
  10. package/lib/cmap/connection.js.map +1 -1
  11. package/lib/cmap/wire_protocol/on_demand/document.js +8 -5
  12. package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
  13. package/lib/cmap/wire_protocol/responses.js +116 -40
  14. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  15. package/lib/constants.js +9 -1
  16. package/lib/constants.js.map +1 -1
  17. package/lib/cursor/abstract_cursor.js +24 -60
  18. package/lib/cursor/abstract_cursor.js.map +1 -1
  19. package/lib/cursor/aggregation_cursor.js +2 -3
  20. package/lib/cursor/aggregation_cursor.js.map +1 -1
  21. package/lib/cursor/change_stream_cursor.js +6 -8
  22. package/lib/cursor/change_stream_cursor.js.map +1 -1
  23. package/lib/cursor/find_cursor.js +5 -17
  24. package/lib/cursor/find_cursor.js.map +1 -1
  25. package/lib/cursor/list_collections_cursor.js +0 -1
  26. package/lib/cursor/list_collections_cursor.js.map +1 -1
  27. package/lib/cursor/list_indexes_cursor.js +0 -1
  28. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  29. package/lib/cursor/run_command_cursor.js +4 -6
  30. package/lib/cursor/run_command_cursor.js.map +1 -1
  31. package/lib/error.js +6 -21
  32. package/lib/error.js.map +1 -1
  33. package/lib/index.js.map +1 -1
  34. package/lib/operations/aggregate.js +2 -2
  35. package/lib/operations/aggregate.js.map +1 -1
  36. package/lib/operations/bulk_write.js +1 -2
  37. package/lib/operations/bulk_write.js.map +1 -1
  38. package/lib/operations/command.js +2 -3
  39. package/lib/operations/command.js.map +1 -1
  40. package/lib/operations/count_documents.js +1 -7
  41. package/lib/operations/count_documents.js.map +1 -1
  42. package/lib/operations/execute_operation.js.map +1 -1
  43. package/lib/operations/find.js +2 -1
  44. package/lib/operations/find.js.map +1 -1
  45. package/lib/operations/get_more.js +1 -1
  46. package/lib/operations/get_more.js.map +1 -1
  47. package/lib/operations/indexes.js +2 -1
  48. package/lib/operations/indexes.js.map +1 -1
  49. package/lib/operations/list_collections.js +2 -1
  50. package/lib/operations/list_collections.js.map +1 -1
  51. package/lib/operations/run_command.js +1 -1
  52. package/lib/operations/run_command.js.map +1 -1
  53. package/lib/operations/update.js +2 -1
  54. package/lib/operations/update.js.map +1 -1
  55. package/lib/sdam/server.js +7 -2
  56. package/lib/sdam/server.js.map +1 -1
  57. package/lib/utils.js +45 -1
  58. package/lib/utils.js.map +1 -1
  59. package/lib/write_concern.js +17 -1
  60. package/lib/write_concern.js.map +1 -1
  61. package/mongodb.d.ts +120 -85
  62. package/package.json +1 -1
  63. package/src/bson.ts +1 -0
  64. package/src/client-side-encryption/auto_encrypter.ts +9 -70
  65. package/src/client-side-encryption/client_encryption.ts +6 -6
  66. package/src/client-side-encryption/providers/index.ts +120 -92
  67. package/src/client-side-encryption/state_machine.ts +22 -18
  68. package/src/cmap/connection.ts +46 -50
  69. package/src/cmap/wire_protocol/on_demand/document.ts +13 -6
  70. package/src/cmap/wire_protocol/responses.ts +140 -45
  71. package/src/constants.ts +9 -0
  72. package/src/cursor/abstract_cursor.ts +51 -71
  73. package/src/cursor/aggregation_cursor.ts +13 -12
  74. package/src/cursor/change_stream_cursor.ts +20 -34
  75. package/src/cursor/find_cursor.ts +17 -25
  76. package/src/cursor/list_collections_cursor.ts +3 -4
  77. package/src/cursor/list_indexes_cursor.ts +3 -4
  78. package/src/cursor/run_command_cursor.ts +13 -19
  79. package/src/error.ts +16 -28
  80. package/src/index.ts +12 -8
  81. package/src/operations/aggregate.ts +12 -5
  82. package/src/operations/bulk_write.ts +1 -2
  83. package/src/operations/command.ts +17 -3
  84. package/src/operations/count_documents.ts +7 -11
  85. package/src/operations/delete.ts +2 -2
  86. package/src/operations/execute_operation.ts +0 -13
  87. package/src/operations/find.ts +7 -3
  88. package/src/operations/find_and_modify.ts +1 -1
  89. package/src/operations/get_more.ts +6 -10
  90. package/src/operations/indexes.ts +7 -3
  91. package/src/operations/list_collections.ts +8 -3
  92. package/src/operations/run_command.ts +16 -6
  93. package/src/operations/update.ts +2 -1
  94. package/src/sdam/server.ts +7 -2
  95. package/src/utils.ts +52 -2
  96. package/src/write_concern.ts +18 -0
@@ -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/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
+ }