mongodb 3.6.5 → 3.6.9

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.
package/HISTORY.md CHANGED
@@ -2,6 +2,47 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [3.6.9](https://github.com/mongodb/node-mongodb-native/compare/v3.6.8...v3.6.9) (2021-05-26)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **NODE-3309:** remove redundant iteration of bulk write result ([#2815](https://github.com/mongodb/node-mongodb-native/issues/2815)) ([fac9610](https://github.com/mongodb/node-mongodb-native/commit/fac961086eafa0f7437576fd6af900e1f9fe22ed))
11
+ * fix url parsing for a mongodb+srv url that has commas in the database name ([#2789](https://github.com/mongodb/node-mongodb-native/issues/2789)) ([58c4e69](https://github.com/mongodb/node-mongodb-native/commit/58c4e693cc3a717254144d5f9bdddd8414217e97))
12
+
13
+ ### [3.6.8](https://github.com/mongodb/node-mongodb-native/compare/v3.6.7...v3.6.8) (2021-05-21)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * **cmap:** undo flipping of `beforeHandshake` flag for timeout errors ([#2813](https://github.com/mongodb/node-mongodb-native/issues/2813)) ([6e3bab3](https://github.com/mongodb/node-mongodb-native/commit/6e3bab32204ea905ab9b949edccb68556b50d382))
19
+
20
+ ### [3.6.7](https://github.com/mongodb/node-mongodb-native/compare/v3.6.6...v3.6.7) (2021-05-18)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * **docs:** removing incorrect apm docs ([#2793](https://github.com/mongodb/node-mongodb-native/issues/2793)) ([971259a](https://github.com/mongodb/node-mongodb-native/commit/971259a868a8018e90ebc2f28d151eb7af3dd50a))
26
+ * **NODE-3173:** Preserve sort key order for numeric string keys ([#2790](https://github.com/mongodb/node-mongodb-native/issues/2790)) ([730f43a](https://github.com/mongodb/node-mongodb-native/commit/730f43af6d9e53603af998353b720d8161426d8c))
27
+ * **NODE-3176:** handle errors from MessageStream ([#2774](https://github.com/mongodb/node-mongodb-native/issues/2774)) ([f1afcc4](https://github.com/mongodb/node-mongodb-native/commit/f1afcc4efbc41ce436812a6bfa22843e939ab5cf))
28
+ * **NODE-3192:** check clusterTime is defined before access ([#2806](https://github.com/mongodb/node-mongodb-native/issues/2806)) ([6ceace6](https://github.com/mongodb/node-mongodb-native/commit/6ceace6b245c42b8498fb1b13e7c37a97a46946d))
29
+ * **NODE-3252:** state transistion from DISCONNECTED ([#2807](https://github.com/mongodb/node-mongodb-native/issues/2807)) ([5d8f649](https://github.com/mongodb/node-mongodb-native/commit/5d8f6493a0ba4b525434c0868e2ae12315b4c249))
30
+ * **sdam:** topology no longer causes close event ([#2791](https://github.com/mongodb/node-mongodb-native/issues/2791)) ([16e7064](https://github.com/mongodb/node-mongodb-native/commit/16e70642f25954a03b91a2c2991cea96b8356de7))
31
+ * invalid case on writeconcern makes skip check fail ([#2773](https://github.com/mongodb/node-mongodb-native/issues/2773)) ([b1363c2](https://github.com/mongodb/node-mongodb-native/commit/b1363c26db5da5003f9db43be7e8d6e9007d45bd))
32
+
33
+ ### [3.6.6](https://github.com/mongodb/node-mongodb-native/compare/v3.6.5...v3.6.6) (2021-04-06)
34
+
35
+
36
+ ### Bug Fixes
37
+
38
+ * always close gridfs upload stream on finish ([#2758](https://github.com/mongodb/node-mongodb-native/issues/2758)) ([c976a01](https://github.com/mongodb/node-mongodb-native/commit/c976a01bf385941bee07fa7f021adf1d425109a8))
39
+ * **csfle:** ensure that monitoring connections are not encrypted ([#2749](https://github.com/mongodb/node-mongodb-native/issues/2749)) ([86bddf1](https://github.com/mongodb/node-mongodb-native/commit/86bddf1ef516d6b8c752082e33c15624753579ab))
40
+ * ensure cursor readPreference is applied to find operations ([#2751](https://github.com/mongodb/node-mongodb-native/issues/2751)) ([91ba19e](https://github.com/mongodb/node-mongodb-native/commit/91ba19efdc4713903584c6161cfdd7b91b0e61f9))
41
+ * ensure monitor has rtt pinger in when calculating rtt ([#2757](https://github.com/mongodb/node-mongodb-native/issues/2757)) ([b94519b](https://github.com/mongodb/node-mongodb-native/commit/b94519ba894b4442d3dabbac59bd12784d8b7178))
42
+ * no infinite loop on windows requiring optional deps ([f2a4ff8](https://github.com/mongodb/node-mongodb-native/commit/f2a4ff870178fbbe8de616c45891368665f29f4b))
43
+ * **NODE-2995:** Add shared metadata MongoClient ([#2760](https://github.com/mongodb/node-mongodb-native/issues/2760)) ([9256242](https://github.com/mongodb/node-mongodb-native/commit/9256242d51c037059c0af5ada9639fc0a74ad033))
44
+ * **NODE-3109:** prevent servername from being IP ([#2763](https://github.com/mongodb/node-mongodb-native/issues/2763)) ([312ffef](https://github.com/mongodb/node-mongodb-native/commit/312ffef18c66a0020f19bdc1d654987d9148d709))
45
+
5
46
  ### [3.6.5](https://github.com/mongodb/node-mongodb-native/compare/v3.6.4...v3.6.5) (2021-03-16)
6
47
 
7
48
 
@@ -5,6 +5,7 @@ const MongoError = require('../core').MongoError;
5
5
  const ObjectID = require('../core').BSON.ObjectID;
6
6
  const BSON = require('../core').BSON;
7
7
  const MongoWriteConcernError = require('../core').MongoWriteConcernError;
8
+ const emitWarningOnce = require('../utils').emitWarningOnce;
8
9
  const toError = require('../utils').toError;
9
10
  const handleCallback = require('../utils').handleCallback;
10
11
  const applyRetryableWrites = require('../utils').applyRetryableWrites;
@@ -56,6 +57,9 @@ class Batch {
56
57
  }
57
58
  }
58
59
 
60
+ const kUpsertedIds = Symbol('upsertedIds');
61
+ const kInsertedIds = Symbol('insertedIds');
62
+
59
63
  /**
60
64
  * @classdesc
61
65
  * The result of a bulk write.
@@ -68,6 +72,60 @@ class BulkWriteResult {
68
72
  */
69
73
  constructor(bulkResult) {
70
74
  this.result = bulkResult;
75
+ this[kUpsertedIds] = undefined;
76
+ this[kInsertedIds] = undefined;
77
+ }
78
+
79
+ /** Number of documents inserted. */
80
+ get insertedCount() {
81
+ return typeof this.result.nInserted !== 'number' ? 0 : this.result.nInserted;
82
+ }
83
+ /** Number of documents matched for update. */
84
+ get matchedCount() {
85
+ return typeof this.result.nMatched !== 'number' ? 0 : this.result.nMatched;
86
+ }
87
+ /** Number of documents modified. */
88
+ get modifiedCount() {
89
+ return typeof this.result.nModified !== 'number' ? 0 : this.result.nModified;
90
+ }
91
+ /** Number of documents deleted. */
92
+ get deletedCount() {
93
+ return typeof this.result.nRemoved !== 'number' ? 0 : this.result.nRemoved;
94
+ }
95
+ /** Number of documents upserted. */
96
+ get upsertedCount() {
97
+ return !this.result.upserted ? 0 : this.result.upserted.length;
98
+ }
99
+
100
+ /** Upserted document generated Id's, hash key is the index of the originating operation */
101
+ get upsertedIds() {
102
+ if (this[kUpsertedIds]) {
103
+ return this[kUpsertedIds];
104
+ }
105
+
106
+ this[kUpsertedIds] = {};
107
+ for (const doc of this.result.upserted || []) {
108
+ this[kUpsertedIds][doc.index] = doc._id;
109
+ }
110
+ return this[kUpsertedIds];
111
+ }
112
+
113
+ /** Inserted document generated Id's, hash key is the index of the originating operation */
114
+ get insertedIds() {
115
+ if (this[kInsertedIds]) {
116
+ return this[kInsertedIds];
117
+ }
118
+
119
+ this[kInsertedIds] = {};
120
+ for (const doc of this.result.insertedIds || []) {
121
+ this[kInsertedIds][doc.index] = doc._id;
122
+ }
123
+ return this[kInsertedIds];
124
+ }
125
+
126
+ /** The number of inserted documents @type {number} */
127
+ get n() {
128
+ return this.result.insertedCount;
71
129
  }
72
130
 
73
131
  /**
@@ -571,6 +629,35 @@ class BulkWriteError extends MongoError {
571
629
  this.name = 'BulkWriteError';
572
630
  this.result = result;
573
631
  }
632
+
633
+ /** Number of documents inserted. */
634
+ get insertedCount() {
635
+ return this.result.insertedCount;
636
+ }
637
+ /** Number of documents matched for update. */
638
+ get matchedCount() {
639
+ return this.result.matchedCount;
640
+ }
641
+ /** Number of documents modified. */
642
+ get modifiedCount() {
643
+ return this.result.modifiedCount;
644
+ }
645
+ /** Number of documents deleted. */
646
+ get deletedCount() {
647
+ return this.result.deletedCount;
648
+ }
649
+ /** Number of documents upserted. */
650
+ get upsertedCount() {
651
+ return this.result.upsertedCount;
652
+ }
653
+ /** Inserted document generated Id's, hash key is the index of the originating operation */
654
+ get insertedIds() {
655
+ return this.result.insertedIds;
656
+ }
657
+ /** Upserted document generated Id's, hash key is the index of the originating operation */
658
+ get upsertedIds() {
659
+ return this.result.upsertedIds;
660
+ }
574
661
  }
575
662
 
576
663
  /**
@@ -737,15 +824,19 @@ class FindOperators {
737
824
 
738
825
  /**
739
826
  * backwards compatability for deleteOne
827
+ * @deprecated
740
828
  */
741
829
  removeOne() {
830
+ emitWarningOnce('bulk operation `removeOne` has been deprecated, please use `deleteOne`');
742
831
  return this.deleteOne();
743
832
  }
744
833
 
745
834
  /**
746
835
  * backwards compatability for delete
836
+ * @deprecated
747
837
  */
748
838
  remove() {
839
+ emitWarningOnce('bulk operation `remove` has been deprecated, please use `delete`');
749
840
  return this.delete();
750
841
  }
751
842
  }
@@ -1041,6 +1132,9 @@ class BulkOperationBase {
1041
1132
  }
1042
1133
 
1043
1134
  if (op.insertMany) {
1135
+ emitWarningOnce(
1136
+ 'bulk operation `insertMany` has been deprecated; use multiple `insertOne` ops instead'
1137
+ );
1044
1138
  for (let i = 0; i < op.insertMany.length; i++) {
1045
1139
  if (forceServerObjectId !== true && op.insertMany[i]._id == null)
1046
1140
  op.insertMany[i]._id = new ObjectID();
@@ -1294,5 +1388,6 @@ module.exports = {
1294
1388
  INSERT: INSERT,
1295
1389
  UPDATE: UPDATE,
1296
1390
  REMOVE: REMOVE,
1297
- BulkWriteError
1391
+ BulkWriteError,
1392
+ BulkWriteResult
1298
1393
  };
@@ -58,38 +58,9 @@ class Connection extends EventEmitter {
58
58
  /* ignore errors, listen to `close` instead */
59
59
  });
60
60
 
61
- stream.on('close', () => {
62
- if (this.closed) {
63
- return;
64
- }
65
-
66
- this.closed = true;
67
- this[kQueue].forEach(op =>
68
- op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} closed`))
69
- );
70
- this[kQueue].clear();
71
-
72
- this.emit('close');
73
- });
74
-
75
- stream.on('timeout', () => {
76
- if (this.closed) {
77
- return;
78
- }
79
-
80
- stream.destroy();
81
- this.closed = true;
82
- this[kQueue].forEach(op =>
83
- op.cb(
84
- new MongoNetworkTimeoutError(`connection ${this.id} to ${this.address} timed out`, {
85
- beforeHandshake: this[kIsMaster] == null
86
- })
87
- )
88
- );
89
-
90
- this[kQueue].clear();
91
- this.emit('close');
92
- });
61
+ this[kMessageStream].on('error', error => this.handleIssue({ destroy: error }));
62
+ stream.on('close', () => this.handleIssue({ isClose: true }));
63
+ stream.on('timeout', () => this.handleIssue({ isTimeout: true, destroy: true }));
93
64
 
94
65
  // hook the message stream up to the passed in stream
95
66
  stream.pipe(this[kMessageStream]);
@@ -132,6 +103,39 @@ class Connection extends EventEmitter {
132
103
  this[kLastUseTime] = now();
133
104
  }
134
105
 
106
+ /**
107
+ * @param {{ isTimeout?: boolean; isClose?: boolean; destroy?: boolean | Error }} issue
108
+ */
109
+ handleIssue(issue) {
110
+ if (this.closed) {
111
+ return;
112
+ }
113
+
114
+ if (issue.destroy) {
115
+ this[kStream].destroy(typeof issue.destroy === 'boolean' ? undefined : issue.destroy);
116
+ }
117
+
118
+ this.closed = true;
119
+
120
+ for (const idAndOp of this[kQueue]) {
121
+ const op = idAndOp[1];
122
+ if (issue.isTimeout) {
123
+ op.cb(
124
+ new MongoNetworkTimeoutError(`connection ${this.id} to ${this.address} timed out`, {
125
+ beforeHandshake: this.ismaster == null
126
+ })
127
+ );
128
+ } else if (issue.isClose) {
129
+ op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} closed`));
130
+ } else {
131
+ op.cb(typeof issue.destroy === 'boolean' ? undefined : issue.destroy);
132
+ }
133
+ }
134
+
135
+ this[kQueue].clear();
136
+ this.emit('close');
137
+ }
138
+
135
139
  destroy(options, callback) {
136
140
  if (typeof options === 'function') {
137
141
  callback = options;
package/lib/collection.js CHANGED
@@ -1655,7 +1655,7 @@ Collection.prototype.stats = function(options, callback) {
1655
1655
 
1656
1656
  /**
1657
1657
  * @typedef {Object} Collection~findAndModifyWriteOpResult
1658
- * @property {object} value Document returned from the `findAndModify` command. If no documents were found, `value` will be `null` by default (`returnOriginal: true`), even if a document was upserted; if `returnOriginal` was false, the upserted document will be returned in that case.
1658
+ * @property {object} value Document returned from the `findAndModify` command. If no documents were found, `value` will be `null` by default even if a document was upserted unless `returnDocument` is specified as `'after'`, in which case the upserted document will be returned.
1659
1659
  * @property {object} lastErrorObject The raw lastErrorObject returned from the command. See {@link https://docs.mongodb.com/manual/reference/command/findAndModify/index.html#lasterrorobject|findAndModify command documentation}.
1660
1660
  * @property {Number} ok Is 1 if the command executed correctly.
1661
1661
  */
@@ -1716,7 +1716,8 @@ Collection.prototype.findOneAndDelete = function(filter, options, callback) {
1716
1716
  * @param {object} [options.projection] Limits the fields to return for all matching documents.
1717
1717
  * @param {object} [options.sort] Determines which document the operation modifies if the query selects multiple documents.
1718
1718
  * @param {boolean} [options.upsert=false] Upsert the document if it does not exist.
1719
- * @param {boolean} [options.returnOriginal=true] When false, returns the updated document rather than the original. The default is true.
1719
+ * @param {'before'|'after'} [options.returnDocument='before'] When set to `'after'`, returns the updated document rather than the original. The default is `'before'`.
1720
+ * @param {boolean} [options.returnOriginal=true] **Deprecated** Use `options.returnDocument` instead.
1720
1721
  * @param {boolean} [options.checkKeys=false] If true, will throw if bson documents start with `$` or include a `.` in any key value
1721
1722
  * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
1722
1723
  * @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
@@ -1725,22 +1726,29 @@ Collection.prototype.findOneAndDelete = function(filter, options, callback) {
1725
1726
  * @param {Collection~findAndModifyCallback} [callback] The collection result callback
1726
1727
  * @return {Promise<Collection~findAndModifyWriteOpResultObject>} returns Promise if no callback passed
1727
1728
  */
1728
- Collection.prototype.findOneAndReplace = function(filter, replacement, options, callback) {
1729
- if (typeof options === 'function') (callback = options), (options = {});
1730
- options = options || {};
1729
+ Collection.prototype.findOneAndReplace = deprecateOptions(
1730
+ {
1731
+ name: 'collection.findOneAndReplace',
1732
+ deprecatedOptions: ['returnOriginal'],
1733
+ optionsIndex: 2
1734
+ },
1735
+ function(filter, replacement, options, callback) {
1736
+ if (typeof options === 'function') (callback = options), (options = {});
1737
+ options = options || {};
1731
1738
 
1732
- // Add ignoreUndefined
1733
- if (this.s.options.ignoreUndefined) {
1734
- options = Object.assign({}, options);
1735
- options.ignoreUndefined = this.s.options.ignoreUndefined;
1736
- }
1739
+ // Add ignoreUndefined
1740
+ if (this.s.options.ignoreUndefined) {
1741
+ options = Object.assign({}, options);
1742
+ options.ignoreUndefined = this.s.options.ignoreUndefined;
1743
+ }
1737
1744
 
1738
- return executeOperation(
1739
- this.s.topology,
1740
- new FindOneAndReplaceOperation(this, filter, replacement, options),
1741
- callback
1742
- );
1743
- };
1745
+ return executeOperation(
1746
+ this.s.topology,
1747
+ new FindOneAndReplaceOperation(this, filter, replacement, options),
1748
+ callback
1749
+ );
1750
+ }
1751
+ );
1744
1752
 
1745
1753
  /**
1746
1754
  * Find a document and update it in one atomic operation. Requires a write lock for the duration of the operation.
@@ -1757,7 +1765,8 @@ Collection.prototype.findOneAndReplace = function(filter, replacement, options,
1757
1765
  * @param {object} [options.projection] Limits the fields to return for all matching documents.
1758
1766
  * @param {object} [options.sort] Determines which document the operation modifies if the query selects multiple documents.
1759
1767
  * @param {boolean} [options.upsert=false] Upsert the document if it does not exist.
1760
- * @param {boolean} [options.returnOriginal=true] When false, returns the updated document rather than the original. The default is true.
1768
+ * @param {'before'|'after'} [options.returnDocument='before'] When set to `'after'`, returns the updated document rather than the original. The default is `'before'`.
1769
+ * @param {boolean} [options.returnOriginal=true] **Deprecated** Use `options.returnDocument` instead.
1761
1770
  * @param {boolean} [options.checkKeys=false] If true, will throw if bson documents start with `$` or include a `.` in any key value
1762
1771
  * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
1763
1772
  * @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
@@ -1766,22 +1775,29 @@ Collection.prototype.findOneAndReplace = function(filter, replacement, options,
1766
1775
  * @param {Collection~findAndModifyCallback} [callback] The collection result callback
1767
1776
  * @return {Promise<Collection~findAndModifyWriteOpResultObject>} returns Promise if no callback passed
1768
1777
  */
1769
- Collection.prototype.findOneAndUpdate = function(filter, update, options, callback) {
1770
- if (typeof options === 'function') (callback = options), (options = {});
1771
- options = options || {};
1778
+ Collection.prototype.findOneAndUpdate = deprecateOptions(
1779
+ {
1780
+ name: 'collection.findOneAndUpdate',
1781
+ deprecatedOptions: ['returnOriginal'],
1782
+ optionsIndex: 2
1783
+ },
1784
+ function(filter, update, options, callback) {
1785
+ if (typeof options === 'function') (callback = options), (options = {});
1786
+ options = options || {};
1772
1787
 
1773
- // Add ignoreUndefined
1774
- if (this.s.options.ignoreUndefined) {
1775
- options = Object.assign({}, options);
1776
- options.ignoreUndefined = this.s.options.ignoreUndefined;
1777
- }
1788
+ // Add ignoreUndefined
1789
+ if (this.s.options.ignoreUndefined) {
1790
+ options = Object.assign({}, options);
1791
+ options.ignoreUndefined = this.s.options.ignoreUndefined;
1792
+ }
1778
1793
 
1779
- return executeOperation(
1780
- this.s.topology,
1781
- new FindOneAndUpdateOperation(this, filter, update, options),
1782
- callback
1783
- );
1784
- };
1794
+ return executeOperation(
1795
+ this.s.topology,
1796
+ new FindOneAndUpdateOperation(this, filter, update, options),
1797
+ callback
1798
+ );
1799
+ }
1800
+ );
1785
1801
 
1786
1802
  /**
1787
1803
  * Find and update a document.
@@ -2199,7 +2215,6 @@ Collection.prototype.initializeUnorderedBulkOp = function(options) {
2199
2215
  * @param {object|WriteConcern} [options.writeConcern] Specify write concern settings.
2200
2216
  * @param {ClientSession} [options.session] optional session to use for this operation
2201
2217
  * @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
2202
- * @param {OrderedBulkOperation} callback The command result callback
2203
2218
  * @return {null}
2204
2219
  */
2205
2220
  Collection.prototype.initializeOrderedBulkOp = function(options) {
@@ -49,16 +49,16 @@ class MongoCredentials {
49
49
  this.mechanism = options.mechanism || 'default';
50
50
  this.mechanismProperties = options.mechanismProperties || {};
51
51
 
52
- if (this.mechanism.match(/MONGODB-AWS/i)) {
53
- if (this.username == null && process.env.AWS_ACCESS_KEY_ID) {
52
+ if (/MONGODB-AWS/i.test(this.mechanism)) {
53
+ if (!this.username && process.env.AWS_ACCESS_KEY_ID) {
54
54
  this.username = process.env.AWS_ACCESS_KEY_ID;
55
55
  }
56
56
 
57
- if (this.password == null && process.env.AWS_SECRET_ACCESS_KEY) {
57
+ if (!this.password && process.env.AWS_SECRET_ACCESS_KEY) {
58
58
  this.password = process.env.AWS_SECRET_ACCESS_KEY;
59
59
  }
60
60
 
61
- if (this.mechanismProperties.AWS_SESSION_TOKEN == null && process.env.AWS_SESSION_TOKEN) {
61
+ if (!this.mechanismProperties.AWS_SESSION_TOKEN && process.env.AWS_SESSION_TOKEN) {
62
62
  this.mechanismProperties.AWS_SESSION_TOKEN = process.env.AWS_SESSION_TOKEN;
63
63
  }
64
64
  }
@@ -90,7 +90,7 @@ class MongoCredentials {
90
90
  */
91
91
  resolveAuthMechanism(ismaster) {
92
92
  // If the mechanism is not "default", then it does not need to be resolved
93
- if (this.mechanism.match(/DEFAULT/i)) {
93
+ if (/DEFAULT/i.test(this.mechanism)) {
94
94
  return new MongoCredentials({
95
95
  username: this.username,
96
96
  password: this.password,
@@ -243,7 +243,7 @@ function parseSslOptions(family, options) {
243
243
  }
244
244
 
245
245
  // Set default sni servername to be the same as host
246
- if (result.servername == null) {
246
+ if (result.servername == null && !net.isIP(result.host)) {
247
247
  result.servername = result.host;
248
248
  }
249
249
 
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const require_optional = require('require_optional');
3
+ const require_optional = require('optional-require')(require);
4
4
 
5
5
  function debugOptions(debugFields, options) {
6
- var finaloptions = {};
6
+ const finaloptions = {};
7
7
  debugFields.forEach(function(n) {
8
8
  finaloptions[n] = options[n];
9
9
  });
@@ -12,16 +12,14 @@ function debugOptions(debugFields, options) {
12
12
  }
13
13
 
14
14
  function retrieveBSON() {
15
- var BSON = require('bson');
15
+ const BSON = require('bson');
16
16
  BSON.native = false;
17
17
 
18
- try {
19
- var optionalBSON = require_optional('bson-ext');
20
- if (optionalBSON) {
21
- optionalBSON.native = true;
22
- return optionalBSON;
23
- }
24
- } catch (err) {} // eslint-disable-line
18
+ const optionalBSON = require_optional('bson-ext');
19
+ if (optionalBSON) {
20
+ optionalBSON.native = true;
21
+ return optionalBSON;
22
+ }
25
23
 
26
24
  return BSON;
27
25
  }
@@ -35,10 +33,7 @@ function noSnappyWarning() {
35
33
 
36
34
  // Facilitate loading Snappy optionally
37
35
  function retrieveSnappy() {
38
- var snappy = null;
39
- try {
40
- snappy = require_optional('snappy');
41
- } catch (error) {} // eslint-disable-line
36
+ let snappy = require_optional('snappy');
42
37
  if (!snappy) {
43
38
  snappy = {
44
39
  compress: noSnappyWarning,
package/lib/core/error.js CHANGED
@@ -102,8 +102,8 @@ class MongoNetworkError extends MongoError {
102
102
  super(message);
103
103
  this.name = 'MongoNetworkError';
104
104
 
105
- if (options && options.beforeHandshake === true) {
106
- this[kBeforeHandshake] = true;
105
+ if (options && typeof options.beforeHandshake === 'boolean') {
106
+ this[kBeforeHandshake] = options.beforeHandshake;
107
107
  }
108
108
  }
109
109
  }
package/lib/core/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  let BSON = require('bson');
4
- const require_optional = require('require_optional');
4
+ const require_optional = require('optional-require')(require);
5
5
  const EJSON = require('./utils').retrieveEJSON();
6
6
 
7
7
  try {
@@ -91,6 +91,10 @@ class Monitor extends EventEmitter {
91
91
 
92
92
  // ensure no authentication is used for monitoring
93
93
  delete connectOptions.credentials;
94
+
95
+ // ensure encryption is not requested for monitoring
96
+ delete connectOptions.autoEncrypter;
97
+
94
98
  this.connectOptions = Object.freeze(connectOptions);
95
99
  }
96
100
 
@@ -222,9 +226,10 @@ function checkServer(monitor, callback) {
222
226
  }
223
227
 
224
228
  const isMaster = result.result;
225
- const duration = isAwaitable
226
- ? monitor[kRTTPinger].roundTripTime
227
- : calculateDurationInMs(start);
229
+ const rttPinger = monitor[kRTTPinger];
230
+
231
+ const duration =
232
+ isAwaitable && rttPinger ? rttPinger.roundTripTime : calculateDurationInMs(start);
228
233
 
229
234
  monitor.emit(
230
235
  'serverHeartbeatSucceeded',
@@ -359,7 +359,6 @@ class Topology extends EventEmitter {
359
359
  this.emit('topologyClosed', new events.TopologyClosedEvent(this.s.id));
360
360
 
361
361
  stateTransition(this, STATE_CLOSED);
362
- this.emit('close');
363
362
 
364
363
  if (typeof callback === 'function') {
365
364
  callback(err);
@@ -558,7 +558,7 @@ var monitorServer = function(host, self, options) {
558
558
  self.s.options.secondaryOnlyConnectionAllowed) ||
559
559
  self.s.replicaSetState.hasPrimary())
560
560
  ) {
561
- stateTransition(self, CONNECTED);
561
+ stateTransition(self, CONNECTING);
562
562
 
563
563
  // Rexecute any stalled operation
564
564
  rexecuteOperations(self);
@@ -52,7 +52,9 @@ function parseSrvConnectionString(uri, options, callback) {
52
52
  }
53
53
 
54
54
  result.domainLength = result.hostname.split('.').length;
55
- if (result.pathname && result.pathname.match(',')) {
55
+
56
+ const hostname = uri.substring('mongodb+srv://'.length).split('/')[0];
57
+ if (hostname.match(',')) {
56
58
  return callback(new MongoParseError('Invalid URI, cannot contain multiple hostnames'));
57
59
  }
58
60
 
package/lib/core/utils.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
  const os = require('os');
3
3
  const crypto = require('crypto');
4
- const requireOptional = require('require_optional');
4
+ const requireOptional = require('optional-require')(require);
5
5
 
6
6
  /**
7
7
  * Generate a UUIDv4
@@ -46,10 +46,7 @@ const noEJSONError = function() {
46
46
 
47
47
  // Facilitate loading EJSON optionally
48
48
  function retrieveEJSON() {
49
- let EJSON = null;
50
- try {
51
- EJSON = requireOptional('mongodb-extjson');
52
- } catch (error) {} // eslint-disable-line
49
+ let EJSON = requireOptional('mongodb-extjson');
53
50
  if (!EJSON) {
54
51
  EJSON = {
55
52
  parse: noEJSONError,
@@ -45,14 +45,19 @@ function _command(server, ns, cmd, options, callback) {
45
45
  const shouldUseOpMsg = supportsOpMsg(server);
46
46
  const session = options.session;
47
47
 
48
- let clusterTime = server.clusterTime;
48
+ const serverClusterTime = server.clusterTime;
49
+ let clusterTime = serverClusterTime;
49
50
  let finalCmd = Object.assign({}, cmd);
50
51
  if (hasSessionSupport(server) && session) {
52
+ const sessionClusterTime = session.clusterTime;
51
53
  if (
52
- session.clusterTime &&
53
- session.clusterTime.clusterTime.greaterThan(clusterTime.clusterTime)
54
+ serverClusterTime &&
55
+ serverClusterTime.clusterTime &&
56
+ sessionClusterTime &&
57
+ sessionClusterTime.clusterTime &&
58
+ sessionClusterTime.clusterTime.greaterThan(serverClusterTime.clusterTime)
54
59
  ) {
55
- clusterTime = session.clusterTime;
60
+ clusterTime = sessionClusterTime;
56
61
  }
57
62
 
58
63
  const err = applySession(session, finalCmd, options);
@@ -61,8 +66,8 @@ function _command(server, ns, cmd, options, callback) {
61
66
  }
62
67
  }
63
68
 
64
- // if we have a known cluster time, gossip it
65
69
  if (clusterTime) {
70
+ // if we have a known cluster time, gossip it
66
71
  finalCmd.$clusterTime = clusterTime;
67
72
  }
68
73