mongodb 3.3.0-beta2 → 3.3.3

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 (66) hide show
  1. package/HISTORY.md +155 -0
  2. package/index.js +1 -0
  3. package/lib/admin.js +6 -6
  4. package/lib/aggregation_cursor.js +180 -228
  5. package/lib/bulk/common.js +150 -73
  6. package/lib/bulk/ordered.js +1 -1
  7. package/lib/bulk/unordered.js +1 -0
  8. package/lib/change_stream.js +66 -66
  9. package/lib/collection.js +131 -44
  10. package/lib/command_cursor.js +87 -167
  11. package/lib/core/connection/connection.js +7 -3
  12. package/lib/core/connection/msg.js +5 -3
  13. package/lib/core/connection/pool.js +114 -143
  14. package/lib/core/cursor.js +569 -435
  15. package/lib/core/error.js +63 -12
  16. package/lib/core/index.js +1 -1
  17. package/lib/core/sdam/monitoring.js +8 -1
  18. package/lib/core/sdam/server.js +58 -14
  19. package/lib/core/sdam/topology.js +66 -31
  20. package/lib/core/sdam/topology_description.js +1 -1
  21. package/lib/core/sessions.js +68 -12
  22. package/lib/core/topologies/mongos.js +81 -26
  23. package/lib/core/topologies/replset.js +56 -10
  24. package/lib/core/topologies/replset_state.js +5 -5
  25. package/lib/core/topologies/server.js +7 -2
  26. package/lib/core/topologies/shared.js +23 -0
  27. package/lib/core/transactions.js +1 -0
  28. package/lib/core/uri_parser.js +8 -2
  29. package/lib/core/utils.js +13 -1
  30. package/lib/core/wireprotocol/get_more.js +4 -0
  31. package/lib/core/wireprotocol/query.js +8 -1
  32. package/lib/cursor.js +782 -844
  33. package/lib/db.js +27 -75
  34. package/lib/gridfs-stream/download.js +12 -5
  35. package/lib/gridfs-stream/index.js +1 -1
  36. package/lib/mongo_client.js +27 -11
  37. package/lib/operations/aggregate.js +75 -101
  38. package/lib/operations/close.js +12 -13
  39. package/lib/operations/collection_ops.js +3 -916
  40. package/lib/operations/command_v2.js +70 -4
  41. package/lib/operations/common_functions.js +48 -14
  42. package/lib/operations/connect.js +29 -36
  43. package/lib/operations/count.js +8 -8
  44. package/lib/operations/count_documents.js +24 -29
  45. package/lib/operations/cursor_ops.js +22 -32
  46. package/lib/operations/db_ops.js +0 -178
  47. package/lib/operations/estimated_document_count.js +43 -18
  48. package/lib/operations/execute_operation.js +51 -18
  49. package/lib/operations/explain.js +2 -2
  50. package/lib/operations/find.js +35 -0
  51. package/lib/operations/insert_one.js +1 -37
  52. package/lib/operations/list_collections.js +106 -0
  53. package/lib/operations/list_databases.js +38 -0
  54. package/lib/operations/list_indexes.js +28 -52
  55. package/lib/operations/operation.js +4 -0
  56. package/lib/operations/rename.js +1 -1
  57. package/lib/operations/replace_one.js +1 -1
  58. package/lib/operations/to_array.js +3 -5
  59. package/lib/read_concern.js +7 -1
  60. package/lib/topologies/mongos.js +1 -1
  61. package/lib/topologies/replset.js +1 -1
  62. package/lib/topologies/server.js +2 -2
  63. package/lib/topologies/topology_base.js +4 -5
  64. package/lib/utils.js +4 -4
  65. package/package.json +9 -5
  66. package/lib/operations/aggregate_operation.js +0 -127
@@ -1,66 +1,42 @@
1
1
  'use strict';
2
2
 
3
- const OperationBase = require('./operation').OperationBase;
4
- const CommandCursor = require('../command_cursor');
5
- const MongoError = require('../core').MongoError;
6
- const resolveReadPreference = require('../utils').resolveReadPreference;
3
+ const CommandOperationV2 = require('./command_v2');
4
+ const Aspect = require('./operation').Aspect;
5
+ const defineAspects = require('./operation').defineAspects;
6
+ const maxWireVersion = require('../core/utils').maxWireVersion;
7
7
 
