mongodb 4.1.4 → 4.2.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 (59) hide show
  1. package/README.md +15 -14
  2. package/lib/bulk/common.js +0 -1
  3. package/lib/bulk/common.js.map +1 -1
  4. package/lib/change_stream.js.map +1 -1
  5. package/lib/cmap/connection.js.map +1 -1
  6. package/lib/cmap/wire_protocol/constants.js +4 -4
  7. package/lib/collection.js +1 -0
  8. package/lib/collection.js.map +1 -1
  9. package/lib/connection_string.js +62 -30
  10. package/lib/connection_string.js.map +1 -1
  11. package/lib/db.js.map +1 -1
  12. package/lib/mongo_client.js.map +1 -1
  13. package/lib/operations/aggregate.js +1 -2
  14. package/lib/operations/aggregate.js.map +1 -1
  15. package/lib/operations/command.js +4 -0
  16. package/lib/operations/command.js.map +1 -1
  17. package/lib/operations/execute_operation.js +12 -2
  18. package/lib/operations/execute_operation.js.map +1 -1
  19. package/lib/operations/list_collections.js +8 -3
  20. package/lib/operations/list_collections.js.map +1 -1
  21. package/lib/operations/operation.js +1 -0
  22. package/lib/operations/operation.js.map +1 -1
  23. package/lib/sdam/server.js +7 -0
  24. package/lib/sdam/server.js.map +1 -1
  25. package/lib/sdam/server_selection.js +20 -1
  26. package/lib/sdam/server_selection.js.map +1 -1
  27. package/lib/sdam/srv_polling.js +9 -9
  28. package/lib/sdam/srv_polling.js.map +1 -1
  29. package/lib/sdam/topology.js +15 -7
  30. package/lib/sdam/topology.js.map +1 -1
  31. package/lib/sdam/topology_description.js +34 -12
  32. package/lib/sdam/topology_description.js.map +1 -1
  33. package/lib/transactions.js.map +1 -1
  34. package/lib/utils.js +52 -16
  35. package/lib/utils.js.map +1 -1
  36. package/mongodb.d.ts +42 -22
  37. package/mongodb.ts34.d.ts +43 -22
  38. package/package.json +4 -3
  39. package/src/bulk/common.ts +8 -2
  40. package/src/change_stream.ts +7 -7
  41. package/src/cmap/connection.ts +1 -0
  42. package/src/cmap/wire_protocol/constants.ts +4 -4
  43. package/src/collection.ts +24 -16
  44. package/src/connection_string.ts +80 -36
  45. package/src/db.ts +5 -6
  46. package/src/mongo_client.ts +12 -0
  47. package/src/operations/aggregate.ts +1 -2
  48. package/src/operations/command.ts +5 -0
  49. package/src/operations/create_collection.ts +1 -1
  50. package/src/operations/execute_operation.ts +13 -2
  51. package/src/operations/list_collections.ts +12 -4
  52. package/src/operations/operation.ts +3 -0
  53. package/src/sdam/server.ts +8 -0
  54. package/src/sdam/server_selection.ts +25 -0
  55. package/src/sdam/srv_polling.ts +12 -11
  56. package/src/sdam/topology.ts +27 -10
  57. package/src/sdam/topology_description.ts +35 -11
  58. package/src/transactions.ts +2 -2
  59. package/src/utils.ts +62 -18
package/mongodb.ts34.d.ts CHANGED
@@ -25,6 +25,7 @@ import { Readable } from 'stream';
25
25
  import { serialize as serialize_2 } from 'bson';
26
26
  import { SerializeOptions } from 'bson';
27
27
  import { Socket } from 'net';
28
+ import { SrvRecord } from 'dns';
28
29
  import { TcpNetConnectOpts } from 'net';
29
30
  import { Timestamp } from 'bson';
30
31
  import { TLSSocket } from 'tls';
@@ -746,8 +747,10 @@ export declare abstract class BulkOperationBase {
746
747
  readonly bsonOptions: BSONSerializeOptions;
747
748
  readonly writeConcern: WriteConcern | undefined;
748
749
  readonly batches: Batch[];
749
- /** An internal helper method. Do not invoke directly. Will be going away in the future */
750
- execute(options?: BulkWriteOptions, callback?: Callback<BulkWriteResult>): Promise<BulkWriteResult> | void;
750
+ execute(options?: BulkWriteOptions): Promise<BulkWriteResult>;
751
+ execute(callback: Callback<BulkWriteResult>): void;
752
+ execute(options: BulkWriteOptions | undefined, callback: Callback<BulkWriteResult>): void;
753
+ execute(options?: BulkWriteOptions | Callback<BulkWriteResult>, callback?: Callback<BulkWriteResult>): Promise<BulkWriteResult> | void;
751
754
  /* Excluded from this release type: handleWriteError */
752
755
  abstract addToOperationsList(batchType: BatchType, document: Document | UpdateStatement | DeleteStatement): this;
753
756
  }
