mongodb 3.5.9 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/HISTORY.md +110 -18
  2. package/lib/admin.js +1 -0
  3. package/lib/bulk/common.js +48 -4
  4. package/lib/change_stream.js +7 -3
  5. package/lib/cmap/connection.js +9 -6
  6. package/lib/collection.js +61 -84
  7. package/lib/core/auth/auth_provider.js +29 -132
  8. package/lib/core/auth/defaultAuthProviders.js +2 -2
  9. package/lib/core/auth/gssapi.js +69 -219
  10. package/lib/core/auth/mongo_credentials.js +29 -3
  11. package/lib/core/auth/mongocr.js +6 -12
  12. package/lib/core/auth/mongodb_aws.js +256 -0
  13. package/lib/core/auth/plain.js +5 -12
  14. package/lib/core/auth/scram.js +229 -212
  15. package/lib/core/auth/x509.js +25 -16
  16. package/lib/core/connection/connect.js +97 -161
  17. package/lib/core/connection/connection.js +71 -3
  18. package/lib/core/connection/pool.js +2 -2
  19. package/lib/core/cursor.js +30 -39
  20. package/lib/core/error.js +82 -8
  21. package/lib/core/sdam/common.js +8 -0
  22. package/lib/core/sdam/monitor.js +240 -79
  23. package/lib/core/sdam/server.js +82 -17
  24. package/lib/core/sdam/server_description.js +47 -2
  25. package/lib/core/sdam/topology.js +43 -32
  26. package/lib/core/sdam/topology_description.js +21 -3
  27. package/lib/core/sessions.js +14 -16
  28. package/lib/core/topologies/mongos.js +18 -6
  29. package/lib/core/topologies/read_preference.js +71 -7
  30. package/lib/core/topologies/replset.js +4 -4
  31. package/lib/core/topologies/server.js +1 -1
  32. package/lib/core/topologies/shared.js +39 -16
  33. package/lib/core/uri_parser.js +41 -6
  34. package/lib/core/utils.js +30 -0
  35. package/lib/core/wireprotocol/command.js +2 -10
  36. package/lib/core/wireprotocol/constants.js +2 -2
  37. package/lib/core/wireprotocol/query.js +4 -0
  38. package/lib/cursor.js +0 -1
  39. package/lib/db.js +7 -6
  40. package/lib/error.js +6 -1
  41. package/lib/gridfs-stream/download.js +13 -2
  42. package/lib/mongo_client.js +6 -4
  43. package/lib/operations/collection_ops.js +1 -22
  44. package/lib/operations/command.js +2 -3
  45. package/lib/operations/command_v2.js +8 -7
  46. package/lib/operations/common_functions.js +3 -0
  47. package/lib/operations/connect.js +11 -14
  48. package/lib/operations/create_collection.js +37 -52
  49. package/lib/operations/create_indexes.js +91 -35
  50. package/lib/operations/db_ops.js +1 -2
  51. package/lib/operations/find.js +9 -3
  52. package/lib/operations/find_and_modify.js +17 -0
  53. package/lib/operations/find_one_and_delete.js +5 -0
  54. package/lib/operations/find_one_and_replace.js +13 -0
  55. package/lib/operations/find_one_and_update.js +13 -0
  56. package/lib/operations/geo_haystack_search.js +2 -2
  57. package/lib/operations/map_reduce.js +3 -3
  58. package/lib/operations/operation.js +2 -1
  59. package/lib/operations/re_index.js +22 -17
  60. package/lib/operations/replace_one.js +11 -4
  61. package/lib/operations/run_command.js +19 -0
  62. package/lib/operations/update_many.js +5 -0
  63. package/lib/operations/update_one.js +5 -0
  64. package/lib/operations/validate_collection.js +1 -2
  65. package/lib/topologies/mongos.js +1 -1
  66. package/lib/topologies/replset.js +1 -1
  67. package/lib/topologies/server.js +1 -1
  68. package/lib/topologies/topology_base.js +4 -4
  69. package/lib/utils.js +18 -60
  70. package/lib/write_concern.js +10 -0
  71. package/package.json +2 -2
  72. package/lib/core/auth/sspi.js +0 -131
  73. package/lib/operations/create_index.js +0 -92
