mongodb 2.2.31 → 2.2.35

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.
@@ -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
@@ -115,7 +115,7 @@ function MongoClient() {
115
115
  * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
116
116
  * @param {string} [options.authSource=undefined] Define the database to authenticate against
117
117
  * @param {string} [options.auth.user=undefined] The username for auth
118
- * @param {string} [options.auth.password=undefined] The username for auth
118
+ * @param {string} [options.auth.password=undefined] The password for auth
119
119
  * @param {(number|string)} [options.w=null] The write concern.
120
120
  * @param {number} [options.wtimeout=null] The write concern timeout.
121
121
  * @param {boolean} [options.j=false] Specify a journal write concern.
@@ -186,7 +186,7 @@ var define = MongoClient.define = new Define('MongoClient', MongoClient, false);
186
186
  * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
187
187
  * @param {string} [options.authSource=undefined] Define the database to authenticate against
188
188
  * @param {string} [options.auth.user=undefined] The username for auth
189
- * @param {string} [options.auth.password=undefined] The username for auth
189
+ * @param {string} [options.auth.password=undefined] The password for auth
190
190
  * @param {(number|string)} [options.w=null] The write concern.
191
191
  * @param {number} [options.wtimeout=null] The write concern timeout.
192
192
  * @param {boolean} [options.j=false] Specify a journal write concern.
@@ -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'
@@ -39,7 +39,7 @@
39
39
  * @param {string} mode The ReadPreference mode as listed above.
40
40
  * @param {array|object} tags An object representing read preference tags.
41
41
  * @param {object} [options] Additional read preference options
42
- * @param {number} [options.maxStalenessSeconds] Max Secondary Read Stalleness in Seconds
42
+ * @param {number} [options.maxStalenessSeconds] Max Secondary Read Staleness in Seconds
43
43
  * @return {ReadPreference} a ReadPreference instance.
44
44
  */
45
45
  var ReadPreference = function(mode, tags, options) {
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'
@@ -70,8 +70,8 @@ var release = os.release();
70
70
  * @param {(Buffer|string)} [options.sslKey=null] String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
71
71
  * @param {(Buffer|string)} [options.sslPass=null] String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
72
72
  * @param {string} [options.servername=null] String containing the server name requested via TLS SNI.
73
+ * @param {boolean} [options.autoReconnect=true] Reconnect on error or timeout.
73
74
  * @param {object} [options.socketOptions=null] Socket options
74
- * @param {boolean} [options.socketOptions.autoReconnect=true] Reconnect on error.
75
75
  * @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
76
76
  * @param {number} [options.socketOptions.keepAlive=0] TCP KeepAlive on the socket with a X ms delay before start.
77
77
  * @param {number} [options.socketOptions.connectTimeoutMS=0] TCP Connection timeout setting
package/lib/url_parser.js CHANGED
@@ -3,9 +3,122 @@
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 base = result.auth ? 'mongodb://' + result.auth + '@' : 'mongodb://';
49
+ var connectionStrings = addresses.map(function(address, i) {
50
+ if (i === 0) return base + address.name + ':' + address.port;
51
+ else return address.name + ':' + address.port;
52
+ });
53
+
54
+ var connectionString = connectionStrings.join(',') + '/';
55
+ var connectionStringOptions = [];
56
+
57
+ // Default to SSL true
58
+ if (!options.ssl && !result.search) {
59
+ connectionStringOptions.push('ssl=true');
60
+ } else if (!options.ssl && result.search && !result.search.match('ssl')) {
61
+ connectionStringOptions.push('ssl=true');
62
+ }
63
+
64
+ // Keep original uri options
65
+ if (result.search) {
66
+ connectionStringOptions.push(result.search.replace('?', ''));
67
+ }
68
+
69
+ dns.resolveTxt(result.host, function(err, record) {
70
+ if (err && err.code !== 'ENODATA') return callback(err);
71
+ if (err && err.code === 'ENODATA') record = null;
72
+
73
+ if (record) {
74
+ if (record.length > 1) {
75
+ return callback(new Error('multiple text records not allowed'));
76
+ }
77
+
78
+ record = record[0];
79
+ if (record.length > 1) record = record.join('');
80
+ else record = record[0];
81
+
82
+ if (!record.includes('authSource') && !record.includes('replicaSet')) {
83
+ return callback(new Error('text record must only set `authSource` or `replicaSet`'));
84
+ }
85
+
86
+ connectionStringOptions.push(record);
87
+ }
88
+
89
+ // Add any options to the connection string
90
+ if (connectionStringOptions.length) {
91
+ connectionString += '?' + connectionStringOptions.join('&');
92
+ }
93
+
94
+ parseHandler(connectionString, options, callback);
95
+ });
96
+ });
97
+ } else {
98
+ parseHandler(url, options, callback);
99
+ }
100
+ };
101
+
102
+ function matchesParentDomain(srvAddress, parentDomain) {
103
+ var regex = /^.*?\./;
104
+ var srv = '.' + srvAddress.replace(regex, '');
105
+ var parent = '.' + parentDomain.replace(regex, '');
106
+ if (srv.endsWith(parent)) return true;
107
+ else return false;
108
+ }
109
+
110
+ function parseHandler(address, options, callback) {
111
+ var result, err;
112
+ try {
113
+ result = parseConnectionString(address, options);
114
+ } catch (e) {
115
+ err = e;
116
+ }
117
+
118
+ return err ? callback(err, null) : callback(null, result);
119
+ }
120
+
121
+ function parseConnectionString(url, options) {
9
122
  // Variables
10
123
  var connection_part = '';
11
124
  var auth_part = '';
@@ -15,10 +128,6 @@ module.exports = function(url, options) {
15
128
  // Url parser result
16
129
  var result = parser.parse(url, true);
17
130
 
18
- if(result.protocol != 'mongodb:') {
19
- throw new Error('invalid schema, expected mongodb');
20
- }
21
-
22
131
  if((result.hostname == null || result.hostname == '') && url.indexOf('.sock') == -1) {
23
132
  throw new Error('no hostname or hostnames provided in connection string');
24
133
  }
@@ -87,7 +196,13 @@ module.exports = function(url, options) {
87
196
  for(i = 0; i < hosts.length; i++) {
88
197
  var r = parser.parse(f('mongodb://%s', hosts[i].trim()));
89
198
  if(r.path && r.path.indexOf(':') != -1) {
90
- throw new Error('double colon in host identifier');
199
+ // Not connecting to a socket so check for an extra slash in the hostname.
200
+ // Using String#split as perf is better than match.
201
+ if (r.path.split('/').length > 1) {
202
+ throw new Error('slash in host identifier');
203
+ } else {
204
+ throw new Error('double colon in host identifier');
205
+ }
91
206
  }
92
207
  }
93
208
 
@@ -193,7 +308,7 @@ module.exports = function(url, options) {
193
308
  if(_host.indexOf("?") != -1) _host = _host.split(/\?/)[0];
194
309
  }
195
310
 
196
- // No entry returned for duplicate servr
311
+ // No entry returned for duplicate server
197
312
  if(deduplicatedServers[_host + "_" + _port]) return null;
198
313
  deduplicatedServers[_host + "_" + _port] = 1;
199
314
 
package/lib/utils.js CHANGED
@@ -107,7 +107,7 @@ var checkCollectionName = function checkCollectionName (collectionName) {
107
107
  throw new MongoError("collection names must not start or end with '.'");
108
108
  }
109
109
 
110
- // Validate that we are not passing 0x00 in the colletion name
110
+ // Validate that we are not passing 0x00 in the collection name
111
111
  if(!!~collectionName.indexOf("\x00")) {
112
112
  throw new MongoError("collection names cannot contain a null character");
113
113
  }
@@ -295,7 +295,7 @@ var filterOptions = function(options, names) {
295
295
  return filterOptions;
296
296
  }
297
297
 
298
- // Object.assign method or polyfille
298
+ // Object.assign method or polyfill
299
299
  var assign = Object.assign ? Object.assign : function assign(target) {
300
300
  if (target === undefined || target === null) {
301
301
  throw new TypeError('Cannot convert first argument to object');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "2.2.31",
3
+ "version": "2.2.35",
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.15",
17
+ "mongodb-core": "2.1.19",
18
18
  "readable-stream": "2.2.7"
19
19
  },
20
20
  "devDependencies": {
@@ -25,6 +25,7 @@
25
25
  "cli-table": "^0.3.1",
26
26
  "co": "4.6.0",
27
27
  "colors": "^1.1.2",
28
+ "conventional-changelog-cli": "^1.3.5",
28
29
  "coveralls": "^2.11.6",
29
30
  "eslint": "^3.8.1",
30
31
  "event-stream": "^3.3.2",
@@ -52,7 +53,8 @@
52
53
  "scripts": {
53
54
  "test": "node test/runner.js -t functional",
54
55
  "coverage": "node_modules/.bin/nyc node test/runner.js -t functional && node_modules/.bin/nyc report --reporter=text-lcov | node_modules/.bin/coveralls",
55
- "lint": "eslint lib"
56
+ "lint": "eslint lib",
57
+ "changelog": "conventional-changelog -p angular -i HISTORY.md -s"
56
58
  },
57
59
  "nyc": {
58
60
  "include": [