mongodb 2.2.33 → 2.2.34

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
@@ -1,3 +1,22 @@
1
+ <a name="2.2.34"></a>
2
+ ## [2.2.34](https://github.com/mongodb/node-mongodb-native/compare/v2.2.33...v2.2.34) (2018-01-03)
3
+
4
+
5
+ ### Bug Fixes
6
+
7
+ * **collection:** allow { upsert: 1 } for findOneAndUpdate() and update() ([#1580](https://github.com/mongodb/node-mongodb-native/issues/1580)) ([0f338c8](https://github.com/mongodb/node-mongodb-native/commit/0f338c8)), closes [Automattic/mongoose#5839](https://github.com/Automattic/mongoose/issues/5839)
8
+ * **GridFS:** fix TypeError: doc.data.length is not a function ([811de0c](https://github.com/mongodb/node-mongodb-native/commit/811de0c))
9
+ * **import:** adds missing import to lib/authenticate.js ([10db9a2](https://github.com/mongodb/node-mongodb-native/commit/10db9a2))
10
+ * **list-collections:** ensure default of primary ReadPreference ([0935306](https://github.com/mongodb/node-mongodb-native/commit/0935306))
11
+
12
+
13
+ ### Features
14
+
15
+ * **ssl:** adds missing ssl options ssl options for `ciphers` and `ecdhCurve` ([bd4fb53](https://github.com/mongodb/node-mongodb-native/commit/bd4fb53))
16
+ * **url parser:** add dns seedlist support ([2d357bc](https://github.com/mongodb/node-mongodb-native/commit/2d357bc))
17
+ * **core**: update mongodb-core to 2.1.18
18
+
19
+
1
20
  2.2.33 2017-10-12
2
21
  -----------------
3
22
  * update to mongodb-core 2.1.17
package/README.md CHANGED
@@ -325,7 +325,7 @@ Next lets delete the document where the field **a** equals to **3**.
325
325
  var deleteDocument = function(db, callback) {
326
326
  // Get the documents collection
327
327
  var collection = db.collection('documents');
328
- // Insert some documents
328
+ // Delete document where a is 3
329
329
  collection.deleteOne({ a : 3 }, function(err, result) {
330
330
  assert.equal(err, null);
331
331
  assert.equal(1, result.result.n);
@@ -1,6 +1,7 @@
1
1
  var shallowClone = require('./utils').shallowClone
2
2
  , handleCallback = require('./utils').handleCallback
3
- , MongoError = require('mongodb-core').MongoError;
3
+ , MongoError = require('mongodb-core').MongoError
4
+ , f = require('util').format;
4
5
 
5
6
  var authenticate = function(self, username, password, options, callback) {
6
7
  // Did the user destroy the topology
package/lib/collection.js CHANGED
@@ -1044,8 +1044,8 @@ var updateDocuments = function(self, selector, document, options, callback) {
1044
1044
 
1045
1045
  // Execute the operation
1046
1046
  var op = {q: selector, u: document};
1047
- op.upsert = typeof options.upsert == 'boolean' ? options.upsert : false;
1048
- op.multi = typeof options.multi == 'boolean' ? options.multi : false;
1047
+ op.upsert = options.upsert !== void 0 ? !!options.upsert : false;
1048
+ op.multi = options.multi !== void 0 ? !!options.multi : false;
1049
1049
 
1050
1050
  // Have we specified collation
1051
1051
  decorateWithCollation(finalOptions, self, options);
@@ -2371,8 +2371,8 @@ var findOneAndUpdate = function(self, filter, update, options, callback) {
2371
2371
  var finalOptions = shallowClone(options);
2372
2372
  finalOptions['fields'] = options.projection;
2373
2373
  finalOptions['update'] = true;
2374
- finalOptions['new'] = typeof options.returnOriginal == 'boolean' ? !options.returnOriginal : false;
2375
- finalOptions['upsert'] = typeof options.upsert == 'boolean' ? options.upsert : false;
2374
+ finalOptions['new'] = options.returnOriginal !== void 0 ? !options.returnOriginal : false;
2375
+ finalOptions['upsert'] = options.upsert !== void 0 ? !!options.upsert : false;
2376
2376
 
2377
2377
  // Execute findAndModify
2378
2378
  self.findAndModify(
package/lib/db.js CHANGED
@@ -653,7 +653,7 @@ var listCollectionsTranforms = function(databaseName) {
653
653
  * Get the list of all collection information for the specified db.
654
654
  *
655
655
  * @method
656
- * @param {object} filter Query to filter collections by
656
+ * @param {object} [filter={}] Query to filter collections by
657
657
  * @param {object} [options=null] Optional settings.
658
658
  * @param {number} [options.batchSize=null] The batchSize for the returned command cursor or if pre 2.8 the systems batch collection
659
659
  * @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
@@ -671,6 +671,8 @@ Db.prototype.listCollections = function(filter, options) {
671
671
  // Ensure valid readPreference
672
672
  if(options.readPreference) {
673
673
  options.readPreference = convertReadPreference(options.readPreference);
674
+ } else {
675
+ options.readPreference = this.s.readPreference || CoreReadPreference.primary;
674
676
  }
675
677
 
676
678
  // We have a list collections command
@@ -209,26 +209,27 @@ function doRead(_this) {
209
209
  return __handleError(_this, new Error(errmsg));
210
210
  }
211
211
 
212
- if (doc.data.length() !== expectedLength) {
212
+ var buf = Buffer.isBuffer(doc.data) ? doc.data : doc.data.buffer;
213
+
214
+ if (buf.length !== expectedLength) {
213
215
  if (bytesRemaining <= 0) {
214
216
  errmsg = 'ExtraChunk: Got unexpected n: ' + doc.n;
215
217
  return __handleError(_this, new Error(errmsg));
216
218
  }
217
219
 
218
220
  errmsg = 'ChunkIsWrongSize: Got unexpected length: ' +
219
- doc.data.length() + ', expected: ' + expectedLength;
221
+ buf.length + ', expected: ' + expectedLength;
220
222
  return __handleError(_this, new Error(errmsg));
221
223
  }
222
224
 
223
- _this.s.bytesRead += doc.data.length();
225
+ _this.s.bytesRead += buf.length;
224
226
 
225
- if (doc.data.buffer.length === 0) {
227
+ if (buf.length === 0) {
226
228
  return _this.push(null);
227
229
  }
228
230
 
229
231
  var sliceStart = null;
230
232
  var sliceEnd = null;
231
- var buf = doc.data.buffer;
232
233
 
233
234
  if (_this.s.bytesToSkip != null) {
234
235
  sliceStart = _this.s.bytesToSkip;
@@ -241,7 +242,7 @@ function doRead(_this) {
241
242
 
242
243
  // If the remaining amount of data left is < chunkSize read the right amount of data
243
244
  if (_this.s.options.end && (
244
- (_this.s.options.end - _this.s.bytesToSkip) < doc.data.length()
245
+ (_this.s.options.end - _this.s.bytesToSkip) < buf.length
245
246
  )) {
246
247
  sliceEnd = (_this.s.options.end - _this.s.bytesToSkip);
247
248
  }
@@ -30,7 +30,7 @@ var parse = require('./url_parser')
30
30
  * db.close();
31
31
  * });
32
32
  */
33
- var validOptionNames = ['poolSize', 'ssl', 'sslValidate', 'sslCA', 'sslCert',
33
+ var validOptionNames = ['poolSize', 'ssl', 'sslValidate', 'sslCA', 'sslCert', 'ciphers', 'ecdhCurve',
34
34
  'sslKey', 'sslPass', 'sslCRL', 'autoReconnect', 'noDelay', 'keepAlive', 'connectTimeoutMS', 'family',
35
35
  'socketTimeoutMS', 'reconnectTries', 'reconnectInterval', 'ha', 'haInterval',
36
36
  'replicaSet', 'secondaryAcceptableLatencyMS', 'acceptableLatencyMS',
@@ -102,7 +102,7 @@ function MongoClient() {
102
102
  * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances
103
103
  * @param {boolean} [options.noDelay=true] TCP Connection no delay
104
104
  * @param {number} [options.family=4] Version of IP stack. Defaults to 4.
105
- * @param {boolean} [options.keepAlive=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
105
+ * @param {number} [options.keepAlive=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
106
106
  * @param {number} [options.connectTimeoutMS=30000] TCP Connection timeout setting
107
107
  * @param {number} [options.socketTimeoutMS=360000] TCP Socket timeout setting
108
108
  * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
@@ -482,24 +482,36 @@ var connect = function(self, url, options, callback) {
482
482
  // Get a logger for MongoClient
483
483
  var logger = Logger('MongoClient', options);
484
484
 
485
- // Parse the string
486
- var object = parse(url, options);
487
- var _finalOptions = createUnifiedOptions({}, object);
488
- _finalOptions = mergeOptions(_finalOptions, object, false);
489
- _finalOptions = createUnifiedOptions(_finalOptions, options);
485
+ parse(url, options, function(err, object) {
486
+ if (err) return callback(err);
490
487
 
491
- // Check if we have connection and socket timeout set
492
- if(_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 360000;
493
- if(_finalOptions.connectTimeoutMS == null) _finalOptions.connectTimeoutMS = 30000;
488
+ // Parse the string
489
+ var _finalOptions = createUnifiedOptions({}, object);
490
+ _finalOptions = mergeOptions(_finalOptions, object, false);
491
+ _finalOptions = createUnifiedOptions(_finalOptions, options);
494
492
 
495
- if (_finalOptions.db_options && _finalOptions.db_options.auth) {
496
- delete _finalOptions.db_options.auth;
497
- }
493
+ // Check if we have connection and socket timeout set
494
+ if(_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 360000;
495
+ if(_finalOptions.connectTimeoutMS == null) _finalOptions.connectTimeoutMS = 30000;
498
496
 
499
- // Failure modes
500
- if(object.servers.length == 0) {
501
- throw new Error("connection string must contain at least one seed host");
502
- }
497
+ if (_finalOptions.db_options && _finalOptions.db_options.auth) {
498
+ delete _finalOptions.db_options.auth;
499
+ }
500
+
501
+ // Failure modes
502
+ if(object.servers.length == 0) {
503
+ throw new Error("connection string must contain at least one seed host");
504
+ }
505
+
506
+ // Do we have a replicaset then skip discovery and go straight to connectivity
507
+ if(_finalOptions.replicaSet || _finalOptions.rs_name) {
508
+ return createReplicaset(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
509
+ } else if(object.servers.length > 1) {
510
+ return createMongos(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
511
+ } else {
512
+ return createServer(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
513
+ }
514
+ });
503
515
 
504
516
  function connectCallback(err, db) {
505
517
  if(err && err.message == 'no mongos proxies found in seed list') {
@@ -514,15 +526,6 @@ var connect = function(self, url, options, callback) {
514
526
  // Return the error and db instance
515
527
  callback(err, db);
516
528
  }
517
-
518
- // Do we have a replicaset then skip discovery and go straight to connectivity
519
- if(_finalOptions.replicaSet || _finalOptions.rs_name) {
520
- return createReplicaset(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
521
- } else if(object.servers.length > 1) {
522
- return createMongos(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
523
- } else {
524
- return createServer(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
525
- }
526
529
  }
527
530
 
528
531
  module.exports = MongoClient
package/lib/mongos.js CHANGED
@@ -48,7 +48,7 @@ var release = os.release();
48
48
 
49
49
  // Allowed parameters
50
50
  var legalOptionNames = ['ha', 'haInterval', 'acceptableLatencyMS'
51
- , 'poolSize', 'ssl', 'checkServerIdentity', 'sslValidate'
51
+ , 'poolSize', 'ssl', 'checkServerIdentity', 'sslValidate', 'ciphers', 'ecdhCurve'
52
52
  , 'sslCA', 'sslCRL', 'sslCert', 'sslKey', 'sslPass', 'socketOptions', 'bufferMaxEntries'
53
53
  , 'store', 'auto_reconnect', 'autoReconnect', 'emitError'
54
54
  , 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS'
package/lib/server.js CHANGED
@@ -45,7 +45,7 @@ var release = os.release();
45
45
 
46
46
  // Allowed parameters
47
47
  var legalOptionNames = ['ha', 'haInterval', 'acceptableLatencyMS'
48
- , 'poolSize', 'ssl', 'checkServerIdentity', 'sslValidate'
48
+ , 'poolSize', 'ssl', 'checkServerIdentity', 'sslValidate', 'ciphers', 'ecdhCurve'
49
49
  , 'sslCA', 'sslCRL', 'sslCert', 'sslKey', 'sslPass', 'socketOptions', 'bufferMaxEntries'
50
50
  , 'store', 'auto_reconnect', 'autoReconnect', 'emitError'
51
51
  , 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS', 'family'
package/lib/url_parser.js CHANGED
@@ -3,9 +3,121 @@
3
3
  var ReadPreference = require('./read_preference'),
4
4
  parser = require('url'),
5
5
  f = require('util').format,
6
- assign = require('./utils').assign;
6
+ assign = require('./utils').assign,
7
+ dns = require('dns');
7
8
 
8
- module.exports = function(url, options) {
9
+ module.exports = function(url, options, callback) {
10
+ if (typeof options === 'function') (callback = options), (options = {});
11
+ options = options || {};
12
+
13
+ var result = parser.parse(url, true);
14
+ if (result.protocol !== 'mongodb:' && result.protocol !== 'mongodb+srv:') {
15
+ return callback(new Error('invalid schema, expected mongodb or mongodb+srv'));
16
+ }
17
+
18
+ if (result.protocol === 'mongodb+srv:') {
19
+
20
+ if (result.hostname.split('.').length < 3) {
21
+ return callback(new Error('uri does not have hostname, domainname and tld'));
22
+ }
23
+
24
+ result.domainLength = result.hostname.split('.').length;
25
+
26
+ if (result.pathname && result.pathname.match(',')) {
27
+ return callback(new Error('invalid uri, cannot contain multiple hostnames'));
28
+ }
29
+
30
+ if (result.port) {
31
+ return callback(new Error('Ports not accepted with mongodb+srv'));
32
+ }
33
+
34
+ var srvAddress = '_mongodb._tcp.' + result.host;
35
+ dns.resolveSrv(srvAddress, function(err, addresses) {
36
+ if (err) return callback(err);
37
+
38
+ if (addresses.length === 0) {
39
+ return callback(new Error('No addresses found at host'));
40
+ }
41
+
42
+ for (var i = 0; i < addresses.length; i++) {
43
+ if (!matchesParentDomain(addresses[i].name, result.hostname, result.domainLength)) {
44
+ return callback(new Error('srv record does not share hostname with parent uri'));
45
+ }
46
+ }
47
+
48
+ var connectionStrings = addresses.map(function(address, i) {
49
+ if (i === 0) return 'mongodb://' + address.name + ':' + address.port;
50
+ else return address.name + ':' + address.port;
51
+ });
52
+
53
+ var connectionString = connectionStrings.join(',') + '/';
54
+ var connectionStringOptions = [];
55
+
56
+ // Default to SSL true
57
+ if (!options.ssl && !result.search) {
58
+ connectionStringOptions.push('ssl=true');
59
+ } else if (!options.ssl && result.search && !result.search.match('ssl')) {
60
+ connectionStringOptions.push('ssl=true');
61
+ }
62
+
63
+ // Keep original uri options
64
+ if (result.search) {
65
+ connectionStringOptions.push(result.search.replace('?', ''));
66
+ }
67
+
68
+ dns.resolveTxt(result.host, function(err, record) {
69
+ if (err && err.code !== 'ENODATA') return callback(err);
70
+ if (err && err.code === 'ENODATA') record = null;
71
+
72
+ if (record) {
73
+ if (record.length > 1) {
74
+ return callback(new Error('multiple text records not allowed'));
75
+ }
76
+
77
+ record = record[0];
78
+ if (record.length > 1) record = record.join('');
79
+ else record = record[0];
80
+
81
+ if (!record.includes('authSource') && !record.includes('replicaSet')) {
82
+ return callback(new Error('text record must only set `authSource` or `replicaSet`'));
83
+ }
84
+
85
+ connectionStringOptions.push(record);
86
+ }
87
+
88
+ // Add any options to the connection string
89
+ if (connectionStringOptions.length) {
90
+ connectionString += '?' + connectionStringOptions.join('&');
91
+ }
92
+
93
+ parseHandler(connectionString, options, callback);
94
+ });
95
+ });
96
+ } else {
97
+ parseHandler(url, options, callback);
98
+ }
99
+ };
100
+
101
+ function matchesParentDomain(srvAddress, parentDomain) {
102
+ var regex = /^.*?\./;
103
+ var srv = '.' + srvAddress.replace(regex, '');
104
+ var parent = '.' + parentDomain.replace(regex, '');
105
+ if (srv.endsWith(parent)) return true;
106
+ else return false;
107
+ }
108
+
109
+ function parseHandler(address, options, callback) {
110
+ var result, err;
111
+ try {
112
+ result = parseConnectionString(address, options);
113
+ } catch (e) {
114
+ err = e;
115
+ }
116
+
117
+ return err ? callback(err, null) : callback(null, result);
118
+ }
119
+
120
+ function parseConnectionString(url, options) {
9
121
  // Variables
10
122
  var connection_part = '';
11
123
  var auth_part = '';
@@ -15,10 +127,6 @@ module.exports = function(url, options) {
15
127
  // Url parser result
16
128
  var result = parser.parse(url, true);
17
129
 
18
- if(result.protocol != 'mongodb:') {
19
- throw new Error('invalid schema, expected mongodb');
20
- }
21
-
22
130
  if((result.hostname == null || result.hostname == '') && url.indexOf('.sock') == -1) {
23
131
  throw new Error('no hostname or hostnames provided in connection string');
24
132
  }
@@ -87,7 +195,13 @@ module.exports = function(url, options) {
87
195
  for(i = 0; i < hosts.length; i++) {
88
196
  var r = parser.parse(f('mongodb://%s', hosts[i].trim()));
89
197
  if(r.path && r.path.indexOf(':') != -1) {
90
- throw new Error('double colon in host identifier');
198
+ // Not connecting to a socket so check for an extra slash in the hostname.
199
+ // Using String#split as perf is better than match.
200
+ if (r.path.split('/').length > 1) {
201
+ throw new Error('slash in host identifier');
202
+ } else {
203
+ throw new Error('double colon in host identifier');
204
+ }
91
205
  }
92
206
  }
93
207
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "2.2.33",
3
+ "version": "2.2.34",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "dependencies": {
16
16
  "es6-promise": "3.2.1",
17
- "mongodb-core": "2.1.17",
17
+ "mongodb-core": "2.1.18",
18
18
  "readable-stream": "2.2.7"
19
19
  },
20
20
  "devDependencies": {