@@ -82,7 +82,7 @@ var legalOptionNames = [
82
82
  * @param {object} [options.socketOptions] Socket options
83
83
  * @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
84
84
  * @param {boolean} [options.socketOptions.keepAlive=true] TCP Connection keep alive enabled
85
- * @param {number} [options.socketOptions.keepAliveInitialDelay=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
85
+ * @param {number} [options.socketOptions.keepAliveInitialDelay=120000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
86
86
  * @param {number} [options.socketOptions.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
87
87
  * @param {number} [options.socketOptions.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
88
88
  * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
@@ -92,7 +92,7 @@ var legalOptionNames = [
92
92
  * @param {object} [options.socketOptions] Socket options
93
93
  * @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
94
94
  * @param {boolean} [options.socketOptions.keepAlive=true] TCP Connection keep alive enabled
95
- * @param {number} [options.socketOptions.keepAliveInitialDelay=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
95
+ * @param {number} [options.socketOptions.keepAliveInitialDelay=120000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
96
96
  * @param {number} [options.socketOptions.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
97
97
  * @param {number} [options.socketOptions.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
98
98
  * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
@@ -84,7 +84,7 @@ var legalOptionNames = [
84
84
  * @param {boolean} [options.socketOptions.autoReconnect=true] Reconnect on error.
85
85
  * @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
86
86
  * @param {boolean} [options.socketOptions.keepAlive=true] TCP Connection keep alive enabled
87
- * @param {number} [options.socketOptions.keepAliveInitialDelay=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
87
+ * @param {number} [options.socketOptions.keepAliveInitialDelay=120000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
88
88
  * @param {number} [options.socketOptions.connectTimeoutMS=10000] How long to wait for a connection to be established before timing out
89
89
  * @param {number} [options.socketOptions.socketTimeoutMS=360000] How long a send or receive on a socket can take before timing out
90
90
  * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
@@ -3,7 +3,7 @@
3
3
  const EventEmitter = require('events'),
4
4
  MongoError = require('../core').MongoError,
5
5
  f = require('util').format,
6
- translateReadPreference = require('../utils').translateReadPreference,
6
+ ReadPreference = require('../core').ReadPreference,
7
7
  ClientSession = require('../core').Sessions.ClientSession;
8
8
 
9
9
  // The store of ops
@@ -293,7 +293,7 @@ class TopologyBase extends EventEmitter {
293
293
 
294
294
  // Command
295
295
  command(ns, cmd, options, callback) {
296
- this.s.coreTopology.command(ns.toString(), cmd, translateReadPreference(options), callback);
296
+ this.s.coreTopology.command(ns.toString(), cmd, ReadPreference.translate(options), callback);
297
297
  }
298
298
 
299
299
  // Insert
@@ -314,7 +314,7 @@ class TopologyBase extends EventEmitter {
314
314
  // IsConnected
315
315
  isConnected(options) {
316
316
  options = options || {};
317
- options = translateReadPreference(options);
317
+ options = ReadPreference.translate(options);
318
318
 
319
319
  return this.s.coreTopology.isConnected(options);
320
320
  }
@@ -327,7 +327,7 @@ class TopologyBase extends EventEmitter {
327
327
  // Cursor
328
328
  cursor(ns, cmd, options) {
329
329
  options = options || {};
330
- options = translateReadPreference(options);
330
+ options = ReadPreference.translate(options);
331
331
  options.disconnectHandler = this.s.store;
332
332
  options.topology = this;
333
333
 
package/lib/utils.js CHANGED
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
  const MongoError = require('./core/error').MongoError;
3
- const ReadPreference = require('./core/topologies/read_preference');
4
3
  const WriteConcern = require('./write_concern');
5
4
 
6
5
  var shallowClone = function(obj) {
@@ -9,31 +8,6 @@ var shallowClone = function(obj) {
9
8
  return copy;
10
9
  };
11
10
 
12
- // Figure out the read preference
13
- var translateReadPreference = function(options) {
14
- var r = null;
15
- if (options.readPreference) {
16
- r = options.readPreference;
17
- } else {
18
- return options;
19
- }
20
-
21
- if (typeof r === 'string') {
22
- options.readPreference = new ReadPreference(r);
23
- } else if (r && !(r instanceof ReadPreference) && typeof r === 'object') {
24
- const mode = r.mode || r.preference;
25
- if (mode && typeof mode === 'string') {
26
- options.readPreference = new ReadPreference(mode, r.tags, {
27
- maxStalenessSeconds: r.maxStalenessSeconds
28
- });
29
- }
30
- } else if (!(r instanceof ReadPreference)) {
31
- throw new TypeError('Invalid read preference: ' + r);
32
- }
33
-
34
- return options;
35
- };
36
-
37
11
  // Set simple property
38
12
  var getSingleProperty = function(obj, name, value) {
39
13
  Object.defineProperty(obj, name, {
@@ -490,37 +464,6 @@ function applyWriteConcern(target, sources, options) {
490
464
  return target;
491
465
  }
492
466
 
493
- /**
494
- * Resolves a read preference based on well-defined inheritance rules. This method will not only
495
- * determine the read preference (if there is one), but will also ensure the returned value is a
496
- * properly constructed instance of `ReadPreference`.
497
- *
498
- * @param {Collection|Db|MongoClient} parent The parent of the operation on which to determine the read
499
- * preference, used for determining the inherited read preference.
500
- * @param {Object} options The options passed into the method, potentially containing a read preference
501
- * @returns {(ReadPreference|null)} The resolved read preference
502
- */
503
- function resolveReadPreference(parent, options) {
504
- options = options || {};
505
- const session = options.session;
506
-
507
- const inheritedReadPreference = parent.readPreference;
508
-
509
- let readPreference;
510
- if (options.readPreference) {
511
- readPreference = ReadPreference.fromOptions(options);
512
- } else if (session && session.inTransaction() && session.transaction.options.readPreference) {
513
- // The transaction’s read preference MUST override all other user configurable read preferences.
514
- readPreference = session.transaction.options.readPreference;
515
- } else if (inheritedReadPreference != null) {
516
- readPreference = inheritedReadPreference;
517
- } else {
518
- throw new Error('No readPreference was provided or inherited.');
519
- }
520
-
521
- return typeof readPreference === 'string' ? new ReadPreference(readPreference) : readPreference;
522
- }
523
-
524
467
  /**
525
468
  * Checks if a given value is a Promise
526
469
  *
@@ -778,6 +721,12 @@ function makeInterruptableAsyncInterval(fn, options) {
778
721
  const timeUntilNextCall = Math.max(interval - timeSinceLastCall, 0);
779
722
  lastWakeTime = currentTime;
780
723
 
724
+ // For the streaming protocol: there is nothing obviously stopping this
725
+ // interval from being woken up again while we are waiting "infinitely"
726
+ // for `fn` to be called again`. Since the function effectively
727
+ // never completes, the `timeUntilNextCall` will continue to grow
728
+ // negatively unbounded, so it will never trigger a reschedule here.
729
+
781
730
  // debounce multiple calls to wake within the `minInterval`
782
731
  if (timeSinceLastWake < minInterval) {
783
732
  return;
@@ -810,6 +759,7 @@ function makeInterruptableAsyncInterval(fn, options) {
810
759
  function executeAndReschedule() {
811
760
  lastWakeTime = 0;
812
761
  lastCallTime = now();
762
+
813
763
  fn(err => {
814
764
  if (err) throw err;
815
765
  reschedule(interval);
@@ -826,6 +776,15 @@ function makeInterruptableAsyncInterval(fn, options) {
826
776
  return { wake, stop };
827
777
  }
828
778
 
779
+ function hasAtomicOperators(doc) {
780
+ if (Array.isArray(doc)) {
781
+ return doc.reduce((err, u) => err || hasAtomicOperators(u), null);
782
+ }
783
+
784
+ const keys = Object.keys(doc);
785
+ return keys.length > 0 && keys[0][0] === '$';
786
+ }
787
+
829
788
  module.exports = {
830
789
  filterOptions,
831
790
  mergeOptions,
@@ -843,7 +802,6 @@ module.exports = {
843
802
  debugOptions,
844
803
  MAX_JS_INT: Number.MAX_SAFE_INTEGER + 1,
845
804
  mergeOptionsAndWriteConcern,
846
- translateReadPreference,
847
805
  executeLegacyOperation,
848
806
  applyRetryableWrites,
849
807
  applyWriteConcern,
@@ -853,11 +811,11 @@ module.exports = {
853
811
  deprecateOptions,
854
812
  SUPPORTS,
855
813
  MongoDBNamespace,
856
- resolveReadPreference,
857
814
  emitDeprecationWarning,
858
815
  makeCounter,
859
816
  maybePromise,
860
817
  now,
861
818
  calculateDurationInMs,
862
- makeInterruptableAsyncInterval
819
+ makeInterruptableAsyncInterval,
820
+ hasAtomicOperators
863
821
  };
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const kWriteConcernKeys = new Set(['w', 'wtimeout', 'j', 'fsync']);
4
+
3
5
  /**
4
6
  * The **WriteConcern** class is a class that represents a MongoDB WriteConcern.
5
7
  * @class
@@ -51,6 +53,14 @@ class WriteConcern {
51
53
  }
52
54
 
53
55
  if (options.writeConcern) {
56
+ if (typeof options.writeConcern === 'string') {
57
+ return new WriteConcern(options.writeConcern);
58
+ }
59
+
60
+ if (!Object.keys(options.writeConcern).some(key => kWriteConcernKeys.has(key))) {
61
+ return;
62
+ }
63
+
54
64
  return new WriteConcern(
55
65
  options.writeConcern.w,
56
66
  options.writeConcern.wtimeout,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "3.5.9",
3
+ "version": "3.6.0",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -64,7 +64,7 @@
64
64
  "url": "https://github.com/mongodb/node-mongodb-native/issues"
65
65
  },
66
66
  "scripts": {
67
- "atlas": "node ./test/tools/atlas_connectivity_tests.js",
67
+ "atlas": "mocha --opts '{}' ./test/manual/atlas_connectivity.test.js",
68
68
  "test": "npm run lint && mocha --recursive test/functional test/unit test/core",
69
69
  "test-nolint": "mocha --recursive test/functional test/unit test/core",
70
70
  "coverage": "istanbul cover mongodb-test-runner -- -t 60000 test/core test/unit test/functional",
@@ -1,131 +0,0 @@
1
- 'use strict';
2
-
3
- const AuthProvider = require('./auth_provider').AuthProvider;
4
- const retrieveKerberos = require('../utils').retrieveKerberos;
5
- let kerberos;
6
-
7
- /**
8
- * Creates a new SSPI authentication mechanism
9
- * @class
10
- * @extends AuthProvider
11
- */
12
- class SSPI extends AuthProvider {
13
- /**
14
- * Implementation of authentication for a single connection
15
- * @override
16
- */
17
- _authenticateSingleConnection(sendAuthCommand, connection, credentials, callback) {
18
- // TODO: Destructure this
19
- const username = credentials.username;
20
- const password = credentials.password;
21
- const mechanismProperties = credentials.mechanismProperties;
22
- const gssapiServiceName =
23
- mechanismProperties['gssapiservicename'] ||
24
- mechanismProperties['gssapiServiceName'] ||
25
- 'mongodb';
26
-
27
- SSIPAuthenticate(
28
- this,
29
- kerberos.processes.MongoAuthProcess,
30
- username,
31
- password,
32
- gssapiServiceName,
33
- sendAuthCommand,
34
- connection,
35
- mechanismProperties,
36
- callback
37
- );
38
- }
39
-
40
- /**
41
- * Authenticate
42
- * @override
43
- * @method
44
- */
45
- auth(sendAuthCommand, connections, credentials, callback) {
46
- if (kerberos == null) {
47
- try {
48
- kerberos = retrieveKerberos();
49
- } catch (e) {
50
- return callback(e, null);
51
- }
52
- }
53
-
54
- super.auth(sendAuthCommand, connections, credentials, callback);
55
- }
56
- }
57
-
58
- function SSIPAuthenticate(
59
- self,
60
- MongoAuthProcess,
61
- username,
62
- password,
63
- gssapiServiceName,
64
- sendAuthCommand,
65
- connection,
66
- options,
67
- callback
68
- ) {
69
- const authProcess = new MongoAuthProcess(
70
- connection.host,
71
- connection.port,
72
- gssapiServiceName,
73
- options
74
- );
75
-
76
- function authCommand(command, authCb) {
77
- sendAuthCommand(connection, '$external.$cmd', command, authCb);
78
- }
79
-
80
- authProcess.init(username, password, err => {
81
- if (err) return callback(err, false);
82
-
83
- authProcess.transition('', (err, payload) => {
84
- if (err) return callback(err, false);
85
-
86
- const command = {
87
- saslStart: 1,
88
- mechanism: 'GSSAPI',
89
- payload,
90
- autoAuthorize: 1
91
- };
92
-
93
- authCommand(command, (err, doc) => {
94
- if (err) return callback(err, false);
95
-
96
- authProcess.transition(doc.payload, (err, payload) => {
97
- if (err) return callback(err, false);
98
- const command = {
99
- saslContinue: 1,
100
- conversationId: doc.conversationId,
101
- payload
102
- };
103
-
104
- authCommand(command, (err, doc) => {
105
- if (err) return callback(err, false);
106
-
107
- authProcess.transition(doc.payload, (err, payload) => {
108
- if (err) return callback(err, false);
109
- const command = {
110
- saslContinue: 1,
111
- conversationId: doc.conversationId,
112
- payload
113
- };
114
-
115
- authCommand(command, (err, response) => {
116
- if (err) return callback(err, false);
117
-
118
- authProcess.transition(null, err => {
119
- if (err) return callback(err, null);
120
- callback(null, response);
121
- });
122
- });
123
- });
124
- });
125
- });
126
- });
127
- });
128
- });
129
- }
130
-
131
- module.exports = SSPI;
@@ -1,92 +0,0 @@
1
- 'use strict';
2
-
3
- const Aspect = require('./operation').Aspect;
4
- const CommandOperation = require('./command');
5
- const defineAspects = require('./operation').defineAspects;
6
- const handleCallback = require('../utils').handleCallback;
7
- const MongoError = require('../core').MongoError;
8
- const parseIndexOptions = require('../utils').parseIndexOptions;
9
-
10
- const keysToOmit = new Set([
11
- 'name',
12
- 'key',
13
- 'writeConcern',
14
- 'w',
15
- 'wtimeout',
16
- 'j',
17
- 'fsync',
18
- 'readPreference',
19
- 'session'
20
- ]);
21
-
22
- class CreateIndexOperation extends CommandOperation {
23
- constructor(db, name, fieldOrSpec, options) {
24
- super(db, options);
25
-
26
- // Build the index
27
- const indexParameters = parseIndexOptions(fieldOrSpec);
28
- // Generate the index name
29
- const indexName = typeof options.name === 'string' ? options.name : indexParameters.name;
30
- // Set up the index
31
- const indexesObject = { name: indexName, key: indexParameters.fieldHash };
32
-
33
- this.name = name;
34
- this.fieldOrSpec = fieldOrSpec;
35
- this.indexes = indexesObject;
36
- }
37
-
38
- _buildCommand() {
39
- const options = this.options;
40
- const name = this.name;
41
- const indexes = this.indexes;
42
-
43
- // merge all the options
44
- for (let optionName in options) {
45
- if (!keysToOmit.has(optionName)) {
46
- indexes[optionName] = options[optionName];
47
- }
48
- }
49
-
50
- // Create command, apply write concern to command
51
- const cmd = { createIndexes: name, indexes: [indexes] };
52
-
53
- return cmd;
54
- }
55
-
56
- execute(callback) {
57
- const db = this.db;
58
- const options = this.options;
59
- const indexes = this.indexes;
60
-
61
- // Get capabilities
62
- const capabilities = db.s.topology.capabilities();
63
-
64
- // Did the user pass in a collation, check if our write server supports it
65
- if (options.collation && capabilities && !capabilities.commandsTakeCollation) {
66
- // Create a new error
67
- const error = new MongoError('server/primary/mongos does not support collation');
68
- error.code = 67;
69
- // Return the error
70
- return callback(error);
71
- }
72
-
73
- // Ensure we have a callback
74
- if (options.writeConcern && typeof callback !== 'function') {
75
- throw MongoError.create({
76
- message: 'Cannot use a writeConcern without a provided callback',
77
- driver: true
78
- });
79
- }
80
-
81
- // Attempt to run using createIndexes command
82
- super.execute((err, result) => {
83
- if (err == null) return handleCallback(callback, err, indexes.name);
84
-
85
- return handleCallback(callback, err, result);
86
- });
87
- }
88
- }
89
-
90
- defineAspects(CreateIndexOperation, Aspect.WRITE_OPERATION);
91
-
92
- module.exports = CreateIndexOperation;