8
- class ListIndexesOperation extends OperationBase {
8
+ const LIST_INDEXES_WIRE_VERSION = 3;
9
+
10
+ class ListIndexesOperation extends CommandOperationV2 {
9
11
  constructor(collection, options) {
10
- super(options);
12
+ super(collection, options, { fullResponse: true });
11
13
 
12
- this.collection = collection;
14
+ this.collectionNamespace = collection.s.namespace;
13
15
  }
14
16
 
15
- execute() {
16
- const coll = this.collection;
17
- let options = this.options;
18
-
19
- options = options || {};
20
- // Clone the options
21
- options = Object.assign({}, options);
22
- // Determine the read preference in the options.
23
- options.readPreference = resolveReadPreference(coll, options);
24
- // Set the CommandCursor constructor
25
- options.cursorFactory = CommandCursor;
26
- // Set the promiseLibrary
27
- options.promiseLibrary = coll.s.promiseLibrary;
28
-
29
- if (!coll.s.topology.capabilities()) {
30
- throw new MongoError('cannot connect to server');
31
- }
32
-
33
- // Cursor options
34
- let cursor = options.batchSize ? { batchSize: options.batchSize } : {};
17
+ execute(server, callback) {
18
+ const serverWireVersion = maxWireVersion(server);
19
+ if (serverWireVersion < LIST_INDEXES_WIRE_VERSION) {
20
+ const systemIndexesNS = this.collectionNamespace.withCollection('system.indexes').toString();
21
+ const collectionNS = this.collectionNamespace.toString();
35
22
 
36
- // We have a list collections command
37
- if (coll.s.topology.capabilities().hasListIndexesCommand) {
38
- // Build the command
39
- const command = { listIndexes: coll.collectionName, cursor: cursor };
40
- // Execute the cursor
41
- cursor = coll.s.topology.cursor(
42
- coll.s.namespace.withCollection('$cmd').toString(),
43
- command,
44
- options
45
- );
46
- // Do we have a readPreference, apply it
47
- if (options.readPreference) cursor.setReadPreference(options.readPreference);
48
- // Return the cursor
49
- return cursor;
23
+ server.query(systemIndexesNS, { query: { ns: collectionNS } }, {}, this.options, callback);
24
+ return;
50
25
  }
51
26
 
52
- // Get the namespace
53
- const namespace = coll.s.namespace.withCollection('system.indexes');
54
- const ns = namespace.toString();
55
- // Get the query
56
- cursor = coll.s.topology.cursor(ns, { find: ns, query: { ns: coll.namespace } }, options);
57
- // Do we have a readPreference, apply it
58
- if (options.readPreference) cursor.setReadPreference(options.readPreference);
59
- // Set the passed in batch size if one was provided
60
- if (options.batchSize) cursor = cursor.batchSize(options.batchSize);
61
- // Return the cursor
62
- return cursor;
27
+ const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {};
28
+ super.executeCommand(
29
+ server,
30
+ { listIndexes: this.collectionNamespace.collection, cursor },
31
+ callback
32
+ );
63
33
  }
64
34
  }
65
35
 
36
+ defineAspects(ListIndexesOperation, [
37
+ Aspect.READ_OPERATION,
38
+ Aspect.RETRYABLE,
39
+ Aspect.EXECUTE_WITH_SELECTION
40
+ ]);
41
+
66
42
  module.exports = ListIndexesOperation;
@@ -39,6 +39,10 @@ class OperationBase {
39
39
  delete this.options.session;
40
40
  }
41
41
 
42
+ get canRetryRead() {
43
+ return true;
44
+ }
45
+
42
46
  execute() {
43
47
  throw new TypeError('`execute` must be implemented for OperationBase subclasses');
44
48
  }
@@ -45,7 +45,7 @@ class RenameOperation extends OperationBase {
45
45
  new Collection(
46
46
  coll.s.db,
47
47
  coll.s.topology,
48
- coll.databaseName,
48
+ coll.s.namespace.db,
49
49
  newName,
50
50
  coll.s.pkFactory,
51
51
  coll.s.options
@@ -40,7 +40,7 @@ function replaceCallback(err, r, doc, callback) {
40
40
  Array.isArray(r.result.upserted) && r.result.upserted.length ? r.result.upserted.length : 0;
41
41
  r.matchedCount =
42
42
  Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? 0 : r.result.n;
43
- r.ops = [doc];
43
+ r.ops = [doc]; // TODO: Should we still have this?
44
44
  if (callback) callback(null, r);
45
45
  }
46
46
 
@@ -3,7 +3,7 @@
3
3
  const Aspect = require('./operation').Aspect;
4
4
  const defineAspects = require('./operation').defineAspects;
5
5
  const handleCallback = require('../utils').handleCallback;
6
- const loadCursor = require('../dynamic_loaders').loadCursor;
6
+ const CursorState = require('../core/cursor').CursorState;
7
7
  const OperationBase = require('./operation').OperationBase;
8
8
  const push = Array.prototype.push;
9
9
 
@@ -16,14 +16,11 @@ class ToArrayOperation extends OperationBase {
16
16
 
17
17
  execute(callback) {
18
18
  const cursor = this.cursor;
19
-
20
- let Cursor = loadCursor();
21
-
22
19
  const items = [];
23
20
 
24
21
  // Reset cursor
25
22
  cursor.rewind();
26
- cursor.s.state = Cursor.INIT;
23
+ cursor.s.state = CursorState.INIT;
27
24
 
28
25
  // Fetch all the documents
29
26
  const fetchDocs = () => {
@@ -33,6 +30,7 @@ class ToArrayOperation extends OperationBase {
33
30
  ? cursor._endSession(() => handleCallback(callback, err))
34
31
  : handleCallback(callback, err);
35
32
  }
33
+
36
34
  if (doc == null) {
37
35
  return cursor.close({ skipKillCursors: true }, () =>
38
36
  handleCallback(callback, null, items)
@@ -29,10 +29,16 @@ class ReadConcern {
29
29
  }
30
30
 
31
31
  if (options.readConcern) {
32
+ if (options.readConcern instanceof ReadConcern) {
33
+ return options.readConcern;
34
+ }
35
+
32
36
  return new ReadConcern(options.readConcern.level);
33
37
  }
34
38
 
35
- return new ReadConcern(options.level);
39
+ if (options.level) {
40
+ return new ReadConcern(options.level);
41
+ }
36
42
  }
37
43
 
38
44
  static get MAJORITY() {
@@ -194,7 +194,7 @@ class Mongos extends TopologyBase {
194
194
  // Server Session Pool
195
195
  sessionPool: null,
196
196
  // Active client sessions
197
- sessions: [],
197
+ sessions: new Set(),
198
198
  // Promise library
199
199
  promiseLibrary: options.promiseLibrary || Promise
200
200
  };
@@ -210,7 +210,7 @@ class ReplSet extends TopologyBase {
210
210
  // Server Session Pool
211
211
  sessionPool: null,
212
212
  // Active client sessions
213
- sessions: [],
213
+ sessions: new Set(),
214
214
  // Promise library
215
215
  promiseLibrary: options.promiseLibrary || Promise
216
216
  };
@@ -89,7 +89,7 @@ var legalOptionNames = [
89
89
  * @param {number} [options.socketOptions.socketTimeoutMS=0] TCP Socket timeout setting
90
90
  * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
91
91
  * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
92
- * @param {number} [options.monitoring=true] Triggers the server instance to call ismaster
92
+ * @param {boolean} [options.monitoring=true] Triggers the server instance to call ismaster
93
93
  * @param {number} [options.haInterval=10000] The interval of calling ismaster when monitoring is enabled.
94
94
  * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
95
95
  * @param {boolean} [options.monitorCommands=false] Enable command monitoring for this topology
@@ -202,7 +202,7 @@ class Server extends TopologyBase {
202
202
  // Server Session Pool
203
203
  sessionPool: null,
204
204
  // Active client sessions
205
- sessions: [],
205
+ sessions: new Set(),
206
206
  // Promise library
207
207
  promiseLibrary: promiseLibrary || Promise
208
208
  };
@@ -291,11 +291,12 @@ class TopologyBase extends EventEmitter {
291
291
 
292
292
  startSession(options, clientOptions) {
293
293
  const session = new ClientSession(this, this.s.sessionPool, options, clientOptions);
294
+
294
295
  session.once('ended', () => {
295
- this.s.sessions = this.s.sessions.filter(s => !s.equals(session));
296
+ this.s.sessions.delete(session);
296
297
  });
297
298
 
298
- this.s.sessions.push(session);
299
+ this.s.sessions.add(session);
299
300
  return session;
300
301
  }
301
302
 
@@ -382,9 +383,7 @@ class TopologyBase extends EventEmitter {
382
383
  close(forceClosed, callback) {
383
384
  // If we have sessions, we want to individually move them to the session pool,
384
385
  // and then send a single endSessions call.
385
- if (this.s.sessions.length) {
386
- this.s.sessions.forEach(session => session.endSession());
387
- }
386
+ this.s.sessions.forEach(session => session.endSession());
388
387
 
389
388
  if (this.s.sessionPool) {
390
389
  this.s.sessionPool.endAllPooledSessions();
package/lib/utils.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const MongoError = require('./core').MongoError;
4
- const ReadPreference = require('./core').ReadPreference;
3
+ const MongoError = require('./core/error').MongoError;
4
+ const ReadPreference = require('./core/topologies/read_preference');
5
5
  const WriteConcern = require('./write_concern');
6
6
 
7
7
  var shallowClone = function(obj) {
@@ -519,7 +519,7 @@ function resolveReadPreference(parent, options) {
519
519
  throw new Error('No readPreference was provided or inherited.');
520
520
  }
521
521
 
522
- return readPreference;
522
+ return typeof readPreference === 'string' ? new ReadPreference(readPreference) : readPreference;
523
523
  }
524
524
 
525
525
  /**
@@ -540,7 +540,7 @@ function isPromiseLike(maybePromise) {
540
540
  * @param {object} [options] options containing collation settings
541
541
  */
542
542
  function decorateWithCollation(command, target, options) {
543
- const topology = target.s && target.s.topology;
543
+ const topology = (target.s && target.s.topology) || target.topology;
544
544
 
545
545
  if (!topology) {
546
546
  throw new TypeError('parameter "target" is missing a topology');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "3.3.0-beta2",
3
+ "version": "3.3.3",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -17,7 +17,7 @@
17
17
  "official"
18
18
  ],
19
19
  "peerOptionalDependencies": {
20
- "kerberos": "^1.0.0",
20
+ "kerberos": "^1.1.0",
21
21
  "mongodb-client-encryption": "^1.0.0",
22
22
  "mongodb-extjson": "^2.1.2",
23
23
  "snappy": "^6.1.1",
@@ -32,6 +32,7 @@
32
32
  "bluebird": "3.5.0",
33
33
  "chai": "^4.1.1",
34
34
  "chai-subset": "^1.6.0",
35
+ "chalk": "^2.4.2",
35
36
  "co": "4.6.0",
36
37
  "coveralls": "^2.11.6",
37
38
  "eslint": "^4.5.0",
@@ -39,10 +40,10 @@
39
40
  "istanbul": "^0.4.5",
40
41
  "jsdoc": "3.5.5",
41
42
  "lodash.camelcase": "^4.3.0",
43
+ "mocha": "5.2.0",
42
44
  "mocha-sinon": "^2.1.0",
43
45
  "mongodb-extjson": "^2.1.1",
44
46
  "mongodb-mock-server": "^1.0.1",
45
- "mongodb-test-runner": "^1.1.18",
46
47
  "prettier": "~1.12.0",
47
48
  "semver": "^5.5.0",
48
49
  "sinon": "^4.3.0",
@@ -61,7 +62,7 @@
61
62
  },
62
63
  "scripts": {
63
64
  "atlas": "node ./test/atlas_connectivity_tests.js",
64
- "test": "npm run lint && mongodb-test-runner -t 60000 test/core test/unit test/functional",
65
+ "test": "npm run lint && mocha --recursive test/functional test/unit test/core",
65
66
  "coverage": "istanbul cover mongodb-test-runner -- -t 60000 test/core test/unit test/functional",
66
67
  "lint": "eslint lib test",
67
68
  "format": "prettier --print-width 100 --tab-width 2 --single-quote --write 'test/**/*.js' 'lib/**/*.js'",
@@ -69,5 +70,8 @@
69
70
  "generate-evergreen": "node .evergreen/generate_evergreen_tasks.js",
70
71
  "release": "standard-version -i HISTORY.md"
71
72
  },
72
- "homepage": "https://github.com/mongodb/node-mongodb-native"
73
+ "homepage": "https://github.com/mongodb/node-mongodb-native",
74
+ "optionalDependencies": {
75
+ "saslprep": "^1.0.0"
76
+ }
73
77
  }
@@ -1,127 +0,0 @@
1
- 'use strict';
2
-
3
- const OperationBase = require('./operation').OperationBase;
4
- const AggregationCursor = require('../aggregation_cursor');
5
- const applyWriteConcern = require('../utils').applyWriteConcern;
6
- const decorateWithCollation = require('../utils').decorateWithCollation;
7
- const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
8
- const handleCallback = require('../utils').handleCallback;
9
- const MongoError = require('../core').MongoError;
10
- const resolveReadPreference = require('../utils').resolveReadPreference;
11
- const toError = require('../utils').toError;
12
-
13
- const DB_AGGREGATE_COLLECTION = 1;
14
-
15
- class AggregateOperation extends OperationBase {
16
- constructor(db, collection, pipeline, options) {
17
- super(options);
18
-
19
- this.db = db;
20
- this.collection = collection;
21
- this.pipeline = pipeline;
22
- }
23
-
24
- execute(callback) {
25
- const db = this.db;
26
- const coll = this.collection;
27
- let pipeline = this.pipeline;
28
- let options = this.options;
29
-
30
- const isDbAggregate = typeof coll === 'string';
31
- const target = isDbAggregate ? db : coll;
32
- const topology = target.s.topology;
33
- let hasOutStage = false;
34
-
35
- if (typeof options.out === 'string') {
36
- pipeline = pipeline.concat({ $out: options.out });
37
- hasOutStage = true;
38
- } else if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out']) {
39
- hasOutStage = true;
40
- }
41
-
42
- let command;
43
- let namespace;
44
- let optionSources;
45
-
46
- if (isDbAggregate) {
47
- command = { aggregate: DB_AGGREGATE_COLLECTION, pipeline: pipeline };
48
- namespace = db.s.namespace.withCollection(DB_AGGREGATE_COLLECTION);
49
-
50
- optionSources = { db };
51
- } else {
52
- command = { aggregate: coll.collectionName, pipeline: pipeline };
53
- namespace = coll.s.namespace;
54
-
55
- optionSources = { db: coll.s.db, collection: coll };
56
- }
57
-
58
- const takesWriteConcern = topology.capabilities().commandsTakeWriteConcern;
59
-
60
- if (!hasOutStage) {
61
- decorateWithReadConcern(command, target, options);
62
- }
63
-
64
- if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out'] && takesWriteConcern) {
65
- applyWriteConcern(command, optionSources, options);
66
- }
67
-
68
- try {
69
- decorateWithCollation(command, target, options);
70
- } catch (err) {
71
- if (typeof callback === 'function') return callback(err, null);
72
- throw err;
73
- }
74
-
75
- if (options.bypassDocumentValidation === true) {
76
- command.bypassDocumentValidation = options.bypassDocumentValidation;
77
- }
78
-
79
- if (typeof options.allowDiskUse === 'boolean') command.allowDiskUse = options.allowDiskUse;
80
- if (typeof options.maxTimeMS === 'number') command.maxTimeMS = options.maxTimeMS;
81
-
82
- if (options.hint) command.hint = options.hint;
83
-
84
- options = Object.assign({}, options);
85
-
86
- // Ensure we have the right read preference inheritance
87
- options.readPreference = resolveReadPreference(options, optionSources);
88
-
89
- if (options.explain) {
90
- if (command.readConcern || command.writeConcern) {
91
- throw toError(
92
- '"explain" cannot be used on an aggregate call with readConcern/writeConcern'
93
- );
94
- }
95
- command.explain = options.explain;
96
- }
97
-
98
- if (typeof options.comment === 'string') command.comment = options.comment;
99
-
100
- // Validate that cursor options is valid
101
- if (options.cursor != null && typeof options.cursor !== 'object') {
102
- throw toError('cursor options must be an object');
103
- }
104
-
105
- options.cursor = options.cursor || {};
106
- if (options.batchSize && !hasOutStage) options.cursor.batchSize = options.batchSize;
107
- command.cursor = options.cursor;
108
-
109
- // promiseLibrary
110
- options.promiseLibrary = target.s.promiseLibrary;
111
-
112
- // Set the AggregationCursor constructor
113
- options.cursorFactory = AggregationCursor;
114
-
115
- if (typeof callback !== 'function') {
116
- if (!topology.capabilities()) {
117
- throw new MongoError('cannot connect to server');
118
- }
119
-
120
- return topology.cursor(namespace.toString(), command, options);
121
- }
122
-
123
- return handleCallback(callback, null, topology.cursor(namespace.toString(), command, options));
124
- }
125
- }
126
-
127
- module.exports = AggregateOperation;