mongodb 4.1.0 → 4.1.4

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 (209) hide show
  1. package/README.md +64 -32
  2. package/lib/admin.js +5 -5
  3. package/lib/admin.js.map +1 -1
  4. package/lib/bulk/common.js +93 -71
  5. package/lib/bulk/common.js.map +1 -1
  6. package/lib/change_stream.js +35 -27
  7. package/lib/change_stream.js.map +1 -1
  8. package/lib/cmap/auth/auth_provider.js +2 -2
  9. package/lib/cmap/auth/auth_provider.js.map +1 -1
  10. package/lib/cmap/auth/gssapi.js +3 -2
  11. package/lib/cmap/auth/gssapi.js.map +1 -1
  12. package/lib/cmap/auth/mongo_credentials.js +8 -7
  13. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  14. package/lib/cmap/auth/mongocr.js +2 -2
  15. package/lib/cmap/auth/mongocr.js.map +1 -1
  16. package/lib/cmap/auth/mongodb_aws.js +32 -32
  17. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  18. package/lib/cmap/auth/plain.js +1 -1
  19. package/lib/cmap/auth/plain.js.map +1 -1
  20. package/lib/cmap/auth/scram.js +11 -8
  21. package/lib/cmap/auth/scram.js.map +1 -1
  22. package/lib/cmap/auth/x509.js +1 -1
  23. package/lib/cmap/auth/x509.js.map +1 -1
  24. package/lib/cmap/command_monitoring_events.js +15 -15
  25. package/lib/cmap/command_monitoring_events.js.map +1 -1
  26. package/lib/cmap/commands.js +6 -6
  27. package/lib/cmap/commands.js.map +1 -1
  28. package/lib/cmap/connect.js +5 -4
  29. package/lib/cmap/connect.js.map +1 -1
  30. package/lib/cmap/connection.js +27 -23
  31. package/lib/cmap/connection.js.map +1 -1
  32. package/lib/cmap/connection_pool.js +7 -5
  33. package/lib/cmap/connection_pool.js.map +1 -1
  34. package/lib/cmap/message_stream.js +3 -3
  35. package/lib/cmap/message_stream.js.map +1 -1
  36. package/lib/cmap/stream_description.js +1 -1
  37. package/lib/cmap/stream_description.js.map +1 -1
  38. package/lib/cmap/wire_protocol/compression.js +22 -9
  39. package/lib/cmap/wire_protocol/compression.js.map +1 -1
  40. package/lib/collection.js +53 -48
  41. package/lib/collection.js.map +1 -1
  42. package/lib/connection_string.js +42 -36
  43. package/lib/connection_string.js.map +1 -1
  44. package/lib/cursor/abstract_cursor.js +18 -18
  45. package/lib/cursor/abstract_cursor.js.map +1 -1
  46. package/lib/cursor/aggregation_cursor.js +56 -15
  47. package/lib/cursor/aggregation_cursor.js.map +1 -1
  48. package/lib/cursor/find_cursor.js +63 -23
  49. package/lib/cursor/find_cursor.js.map +1 -1
  50. package/lib/db.js +35 -30
  51. package/lib/db.js.map +1 -1
  52. package/lib/deps.js +8 -1
  53. package/lib/deps.js.map +1 -1
  54. package/lib/error.js +16 -54
  55. package/lib/error.js.map +1 -1
  56. package/lib/gridfs/download.js +14 -24
  57. package/lib/gridfs/download.js.map +1 -1
  58. package/lib/gridfs/index.js +5 -5
  59. package/lib/gridfs/index.js.map +1 -1
  60. package/lib/gridfs/upload.js +13 -21
  61. package/lib/gridfs/upload.js.map +1 -1
  62. package/lib/index.js +22 -2
  63. package/lib/index.js.map +1 -1
  64. package/lib/logger.js +5 -5
  65. package/lib/logger.js.map +1 -1
  66. package/lib/mongo_client.js +9 -8
  67. package/lib/mongo_client.js.map +1 -1
  68. package/lib/mongo_types.js.map +1 -1
  69. package/lib/operations/add_user.js +3 -3
  70. package/lib/operations/add_user.js.map +1 -1
  71. package/lib/operations/aggregate.js +2 -2
  72. package/lib/operations/aggregate.js.map +1 -1
  73. package/lib/operations/bulk_write.js +1 -1
  74. package/lib/operations/bulk_write.js.map +1 -1
  75. package/lib/operations/command.js +4 -6
  76. package/lib/operations/command.js.map +1 -1
  77. package/lib/operations/common_functions.js +2 -2
  78. package/lib/operations/common_functions.js.map +1 -1
  79. package/lib/operations/connect.js +3 -2
  80. package/lib/operations/connect.js.map +1 -1
  81. package/lib/operations/count.js +1 -1
  82. package/lib/operations/count.js.map +1 -1
  83. package/lib/operations/count_documents.js.map +1 -1
  84. package/lib/operations/create_collection.js +1 -1
  85. package/lib/operations/create_collection.js.map +1 -1
  86. package/lib/operations/delete.js +6 -6
  87. package/lib/operations/delete.js.map +1 -1
  88. package/lib/operations/distinct.js +5 -5
  89. package/lib/operations/distinct.js.map +1 -1
  90. package/lib/operations/drop.js +2 -2
  91. package/lib/operations/drop.js.map +1 -1
  92. package/lib/operations/estimated_document_count.js +2 -2
  93. package/lib/operations/estimated_document_count.js.map +1 -1
  94. package/lib/operations/eval.js.map +1 -1
  95. package/lib/operations/execute_operation.js +10 -15
  96. package/lib/operations/execute_operation.js.map +1 -1
  97. package/lib/operations/find.js +8 -9
  98. package/lib/operations/find.js.map +1 -1
  99. package/lib/operations/find_and_modify.js +7 -7
  100. package/lib/operations/find_and_modify.js.map +1 -1
  101. package/lib/operations/indexes.js +14 -14
  102. package/lib/operations/indexes.js.map +1 -1
  103. package/lib/operations/insert.js +8 -6
  104. package/lib/operations/insert.js.map +1 -1
  105. package/lib/operations/is_capped.js +2 -1
  106. package/lib/operations/is_capped.js.map +1 -1
  107. package/lib/operations/list_collections.js +4 -4
  108. package/lib/operations/list_collections.js.map +1 -1
  109. package/lib/operations/list_databases.js +1 -1
  110. package/lib/operations/list_databases.js.map +1 -1
  111. package/lib/operations/map_reduce.js +6 -6
  112. package/lib/operations/map_reduce.js.map +1 -1
  113. package/lib/operations/operation.js +1 -1
  114. package/lib/operations/operation.js.map +1 -1
  115. package/lib/operations/options_operation.js +2 -1
  116. package/lib/operations/options_operation.js.map +1 -1
  117. package/lib/operations/profiling_level.js +2 -2
  118. package/lib/operations/profiling_level.js.map +1 -1
  119. package/lib/operations/remove_user.js +1 -1
  120. package/lib/operations/remove_user.js.map +1 -1
  121. package/lib/operations/rename.js +2 -2
  122. package/lib/operations/rename.js.map +1 -1
  123. package/lib/operations/set_profiling_level.js +2 -2
  124. package/lib/operations/set_profiling_level.js.map +1 -1
  125. package/lib/operations/stats.js +2 -2
  126. package/lib/operations/stats.js.map +1 -1
  127. package/lib/operations/update.js +12 -12
  128. package/lib/operations/update.js.map +1 -1
  129. package/lib/operations/validate_collection.js +4 -4
  130. package/lib/operations/validate_collection.js.map +1 -1
  131. package/lib/sdam/monitor.js +14 -14
  132. package/lib/sdam/monitor.js.map +1 -1
  133. package/lib/sdam/server.js +16 -17
  134. package/lib/sdam/server.js.map +1 -1
  135. package/lib/sdam/server_description.js +3 -3
  136. package/lib/sdam/server_description.js.map +1 -1
  137. package/lib/sdam/srv_polling.js +1 -2
  138. package/lib/sdam/srv_polling.js.map +1 -1
  139. package/lib/sdam/topology.js +21 -18
  140. package/lib/sdam/topology.js.map +1 -1
  141. package/lib/sdam/topology_description.js +1 -1
  142. package/lib/sdam/topology_description.js.map +1 -1
  143. package/lib/sessions.js +33 -33
  144. package/lib/sessions.js.map +1 -1
  145. package/lib/transactions.js +2 -2
  146. package/lib/transactions.js.map +1 -1
  147. package/lib/utils.js +15 -37
  148. package/lib/utils.js.map +1 -1
  149. package/mongodb.d.ts +384 -121
  150. package/mongodb.ts34.d.ts +365 -124
  151. package/package.json +53 -58
  152. package/src/bulk/common.ts +105 -61
  153. package/src/change_stream.ts +41 -22
  154. package/src/cmap/auth/auth_provider.ts +3 -3
  155. package/src/cmap/auth/gssapi.ts +3 -2
  156. package/src/cmap/auth/mongo_credentials.ts +21 -10
  157. package/src/cmap/auth/mongodb_aws.ts +41 -36
  158. package/src/cmap/auth/scram.ts +6 -4
  159. package/src/cmap/command_monitoring_events.ts +1 -1
  160. package/src/cmap/commands.ts +6 -6
  161. package/src/cmap/connect.ts +5 -4
  162. package/src/cmap/connection.ts +15 -12
  163. package/src/cmap/connection_pool.ts +5 -3
  164. package/src/cmap/message_stream.ts +2 -4
  165. package/src/cmap/wire_protocol/compression.ts +26 -13
  166. package/src/collection.ts +54 -56
  167. package/src/connection_string.ts +37 -26
  168. package/src/cursor/abstract_cursor.ts +45 -35
  169. package/src/cursor/aggregation_cursor.ts +30 -9
  170. package/src/cursor/find_cursor.ts +27 -7
  171. package/src/db.ts +14 -14
  172. package/src/deps.ts +103 -23
  173. package/src/error.ts +33 -66
  174. package/src/gridfs/download.ts +37 -27
  175. package/src/gridfs/index.ts +3 -3
  176. package/src/gridfs/upload.ts +32 -33
  177. package/src/index.ts +34 -3
  178. package/src/mongo_client.ts +9 -13
  179. package/src/mongo_types.ts +22 -26
  180. package/src/operations/command.ts +2 -5
  181. package/src/operations/common_functions.ts +2 -3
  182. package/src/operations/connect.ts +3 -2
  183. package/src/operations/count.ts +1 -1
  184. package/src/operations/count_documents.ts +1 -1
  185. package/src/operations/distinct.ts +1 -1
  186. package/src/operations/eval.ts +1 -1
  187. package/src/operations/execute_operation.ts +9 -10
  188. package/src/operations/find.ts +7 -5
  189. package/src/operations/indexes.ts +2 -2
  190. package/src/operations/insert.ts +4 -1
  191. package/src/operations/is_capped.ts +3 -2
  192. package/src/operations/list_collections.ts +3 -1
  193. package/src/operations/list_databases.ts +6 -1
  194. package/src/operations/operation.ts +0 -1
  195. package/src/operations/options_operation.ts +3 -2
  196. package/src/operations/profiling_level.ts +3 -3
  197. package/src/operations/set_profiling_level.ts +2 -2
  198. package/src/operations/validate_collection.ts +5 -5
  199. package/src/sdam/server.ts +6 -7
  200. package/src/sdam/srv_polling.ts +2 -3
  201. package/src/sdam/topology.ts +15 -9
  202. package/src/sdam/topology_description.ts +2 -2
  203. package/src/sessions.ts +20 -16
  204. package/src/transactions.ts +3 -3
  205. package/src/utils.ts +20 -41
  206. package/HISTORY.md +0 -3026
  207. package/lib/operations/find_one.js +0 -34
  208. package/lib/operations/find_one.js.map +0 -1
  209. package/src/operations/find_one.ts +0 -43