@@ -860,7 +863,7 @@ export declare class CancellationToken extends TypedEventEmitter<{
860
863
  * Creates a new Change Stream instance. Normally created using {@link Collection#watch|Collection.watch()}.
861
864
  * @public
862
865
  */
863
- export declare class ChangeStream<TSchema extends Document = Document> extends TypedEventEmitter<ChangeStreamEvents> {
866
+ export declare class ChangeStream<TSchema extends Document = Document> extends TypedEventEmitter<ChangeStreamEvents<TSchema>> {
864
867
  pipeline: Document[];
865
868
  options: ChangeStreamOptions;
866
869
  parent: MongoClient | Db | Collection;
@@ -974,14 +977,14 @@ export declare interface ChangeStreamDocument<TSchema extends Document = Documen
974
977
  fullDocument?: TSchema;
975
978
  }
976
979
  /** @public */
977
- export declare type ChangeStreamEvents = {
980
+ export declare type ChangeStreamEvents<TSchema extends Document = Document> = {
978
981
  resumeTokenChanged(token: ResumeToken): void;
979
- init(response: Document): void;
980
- more(response?: Document | undefined): void;
982
+ init(response: TSchema): void;
983
+ more(response?: TSchema | undefined): void;
981
984
  response(): void;
982
985
  end(): void;
983
986
  error(error: Error): void;
984
- change(change: ChangeStreamDocument): void;
987
+ change(change: ChangeStreamDocument<TSchema>): void;
985
988
  } & AbstractCursorEvents;
986
989
  /**
987
990
  * Options that can be passed to a ChangeStream. Note that startAfter, resumeAfter, and startAtOperationTime are all mutually exclusive, and the server will error if more than one is specified.
@@ -1381,12 +1384,12 @@ export declare class Collection<TSchema extends Document = Document> {
1381
1384
  * @param options - Optional settings for the command
1382
1385
  * @param callback - An optional callback, a Promise will be returned if none is provided
1383
1386
  */
1384
- findOne(): Promise<TSchema | null>;
1385
- findOne(callback: Callback<TSchema | null>): void;
1386
- findOne(filter: Filter<TSchema>): Promise<TSchema | null>;
1387
- findOne(filter: Filter<TSchema>, callback: Callback<TSchema | null>): void;
1388
- findOne(filter: Filter<TSchema>, options: FindOptions): Promise<TSchema | null>;
1389
- findOne(filter: Filter<TSchema>, options: FindOptions, callback: Callback<TSchema | null>): void;
1387
+ findOne(): Promise<WithId<TSchema> | null>;
1388
+ findOne(callback: Callback<WithId<TSchema> | null>): void;
1389
+ findOne(filter: Filter<TSchema>): Promise<WithId<TSchema> | null>;
1390
+ findOne(filter: Filter<TSchema>, callback: Callback<WithId<TSchema> | null>): void;
1391
+ findOne(filter: Filter<TSchema>, options: FindOptions): Promise<WithId<TSchema> | null>;
1392
+ findOne(filter: Filter<TSchema>, options: FindOptions, callback: Callback<WithId<TSchema> | null>): void;
1390
1393
  findOne<T = TSchema>(): Promise<T | null>;
1391
1394
  findOne<T = TSchema>(callback: Callback<T | null>): void;
1392
1395
  findOne<T = TSchema>(filter: Filter<TSchema>): Promise<T | null>;
@@ -1397,9 +1400,9 @@ export declare class Collection<TSchema extends Document = Document> {
1397
1400
  *
1398
1401
  * @param filter - The filter predicate. If unspecified, then all documents in the collection will match the predicate
1399
1402
  */
1400
- find(): FindCursor<TSchema>;
1401
- find(filter: Filter<TSchema>, options?: FindOptions): FindCursor<TSchema>;
1402
- find<T>(filter: Filter<TSchema>, options?: FindOptions): FindCursor<T>;
1403
+ find(): FindCursor<WithId<TSchema>>;
1404
+ find(filter: Filter<WithId<TSchema>>, options?: FindOptions): FindCursor<WithId<TSchema>>;
1405
+ find<T>(filter: Filter<WithId<TSchema>>, options?: FindOptions): FindCursor<T>;
1403
1406
  /**
1404
1407
  * Returns the options of the collection.
1405
1408
  *
@@ -1673,6 +1676,7 @@ export declare class Collection<TSchema extends Document = Document> {
1673
1676
  /**
1674
1677
  * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection.
1675
1678
  *
1679
+ * @deprecated collection.mapReduce is deprecated. Use the aggregation pipeline instead. Visit https://docs.mongodb.com/manual/reference/map-reduce-to-aggregation-pipeline for more information on how to translate map-reduce operations to the aggregation pipeline.
1676
1680
  * @param map - The mapping function.
1677
1681
  * @param reduce - The reduce function.
1678
1682
  * @param options - Optional settings for the command
@@ -2225,10 +2229,9 @@ export declare class Db {
2225
2229
  * @param options - Optional settings for the command
2226
2230
  * @param callback - An optional callback, a Promise will be returned if none is provided
2227
2231
  */
2228
- createCollection<TSchema extends Document = Document>(name: string): Promise<Collection<TSchema>>;
2232
+ createCollection<TSchema extends Document = Document>(name: string, options?: CreateCollectionOptions): Promise<Collection<TSchema>>;
2229
2233
  createCollection<TSchema extends Document = Document>(name: string, callback: Callback<Collection<TSchema>>): void;
2230
- createCollection<TSchema extends Document = Document>(name: string, options: CreateCollectionOptions): Promise<Collection<TSchema>>;
2231
- createCollection<TSchema extends Document = Document>(name: string, options: CreateCollectionOptions, callback: Callback<Collection<TSchema>>): void;
2234
+ createCollection<TSchema extends Document = Document>(name: string, options: CreateCollectionOptions | undefined, callback: Callback<Collection<TSchema>>): void;
2232
2235
  /**
2233
2236
  * Execute a command
2234
2237
  *
@@ -3181,11 +3184,13 @@ export declare class HostAddress {
3181
3184
  socketPath: string | undefined;
3182
3185
  isIPv6: boolean | undefined;
3183
3186
  constructor(hostString: string);
3187
+ inspect(): string;
3184
3188
  /**
3185
3189
  * @param ipv6Brackets - optionally request ipv6 bracket notation required for connection strings
3186
3190
  */
3187
3191
  toString(ipv6Brackets?: boolean): string;
3188
3192
  static fromString(s: string): HostAddress;
3193
+ static fromSrvRecord({ name, port }: SrvRecord): HostAddress;
3189
3194
  }
3190
3195
  /** @public */
3191
3196
  export declare interface IndexDescription extends Pick<CreateIndexesOptions, 'background' | 'unique' | 'partialFilterExpression' | 'sparse' | 'hidden' | 'expireAfterSeconds' | 'storageEngine' | 'version' | 'weights' | 'default_language' | 'language_override' | 'textIndexVersion' | '2dsphereIndexVersion' | 'bits' | 'min' | 'max' | 'bucketSize' | 'wildcardProjection'> {
@@ -3366,6 +3371,8 @@ export declare class ListCollectionsCursor<T extends Pick<CollectionInfo, 'name'
3366
3371
  export declare interface ListCollectionsOptions extends CommandOperationOptions {
3367
3372
  /** Since 4.0: If true, will only return the collection name in the response, and will omit additional info */
3368
3373
  nameOnly?: boolean;
3374
+ /** Since 4.0: If true and nameOnly is true, allows a user without the required privilege (i.e. listCollections action on the database) to run the command when access control is enforced. */
3375
+ authorizedCollections?: boolean;
3369
3376
  /** The batchSize for the returned command cursor or if pre 2.8 the systems batch collection */
3370
3377
  batchSize?: number;
3371
3378
  }
@@ -3778,6 +3785,16 @@ export declare interface MongoClientOptions extends BSONSerializeOptions, Suppor
3778
3785
  compressors?: CompressorName[] | string;
3779
3786
  /** An integer that specifies the compression level if using zlib for network compression. */
3780
3787
  zlibCompressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | undefined;
3788
+ /** The maximum number of hosts to connect to when using an srv connection string, a setting of `0` means unlimited hosts */
3789
+ srvMaxHosts?: number;
3790
+ /**
3791
+ * Modifies the srv URI to look like:
3792
+ *
3793
+ * `_{srvServiceName}._tcp.{hostname}.{domainname}`
3794
+ *
3795
+ * Querying this DNS URI is expected to respond with SRV records
3796
+ */
3797
+ srvServiceName?: string;
3781
3798
  /** The maximum number of connections in the connection pool. */
3782
3799
  maxPoolSize?: number;
3783
3800
  /** The minimum number of connections in the connection pool. */
@@ -4136,7 +4153,7 @@ export declare class MongoNotConnectedError extends MongoAPIError {
4136
4153
  * Mongo Client Options
4137
4154
  * @public
4138
4155
  */
4139
- export declare interface MongoOptions extends Required<Pick<MongoClientOptions, 'autoEncryption' | 'connectTimeoutMS' | 'directConnection' | 'driverInfo' | 'forceServerObjectId' | 'minHeartbeatFrequencyMS' | 'heartbeatFrequencyMS' | 'keepAlive' | 'keepAliveInitialDelay' | 'localThresholdMS' | 'logger' | 'maxIdleTimeMS' | 'maxPoolSize' | 'minPoolSize' | 'monitorCommands' | 'noDelay' | 'pkFactory' | 'promiseLibrary' | 'raw' | 'replicaSet' | 'retryReads' | 'retryWrites' | 'serverSelectionTimeoutMS' | 'socketTimeoutMS' | 'tlsAllowInvalidCertificates' | 'tlsAllowInvalidHostnames' | 'tlsInsecure' | 'waitQueueTimeoutMS' | 'zlibCompressionLevel'>>, SupportedNodeConnectionOptions {
4156
+ export declare interface MongoOptions extends Required<Pick<MongoClientOptions, 'autoEncryption' | 'connectTimeoutMS' | 'directConnection' | 'driverInfo' | 'forceServerObjectId' | 'minHeartbeatFrequencyMS' | 'heartbeatFrequencyMS' | 'keepAlive' | 'keepAliveInitialDelay' | 'localThresholdMS' | 'logger' | 'maxIdleTimeMS' | 'maxPoolSize' | 'minPoolSize' | 'monitorCommands' | 'noDelay' | 'pkFactory' | 'promiseLibrary' | 'raw' | 'replicaSet' | 'retryReads' | 'retryWrites' | 'serverSelectionTimeoutMS' | 'socketTimeoutMS' | 'srvMaxHosts' | 'srvServiceName' | 'tlsAllowInvalidCertificates' | 'tlsAllowInvalidHostnames' | 'tlsInsecure' | 'waitQueueTimeoutMS' | 'zlibCompressionLevel'>>, SupportedNodeConnectionOptions {
4140
4157
  hosts: HostAddress[];
4141
4158
  srvHost?: string;
4142
4159
  credentials?: MongoCredentials;
@@ -4321,6 +4338,8 @@ export declare interface OperationOptions extends BSONSerializeOptions {
4321
4338
  willRetryWrites?: boolean;
4322
4339
  /** The preferred read preference (ReadPreference.primary, ReadPreference.primary_preferred, ReadPreference.secondary, ReadPreference.secondary_preferred, ReadPreference.nearest). */
4323
4340
  readPreference?: ReadPreferenceLike;
4341
+ /* Excluded from this release type: bypassPinningCheck */
4342
+ omitReadPreference?: boolean;
4324
4343
  }
4325
4344
  /* Excluded from this release type: OperationParent */
4326
4345
  /**
@@ -4938,7 +4957,7 @@ export declare type TagSet = {
4938
4957
  export declare interface TimeSeriesCollectionOptions extends Document {
4939
4958
  timeField: string;
4940
4959
  metaField?: string;
4941
- granularity?: string;
4960
+ granularity?: 'seconds' | 'minutes' | 'hours' | string;
4942
4961
  }
4943
4962
  export { Timestamp };
4944
4963
  /* Excluded from this release type: Topology */
@@ -5027,6 +5046,8 @@ export declare class TopologyOpeningEvent {
5027
5046
  }
5028
5047
  /** @public */
5029
5048
  export declare interface TopologyOptions extends BSONSerializeOptions, ServerOptions {
5049
+ srvMaxHosts: number;
5050
+ srvServiceName: string;
5030
5051
  hosts: HostAddress[];
5031
5052
  retryWrites: boolean;
5032
5053
  retryReads: boolean;
@@ -5090,7 +5111,7 @@ export declare class Transaction {
5090
5111
  */
5091
5112
  export declare interface TransactionOptions extends CommandOperationOptions {
5092
5113
  /** A default read concern for commands in this transaction */
5093
- readConcern?: ReadConcern;
5114
+ readConcern?: ReadConcernLike;
5094
5115
  /** A default writeConcern for commands in this transaction */
5095
5116
  writeConcern?: WriteConcern;
5096
5117
  /** A default read preference for commands in this transaction */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "4.1.4",
3
+ "version": "4.2.0",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -34,7 +34,7 @@
34
34
  "dependencies": {
35
35
  "bson": "^4.5.4",
36
36
  "denque": "^2.0.1",
37
- "mongodb-connection-string-url": "^2.1.0"
37
+ "mongodb-connection-string-url": "^2.2.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@istanbuljs/nyc-config-typescript": "^1.0.1",
@@ -47,6 +47,7 @@
47
47
  "@types/node": "^16.10.3",
48
48
  "@types/saslprep": "^1.0.1",
49
49
  "@types/semver": "^7.3.8",
50
+ "@types/sinon": "^10.0.6",
50
51
  "@types/whatwg-url": "^8.2.1",
51
52
  "@typescript-eslint/eslint-plugin": "^4.33.0",
52
53
  "@typescript-eslint/parser": "^4.33.0",
@@ -69,7 +70,7 @@
69
70
  "prettier": "^2.4.1",
70
71
  "rimraf": "^3.0.2",
71
72
  "semver": "^7.3.5",
72
- "sinon": "^11.1.2",
73
+ "sinon": "^12.0.1",
73
74
  "sinon-chai": "^3.7.0",
74
75
  "source-map-support": "^0.5.20",
75
76
  "standard-version": "^9.3.1",
@@ -1216,9 +1216,15 @@ export abstract class BulkOperationBase {
1216
1216
  return batches;
1217
1217
  }
1218
1218
 
1219
- /** An internal helper method. Do not invoke directly. Will be going away in the future */
1219
+ execute(options?: BulkWriteOptions): Promise<BulkWriteResult>;
1220
+ execute(callback: Callback<BulkWriteResult>): void;
1221
+ execute(options: BulkWriteOptions | undefined, callback: Callback<BulkWriteResult>): void;
1220
1222
  execute(
1221
- options?: BulkWriteOptions,
1223
+ options?: BulkWriteOptions | Callback<BulkWriteResult>,
1224
+ callback?: Callback<BulkWriteResult>
1225
+ ): Promise<BulkWriteResult> | void;
1226
+ execute(
1227
+ options?: BulkWriteOptions | Callback<BulkWriteResult>,
1222
1228
  callback?: Callback<BulkWriteResult>
1223
1229
  ): Promise<BulkWriteResult> | void {
1224
1230
  if (typeof options === 'function') (callback = options), (options = {});
@@ -184,23 +184,23 @@ export interface UpdateDescription<TSchema extends Document = Document> {
184
184
  }
185
185
 
186
186
  /** @public */
187
- export type ChangeStreamEvents = {
187
+ export type ChangeStreamEvents<TSchema extends Document = Document> = {
188
188
  resumeTokenChanged(token: ResumeToken): void;
189
- init(response: Document): void;
190
- more(response?: Document | undefined): void;
189
+ init(response: TSchema): void;
190
+ more(response?: TSchema | undefined): void;
191
191
  response(): void;
192
192
  end(): void;
193
193
  error(error: Error): void;
194
- change(change: ChangeStreamDocument): void;
194
+ change(change: ChangeStreamDocument<TSchema>): void;
195
195
  } & AbstractCursorEvents;
196
196
 
197
197
  /**
198
198
  * Creates a new Change Stream instance. Normally created using {@link Collection#watch|Collection.watch()}.
199
199
  * @public
200
200
  */
201
- export class ChangeStream<
202
- TSchema extends Document = Document
203
- > extends TypedEventEmitter<ChangeStreamEvents> {
201
+ export class ChangeStream<TSchema extends Document = Document> extends TypedEventEmitter<
202
+ ChangeStreamEvents<TSchema>
203
+ > {
204
204
  pipeline: Document[];
205
205
  options: ChangeStreamOptions;
206
206
  parent: MongoClient | Db | Collection;
@@ -97,6 +97,7 @@ export interface CommandOptions extends BSONSerializeOptions {
97
97
  session?: ClientSession;
98
98
  documentsReturnedIn?: string;
99
99
  noResponse?: boolean;
100
+ omitReadPreference?: boolean;
100
101
 
101
102
  // FIXME: NODE-2802
102
103
  willRetryWrite?: boolean;
@@ -1,7 +1,7 @@
1
- export const MIN_SUPPORTED_SERVER_VERSION = '2.6';
2
- export const MAX_SUPPORTED_SERVER_VERSION = '5.0';
3
- export const MIN_SUPPORTED_WIRE_VERSION = 2;
4
- export const MAX_SUPPORTED_WIRE_VERSION = 13;
1
+ export const MIN_SUPPORTED_SERVER_VERSION = '3.6';
2
+ export const MAX_SUPPORTED_SERVER_VERSION = '5.1';
3
+ export const MIN_SUPPORTED_WIRE_VERSION = 6;
4
+ export const MAX_SUPPORTED_WIRE_VERSION = 14;
5
5
  export const OP_REPLY = 1;
6
6
  export const OP_UPDATE = 2001;
7
7
  export const OP_INSERT = 2002;
package/src/collection.ts CHANGED
@@ -676,12 +676,16 @@ export class Collection<TSchema extends Document = Document> {
676
676
  * @param options - Optional settings for the command
677
677
  * @param callback - An optional callback, a Promise will be returned if none is provided
678
678
  */
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;
679
+ findOne(): Promise<WithId<TSchema> | null>;
680
+ findOne(callback: Callback<WithId<TSchema> | null>): void;
681
+ findOne(filter: Filter<TSchema>): Promise<WithId<TSchema> | null>;
682
+ findOne(filter: Filter<TSchema>, callback: Callback<WithId<TSchema> | null>): void;
683
+ findOne(filter: Filter<TSchema>, options: FindOptions): Promise<WithId<TSchema> | null>;
684
+ findOne(
685
+ filter: Filter<TSchema>,
686
+ options: FindOptions,
687
+ callback: Callback<WithId<TSchema> | null>
688
+ ): void;
685
689
 
686
690
  // allow an override of the schema.
687
691
  findOne<T = TSchema>(): Promise<T | null>;
@@ -695,10 +699,10 @@ export class Collection<TSchema extends Document = Document> {
695
699
  ): void;
696
700
 
697
701
  findOne(
698
- filter?: Filter<TSchema> | Callback<TSchema | null>,
699
- options?: FindOptions | Callback<TSchema | null>,
700
- callback?: Callback<TSchema | null>
701
- ): Promise<TSchema | null> | void {
702
+ filter?: Filter<TSchema> | Callback<WithId<TSchema> | null>,
703
+ options?: FindOptions | Callback<WithId<TSchema> | null>,
704
+ callback?: Callback<WithId<TSchema> | null>
705
+ ): Promise<WithId<TSchema> | null> | void {
702
706
  if (callback != null && typeof callback !== 'function') {
703
707
  throw new MongoInvalidArgumentError(
704
708
  'Third parameter to `findOne()` must be a callback or undefined'
@@ -706,7 +710,7 @@ export class Collection<TSchema extends Document = Document> {
706
710
  }
707
711
 
708
712
  if (typeof filter === 'function') {
709
- callback = filter as Callback<TSchema | null>;
713
+ callback = filter as Callback<WithId<TSchema> | null>;
710
714
  filter = {};
711
715
  options = {};
712
716
  }
@@ -725,10 +729,10 @@ export class Collection<TSchema extends Document = Document> {
725
729
  *
726
730
  * @param filter - The filter predicate. If unspecified, then all documents in the collection will match the predicate
727
731
  */
728
- find(): 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> {
732
+ find(): FindCursor<WithId<TSchema>>;
733
+ find(filter: Filter<WithId<TSchema>>, options?: FindOptions): FindCursor<WithId<TSchema>>;
734
+ find<T>(filter: Filter<WithId<TSchema>>, options?: FindOptions): FindCursor<T>;
735
+ find(filter?: Filter<WithId<TSchema>>, options?: FindOptions): FindCursor<WithId<TSchema>> {
732
736
  if (arguments.length > 2) {
733
737
  throw new MongoInvalidArgumentError(
734
738
  'Method "collection.find()" accepts at most two arguments'
@@ -738,7 +742,7 @@ export class Collection<TSchema extends Document = Document> {
738
742
  throw new MongoInvalidArgumentError('Argument "options" must not be function');
739
743
  }
740
744
 
741
- return new FindCursor<TSchema>(
745
+ return new FindCursor<WithId<TSchema>>(
742
746
  getTopology(this),
743
747
  this.s.namespace,
744
748
  filter,
@@ -1415,6 +1419,7 @@ export class Collection<TSchema extends Document = Document> {
1415
1419
  /**
1416
1420
  * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection.
1417
1421
  *
1422
+ * @deprecated collection.mapReduce is deprecated. Use the aggregation pipeline instead. Visit https://docs.mongodb.com/manual/reference/map-reduce-to-aggregation-pipeline for more information on how to translate map-reduce operations to the aggregation pipeline.
1418
1423
  * @param map - The mapping function.
1419
1424
  * @param reduce - The reduce function.
1420
1425
  * @param options - Optional settings for the command
@@ -1446,6 +1451,9 @@ export class Collection<TSchema extends Document = Document> {
1446
1451
  options?: MapReduceOptions<TKey, TValue> | Callback<Document | Document[]>,
1447
1452
  callback?: Callback<Document | Document[]>
1448
1453
  ): Promise<Document | Document[]> | void {
1454
+ emitWarningOnce(
1455
+ 'collection.mapReduce is deprecated. Use the aggregation pipeline instead. Visit https://docs.mongodb.com/manual/reference/map-reduce-to-aggregation-pipeline for more information on how to translate map-reduce operations to the aggregation pipeline.'
1456
+ );
1449
1457
  if ('function' === typeof options) (callback = options), (options = {});
1450
1458
  // Out must always be defined (make sure we don't break weirdly on pre 1.8+ servers)
1451
1459
  // TODO NODE-3339: Figure out if this is still necessary given we no longer officially support pre-1.8
@@ -75,7 +75,7 @@ export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostA
75
75
 
76
76
  // Resolve the SRV record and use the result as the list of hosts to connect to.
77
77
  const lookupAddress = options.srvHost;
78
- dns.resolveSrv(`_mongodb._tcp.${lookupAddress}`, (err, addresses) => {
78
+ dns.resolveSrv(`_${options.srvServiceName}._tcp.${lookupAddress}`, (err, addresses) => {
79
79
  if (err) return callback(err);
80
80
 
81
81
  if (addresses.length === 0) {
@@ -92,7 +92,7 @@ export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostA
92
92
  HostAddress.fromString(`${r.name}:${r.port ?? 27017}`)
93
93
  );
94
94
 
95
- const lbError = validateLoadBalancedOptions(hostAddresses, options);
95
+ const lbError = validateLoadBalancedOptions(hostAddresses, options, true);
96
96
  if (lbError) {
97
97
  return callback(lbError);
98
98
  }
@@ -116,14 +116,14 @@ export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostA
116
116
  );
117
117
  }
118
118
 
119
+ if (VALID_TXT_RECORDS.some(option => txtRecordOptions.get(option) === '')) {
120
+ return callback(new MongoParseError('Cannot have empty URI params in DNS TXT Record'));
121
+ }
122
+
119
123
  const source = txtRecordOptions.get('authSource') ?? undefined;
120
124
  const replicaSet = txtRecordOptions.get('replicaSet') ?? undefined;
121
125
  const loadBalanced = txtRecordOptions.get('loadBalanced') ?? undefined;
122
126
 
123
- if (source === '' || replicaSet === '') {
124
- return callback(new MongoParseError('Cannot have empty URI params in DNS TXT Record'));
125
- }
126
-
127
127
  if (!options.userSpecifiedAuthSource && source) {
128
128
  options.credentials = MongoCredentials.merge(options.credentials, { source });
129
129
  }
@@ -136,7 +136,11 @@ export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostA
136
136
  options.loadBalanced = true;
137
137
  }
138
138
 
139
- const lbError = validateLoadBalancedOptions(hostAddresses, options);
139
+ if (options.replicaSet && options.srvMaxHosts > 0) {
140
+ return callback(new MongoParseError('Cannot combine replicaSet option with srvMaxHosts'));
141
+ }
142
+
143
+ const lbError = validateLoadBalancedOptions(hostAddresses, options, true);
140
144
  if (lbError) {
141
145
  return callback(lbError);
142
146
  }
@@ -251,13 +255,6 @@ export function parseOptions(
251
255
 
252
256
  const mongoOptions = Object.create(null);
253
257
  mongoOptions.hosts = isSRV ? [] : hosts.map(HostAddress.fromString);
254
- if (isSRV) {
255
- // SRV Record is resolved upon connecting
256
- mongoOptions.srvHost = hosts[0];
257
- if (!url.searchParams.has('tls') && !url.searchParams.has('ssl')) {
258
- options.tls = true;
259
- }
260
- }
261
258
 
262
259
  const urlOptions = new CaseInsensitiveMap();
263
260
 
@@ -289,30 +286,34 @@ export function parseOptions(
289
286
  throw new MongoAPIError('URI cannot contain options with no value');
290
287
  }
291
288
 
292
- if (key.toLowerCase() === 'serverapi') {
293
- throw new MongoParseError(
294
- 'URI cannot contain `serverApi`, it can only be passed to the client'
295
- );
296
- }
297
-
298
- if (key.toLowerCase() === 'authsource' && urlOptions.has('authSource')) {
299
- // If authSource is an explicit key in the urlOptions we need to remove the implicit dbName
300
- urlOptions.delete('authSource');
301
- }
302
-
303
289
  if (!urlOptions.has(key)) {
304
290
  urlOptions.set(key, values);
305
291
  }
306
292
  }
307
293
 
294
+ if (urlOptions.has('authSource')) {
295
+ // If authSource is an explicit key in the urlOptions we need to remove the dbName
296
+ urlOptions.delete('dbName');
297
+ }
298
+
308
299
  const objectOptions = new CaseInsensitiveMap(
309
300
  Object.entries(options).filter(([, v]) => v != null)
310
301
  );
311
302
 
303
+ // Validate options that can only be provided by one of uri or object
304
+
305
+ if (urlOptions.has('serverApi')) {
306
+ throw new MongoParseError(
307
+ 'URI cannot contain `serverApi`, it can only be passed to the client'
308
+ );
309
+ }
310
+
312
311
  if (objectOptions.has('loadBalanced')) {
313
312
  throw new MongoParseError('loadBalanced is only a valid option in the URI');
314
313
  }
315
314
 
315
+ // All option collection
316
+
316
317
  const allOptions = new CaseInsensitiveMap();
317
318
 
318
319
  const allKeys = new Set<string>([
@@ -360,6 +361,8 @@ export function parseOptions(
360
361
  );
361
362
  }
362
363
 
364
+ // Option parsing and setting
365
+
363
366
  for (const [key, descriptor] of Object.entries(OPTIONS)) {
364
367
  const values = allOptions.get(key);
365
368
  if (!values || values.length === 0) continue;
@@ -401,25 +404,53 @@ export function parseOptions(
401
404
 
402
405
  if (options.promiseLibrary) PromiseProvider.set(options.promiseLibrary);
403
406
 
404
- if (mongoOptions.directConnection && typeof mongoOptions.srvHost === 'string') {
405
- throw new MongoAPIError('SRV URI does not support directConnection');
406
- }
407
-
408
- const lbError = validateLoadBalancedOptions(hosts, mongoOptions);
407
+ const lbError = validateLoadBalancedOptions(hosts, mongoOptions, isSRV);
409
408
  if (lbError) {
410
409
  throw lbError;
411
410
  }
411
+ if (mongoClient && mongoOptions.autoEncryption) {
412
+ Encrypter.checkForMongoCrypt();
413
+ mongoOptions.encrypter = new Encrypter(mongoClient, uri, options);
414
+ mongoOptions.autoEncrypter = mongoOptions.encrypter.autoEncrypter;
415
+ }
416
+
417
+ // Potential SRV Overrides and SRV connection string validations
412
418
 
413
- // Potential SRV Overrides
414
419
  mongoOptions.userSpecifiedAuthSource =
415
420
  objectOptions.has('authSource') || urlOptions.has('authSource');
416
421
  mongoOptions.userSpecifiedReplicaSet =
417
422
  objectOptions.has('replicaSet') || urlOptions.has('replicaSet');
418
423
 
419
- if (mongoClient && mongoOptions.autoEncryption) {
420
- Encrypter.checkForMongoCrypt();
421
- mongoOptions.encrypter = new Encrypter(mongoClient, uri, options);
422
- mongoOptions.autoEncrypter = mongoOptions.encrypter.autoEncrypter;
424
+ if (isSRV) {
425
+ // SRV Record is resolved upon connecting
426
+ mongoOptions.srvHost = hosts[0];
427
+
428
+ if (mongoOptions.directConnection) {
429
+ throw new MongoAPIError('SRV URI does not support directConnection');
430
+ }
431
+
432
+ if (mongoOptions.srvMaxHosts > 0 && typeof mongoOptions.replicaSet === 'string') {
433
+ throw new MongoParseError('Cannot use srvMaxHosts option with replicaSet');
434
+ }
435
+
436
+ // SRV turns on TLS by default, but users can override and turn it off
437
+ const noUserSpecifiedTLS = !objectOptions.has('tls') && !urlOptions.has('tls');
438
+ const noUserSpecifiedSSL = !objectOptions.has('ssl') && !urlOptions.has('ssl');
439
+ if (noUserSpecifiedTLS && noUserSpecifiedSSL) {
440
+ mongoOptions.tls = true;
441
+ }
442
+ } else {
443
+ const userSpecifiedSrvOptions =
444
+ urlOptions.has('srvMaxHosts') ||
445
+ objectOptions.has('srvMaxHosts') ||
446
+ urlOptions.has('srvServiceName') ||
447
+ objectOptions.has('srvServiceName');
448
+
449
+ if (userSpecifiedSrvOptions) {
450
+ throw new MongoParseError(
451
+ 'Cannot use srvMaxHosts or srvServiceName with a non-srv connection string'
452
+ );
453
+ }
423
454
  }
424
455
 
425
456
  return mongoOptions;
@@ -427,7 +458,8 @@ export function parseOptions(
427
458
 
428
459
  function validateLoadBalancedOptions(
429
460
  hosts: HostAddress[] | string[],
430
- mongoOptions: MongoOptions
461
+ mongoOptions: MongoOptions,
462
+ isSrv: boolean
431
463
  ): MongoParseError | undefined {
432
464
  if (mongoOptions.loadBalanced) {
433
465
  if (hosts.length > 1) {
@@ -439,6 +471,10 @@ function validateLoadBalancedOptions(
439
471
  if (mongoOptions.directConnection) {
440
472
  return new MongoParseError(LB_DIRECT_CONNECTION_ERROR);
441
473
  }
474
+
475
+ if (isSrv && mongoOptions.srvMaxHosts > 0) {
476
+ return new MongoParseError('Cannot limit srv hosts with loadBalanced enabled');
477
+ }
442
478
  }
443
479
  }
444
480
 
@@ -924,6 +960,14 @@ export const OPTIONS = {
924
960
  default: 0,
925
961
  type: 'uint'
926
962
  },
963
+ srvMaxHosts: {
964
+ type: 'uint',
965
+ default: 0
966
+ },
967
+ srvServiceName: {
968
+ type: 'string',
969
+ default: 'mongodb'
970
+ },
927
971
  ssl: {
928
972
  target: 'tls',
929
973
  type: 'boolean'
package/src/db.ts CHANGED
@@ -226,18 +226,17 @@ export class Db {
226
226
  * @param options - Optional settings for the command
227
227
  * @param callback - An optional callback, a Promise will be returned if none is provided
228
228
  */
229
- createCollection<TSchema extends Document = Document>(name: string): Promise<Collection<TSchema>>;
230
229
  createCollection<TSchema extends Document = Document>(
231
230
  name: string,
232
- callback: Callback<Collection<TSchema>>
233
- ): void;
231
+ options?: CreateCollectionOptions
232
+ ): Promise<Collection<TSchema>>;
234
233
  createCollection<TSchema extends Document = Document>(
235
234
  name: string,
236
- options: CreateCollectionOptions
237
- ): Promise<Collection<TSchema>>;
235
+ callback: Callback<Collection<TSchema>>
236
+ ): void;
238
237
  createCollection<TSchema extends Document = Document>(
239
238
  name: string,
240
- options: CreateCollectionOptions,
239
+ options: CreateCollectionOptions | undefined,
241
240
  callback: Callback<Collection<TSchema>>
242
241
  ): void;
243
242
  createCollection<TSchema extends Document = Document>(
@@ -132,6 +132,16 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
132
132
  compressors?: CompressorName[] | string;
133
133
  /** An integer that specifies the compression level if using zlib for network compression. */
134
134
  zlibCompressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | undefined;
135
+ /** The maximum number of hosts to connect to when using an srv connection string, a setting of `0` means unlimited hosts */
136
+ srvMaxHosts?: number;
137
+ /**
138
+ * Modifies the srv URI to look like:
139
+ *
140
+ * `_{srvServiceName}._tcp.{hostname}.{domainname}`
141
+ *
142
+ * Querying this DNS URI is expected to respond with SRV records
143
+ */
144
+ srvServiceName?: string;
135
145
  /** The maximum number of connections in the connection pool. */
136
146
  maxPoolSize?: number;
137
147
  /** The minimum number of connections in the connection pool. */
@@ -643,6 +653,8 @@ export interface MongoOptions
643
653
  | 'retryWrites'
644
654
  | 'serverSelectionTimeoutMS'
645
655
  | 'socketTimeoutMS'
656
+ | 'srvMaxHosts'
657
+ | 'srvServiceName'
646
658
  | 'tlsAllowInvalidCertificates'
647
659
  | 'tlsAllowInvalidHostnames'
648
660
  | 'tlsInsecure'