mongodb 2.2.26 → 2.2.27

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.
File without changes
package/HISTORY.md CHANGED
@@ -1,3 +1,17 @@
1
+ 2.2.27 2017-05-22
2
+ -----------------
3
+ * Updated mongodb-core to 2.1.11
4
+ * NODE-987 Clear out old intervalIds on when calling topologyMonitor.
5
+ * NODE-987 Moved filtering to pingServer method and added test case.
6
+ * Check for connection destroyed just before writing out and flush out operations correctly if it is (Issue #179, https://github.com/jmholzinger).
7
+ * NODE-989 Refactored Replicaset monitoring to correcly monitor newly added servers, Also extracted setTimeout and setInterval to use custom wrappers Timeout and Interval.
8
+ * NODE-985 Deprecated Db.authenticate and Admin.authenticate and moved auth methods into authenticate.js to ensure MongoClient.connect does not print deprecation warnings.
9
+ * NODE-988 Merged readConcern and hint correctly on collection(...).find(...).count()
10
+ * Fix passing the readConcern option to MongoClient.connect (Issue #1514, https://github.com/bausmeier).
11
+ * NODE-996 Propegate all events up to a MongoClient instance.
12
+ * Allow saving doc with null `_id` (Issue #1517, https://github.com/vkarpov15).
13
+ * NODE-993 Expose hasNext for command cursor and add docs for both CommandCursor and Aggregation Cursor.
14
+
1
15
  2.2.26 2017-04-18
2
16
  -----------------
3
17
  * Updated mongodb-core to 2.1.10
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/mongodb/node-mongodb-native.svg?branch=2.1)](http://travis-ci.org/mongodb/node-mongodb-native)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/mongodb/node-mongodb-native/badge.svg?branch=2.1)](https://coveralls.io/github/mongodb/node-mongodb-native?branch=2.1)
5
- [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/mongodb/node-mongodb-native?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
5
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mongodb/node-mongodb-native?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
6
6
 
7
7
  # Description
8
8
 
package/lib/admin.js CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  var toError = require('./utils').toError,
4
4
  Define = require('./metadata'),
5
- shallowClone = require('./utils').shallowClone;
5
+ shallowClone = require('./utils').shallowClone,
6
+ assign = require('./utils').assign,
7
+ authenticate = require('./authenticate');
6
8
 
7
9
  /**
8
10
  * @fileOverview The **Admin** class is an internal class that allows convenient access to
@@ -239,23 +241,23 @@ define.classMethod('ping', {callback: true, promise:true});
239
241
  * @param {string} [password] The password.
240
242
  * @param {Admin~resultCallback} [callback] The command result callback
241
243
  * @return {Promise} returns Promise if no callback passed
244
+ * @deprecated This method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.
242
245
  */
243
246
  Admin.prototype.authenticate = function(username, password, options, callback) {
244
- var self = this;
245
- if(typeof options == 'function') callback = options, options = {};
246
- options = shallowClone(options);
247
- options.authdb = 'admin';
248
-
249
- // Execute using callback
250
- if(typeof callback == 'function') return this.s.db.authenticate(username, password, options, callback);
247
+ console.warn("Admin.prototype.authenticate method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.");
248
+ var finalArguments = [this.s.db];
249
+ if(typeof username == 'string') finalArguments.push(username);
250
+ if(typeof password == 'string') finalArguments.push(password);
251
+ if(typeof options == 'function') {
252
+ finalArguments.push({ authdb: 'admin' });
253
+ finalArguments.push(options);
254
+ } else {
255
+ finalArguments.push(assign({}, options, { authdb: 'admin' }));
256
+ }
251
257
 
252
- // Return a Promise
253
- return new this.s.promiseLibrary(function(resolve, reject) {
254
- self.s.db.authenticate(username, password, options, function(err, r) {
255
- if(err) return reject(err);
256
- resolve(r);
257
- });
258
- });
258
+ if(typeof callback == 'function') finalArguments.push(callback);
259
+ // Excute authenticate method
260
+ return authenticate.apply(this.s.db, finalArguments);
259
261
  }
260
262
 
261
263
  define.classMethod('authenticate', {callback: true, promise:true});
@@ -316,6 +316,7 @@ AggregationCursor.prototype.get = AggregationCursor.prototype.toArray;
316
316
  define.classMethod('toArray', {callback: true, promise:true});
317
317
  define.classMethod('each', {callback: true, promise:false});
318
318
  define.classMethod('forEach', {callback: true, promise:false});
319
+ define.classMethod('hasNext', {callback: true, promise:true});
319
320
  define.classMethod('next', {callback: true, promise:true});
320
321
  define.classMethod('close', {callback: true, promise:true});
321
322
  define.classMethod('isClosed', {callback: false, promise:false, returns: [Boolean]});
@@ -331,6 +332,14 @@ define.classMethod('readBufferedDocuments', {callback: false, promise:false, ret
331
332
  * @return {Promise} returns Promise if no callback passed
332
333
  */
333
334
 
335
+ /**
336
+ * Check if there is any document still available in the cursor
337
+ * @function AggregationCursor.prototype.hasNext
338
+ * @param {AggregationCursor~resultCallback} [callback] The result callback.
339
+ * @throws {MongoError}
340
+ * @return {Promise} returns Promise if no callback passed
341
+ */
342
+
334
343
  /**
335
344
  * The callback format for results
336
345
  * @callback AggregationCursor~toArrayResultCallback
@@ -0,0 +1,109 @@
1
+ var shallowClone = require('./utils').shallowClone
2
+ , handleCallback = require('./utils').handleCallback
3
+ , MongoError = require('mongodb-core').MongoError;
4
+
5
+ var authenticate = function(self, username, password, options, callback) {
6
+ // Did the user destroy the topology
7
+ if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
8
+
9
+ // the default db to authenticate against is 'self'
10
+ // if authententicate is called from a retry context, it may be another one, like admin
11
+ var authdb = options.dbName ? options.dbName : self.databaseName;
12
+ authdb = self.authSource ? self.authSource : authdb;
13
+ authdb = options.authdb ? options.authdb : authdb;
14
+ authdb = options.authSource ? options.authSource : authdb;
15
+
16
+ // Callback
17
+ var _callback = function(err, result) {
18
+ if(self.listeners('authenticated').length > 0) {
19
+ self.emit('authenticated', err, result);
20
+ }
21
+
22
+ // Return to caller
23
+ handleCallback(callback, err, result);
24
+ }
25
+
26
+ // authMechanism
27
+ var authMechanism = options.authMechanism || '';
28
+ authMechanism = authMechanism.toUpperCase();
29
+
30
+ // If classic auth delegate to auth command
31
+ if(authMechanism == 'MONGODB-CR') {
32
+ self.s.topology.auth('mongocr', authdb, username, password, function(err) {
33
+ if(err) return handleCallback(callback, err, false);
34
+ _callback(null, true);
35
+ });
36
+ } else if(authMechanism == 'PLAIN') {
37
+ self.s.topology.auth('plain', authdb, username, password, function(err) {
38
+ if(err) return handleCallback(callback, err, false);
39
+ _callback(null, true);
40
+ });
41
+ } else if(authMechanism == 'MONGODB-X509') {
42
+ self.s.topology.auth('x509', authdb, username, password, function(err) {
43
+ if(err) return handleCallback(callback, err, false);
44
+ _callback(null, true);
45
+ });
46
+ } else if(authMechanism == 'SCRAM-SHA-1') {
47
+ self.s.topology.auth('scram-sha-1', authdb, username, password, function(err) {
48
+ if(err) return handleCallback(callback, err, false);
49
+ _callback(null, true);
50
+ });
51
+ } else if(authMechanism == 'GSSAPI') {
52
+ if(process.platform == 'win32') {
53
+ self.s.topology.auth('sspi', authdb, username, password, options, function(err) {
54
+ if(err) return handleCallback(callback, err, false);
55
+ _callback(null, true);
56
+ });
57
+ } else {
58
+ self.s.topology.auth('gssapi', authdb, username, password, options, function(err) {
59
+ if(err) return handleCallback(callback, err, false);
60
+ _callback(null, true);
61
+ });
62
+ }
63
+ } else if(authMechanism == 'DEFAULT') {
64
+ self.s.topology.auth('default', authdb, username, password, function(err) {
65
+ if(err) return handleCallback(callback, err, false);
66
+ _callback(null, true);
67
+ });
68
+ } else {
69
+ handleCallback(callback, MongoError.create({message: f("authentication mechanism %s not supported", options.authMechanism), driver:true}));
70
+ }
71
+ }
72
+
73
+ module.exports = function(self, username, password, options, callback) {
74
+ if(typeof options == 'function') callback = options, options = {};
75
+ // Shallow copy the options
76
+ options = shallowClone(options);
77
+
78
+ // Set default mechanism
79
+ if(!options.authMechanism) {
80
+ options.authMechanism = 'DEFAULT';
81
+ } else if(options.authMechanism != 'GSSAPI'
82
+ && options.authMechanism != 'DEFAULT'
83
+ && options.authMechanism != 'MONGODB-CR'
84
+ && options.authMechanism != 'MONGODB-X509'
85
+ && options.authMechanism != 'SCRAM-SHA-1'
86
+ && options.authMechanism != 'PLAIN') {
87
+ return handleCallback(callback, MongoError.create({message: "only DEFAULT, GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism", driver:true}));
88
+ }
89
+
90
+ // If we have a callback fallback
91
+ if(typeof callback == 'function') return authenticate(self, username, password, options, function(err, r) {
92
+ // Support failed auth method
93
+ if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
94
+ // Reject error
95
+ if(err) return callback(err, r);
96
+ callback(null, r);
97
+ });
98
+
99
+ // Return a promise
100
+ return new self.s.promiseLibrary(function(resolve, reject) {
101
+ authenticate(self, username, password, options, function(err, r) {
102
+ // Support failed auth method
103
+ if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
104
+ // Reject error
105
+ if(err) return reject(err);
106
+ resolve(r);
107
+ });
108
+ });
109
+ };
package/lib/collection.js CHANGED
@@ -736,7 +736,7 @@ var insertDocuments = function(self, docs, options, callback) {
736
736
  // Add _id if not specified
737
737
  if(forceServerObjectId !== true){
738
738
  for(var i = 0; i < docs.length; i++) {
739
- if(docs[i]._id == null) docs[i]._id = self.s.pkFactory.createPk();
739
+ if(docs[i]._id === void 0) docs[i]._id = self.s.pkFactory.createPk();
740
740
  }
741
741
  }
742
742
 
@@ -2040,7 +2040,7 @@ var count = function(self, query, options, callback) {
2040
2040
  if(typeof skip == 'number') cmd.skip = skip;
2041
2041
  if(typeof limit == 'number') cmd.limit = limit;
2042
2042
  if(typeof maxTimeMS == 'number') cmd.maxTimeMS = maxTimeMS;
2043
- if(hint) options.hint = hint;
2043
+ if(hint) cmd.hint = hint;
2044
2044
 
2045
2045
  options = shallowClone(options);
2046
2046
  // Ensure we have the right read preference inheritance
@@ -131,7 +131,7 @@ var CommandCursor = function(bson, ns, cmd, options, topology, topologyOptions)
131
131
  inherits(CommandCursor, Readable);
132
132
 
133
133
  // Set the methods to inherit from prototype
134
- var methodsToInherit = ['_next', 'next', 'each', 'forEach', 'toArray'
134
+ var methodsToInherit = ['_next', 'next', 'hasNext', 'each', 'forEach', 'toArray'
135
135
  , 'rewind', 'bufferedCount', 'readBufferedDocuments', 'close', 'isClosed', 'kill', 'setCursorBatchSize'
136
136
  , '_find', '_getmore', '_killcursor', 'isDead', 'explain', 'isNotified', 'isKilled'];
137
137
 
@@ -207,6 +207,7 @@ define.classMethod('toArray', {callback: true, promise:true});
207
207
  define.classMethod('each', {callback: true, promise:false});
208
208
  define.classMethod('forEach', {callback: true, promise:false});
209
209
  define.classMethod('next', {callback: true, promise:true});
210
+ define.classMethod('hasNext', {callback: true, promise:true});
210
211
  define.classMethod('close', {callback: true, promise:true});
211
212
  define.classMethod('isClosed', {callback: false, promise:false, returns: [Boolean]});
212
213
  define.classMethod('rewind', {callback: false, promise:false});
@@ -221,6 +222,14 @@ define.classMethod('readBufferedDocuments', {callback: false, promise:false, ret
221
222
  * @return {Promise} returns Promise if no callback passed
222
223
  */
223
224
 
225
+ /**
226
+ * Check if there is any document still available in the cursor
227
+ * @function CommandCursor.prototype.hasNext
228
+ * @param {CommandCursor~resultCallback} [callback] The result callback.
229
+ * @throws {MongoError}
230
+ * @return {Promise} returns Promise if no callback passed
231
+ */
232
+
224
233
  /**
225
234
  * The callback format for results
226
235
  * @callback CommandCursor~toArrayResultCallback
package/lib/cursor.js CHANGED
@@ -941,6 +941,16 @@ var count = function(self, applySkipLimit, opts, callback) {
941
941
  'count': self.s.ns.substr(delimiter+1), 'query': self.s.cmd.query
942
942
  }
943
943
 
944
+ // Apply a readConcern if set
945
+ if(self.s.cmd.readConcern) {
946
+ command.readConcern = self.s.cmd.readConcern;
947
+ }
948
+
949
+ // Apply a hint if set
950
+ if(self.s.cmd.hint) {
951
+ command.hint = self.s.cmd.hint;
952
+ }
953
+
944
954
  if(typeof opts.maxTimeMS == 'number') {
945
955
  command.maxTimeMS = opts.maxTimeMS;
946
956
  } else if(self.s.cmd && typeof self.s.cmd.maxTimeMS == 'number') {
package/lib/db.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  var EventEmitter = require('events').EventEmitter
4
+ , authenticate = require('./authenticate')
4
5
  , inherits = require('util').inherits
5
6
  , getSingleProperty = require('./utils').getSingleProperty
6
7
  , shallowClone = require('./utils').shallowClone
@@ -1469,74 +1470,6 @@ Db.prototype.removeUser = function(username, options, callback) {
1469
1470
  });
1470
1471
  };
1471
1472
 
1472
- var authenticate = function(self, username, password, options, callback) {
1473
- // Did the user destroy the topology
1474
- if(self.serverConfig && self.serverConfig.isDestroyed()) return callback(new MongoError('topology was destroyed'));
1475
-
1476
- // the default db to authenticate against is 'self'
1477
- // if authententicate is called from a retry context, it may be another one, like admin
1478
- var authdb = options.dbName ? options.dbName : self.databaseName;
1479
- authdb = self.authSource ? self.authSource : authdb;
1480
- authdb = options.authdb ? options.authdb : authdb;
1481
- authdb = options.authSource ? options.authSource : authdb;
1482
-
1483
- // Callback
1484
- var _callback = function(err, result) {
1485
- if(self.listeners('authenticated').length > 0) {
1486
- self.emit('authenticated', err, result);
1487
- }
1488
-
1489
- // Return to caller
1490
- handleCallback(callback, err, result);
1491
- }
1492
-
1493
- // authMechanism
1494
- var authMechanism = options.authMechanism || '';
1495
- authMechanism = authMechanism.toUpperCase();
1496
-
1497
- // If classic auth delegate to auth command
1498
- if(authMechanism == 'MONGODB-CR') {
1499
- self.s.topology.auth('mongocr', authdb, username, password, function(err) {
1500
- if(err) return handleCallback(callback, err, false);
1501
- _callback(null, true);
1502
- });
1503
- } else if(authMechanism == 'PLAIN') {
1504
- self.s.topology.auth('plain', authdb, username, password, function(err) {
1505
- if(err) return handleCallback(callback, err, false);
1506
- _callback(null, true);
1507
- });
1508
- } else if(authMechanism == 'MONGODB-X509') {
1509
- self.s.topology.auth('x509', authdb, username, password, function(err) {
1510
- if(err) return handleCallback(callback, err, false);
1511
- _callback(null, true);
1512
- });
1513
- } else if(authMechanism == 'SCRAM-SHA-1') {
1514
- self.s.topology.auth('scram-sha-1', authdb, username, password, function(err) {
1515
- if(err) return handleCallback(callback, err, false);
1516
- _callback(null, true);
1517
- });
1518
- } else if(authMechanism == 'GSSAPI') {
1519
- if(process.platform == 'win32') {
1520
- self.s.topology.auth('sspi', authdb, username, password, options, function(err) {
1521
- if(err) return handleCallback(callback, err, false);
1522
- _callback(null, true);
1523
- });
1524
- } else {
1525
- self.s.topology.auth('gssapi', authdb, username, password, options, function(err) {
1526
- if(err) return handleCallback(callback, err, false);
1527
- _callback(null, true);
1528
- });
1529
- }
1530
- } else if(authMechanism == 'DEFAULT') {
1531
- self.s.topology.auth('default', authdb, username, password, function(err) {
1532
- if(err) return handleCallback(callback, err, false);
1533
- _callback(null, true);
1534
- });
1535
- } else {
1536
- handleCallback(callback, MongoError.create({message: f("authentication mechanism %s not supported", options.authMechanism), driver:true}));
1537
- }
1538
- }
1539
-
1540
1473
  /**
1541
1474
  * Authenticate a user against the server.
1542
1475
  * @method
@@ -1546,44 +1479,11 @@ var authenticate = function(self, username, password, options, callback) {
1546
1479
  * @param {string} [options.authMechanism=MONGODB-CR] The authentication mechanism to use, GSSAPI, MONGODB-CR, MONGODB-X509, PLAIN
1547
1480
  * @param {Db~resultCallback} [callback] The command result callback
1548
1481
  * @return {Promise} returns Promise if no callback passed
1482
+ * @deprecated This method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.
1549
1483
  */
1550
1484
  Db.prototype.authenticate = function(username, password, options, callback) {
1551
- if(typeof options == 'function') callback = options, options = {};
1552
- var self = this;
1553
- // Shallow copy the options
1554
- options = shallowClone(options);
1555
-
1556
- // Set default mechanism
1557
- if(!options.authMechanism) {
1558
- options.authMechanism = 'DEFAULT';
1559
- } else if(options.authMechanism != 'GSSAPI'
1560
- && options.authMechanism != 'DEFAULT'
1561
- && options.authMechanism != 'MONGODB-CR'
1562
- && options.authMechanism != 'MONGODB-X509'
1563
- && options.authMechanism != 'SCRAM-SHA-1'
1564
- && options.authMechanism != 'PLAIN') {
1565
- return handleCallback(callback, MongoError.create({message: "only DEFAULT, GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism", driver:true}));
1566
- }
1567
-
1568
- // If we have a callback fallback
1569
- if(typeof callback == 'function') return authenticate(self, username, password, options, function(err, r) {
1570
- // Support failed auth method
1571
- if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
1572
- // Reject error
1573
- if(err) return callback(err, r);
1574
- callback(null, r);
1575
- });
1576
-
1577
- // Return a promise
1578
- return new this.s.promiseLibrary(function(resolve, reject) {
1579
- authenticate(self, username, password, options, function(err, r) {
1580
- // Support failed auth method
1581
- if(err && err.message && err.message.indexOf('saslStart') != -1) err.code = 59;
1582
- // Reject error
1583
- if(err) return reject(err);
1584
- resolve(r);
1585
- });
1586
- });
1485
+ console.warn("Db.prototype.authenticate method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials.");
1486
+ return authenticate.apply(this, [this].concat(Array.prototype.slice.call(arguments)));
1587
1487
  };
1588
1488
 
1589
1489
  define.classMethod('authenticate', {callback: true, promise:true});
@@ -4,13 +4,16 @@ var parse = require('./url_parser')
4
4
  , Server = require('./server')
5
5
  , Mongos = require('./mongos')
6
6
  , ReplSet = require('./replset')
7
+ , EventEmitter = require('events').EventEmitter
8
+ , inherits = require('util').inherits
7
9
  , Define = require('./metadata')
8
10
  , ReadPreference = require('./read_preference')
9
11
  , Logger = require('mongodb-core').Logger
10
12
  , MongoError = require('mongodb-core').MongoError
11
13
  , Db = require('./db')
12
14
  , f = require('util').format
13
- , shallowClone = require('./utils').shallowClone;
15
+ , shallowClone = require('./utils').shallowClone
16
+ , authenticate = require('./authenticate');
14
17
 
15
18
  /**
16
19
  * @fileOverview The **MongoClient** class is a class that allows for making Connections to MongoDB.
@@ -65,6 +68,11 @@ function validOptions(options) {
65
68
  * @return {MongoClient} a MongoClient instance.
66
69
  */
67
70
  function MongoClient() {
71
+ if(!(this instanceof MongoClient)) return new MongoClient();
72
+
73
+ // Set up event emitter
74
+ EventEmitter.call(this);
75
+
68
76
  /**
69
77
  * The callback format for results
70
78
  * @callback MongoClient~connectCallback
@@ -120,7 +128,7 @@ function MongoClient() {
120
128
  * @param {object} [options.pkFactory=null] A primary key factory object for generation of custom _id keys.
121
129
  * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
122
130
  * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
123
- * @param {object} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
131
+ * @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
124
132
  * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed);
125
133
  * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
126
134
  * @param {object} [options.logger=undefined] Custom logger object
@@ -131,6 +139,11 @@ function MongoClient() {
131
139
  this.connect = MongoClient.connect;
132
140
  }
133
141
 
142
+ /**
143
+ * @ignore
144
+ */
145
+ inherits(MongoClient, EventEmitter);
146
+
134
147
  var define = MongoClient.define = new Define('MongoClient', MongoClient, false);
135
148
 
136
149
  /**
@@ -182,7 +195,7 @@ var define = MongoClient.define = new Define('MongoClient', MongoClient, false);
182
195
  * @param {object} [options.pkFactory=null] A primary key factory object for generation of custom _id keys.
183
196
  * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
184
197
  * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
185
- * @param {object} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
198
+ * @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
186
199
  * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed);
187
200
  * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
188
201
  * @param {object} [options.logger=undefined] Custom logger object
@@ -195,6 +208,7 @@ MongoClient.connect = function(url, options, callback) {
195
208
  callback = typeof args[args.length - 1] == 'function' ? args.pop() : null;
196
209
  options = args.length ? args.shift() : null;
197
210
  options = options || {};
211
+ var self = this;
198
212
 
199
213
  // Validate options object
200
214
  var err = validOptions(options);
@@ -214,7 +228,7 @@ MongoClient.connect = function(url, options, callback) {
214
228
  // Did we have a validation error
215
229
  if(err) return reject(err);
216
230
  // Attempt to connect
217
- connect(url, options, function(err, db) {
231
+ connect(self, url, options, function(err, db) {
218
232
  if(err) return reject(err);
219
233
  resolve(db);
220
234
  });
@@ -224,7 +238,7 @@ MongoClient.connect = function(url, options, callback) {
224
238
  // Did we have a validation error
225
239
  if(err) return callback(err);
226
240
  // Fallback to callback based connect
227
- connect(url, options, callback);
241
+ connect(self, url, options, callback);
228
242
  }
229
243
 
230
244
  define.staticMethod('connect', {callback: true, promise:true});
@@ -244,7 +258,7 @@ var mergeOptions = function(target, source, flatten) {
244
258
  var createUnifiedOptions = function(finalOptions, options) {
245
259
  var childOptions = ['mongos', 'server', 'db'
246
260
  , 'replset', 'db_options', 'server_options', 'rs_options', 'mongos_options'];
247
- var noMerge = [];
261
+ var noMerge = ['readconcern'];
248
262
 
249
263
  for(var name in options) {
250
264
  if(noMerge.indexOf(name.toLowerCase()) != -1) {
@@ -291,25 +305,50 @@ function translateOptions(options) {
291
305
  });
292
306
  }
293
307
 
294
- function createReplicaset(options, callback) {
308
+ function relayEvents(self, db) {
309
+ if(self instanceof MongoClient) {
310
+ var events = ["timeout", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
311
+ 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
312
+ 'topologyClosed', 'topologyDescriptionChanged', 'joined', 'left', 'ping', 'ha', 'all', 'fullsetup'];
313
+ events.forEach(function(event) {
314
+ db.serverConfig.on(event, function(object1, object2) {
315
+ self.emit(event, object1, object2);
316
+ });
317
+ });
318
+ }
319
+ }
320
+
321
+ function createReplicaset(self, options, callback) {
295
322
  // Set default options
296
323
  var servers = translateOptions(options);
297
324
  // Create Db instance
298
- new Db(options.dbName, new ReplSet(servers, options), options).open(callback);
325
+ var db = new Db(options.dbName, new ReplSet(servers, options), options);
326
+ // Propegate the events to the client
327
+ relayEvents(self, db);
328
+ // Open the connection
329
+ db.open(callback);
299
330
  }
300
331
 
301
- function createMongos(options, callback) {
332
+ function createMongos(self, options, callback) {
302
333
  // Set default options
303
334
  var servers = translateOptions(options);
304
335
  // Create Db instance
305
- new Db(options.dbName, new Mongos(servers, options), options).open(callback);
336
+ var db = new Db(options.dbName, new Mongos(servers, options), options)
337
+ // Propegate the events to the client
338
+ relayEvents(self, db);
339
+ // Open the connection
340
+ db.open(callback);
306
341
  }
307
342
 
308
- function createServer(options, callback) {
343
+ function createServer(self, options, callback) {
309
344
  // Set default options
310
345
  var servers = translateOptions(options);
346
+ // Create db instance
347
+ var db = new Db(options.dbName, servers[0], options);
348
+ // Propegate the events to the client
349
+ relayEvents(self, db);
311
350
  // Create Db instance
312
- new Db(options.dbName, servers[0], options).open(function(err, db) {
351
+ db.open(function(err, db) {
313
352
  if(err) return callback(err);
314
353
  // Check if we are really speaking to a mongos
315
354
  var ismaster = db.serverConfig.lastIsMaster();
@@ -319,7 +358,7 @@ function createServer(options, callback) {
319
358
  // Destroy the current connection
320
359
  db.close();
321
360
  // Create mongos connection instead
322
- return createMongos(options, callback);
361
+ return createMongos(self, options, callback);
323
362
  }
324
363
 
325
364
  // Otherwise callback
@@ -359,7 +398,7 @@ function connectHandler(options, callback) {
359
398
  }
360
399
 
361
400
  // Authenticate
362
- authentication_db.authenticate(options.user, options.password, options, function(err, success){
401
+ authenticate(authentication_db, options.user, options.password, options, function(err, success) {
363
402
  if(success){
364
403
  process.nextTick(function() {
365
404
  try {
@@ -387,7 +426,7 @@ function connectHandler(options, callback) {
387
426
  /*
388
427
  * Connect using MongoClient
389
428
  */
390
- var connect = function(url, options, callback) {
429
+ var connect = function(self, url, options, callback) {
391
430
  options = options || {};
392
431
  options = shallowClone(options);
393
432
 
@@ -430,11 +469,11 @@ var connect = function(url, options, callback) {
430
469
 
431
470
  // Do we have a replicaset then skip discovery and go straight to connectivity
432
471
  if(_finalOptions.replicaSet || _finalOptions.rs_name) {
433
- return createReplicaset(_finalOptions, connectHandler(_finalOptions, connectCallback));
472
+ return createReplicaset(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
434
473
  } else if(object.servers.length > 1) {
435
- return createMongos(_finalOptions, connectHandler(_finalOptions, connectCallback));
474
+ return createMongos(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
436
475
  } else {
437
- return createServer(_finalOptions, connectHandler(_finalOptions, connectCallback));
476
+ return createServer(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
438
477
  }
439
478
  }
440
479
 
package/lib/replset.js CHANGED
@@ -270,69 +270,95 @@ ReplSet.prototype.connect = function(db, _options, callback) {
270
270
  }
271
271
  }
272
272
 
273
- // Connect handler
274
- var connectHandler = function() {
275
- // Clear out all the current handlers left over
276
- ["timeout", "error", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
277
- 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
278
- 'topologyClosed', 'topologyDescriptionChanged'].forEach(function(e) {
279
- self.s.replset.removeAllListeners(e);
280
- });
281
-
282
- // Set up listeners
283
- self.s.replset.once('timeout', errorHandler('timeout'));
284
- self.s.replset.once('error', errorHandler('error'));
285
- self.s.replset.once('close', errorHandler('close'));
273
+ // Clear out all the current handlers left over
274
+ var events = ["timeout", "error", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
275
+ 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
276
+ 'topologyClosed', 'topologyDescriptionChanged', 'joined', 'left', 'ping', 'ha'];
277
+ events.forEach(function(e) {
278
+ self.s.replset.removeAllListeners(e);
279
+ });
286
280
 
287
- // relay the event
288
- var relay = function(event) {
289
- return function(t, server) {
290
- self.emit(event, t, server);
291
- }
281
+ // relay the event
282
+ var relay = function(event) {
283
+ return function(t, server) {
284
+ self.emit(event, t, server);
292
285
  }
286
+ }
293
287
 
294
- // Replset events relay
295
- var replsetRelay = function(event) {
296
- return function(t, server) {
297
- self.emit(event, t, server.lastIsMaster(), server);
298
- }
288
+ // Replset events relay
289
+ var replsetRelay = function(event) {
290
+ return function(t, server) {
291
+ self.emit(event, t, server.lastIsMaster(), server);
299
292
  }
293
+ }
300
294
 
301
- // Relay ha
302
- var relayHa = function(t, state) {
303
- self.emit('ha', t, state);
295
+ // Relay ha
296
+ var relayHa = function(t, state) {
297
+ self.emit('ha', t, state);
304
298
 
305
- if(t == 'start') {
306
- self.emit('ha_connect', t, state);
307
- } else if(t == 'end') {
308
- self.emit('ha_ismaster', t, state);
309
- }
299
+ if(t == 'start') {
300
+ self.emit('ha_connect', t, state);
301
+ } else if(t == 'end') {
302
+ self.emit('ha_ismaster', t, state);
310
303
  }
304
+ }
311
305
 
312
- // Set up serverConfig listeners
313
- self.s.replset.on('joined', replsetRelay('joined'));
314
- self.s.replset.on('left', relay('left'));
315
- self.s.replset.on('ping', relay('ping'));
316
- self.s.replset.on('ha', relayHa);
317
-
318
- // Set up SDAM listeners
319
- self.s.replset.on('serverDescriptionChanged', relay('serverDescriptionChanged'));
320
- self.s.replset.on('serverHeartbeatStarted', relay('serverHeartbeatStarted'));
321
- self.s.replset.on('serverHeartbeatSucceeded', relay('serverHeartbeatSucceeded'));
322
- self.s.replset.on('serverHeartbeatFailed', relay('serverHeartbeatFailed'));
323
- self.s.replset.on('serverOpening', relay('serverOpening'));
324
- self.s.replset.on('serverClosed', relay('serverClosed'));
325
- self.s.replset.on('topologyOpening', relay('topologyOpening'));
326
- self.s.replset.on('topologyClosed', relay('topologyClosed'));
327
- self.s.replset.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
328
-
329
- self.s.replset.on('fullsetup', function() {
330
- self.emit('fullsetup', null, self);
331
- });
306
+ // Set up serverConfig listeners
307
+ self.s.replset.on('joined', replsetRelay('joined'));
308
+ self.s.replset.on('left', relay('left'));
309
+ self.s.replset.on('ping', relay('ping'));
310
+ self.s.replset.on('ha', relayHa);
311
+
312
+ // Set up SDAM listeners
313
+ self.s.replset.on('serverDescriptionChanged', relay('serverDescriptionChanged'));
314
+ self.s.replset.on('serverHeartbeatStarted', relay('serverHeartbeatStarted'));
315
+ self.s.replset.on('serverHeartbeatSucceeded', relay('serverHeartbeatSucceeded'));
316
+ self.s.replset.on('serverHeartbeatFailed', relay('serverHeartbeatFailed'));
317
+ self.s.replset.on('serverOpening', relay('serverOpening'));
318
+ self.s.replset.on('serverClosed', relay('serverClosed'));
319
+ self.s.replset.on('topologyOpening', relay('topologyOpening'));
320
+ self.s.replset.on('topologyClosed', relay('topologyClosed'));
321
+ self.s.replset.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
322
+
323
+ self.s.replset.on('fullsetup', function() {
324
+ self.emit('fullsetup', null, self);
325
+ });
332
326
 
333
- self.s.replset.on('all', function() {
334
- self.emit('all', null, self);
335
- });
327
+ self.s.replset.on('all', function() {
328
+ self.emit('all', null, self);
329
+ });
330
+
331
+ // Connect handler
332
+ var connectHandler = function() {
333
+ // Set up listeners
334
+ self.s.replset.once('timeout', errorHandler('timeout'));
335
+ self.s.replset.once('error', errorHandler('error'));
336
+ self.s.replset.once('close', errorHandler('close'));
337
+
338
+ // // Set up serverConfig listeners
339
+ // self.s.replset.on('joined', replsetRelay('joined'));
340
+ // self.s.replset.on('left', relay('left'));
341
+ // self.s.replset.on('ping', relay('ping'));
342
+ // self.s.replset.on('ha', relayHa);
343
+
344
+ // // Set up SDAM listeners
345
+ // self.s.replset.on('serverDescriptionChanged', relay('serverDescriptionChanged'));
346
+ // self.s.replset.on('serverHeartbeatStarted', relay('serverHeartbeatStarted'));
347
+ // self.s.replset.on('serverHeartbeatSucceeded', relay('serverHeartbeatSucceeded'));
348
+ // self.s.replset.on('serverHeartbeatFailed', relay('serverHeartbeatFailed'));
349
+ // self.s.replset.on('serverOpening', relay('serverOpening'));
350
+ // self.s.replset.on('serverClosed', relay('serverClosed'));
351
+ // self.s.replset.on('topologyOpening', relay('topologyOpening'));
352
+ // self.s.replset.on('topologyClosed', relay('topologyClosed'));
353
+ // self.s.replset.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
354
+
355
+ // self.s.replset.on('fullsetup', function() {
356
+ // self.emit('fullsetup', null, self);
357
+ // });
358
+
359
+ // self.s.replset.on('all', function() {
360
+ // self.emit('all', null, self);
361
+ // });
336
362
 
337
363
  // Emit open event
338
364
  self.emit('open', null, self);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "2.2.26",
3
+ "version": "2.2.27",
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.10",
17
+ "mongodb-core": "2.1.11",
18
18
  "readable-stream": "2.2.7"
19
19
  },
20
20
  "devDependencies": {