package/src/collection.ts CHANGED
@@ -40,7 +40,6 @@ import {
40
40
  EstimatedDocumentCountOptions
41
41
  } from './operations/estimated_document_count';
42
42
  import type { FindOptions } from './operations/find';
43
- import { FindOneOperation } from './operations/find_one';
44
43
  import {
45
44
  FindOneAndDeleteOperation,
46
45
  FindOneAndReplaceOperation,
@@ -100,7 +99,7 @@ import type {
100
99
 
101
100
  /** @public */
102
101
  export interface ModifyResult<TSchema = Document> {
103
- value?: TSchema;
102
+ value: TSchema | null;
104
103
  lastErrorObject?: Document;
105
104
  ok: 0 | 1;
106
105
  }
@@ -415,34 +414,39 @@ export class Collection<TSchema extends Document = Document> {
415
414
  updateOne(
416
415
  filter: Filter<TSchema>,
417
416
  update: UpdateFilter<TSchema> | Partial<TSchema>
418
- ): Promise<UpdateResult | Document>;
417
+ ): Promise<UpdateResult>;
419
418
  updateOne(
420
419
  filter: Filter<TSchema>,
421
420
  update: UpdateFilter<TSchema> | Partial<TSchema>,
422
- callback: Callback<UpdateResult | Document>
421
+ callback: Callback<UpdateResult>
423
422
  ): void;
424
423
  updateOne(
425
424
  filter: Filter<TSchema>,
426
425
  update: UpdateFilter<TSchema> | Partial<TSchema>,
427
426
  options: UpdateOptions
428
- ): Promise<UpdateResult | Document>;
427
+ ): Promise<UpdateResult>;
429
428
  updateOne(
430
429
  filter: Filter<TSchema>,
431
430
  update: UpdateFilter<TSchema> | Partial<TSchema>,
432
431
  options: UpdateOptions,
433
- callback: Callback<UpdateResult | Document>
432
+ callback: Callback<UpdateResult>
434
433
  ): void;
435
434
  updateOne(
436
435
  filter: Filter<TSchema>,
437
436
  update: UpdateFilter<TSchema> | Partial<TSchema>,
438
- options?: UpdateOptions | Callback<UpdateResult | Document>,
439
- callback?: Callback<UpdateResult | Document>
440
- ): Promise<UpdateResult | Document> | void {
437
+ options?: UpdateOptions | Callback<UpdateResult>,
438
+ callback?: Callback<UpdateResult>
439
+ ): Promise<UpdateResult> | void {
441
440
  if (typeof options === 'function') (callback = options), (options = {});
442
441
 
443
442
  return executeOperation(
444
443
  getTopology(this),
445
- new UpdateOneOperation(this as TODO_NODE_3286, filter, update, resolveOptions(this, options)),
444
+ new UpdateOneOperation(
445
+ this as TODO_NODE_3286,
446
+ filter,
447
+ update,
448
+ resolveOptions(this, options)
449
+ ) as TODO_NODE_3286,
446
450
  callback
447
451
  );
448
452
  }
@@ -672,54 +676,48 @@ export class Collection<TSchema extends Document = Document> {
672
676
  * @param options - Optional settings for the command
673
677
  * @param callback - An optional callback, a Promise will be returned if none is provided
674
678
  */
675
- findOne(): Promise<TSchema | undefined>;
676
- findOne(callback: Callback<TSchema | undefined>): void;
677
- findOne(filter: Filter<TSchema>): Promise<TSchema | undefined>;
678
- findOne(filter: Filter<TSchema>, callback: Callback<TSchema | undefined>): void;
679
- findOne(filter: Filter<TSchema>, options: FindOptions<TSchema>): Promise<TSchema | undefined>;
680
- findOne(
681
- filter: Filter<TSchema>,
682
- options: FindOptions<TSchema>,
683
- callback: Callback<TSchema | undefined>
684
- ): void;
679
+ findOne(): Promise<TSchema | null>;
680
+ findOne(callback: Callback<TSchema | null>): void;
681
+ findOne(filter: Filter<TSchema>): Promise<TSchema | null>;
682
+ findOne(filter: Filter<TSchema>, callback: Callback<TSchema | null>): void;
683
+ findOne(filter: Filter<TSchema>, options: FindOptions): Promise<TSchema | null>;
684
+ findOne(filter: Filter<TSchema>, options: FindOptions, callback: Callback<TSchema | null>): void;
685
685
 
686
686
  // allow an override of the schema.
687
- findOne<T = TSchema>(): Promise<T | undefined>;
688
- findOne<T = TSchema>(callback: Callback<T | undefined>): void;
689
- findOne<T = TSchema>(filter: Filter<T>): Promise<T | undefined>;
690
- findOne<T = TSchema>(filter: Filter<T>, options?: FindOptions<T>): Promise<T | undefined>;
687
+ findOne<T = TSchema>(): Promise<T | null>;
688
+ findOne<T = TSchema>(callback: Callback<T | null>): void;
689
+ findOne<T = TSchema>(filter: Filter<TSchema>): Promise<T | null>;
690
+ findOne<T = TSchema>(filter: Filter<TSchema>, options?: FindOptions): Promise<T | null>;
691
691
  findOne<T = TSchema>(
692
- filter: Filter<T>,
693
- options?: FindOptions<T>,
694
- callback?: Callback<T | undefined>
692
+ filter: Filter<TSchema>,
693
+ options?: FindOptions,
694
+ callback?: Callback<T | null>
695
695
  ): void;
696
696
 
697
697
  findOne(
698
- filter?: Filter<TSchema> | Callback<TSchema | undefined>,
699
- options?: FindOptions<TSchema> | Callback<TSchema | undefined>,
700
- callback?: Callback<TSchema>
701
- ): Promise<TSchema | undefined> | void {
698
+ filter?: Filter<TSchema> | Callback<TSchema | null>,
699
+ options?: FindOptions | Callback<TSchema | null>,
700
+ callback?: Callback<TSchema | null>
701
+ ): Promise<TSchema | null> | void {
702
702
  if (callback != null && typeof callback !== 'function') {
703
703
  throw new MongoInvalidArgumentError(
704
704
  'Third parameter to `findOne()` must be a callback or undefined'
705
705
  );
706
706
  }
707
707
 
708
- if (typeof filter === 'function')
709
- (callback = filter as Callback<Document | undefined>), (filter = {}), (options = {});
710
- if (typeof options === 'function') (callback = options), (options = {});
711
-
712
- filter ??= {};
708
+ if (typeof filter === 'function') {
709
+ callback = filter as Callback<TSchema | null>;
710
+ filter = {};
711
+ options = {};
712
+ }
713
+ if (typeof options === 'function') {
714
+ callback = options;
715
+ options = {};
716
+ }
713
717
 
714
- return executeOperation(
715
- getTopology(this),
716
- new FindOneOperation(
717
- this as TODO_NODE_3286,
718
- filter,
719
- resolveOptions(this, options)
720
- ) as TODO_NODE_3286,
721
- callback as TODO_NODE_3286
722
- );
718
+ const finalFilter = filter ?? {};
719
+ const finalOptions = options ?? {};
720
+ return this.find(finalFilter, finalOptions).limit(-1).batchSize(1).next(callback);
723
721
  }
724
722
 
725
723
  /**
@@ -728,9 +726,9 @@ export class Collection<TSchema extends Document = Document> {
728
726
  * @param filter - The filter predicate. If unspecified, then all documents in the collection will match the predicate
729
727
  */
730
728
  find(): FindCursor<TSchema>;
731
- find(filter: Filter<TSchema>, options?: FindOptions<TSchema>): FindCursor<TSchema>;
732
- find<T = TSchema>(filter: Filter<T>, options?: FindOptions<T>): FindCursor<T>;
733
- find(filter?: Filter<TSchema>, options?: FindOptions<TSchema>): FindCursor<TSchema> {
729
+ find(filter: Filter<TSchema>, options?: FindOptions): FindCursor<TSchema>;
730
+ find<T>(filter: Filter<TSchema>, options?: FindOptions): FindCursor<T>;
731
+ find(filter?: Filter<TSchema>, options?: FindOptions): FindCursor<TSchema> {
734
732
  if (arguments.length > 2) {
735
733
  throw new MongoInvalidArgumentError(
736
734
  'Method "collection.find()" accepts at most two arguments'
@@ -1192,14 +1190,14 @@ export class Collection<TSchema extends Document = Document> {
1192
1190
  * @param options - Optional settings for the command
1193
1191
  * @param callback - An optional callback, a Promise will be returned if none is provided
1194
1192
  */
1195
- indexes(): Promise<Document>;
1196
- indexes(callback: Callback<Document>): void;
1197
- indexes(options: IndexInformationOptions): Promise<Document>;
1198
- indexes(options: IndexInformationOptions, callback: Callback<Document>): void;
1193
+ indexes(): Promise<Document[]>;
1194
+ indexes(callback: Callback<Document[]>): void;
1195
+ indexes(options: IndexInformationOptions): Promise<Document[]>;
1196
+ indexes(options: IndexInformationOptions, callback: Callback<Document[]>): void;
1199
1197
  indexes(
1200
- options?: IndexInformationOptions | Callback<Document>,
1201
- callback?: Callback<Document>
1202
- ): Promise<Document> | void {
1198
+ options?: IndexInformationOptions | Callback<Document[]>,
1199
+ callback?: Callback<Document[]>
1200
+ ): Promise<Document[]> | void {
1203
1201
  if (typeof options === 'function') (callback = options), (options = {});
1204
1202
 
1205
1203
  return executeOperation(
@@ -1368,7 +1366,7 @@ export class Collection<TSchema extends Document = Document> {
1368
1366
  * @param pipeline - An array of aggregation pipelines to execute
1369
1367
  * @param options - Optional settings for the command
1370
1368
  */
1371
- aggregate<T = TSchema>(
1369
+ aggregate<T = Document>(
1372
1370
  pipeline: Document[] = [],
1373
1371
  options?: AggregateOptions
1374
1372
  ): AggregationCursor<T> {
@@ -6,7 +6,7 @@ import { AuthMechanism } from './cmap/auth/defaultAuthProviders';
6
6
  import { ReadPreference, ReadPreferenceMode } from './read_preference';
7
7
  import { ReadConcern, ReadConcernLevel } from './read_concern';
8
8
  import { W, WriteConcern } from './write_concern';
9
- import { MongoParseError } from './error';
9
+ import { MongoAPIError, MongoInvalidArgumentError, MongoParseError } from './error';
10
10
  import {
11
11
  AnyOptions,
12
12
  Callback,
@@ -32,6 +32,7 @@ import type { TagSet } from './sdam/server_description';
32
32
  import { Logger, LoggerLevel } from './logger';
33
33
  import { PromiseProvider } from './promise_provider';
34
34
  import { Encrypter } from './encrypter';
35
+ import { Compressor, CompressorName } from './cmap/wire_protocol/compression';
35
36
 
36
37
  const VALID_TXT_RECORDS = ['authSource', 'replicaSet', 'loadBalanced'];
37
38
 
@@ -64,11 +65,12 @@ function matchesParentDomain(srvAddress: string, parentDomain: string): boolean
64
65
  */
65
66
  export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostAddress[]>): void {
66
67
  if (typeof options.srvHost !== 'string') {
67
- return callback(new MongoParseError('Cannot resolve empty srv string'));
68
+ return callback(new MongoAPIError('Option "srvHost" must not be empty'));
68
69
  }
69
70
 
70
71
  if (options.srvHost.split('.').length < 3) {
71
- return callback(new MongoParseError('URI does not have hostname, domain name and tld'));
72
+ // TODO(NODE-3484): Replace with MongoConnectionStringError
73
+ return callback(new MongoAPIError('URI must include hostname, domain name, and tld'));
72
74
  }
73
75
 
74
76
  // Resolve the SRV record and use the result as the list of hosts to connect to.
@@ -77,14 +79,12 @@ export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostA
77
79
  if (err) return callback(err);
78
80
 
79
81
  if (addresses.length === 0) {
80
- return callback(new MongoParseError('No addresses found at host'));
82
+ return callback(new MongoAPIError('No addresses found at host'));
81
83
  }
82
84
 
83
85
  for (const { name } of addresses) {
84
86
  if (!matchesParentDomain(name, lookupAddress)) {
85
- return callback(
86
- new MongoParseError('Server record does not share hostname with parent URI')
87
- );
87
+ return callback(new MongoAPIError('Server record does not share hostname with parent URI'));
88
88
  }
89
89
  }
90
90
 
@@ -176,7 +176,7 @@ function getBoolean(name: string, value: unknown): boolean {
176
176
  const valueString = String(value).toLowerCase();
177
177
  if (TRUTHS.has(valueString)) return true;
178
178
  if (FALSEHOODS.has(valueString)) return false;
179
- throw new MongoParseError(`For ${name} Expected stringified boolean value, got: ${value}`);
179
+ throw new MongoParseError(`Expected ${name} to be stringified boolean value, got: ${value}`);
180
180
  }
181
181
 
182
182
  function getInt(name: string, value: unknown): number {
@@ -286,7 +286,7 @@ export function parseOptions(
286
286
  const values = [...url.searchParams.getAll(key)];
287
287
 
288
288
  if (values.includes('')) {
289
- throw new MongoParseError('URI cannot contain options with no value');
289
+ throw new MongoAPIError('URI cannot contain options with no value');
290
290
  }
291
291
 
292
292
  if (key.toLowerCase() === 'serverapi') {
@@ -335,6 +335,19 @@ export function parseOptions(
335
335
  allOptions.set(key, values);
336
336
  }
337
337
 
338
+ if (allOptions.has('tlsCertificateKeyFile') && !allOptions.has('tlsCertificateFile')) {
339
+ allOptions.set('tlsCertificateFile', allOptions.get('tlsCertificateKeyFile'));
340
+ }
341
+
342
+ if (allOptions.has('tls') || allOptions.has('ssl')) {
343
+ const tlsAndSslOpts = (allOptions.get('tls') || [])
344
+ .concat(allOptions.get('ssl') || [])
345
+ .map(getBoolean.bind(null, 'tls/ssl'));
346
+ if (new Set(tlsAndSslOpts).size !== 1) {
347
+ throw new MongoParseError('All values of tls/ssl must be the same.');
348
+ }
349
+ }
350
+
338
351
  const unsupportedOptions = setDifference(
339
352
  allKeys,
340
353
  Array.from(Object.keys(OPTIONS)).map(s => s.toLowerCase())
@@ -384,24 +397,12 @@ export function parseOptions(
384
397
  mongoOptions.dbName = 'test';
385
398
  }
386
399
 
387
- if (allOptions.has('tls')) {
388
- if (new Set(allOptions.get('tls')?.map(getBoolean)).size !== 1) {
389
- throw new MongoParseError('All values of tls must be the same.');
390
- }
391
- }
392
-
393
- if (allOptions.has('ssl')) {
394
- if (new Set(allOptions.get('ssl')?.map(getBoolean)).size !== 1) {
395
- throw new MongoParseError('All values of ssl must be the same.');
396
- }
397
- }
398
-
399
400
  checkTLSOptions(mongoOptions);
400
401
 
401
402
  if (options.promiseLibrary) PromiseProvider.set(options.promiseLibrary);
402
403
 
403
404
  if (mongoOptions.directConnection && typeof mongoOptions.srvHost === 'string') {
404
- throw new MongoParseError('directConnection not supported with SRV URI');
405
+ throw new MongoAPIError('SRV URI does not support directConnection');
405
406
  }
406
407
 
407
408
  const lbError = validateLoadBalancedOptions(hosts, mongoOptions);
@@ -612,12 +613,22 @@ export const OPTIONS = {
612
613
  target: 'compressors',
613
614
  transform({ values }) {
614
615
  const compressionList = new Set();
615
- for (const compVal of values as string[]) {
616
- for (const c of compVal.split(',')) {
617
- if (['none', 'snappy', 'zlib'].includes(String(c))) {
616
+ for (const compVal of values as (CompressorName[] | string)[]) {
617
+ const compValArray = typeof compVal === 'string' ? compVal.split(',') : compVal;
618
+ if (!Array.isArray(compValArray)) {
619
+ throw new MongoInvalidArgumentError(
620
+ 'compressors must be an array or a comma-delimited list of strings'
621
+ );
622
+ }
623
+ for (const c of compValArray) {
624
+ if (Object.keys(Compressor).includes(String(c))) {
618
625
  compressionList.add(String(c));
619
626
  } else {
620
- throw new MongoParseError(`${c} is not a valid compression mechanism`);
627
+ throw new MongoInvalidArgumentError(
628
+ `${c} is not a valid compression mechanism. Must be one of: ${Object.keys(
629
+ Compressor
630
+ )}.`
631
+ );
621
632
  }
622
633
  }
623
634
  }
@@ -3,7 +3,7 @@ import { Long, Document, BSONSerializeOptions, pluckBSONSerializeOptions } from
3
3
  import { ClientSession, maybeClearPinnedConnection } from '../sessions';
4
4
  import {
5
5
  AnyError,
6
- MongoDriverError,
6
+ MongoRuntimeError,
7
7
  MongoNetworkError,
8
8
  MongoInvalidArgumentError,
9
9
  MongoCursorExhaustedError,
@@ -51,10 +51,11 @@ export const CURSOR_FLAGS = [
51
51
  'partial'
52
52
  ] as const;
53
53
 
54
- /** @public */
55
- // TODO: Remove this as the option is never used. (NODE-3489)
54
+ /** @public
55
+ * @deprecated This interface is deprecated */
56
56
  export interface CursorCloseOptions {
57
57
  /** Bypass calling killCursors when closing the cursor. */
58
+ /** @deprecated the skipKillCursors option is deprecated */
58
59
  skipKillCursors?: boolean;
59
60
  }
60
61
 
@@ -279,8 +280,7 @@ export abstract class AbstractCursor<
279
280
  return done(undefined, true);
280
281
  }
281
282
 
282
- next<any>(this, true, (err, doc) => {
283
- // FIXME(NODE):
283
+ next<TSchema>(this, true, (err, doc) => {
284
284
  if (err) return done(err);
285
285
 
286
286
  if (doc) {
@@ -295,9 +295,10 @@ export abstract class AbstractCursor<
295
295
  }
296
296
 
297
297
  /** Get the next available document from the cursor, returns null if no more documents are available. */
298
- next<T = TSchema>(): Promise<T | null>;
299
- next<T = TSchema>(callback: Callback<T | null>): void;
300
- next<T = TSchema>(callback?: Callback<T | null>): Promise<T | null> | void {
298
+ next(): Promise<TSchema | null>;
299
+ next(callback: Callback<TSchema | null>): void;
300
+ next(callback?: Callback<TSchema | null>): Promise<TSchema | null> | void;
301
+ next(callback?: Callback<TSchema | null>): Promise<TSchema | null> | void {
301
302
  return maybePromise(callback, done => {
302
303
  if (this[kId] === Long.ZERO) {
303
304
  return done(new MongoCursorExhaustedError());
@@ -310,9 +311,9 @@ export abstract class AbstractCursor<
310
311
  /**
311
312
  * Try to get the next available document from the cursor or `null` if an empty batch is returned
312
313
  */
313
- tryNext<T = TSchema>(): Promise<T | null>;
314
- tryNext<T = TSchema>(callback: Callback<T | null>): void;
315
- tryNext<T = TSchema>(callback?: Callback<T | null>): Promise<T | null> | void {
314
+ tryNext(): Promise<TSchema | null>;
315
+ tryNext(callback: Callback<TSchema | null>): void;
316
+ tryNext(callback?: Callback<TSchema | null>): Promise<TSchema | null> | void {
316
317
  return maybePromise(callback, done => {
317
318
  if (this[kId] === Long.ZERO) {
318
319
  return done(new MongoCursorExhaustedError());
@@ -328,10 +329,10 @@ export abstract class AbstractCursor<
328
329
  * @param iterator - The iteration callback.
329
330
  * @param callback - The end callback.
330
331
  */
331
- forEach<T = TSchema>(iterator: (doc: T) => boolean | void): Promise<void>;
332
- forEach<T = TSchema>(iterator: (doc: T) => boolean | void, callback: Callback<void>): void;
333
- forEach<T = TSchema>(
334
- iterator: (doc: T) => boolean | void,
332
+ forEach(iterator: (doc: TSchema) => boolean | void): Promise<void>;
333
+ forEach(iterator: (doc: TSchema) => boolean | void, callback: Callback<void>): void;
334
+ forEach(
335
+ iterator: (doc: TSchema) => boolean | void,
335
336
  callback?: Callback<void>
336
337
  ): Promise<void> | void {
337
338
  if (typeof iterator !== 'function') {
@@ -340,7 +341,7 @@ export abstract class AbstractCursor<
340
341
  return maybePromise(callback, done => {
341
342
  const transform = this[kTransform];
342
343
  const fetchDocs = () => {
343
- next<T>(this, true, (err, doc) => {
344
+ next<TSchema>(this, true, (err, doc) => {
344
345
  if (err || doc == null) return done(err);
345
346
  let result;
346
347
  // NOTE: no need to transform because `next` will do this automatically
@@ -357,7 +358,7 @@ export abstract class AbstractCursor<
357
358
  for (let i = 0; i < internalDocs.length; ++i) {
358
359
  try {
359
360
  result = iterator(
360
- (transform ? transform(internalDocs[i]) : internalDocs[i]) as T // TODO(NODE-3283): Improve transform typing
361
+ (transform ? transform(internalDocs[i]) : internalDocs[i]) as TSchema // TODO(NODE-3283): Improve transform typing
361
362
  );
362
363
  } catch (error) {
363
364
  return done(error);
@@ -373,9 +374,15 @@ export abstract class AbstractCursor<
373
374
  });
374
375
  }
375
376
 
376
- close(): Promise<void>;
377
+ close(): void;
377
378
  close(callback: Callback): void;
379
+ /**
380
+ * @deprecated options argument is deprecated
381
+ */
378
382
  close(options: CursorCloseOptions): Promise<void>;
383
+ /**
384
+ * @deprecated options argument is deprecated
385
+ */
379
386
  close(options: CursorCloseOptions, callback: Callback): void;
380
387
  close(options?: CursorCloseOptions | Callback, callback?: Callback): Promise<void> | void {
381
388
  if (typeof options === 'function') (callback = options), (options = {});
@@ -395,15 +402,15 @@ export abstract class AbstractCursor<
395
402
  *
396
403
  * @param callback - The result callback.
397
404
  */
398
- toArray<T = TSchema>(): Promise<T[]>;
399
- toArray<T = TSchema>(callback: Callback<T[]>): void;
400
- toArray<T = TSchema>(callback?: Callback<T[]>): Promise<T[]> | void {
405
+ toArray(): Promise<TSchema[]>;
406
+ toArray(callback: Callback<TSchema[]>): void;
407
+ toArray(callback?: Callback<TSchema[]>): Promise<TSchema[]> | void {
401
408
  return maybePromise(callback, done => {
402
- const docs: T[] = [];
409
+ const docs: TSchema[] = [];
403
410
  const transform = this[kTransform];
404
411
  const fetchDocs = () => {
405
412
  // NOTE: if we add a `nextBatch` then we should use it here
406
- next<T>(this, true, (err, doc) => {
413
+ next<TSchema>(this, true, (err, doc) => {
407
414
  if (err) return done(err);
408
415
  if (doc == null) return done(undefined, docs);
409
416
 
@@ -411,9 +418,11 @@ export abstract class AbstractCursor<
411
418
  docs.push(doc);
412
419
 
413
420
  // these do need to be transformed since they are copying the rest of the batch
414
- const internalDocs = (transform
415
- ? this[kDocuments].splice(0, this[kDocuments].length).map(transform)
416
- : this[kDocuments].splice(0, this[kDocuments].length)) as T[]; // TODO(NODE-3283): Improve transform typing
421
+ const internalDocs = (
422
+ transform
423
+ ? this[kDocuments].splice(0, this[kDocuments].length).map(transform)
424
+ : this[kDocuments].splice(0, this[kDocuments].length)
425
+ ) as TSchema[]; // TODO(NODE-3283): Improve transform typing
417
426
 
418
427
  if (internalDocs) {
419
428
  docs.push(...internalDocs);
@@ -451,11 +460,12 @@ export abstract class AbstractCursor<
451
460
  * Map all documents using the provided function
452
461
  * If there is a transform set on the cursor, that will be called first and the result passed to
453
462
  * this function's transform.
454
- * @remarks
455
463
  *
456
- * **NOTE:** adding a transform changes the return type of the iteration of this cursor, it **does not** return
457
- * a new instance of a cursor. This means when calling map, you should always assign the result to a new
458
- * variable. Take note of the following example:
464
+ * @remarks
465
+ * **Note for Typescript Users:** adding a transform changes the return type of the iteration of this cursor,
466
+ * it **does not** return a new instance of a cursor. This means when calling map,
467
+ * you should always assign the result to a new variable in order to get a correctly typed cursor variable.
468
+ * Take note of the following example:
459
469
  *
460
470
  * @example
461
471
  * ```typescript
@@ -476,7 +486,7 @@ export abstract class AbstractCursor<
476
486
  this[kTransform] = transform;
477
487
  }
478
488
 
479
- return (this as unknown) as AbstractCursor<T>;
489
+ return this as unknown as AbstractCursor<T>;
480
490
  }
481
491
 
482
492
  /**
@@ -591,12 +601,12 @@ export abstract class AbstractCursor<
591
601
  const server = this[kServer];
592
602
 
593
603
  if (cursorId == null) {
594
- callback(new MongoDriverError('Unable to iterate cursor with no id'));
604
+ callback(new MongoRuntimeError('Unable to iterate cursor with no id'));
595
605
  return;
596
606
  }
597
607
 
598
608
  if (server == null) {
599
- callback(new MongoDriverError('Unable to iterate cursor without selected server'));
609
+ callback(new MongoRuntimeError('Unable to iterate cursor without selected server'));
600
610
  return;
601
611
  }
602
612
 
@@ -762,7 +772,7 @@ function cleanupCursor(
762
772
  }
763
773
 
764
774
  if (!session.inTransaction()) {
765
- maybeClearPinnedConnection(session, { error, force: true });
775
+ maybeClearPinnedConnection(session, { error });
766
776
  }
767
777
  }
768
778
 
@@ -779,7 +789,7 @@ function cleanupCursor(
779
789
  }
780
790
 
781
791
  if (!session.inTransaction()) {
782
- maybeClearPinnedConnection(session, { error, force: true });
792
+ maybeClearPinnedConnection(session, { error });
783
793
  }
784
794
  }
785
795
 
@@ -9,7 +9,6 @@ import type { Callback, MongoDBNamespace } from '../utils';
9
9
  import type { ClientSession } from '../sessions';
10
10
  import type { AbstractCursorOptions } from './abstract_cursor';
11
11
  import type { ExplainVerbosityLike } from '../explain';
12
- import type { Projection } from '../mongo_types';
13
12
 
14
13
  /** @public */
15
14
  export interface AggregationCursorOptions extends AbstractCursorOptions, AggregateOptions {}
@@ -121,8 +120,8 @@ export class AggregationCursor<TSchema = Document> extends AbstractCursor<TSchem
121
120
  return this;
122
121
  }
123
122
 
124
- /** Add a out stage to the aggregation pipeline */
125
- out($out: number): this {
123
+ /** Add an out stage to the aggregation pipeline */
124
+ out($out: { db: string; coll: string } | string): this {
126
125
  assertUninitialized(this);
127
126
  this[kPipeline].push({ $out });
128
127
  return this;
@@ -135,22 +134,44 @@ export class AggregationCursor<TSchema = Document> extends AbstractCursor<TSchem
135
134
  * In order to strictly type this function you must provide an interface
136
135
  * that represents the effect of your projection on the result documents.
137
136
  *
138
- * **NOTE:** adding a projection changes the return type of the iteration of this cursor,
137
+ * By default chaining a projection to your cursor changes the returned type to the generic {@link Document} type.
138
+ * You should specify a parameterized type to have assertions on your final results.
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * // Best way
143
+ * const docs: AggregationCursor<{ a: number }> = cursor.project<{ a: number }>({ _id: 0, a: true });
144
+ * // Flexible way
145
+ * const docs: AggregationCursor<Document> = cursor.project({ _id: 0, a: true });
146
+ * ```
147
+ *
148
+ * @remarks
149
+ * In order to strictly type this function you must provide an interface
150
+ * that represents the effect of your projection on the result documents.
151
+ *
152
+ * **Note for Typescript Users:** adding a transform changes the return type of the iteration of this cursor,
139
153
  * it **does not** return a new instance of a cursor. This means when calling project,
140
- * you should always assign the result to a new variable. Take note of the following example:
154
+ * you should always assign the result to a new variable in order to get a correctly typed cursor variable.
155
+ * Take note of the following example:
141
156
  *
142
157
  * @example
143
158
  * ```typescript
144
159
  * const cursor: AggregationCursor<{ a: number; b: string }> = coll.aggregate([]);
145
- * const projectCursor = cursor.project<{ a: number }>({ a: true });
160
+ * const projectCursor = cursor.project<{ a: number }>({ _id: 0, a: true });
146
161
  * const aPropOnlyArray: {a: number}[] = await projectCursor.toArray();
162
+ *
163
+ * // or always use chaining and save the final cursor
164
+ *
165
+ * const cursor = coll.aggregate().project<{ a: string }>({
166
+ * _id: 0,
167
+ * a: { $convert: { input: '$a', to: 'string' }
168
+ * }});
147
169
  * ```
148
170
  */
149
- project<T = TSchema>($project: Projection<T>): AggregationCursor<T>;
150
- project($project: Document): this {
171
+ project<T extends Document = Document>($project: Document): AggregationCursor<T> {
151
172
  assertUninitialized(this);
152
173
  this[kPipeline].push({ $project });
153
- return this;
174
+ return this as unknown as AggregationCursor<T>;
154
175
  }
155
176
 
156
177
  /** Add a lookup stage to the aggregation pipeline */
@@ -12,7 +12,6 @@ import type { ClientSession } from '../sessions';
12
12
  import { formatSort, Sort, SortDirection } from '../sort';
13
13
  import type { Callback, MongoDBNamespace } from '../utils';
14
14
  import { AbstractCursor, assertUninitialized } from './abstract_cursor';
15
- import type { Projection } from '../mongo_types';
16
15
 
17
16
  /** @internal */
18
17
  const kFilter = Symbol('filter');
@@ -344,22 +343,43 @@ export class FindCursor<TSchema = Document> extends AbstractCursor<TSchema> {
344
343
  * In order to strictly type this function you must provide an interface
345
344
  * that represents the effect of your projection on the result documents.
346
345
  *
347
- * **NOTE:** adding a projection changes the return type of the iteration of this cursor,
346
+ * By default chaining a projection to your cursor changes the returned type to the generic
347
+ * {@link Document} type.
348
+ * You should specify a parameterized type to have assertions on your final results.
349
+ *
350
+ * @example
351
+ * ```typescript
352
+ * // Best way
353
+ * const docs: FindCursor<{ a: number }> = cursor.project<{ a: number }>({ _id: 0, a: true });
354
+ * // Flexible way
355
+ * const docs: FindCursor<Document> = cursor.project({ _id: 0, a: true });
356
+ * ```
357
+ *
358
+ * @remarks
359
+ *
360
+ * **Note for Typescript Users:** adding a transform changes the return type of the iteration of this cursor,
348
361
  * it **does not** return a new instance of a cursor. This means when calling project,
349
- * you should always assign the result to a new variable. Take note of the following example:
362
+ * you should always assign the result to a new variable in order to get a correctly typed cursor variable.
363
+ * Take note of the following example:
350
364
  *
351
365
  * @example
352
366
  * ```typescript
353
367
  * const cursor: FindCursor<{ a: number; b: string }> = coll.find();
354
- * const projectCursor = cursor.project<{ a: number }>({ a: true });
368
+ * const projectCursor = cursor.project<{ a: number }>({ _id: 0, a: true });
355
369
  * const aPropOnlyArray: {a: number}[] = await projectCursor.toArray();
370
+ *
371
+ * // or always use chaining and save the final cursor
372
+ *
373
+ * const cursor = coll.find().project<{ a: string }>({
374
+ * _id: 0,
375
+ * a: { $convert: { input: '$a', to: 'string' }
376
+ * }});
356
377
  * ```
357
378
  */
358
- project<T = TSchema>(value: Projection<T>): FindCursor<T>;
359
- project(value: Projection<TSchema>): this {
379
+ project<T extends Document = Document>(value: Document): FindCursor<T> {
360
380
  assertUninitialized(this);
361
381
  this[kBuiltOptions].projection = value;
362
- return this;
382
+ return this as unknown as FindCursor<T>;
363
383
  }
364
384
 
365
385
  /**