mongodb 3.2.5 → 3.3.0-beta2

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 (133) hide show
  1. package/HISTORY.md +0 -10
  2. package/index.js +4 -4
  3. package/lib/admin.js +56 -56
  4. package/lib/aggregation_cursor.js +7 -3
  5. package/lib/bulk/common.js +18 -13
  6. package/lib/change_stream.js +196 -89
  7. package/lib/collection.js +217 -169
  8. package/lib/command_cursor.js +17 -7
  9. package/lib/core/auth/auth_provider.js +158 -0
  10. package/lib/core/auth/defaultAuthProviders.js +29 -0
  11. package/lib/core/auth/gssapi.js +241 -0
  12. package/lib/core/auth/mongo_credentials.js +81 -0
  13. package/lib/core/auth/mongocr.js +51 -0
  14. package/lib/core/auth/plain.js +35 -0
  15. package/lib/core/auth/scram.js +293 -0
  16. package/lib/core/auth/sspi.js +131 -0
  17. package/lib/core/auth/x509.js +26 -0
  18. package/lib/core/connection/apm.js +236 -0
  19. package/lib/core/connection/command_result.js +36 -0
  20. package/lib/core/connection/commands.js +507 -0
  21. package/lib/core/connection/connect.js +370 -0
  22. package/lib/core/connection/connection.js +624 -0
  23. package/lib/core/connection/logger.js +246 -0
  24. package/lib/core/connection/msg.js +219 -0
  25. package/lib/core/connection/pool.js +1285 -0
  26. package/lib/core/connection/utils.js +57 -0
  27. package/lib/core/cursor.js +752 -0
  28. package/lib/core/error.js +186 -0
  29. package/lib/core/index.js +50 -0
  30. package/lib/core/sdam/monitoring.js +228 -0
  31. package/lib/core/sdam/server.js +467 -0
  32. package/lib/core/sdam/server_description.js +163 -0
  33. package/lib/core/sdam/server_selectors.js +244 -0
  34. package/lib/core/sdam/srv_polling.js +135 -0
  35. package/lib/core/sdam/topology.js +1151 -0
  36. package/lib/core/sdam/topology_description.js +408 -0
  37. package/lib/core/sessions.js +711 -0
  38. package/lib/core/tools/smoke_plugin.js +61 -0
  39. package/lib/core/topologies/mongos.js +1337 -0
  40. package/lib/core/topologies/read_preference.js +202 -0
  41. package/lib/core/topologies/replset.js +1507 -0
  42. package/lib/core/topologies/replset_state.js +1121 -0
  43. package/lib/core/topologies/server.js +984 -0
  44. package/lib/core/topologies/shared.js +453 -0
  45. package/lib/core/transactions.js +167 -0
  46. package/lib/core/uri_parser.js +631 -0
  47. package/lib/core/utils.js +165 -0
  48. package/lib/core/wireprotocol/command.js +170 -0
  49. package/lib/core/wireprotocol/compression.js +73 -0
  50. package/lib/core/wireprotocol/constants.js +13 -0
  51. package/lib/core/wireprotocol/get_more.js +86 -0
  52. package/lib/core/wireprotocol/index.js +18 -0
  53. package/lib/core/wireprotocol/kill_cursors.js +70 -0
  54. package/lib/core/wireprotocol/query.js +224 -0
  55. package/lib/core/wireprotocol/shared.js +115 -0
  56. package/lib/core/wireprotocol/write_command.js +50 -0
  57. package/lib/cursor.js +40 -46
  58. package/lib/db.js +141 -95
  59. package/lib/dynamic_loaders.js +32 -0
  60. package/lib/error.js +12 -10
  61. package/lib/gridfs/chunk.js +2 -2
  62. package/lib/gridfs/grid_store.js +31 -25
  63. package/lib/gridfs-stream/index.js +4 -4
  64. package/lib/gridfs-stream/upload.js +1 -1
  65. package/lib/mongo_client.js +37 -15
  66. package/lib/operations/add_user.js +96 -0
  67. package/lib/operations/aggregate.js +24 -13
  68. package/lib/operations/aggregate_operation.js +127 -0
  69. package/lib/operations/bulk_write.js +104 -0
  70. package/lib/operations/close.js +47 -0
  71. package/lib/operations/collection_ops.js +28 -287
  72. package/lib/operations/collections.js +55 -0
  73. package/lib/operations/command.js +120 -0
  74. package/lib/operations/command_v2.js +43 -0
  75. package/lib/operations/common_functions.js +372 -0
  76. package/lib/operations/{mongo_client_ops.js → connect.js} +185 -157
  77. package/lib/operations/count.js +72 -0
  78. package/lib/operations/count_documents.js +46 -0
  79. package/lib/operations/create_collection.js +118 -0
  80. package/lib/operations/create_index.js +92 -0
  81. package/lib/operations/create_indexes.js +61 -0
  82. package/lib/operations/cursor_ops.js +3 -4
  83. package/lib/operations/db_ops.js +15 -12
  84. package/lib/operations/delete_many.js +25 -0
  85. package/lib/operations/delete_one.js +25 -0
  86. package/lib/operations/distinct.js +85 -0
  87. package/lib/operations/drop.js +53 -0
  88. package/lib/operations/drop_index.js +42 -0
  89. package/lib/operations/drop_indexes.js +23 -0
  90. package/lib/operations/estimated_document_count.js +33 -0
  91. package/lib/operations/execute_db_admin_command.js +34 -0
  92. package/lib/operations/execute_operation.js +165 -0
  93. package/lib/operations/explain.js +23 -0
  94. package/lib/operations/find_and_modify.js +98 -0
  95. package/lib/operations/find_one.js +33 -0
  96. package/lib/operations/find_one_and_delete.js +16 -0
  97. package/lib/operations/find_one_and_replace.js +18 -0
  98. package/lib/operations/find_one_and_update.js +19 -0
  99. package/lib/operations/geo_haystack_search.js +79 -0
  100. package/lib/operations/has_next.js +40 -0
  101. package/lib/operations/index_exists.js +39 -0
  102. package/lib/operations/index_information.js +23 -0
  103. package/lib/operations/indexes.js +22 -0
  104. package/lib/operations/insert_many.js +63 -0
  105. package/lib/operations/insert_one.js +75 -0
  106. package/lib/operations/is_capped.js +19 -0
  107. package/lib/operations/list_indexes.js +66 -0
  108. package/lib/operations/map_reduce.js +189 -0
  109. package/lib/operations/next.js +32 -0
  110. package/lib/operations/operation.js +63 -0
  111. package/lib/operations/options_operation.js +32 -0
  112. package/lib/operations/profiling_level.js +31 -0
  113. package/lib/operations/re_index.js +28 -0
  114. package/lib/operations/remove_user.js +52 -0
  115. package/lib/operations/rename.js +61 -0
  116. package/lib/operations/replace_one.js +47 -0
  117. package/lib/operations/set_profiling_level.js +48 -0
  118. package/lib/operations/stats.js +45 -0
  119. package/lib/operations/to_array.js +68 -0
  120. package/lib/operations/update_many.js +29 -0
  121. package/lib/operations/update_one.js +44 -0
  122. package/lib/operations/validate_collection.js +40 -0
  123. package/lib/read_concern.js +55 -0
  124. package/lib/topologies/mongos.js +3 -3
  125. package/lib/topologies/native_topology.js +22 -2
  126. package/lib/topologies/replset.js +3 -3
  127. package/lib/topologies/server.js +4 -4
  128. package/lib/topologies/topology_base.js +6 -6
  129. package/lib/url_parser.js +4 -3
  130. package/lib/utils.js +46 -59
  131. package/lib/write_concern.js +66 -0
  132. package/package.json +15 -6
  133. package/lib/.DS_Store +0 -0
@@ -36,17 +36,17 @@
36
36
  * });
37
37
  */
38
38
  const Chunk = require('./chunk');
39
- const ObjectID = require('mongodb-core').BSON.ObjectID;
40
- const ReadPreference = require('mongodb-core').ReadPreference;
39
+ const ObjectID = require('../core').BSON.ObjectID;
40
+ const ReadPreference = require('../core').ReadPreference;
41
41
  const Buffer = require('safe-buffer').Buffer;
42
42
  const fs = require('fs');
43
43
  const f = require('util').format;
44
44
  const util = require('util');
45
- const MongoError = require('mongodb-core').MongoError;
45
+ const MongoError = require('../core').MongoError;
46
46
  const inherits = util.inherits;
47
47
  const Duplex = require('stream').Duplex;
48
48
  const shallowClone = require('../utils').shallowClone;
49
- const executeOperation = require('../utils').executeOperation;
49
+ const executeLegacyOperation = require('../utils').executeLegacyOperation;
50
50
  const deprecate = require('util').deprecate;
51
51
 
52
52
  var REFERENCE_BY_FILENAME = 0,
@@ -56,7 +56,7 @@ const deprecationFn = deprecate(() => {},
56
56
  'GridStore is deprecated, and will be removed in a future version. Please use GridFSBucket instead');
57
57
 
58
58
  /**
59
- * Namespace provided by the mongodb-core and node.js
59
+ * Namespace provided by the core module
60
60
  * @external Duplex
61
61
  */
62
62
 
@@ -203,7 +203,7 @@ GridStore.prototype.open = function(options, callback) {
203
203
  throw MongoError.create({ message: 'Illegal mode ' + this.mode, driver: true });
204
204
  }
205
205
 
206
- return executeOperation(this.db.s.topology, open, [this, options, callback], {
206
+ return executeLegacyOperation(this.db.s.topology, open, [this, options, callback], {
207
207
  skipSessions: true
208
208
  });
209
209
  };
@@ -275,7 +275,7 @@ GridStore.prototype.getc = function(options, callback) {
275
275
  if (typeof options === 'function') (callback = options), (options = {});
276
276
  options = options || {};
277
277
 
278
- return executeOperation(this.db.s.topology, getc, [this, options, callback], {
278
+ return executeLegacyOperation(this.db.s.topology, getc, [this, options, callback], {
279
279
  skipSessions: true
280
280
  });
281
281
  };
@@ -312,7 +312,7 @@ GridStore.prototype.puts = function(string, options, callback) {
312
312
  options = options || {};
313
313
 
314
314
  var finalString = string.match(/\n$/) == null ? string + '\n' : string;
315
- return executeOperation(
315
+ return executeLegacyOperation(
316
316
  this.db.s.topology,
317
317
  this.write.bind(this),
318
318
  [finalString, options, callback],
@@ -347,7 +347,7 @@ GridStore.prototype.write = function write(data, close, options, callback) {
347
347
  if (typeof options === 'function') (callback = options), (options = {});
348
348
  options = options || {};
349
349
 
350
- return executeOperation(
350
+ return executeLegacyOperation(
351
351
  this.db.s.topology,
352
352
  _writeNormal,
353
353
  [this, data, close, options, callback],
@@ -388,7 +388,7 @@ GridStore.prototype.writeFile = function(file, options, callback) {
388
388
  if (typeof options === 'function') (callback = options), (options = {});
389
389
  options = options || {};
390
390
 
391
- return executeOperation(this.db.s.topology, writeFile, [this, file, options, callback], {
391
+ return executeLegacyOperation(this.db.s.topology, writeFile, [this, file, options, callback], {
392
392
  skipSessions: true
393
393
  });
394
394
  };
@@ -473,7 +473,7 @@ GridStore.prototype.close = function(options, callback) {
473
473
  if (typeof options === 'function') (callback = options), (options = {});
474
474
  options = options || {};
475
475
 
476
- return executeOperation(this.db.s.topology, close, [this, options, callback], {
476
+ return executeLegacyOperation(this.db.s.topology, close, [this, options, callback], {
477
477
  skipSessions: true
478
478
  });
479
479
  };
@@ -576,7 +576,7 @@ GridStore.prototype.unlink = function(options, callback) {
576
576
  if (typeof options === 'function') (callback = options), (options = {});
577
577
  options = options || {};
578
578
 
579
- return executeOperation(this.db.s.topology, unlink, [this, options, callback], {
579
+ return executeLegacyOperation(this.db.s.topology, unlink, [this, options, callback], {
580
580
  skipSessions: true
581
581
  });
582
582
  };
@@ -639,9 +639,12 @@ GridStore.prototype.readlines = function(separator, options, callback) {
639
639
  separator = separator || '\n';
640
640
  options = args.length ? args.shift() : {};
641
641
 
642
- return executeOperation(this.db.s.topology, readlines, [this, separator, options, callback], {
643
- skipSessions: true
644
- });
642
+ return executeLegacyOperation(
643
+ this.db.s.topology,
644
+ readlines,
645
+ [this, separator, options, callback],
646
+ { skipSessions: true }
647
+ );
645
648
  };
646
649
 
647
650
  var readlines = function(self, separator, options, callback) {
@@ -673,7 +676,7 @@ GridStore.prototype.rewind = function(options, callback) {
673
676
  if (typeof options === 'function') (callback = options), (options = {});
674
677
  options = options || {};
675
678
 
676
- return executeOperation(this.db.s.topology, rewind, [this, options, callback], {
679
+ return executeLegacyOperation(this.db.s.topology, rewind, [this, options, callback], {
677
680
  skipSessions: true
678
681
  });
679
682
  };
@@ -735,9 +738,12 @@ GridStore.prototype.read = function(length, buffer, options, callback) {
735
738
  buffer = args.length ? args.shift() : null;
736
739
  options = args.length ? args.shift() : {};
737
740
 
738
- return executeOperation(this.db.s.topology, read, [this, length, buffer, options, callback], {
739
- skipSessions: true
740
- });
741
+ return executeLegacyOperation(
742
+ this.db.s.topology,
743
+ read,
744
+ [this, length, buffer, options, callback],
745
+ { skipSessions: true }
746
+ );
741
747
  };
742
748
 
743
749
  var read = function(self, length, buffer, options, callback) {
@@ -851,7 +857,7 @@ GridStore.prototype.seek = function(position, seekLocation, options, callback) {
851
857
  seekLocation = args.length ? args.shift() : null;
852
858
  options = args.length ? args.shift() : {};
853
859
 
854
- return executeOperation(
860
+ return executeLegacyOperation(
855
861
  this.db.s.topology,
856
862
  seek,
857
863
  [this, position, seekLocation, options, callback],
@@ -1285,7 +1291,7 @@ GridStore.exist = function(db, fileIdObject, rootCollection, options, callback)
1285
1291
  options = args.length ? args.shift() : {};
1286
1292
  options = options || {};
1287
1293
 
1288
- return executeOperation(
1294
+ return executeLegacyOperation(
1289
1295
  db.s.topology,
1290
1296
  exists,
1291
1297
  [db, fileIdObject, rootCollection, options, callback],
@@ -1348,7 +1354,7 @@ GridStore.list = function(db, rootCollection, options, callback) {
1348
1354
  options = args.length ? args.shift() : {};
1349
1355
  options = options || {};
1350
1356
 
1351
- return executeOperation(db.s.topology, list, [db, rootCollection, options, callback], {
1357
+ return executeLegacyOperation(db.s.topology, list, [db, rootCollection, options, callback], {
1352
1358
  skipSessions: true
1353
1359
  });
1354
1360
  };
@@ -1417,7 +1423,7 @@ GridStore.read = function(db, name, length, offset, options, callback) {
1417
1423
  options = args.length ? args.shift() : null;
1418
1424
  options = options || {};
1419
1425
 
1420
- return executeOperation(
1426
+ return executeLegacyOperation(
1421
1427
  db.s.topology,
1422
1428
  readStatic,
1423
1429
  [db, name, length, offset, options, callback],
@@ -1470,7 +1476,7 @@ GridStore.readlines = function(db, name, separator, options, callback) {
1470
1476
  options = args.length ? args.shift() : null;
1471
1477
  options = options || {};
1472
1478
 
1473
- return executeOperation(
1479
+ return executeLegacyOperation(
1474
1480
  db.s.topology,
1475
1481
  readlinesStatic,
1476
1482
  [db, name, separator, options, callback],
@@ -1506,7 +1512,7 @@ GridStore.unlink = function(db, names, options, callback) {
1506
1512
  options = args.length ? args.shift() : {};
1507
1513
  options = options || {};
1508
1514
 
1509
- return executeOperation(db.s.topology, unlinkStatic, [this, db, names, options, callback], {
1515
+ return executeLegacyOperation(db.s.topology, unlinkStatic, [this, db, names, options, callback], {
1510
1516
  skipSessions: true
1511
1517
  });
1512
1518
  };
@@ -6,7 +6,7 @@ var GridFSBucketWriteStream = require('./upload');
6
6
  var shallowClone = require('../utils').shallowClone;
7
7
  var toError = require('../utils').toError;
8
8
  var util = require('util');
9
- var executeOperation = require('../utils').executeOperation;
9
+ var executeLegacyOperation = require('../utils').executeLegacyOperation;
10
10
 
11
11
  var DEFAULT_GRIDFS_BUCKET_OPTIONS = {
12
12
  bucketName: 'fs',
@@ -162,7 +162,7 @@ GridFSBucket.prototype.openDownloadStream = function(id, options) {
162
162
  */
163
163
 
164
164
  GridFSBucket.prototype.delete = function(id, callback) {
165
- return executeOperation(this.s.db.s.topology, _delete, [this, id, callback], {
165
+ return executeLegacyOperation(this.s.db.s.topology, _delete, [this, id, callback], {
166
166
  skipSessions: true
167
167
  });
168
168
  };
@@ -287,7 +287,7 @@ GridFSBucket.prototype.openDownloadStreamByName = function(filename, options) {
287
287
  */
288
288
 
289
289
  GridFSBucket.prototype.rename = function(id, filename, callback) {
290
- return executeOperation(this.s.db.s.topology, _rename, [this, id, filename, callback], {
290
+ return executeLegacyOperation(this.s.db.s.topology, _rename, [this, id, filename, callback], {
291
291
  skipSessions: true
292
292
  });
293
293
  };
@@ -317,7 +317,7 @@ function _rename(_this, id, filename, callback) {
317
317
  */
318
318
 
319
319
  GridFSBucket.prototype.drop = function(callback) {
320
- return executeOperation(this.s.db.s.topology, _drop, [this, callback], {
320
+ return executeLegacyOperation(this.s.db.s.topology, _drop, [this, callback], {
321
321
  skipSessions: true
322
322
  });
323
323
  };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var core = require('mongodb-core');
3
+ var core = require('../core');
4
4
  var crypto = require('crypto');
5
5
  var stream = require('stream');
6
6
  var util = require('util');
@@ -3,15 +3,15 @@
3
3
  const ChangeStream = require('./change_stream');
4
4
  const Db = require('./db');
5
5
  const EventEmitter = require('events').EventEmitter;
6
- const executeOperation = require('./utils').executeOperation;
6
+ const executeOperation = require('./operations/execute_operation');
7
7
  const inherits = require('util').inherits;
8
- const MongoError = require('mongodb-core').MongoError;
8
+ const MongoError = require('./core').MongoError;
9
9
  const deprecate = require('util').deprecate;
10
+ const WriteConcern = require('./write_concern');
10
11
 
11
12
  // Operations
12
- const connectOp = require('./operations/mongo_client_ops').connectOp;
13
- const validOptions = require('./operations/mongo_client_ops').validOptions;
14
- const closeOperation = require('./operations/mongo_client_ops').closeOperation;
13
+ const ConnectOperation = require('./operations/connect');
14
+ const CloseOperation = require('./operations/close');
15
15
 
16
16
  /**
17
17
  * @fileOverview The **MongoClient** class is a class that allows for making Connections to MongoDB.
@@ -52,6 +52,23 @@ const closeOperation = require('./operations/mongo_client_ops').closeOperation;
52
52
  * @see https://docs.mongodb.com/manual/reference/read-concern/index.html#read-concern-levels
53
53
  */
54
54
 
55
+ /**
56
+ * Configuration options for a automatic client encryption
57
+ *
58
+ * @typedef {Object} AutoEncryptionOptions
59
+ * @property {MongoClient} [keyVaultClient] A `MongoClient` used to fetch keys from a key vault
60
+ * @property {string} [keyVaultNamespace] The namespace where keys are stored in the key vault
61
+ * @property {object} [kmsProviders] Provider details for the desired Key Management Service to use for encryption
62
+ * @property {object} [kmsProviders.aws] Optional settings for the AWS KMS provider
63
+ * @property {string} [kmsProviders.aws.accessKeyId] The access key used for the AWS KMS provider
64
+ * @property {string} [kmsProviders.aws.secretAccessKey] The secret access key used for the AWS KMS provider
65
+ * @property {object} [kmsProviders.local] Optional settings for the local KMS provider
66
+ * @property {string} [kmsProviders.local.key] The master key used to encrypt/decrypt data keys
67
+ * @property {object} [schemaMap] A map of namespaces to a local JSON schema for encryption
68
+ * @property {boolean} [bypassAutoEncryption] Allows the user to bypass auto encryption, maintaining implicit decryption
69
+ * @param {string} [extraOptions.mongocryptURI] A local process the driver communicates with to determine how to encrypt values in a command. Defaults to "mongodb://%2Fvar%2Fmongocryptd.sock" if domain sockets are available or "mongodb://localhost:27020" otherwise.
70
+ */
71
+
55
72
  /**
56
73
  * Creates a new MongoClient instance
57
74
  * @class
@@ -117,6 +134,7 @@ const closeOperation = require('./operations/mongo_client_ops').closeOperation;
117
134
  * @param {number} [options.minSize] If present, the connection pool will be initialized with minSize connections, and will never dip below minSize connections
118
135
  * @param {boolean} [options.useNewUrlParser=false] Determines whether or not to use the new url parser. Enables the new, spec-compliant, url parser shipped in the core driver. This url parser fixes a number of problems with the original parser, and aims to outright replace that parser in the near future.
119
136
  * @param {boolean} [options.useUnifiedTopology] Enables the new unified topology layer
137
+ * @param {AutoEncryptionOptions} [options.autoEncryption] Optionally enable client side auto encryption
120
138
  * @param {MongoClient~connectCallback} [callback] The command result callback
121
139
  * @return {MongoClient} a MongoClient instance
122
140
  */
@@ -131,7 +149,8 @@ function MongoClient(url, options) {
131
149
  options: options || {},
132
150
  promiseLibrary: null,
133
151
  dbCache: {},
134
- sessions: []
152
+ sessions: [],
153
+ writeConcern: WriteConcern.fromOptions(options)
135
154
  };
136
155
 
137
156
  // Get the promiseLibrary
@@ -146,6 +165,13 @@ function MongoClient(url, options) {
146
165
  */
147
166
  inherits(MongoClient, EventEmitter);
148
167
 
168
+ Object.defineProperty(MongoClient.prototype, 'writeConcern', {
169
+ enumerable: true,
170
+ get: function() {
171
+ return this.s.writeConcern;
172
+ }
173
+ });
174
+
149
175
  /**
150
176
  * The callback format for results
151
177
  * @callback MongoClient~connectCallback
@@ -165,16 +191,13 @@ inherits(MongoClient, EventEmitter);
165
191
  * @return {Promise<MongoClient>} returns Promise if no callback passed
166
192
  */
167
193
  MongoClient.prototype.connect = function(callback) {
168
- // Validate options object
169
- const err = validOptions(this.s.options);
170
-
171
194
  if (typeof callback === 'string') {
172
195
  throw new TypeError('`connect` only accepts a callback');
173
196
  }
174
197
 
175
- return executeOperation(this, connectOp, [this, err, callback], {
176
- skipSessions: true
177
- });
198
+ const operation = new ConnectOperation(this);
199
+
200
+ return executeOperation(this, operation, callback);
178
201
  };
179
202
 
180
203
  MongoClient.prototype.logout = deprecate(function(options, callback) {
@@ -191,9 +214,8 @@ MongoClient.prototype.logout = deprecate(function(options, callback) {
191
214
  */
192
215
  MongoClient.prototype.close = function(force, callback) {
193
216
  if (typeof force === 'function') (callback = force), (force = false);
194
- return executeOperation(this, closeOperation, [this, force, callback], {
195
- skipSessions: true
196
- });
217
+ const operation = new CloseOperation(this, force);
218
+ return executeOperation(this, operation, callback);
197
219
  };
198
220
 
199
221
  /**
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ const Aspect = require('./operation').Aspect;
4
+ const CommandOperation = require('./command');
5
+ const defineAspects = require('./operation').defineAspects;
6
+ const crypto = require('crypto');
7
+ const handleCallback = require('../utils').handleCallback;
8
+ const toError = require('../utils').toError;
9
+
10
+ class AddUserOperation extends CommandOperation {
11
+ constructor(db, username, password, options) {
12
+ super(db, options);
13
+
14
+ this.username = username;
15
+ this.password = password;
16
+ }
17
+
18
+ _buildCommand() {
19
+ const db = this.db;
20
+ const username = this.username;
21
+ const password = this.password;
22
+ const options = this.options;
23
+
24
+ // Get additional values
25
+ let roles = Array.isArray(options.roles) ? options.roles : [];
26
+
27
+ // If not roles defined print deprecated message
28
+ // TODO: handle deprecation properly
29
+ if (roles.length === 0) {
30
+ console.log('Creating a user without roles is deprecated in MongoDB >= 2.6');
31
+ }
32
+
33
+ // Check the db name and add roles if needed
34
+ if (
35
+ (db.databaseName.toLowerCase() === 'admin' || options.dbName === 'admin') &&
36
+ !Array.isArray(options.roles)
37
+ ) {
38
+ roles = ['root'];
39
+ } else if (!Array.isArray(options.roles)) {
40
+ roles = ['dbOwner'];
41
+ }
42
+
43
+ const digestPassword = db.s.topology.lastIsMaster().maxWireVersion >= 7;
44
+
45
+ let userPassword = password;
46
+
47
+ if (!digestPassword) {
48
+ // Use node md5 generator
49
+ const md5 = crypto.createHash('md5');
50
+ // Generate keys used for authentication
51
+ md5.update(username + ':mongo:' + password);
52
+ userPassword = md5.digest('hex');
53
+ }
54
+
55
+ // Build the command to execute
56
+ const command = {
57
+ createUser: username,
58
+ customData: options.customData || {},
59
+ roles: roles,
60
+ digestPassword
61
+ };
62
+
63
+ // No password
64
+ if (typeof password === 'string') {
65
+ command.pwd = userPassword;
66
+ }
67
+
68
+ return command;
69
+ }
70
+
71
+ execute(callback) {
72
+ const options = this.options;
73
+
74
+ // Error out if digestPassword set
75
+ if (options.digestPassword != null) {
76
+ return callback(
77
+ toError(
78
+ "The digestPassword option is not supported via add_user. Please use db.command('createUser', ...) instead for this option."
79
+ )
80
+ );
81
+ }
82
+
83
+ // Attempt to execute auth command
84
+ super.execute((err, r) => {
85
+ if (!err) {
86
+ return handleCallback(callback, err, r);
87
+ }
88
+
89
+ return handleCallback(callback, err, null);
90
+ });
91
+ }
92
+ }
93
+
94
+ defineAspects(AddUserOperation, Aspect.WRITE_OPERATION);
95
+
96
+ module.exports = AddUserOperation;
@@ -5,11 +5,13 @@ const applyWriteConcern = require('../utils').applyWriteConcern;
5
5
  const decorateWithCollation = require('../utils').decorateWithCollation;
6
6
  const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
7
7
  const handleCallback = require('../utils').handleCallback;
8
- const MongoError = require('mongodb-core').MongoError;
8
+ const MongoError = require('../core').MongoError;
9
9
  const resolveReadPreference = require('../utils').resolveReadPreference;
10
10
  const toError = require('../utils').toError;
11
+ const ReadPreference = require('../core').ReadPreference;
11
12
 
12
13
  const DB_AGGREGATE_COLLECTION = 1;
14
+ const MIN_WIRE_VERSION_$OUT_READ_CONCERN_SUPPORT = 8;
13
15
 
14
16
  /**
15
17
  * Perform an aggregate operation. See Collection.prototype.aggregate or Db.prototype.aggregate for more information.
@@ -25,13 +27,16 @@ function aggregate(db, coll, pipeline, options, callback) {
25
27
  const isDbAggregate = typeof coll === 'string';
26
28
  const target = isDbAggregate ? db : coll;
27
29
  const topology = target.s.topology;
28
- let hasOutStage = false;
30
+ let hasWriteStage = false;
29
31
 
30
32
  if (typeof options.out === 'string') {
31
33
  pipeline = pipeline.concat({ $out: options.out });
32
- hasOutStage = true;
33
- } else if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out']) {
34
- hasOutStage = true;
34
+ hasWriteStage = true;
35
+ } else if (pipeline.length > 0) {
36
+ const finalStage = pipeline[pipeline.length - 1];
37
+ if (finalStage.$out || finalStage.$merge) {
38
+ hasWriteStage = true;
39
+ }
35
40
  }
36
41
 
37
42
  let command;
@@ -40,23 +45,24 @@ function aggregate(db, coll, pipeline, options, callback) {
40
45
 
41
46
  if (isDbAggregate) {
42
47
  command = { aggregate: DB_AGGREGATE_COLLECTION, pipeline: pipeline };
43
- namespace = `${db.s.databaseName}.${DB_AGGREGATE_COLLECTION}`;
48
+ namespace = db.s.namespace.withCollection(DB_AGGREGATE_COLLECTION);
44
49
 
45
50
  optionSources = { db };
46
51
  } else {
47
- command = { aggregate: coll.s.name, pipeline: pipeline };
52
+ command = { aggregate: coll.collectionName, pipeline: pipeline };
48
53
  namespace = coll.s.namespace;
49
54
 
50
55
  optionSources = { db: coll.s.db, collection: coll };
51
56
  }
52
57
 
53
58
  const takesWriteConcern = topology.capabilities().commandsTakeWriteConcern;
59
+ const ismaster = topology.lastIsMaster() || {};
54
60
 
55
- if (!hasOutStage) {
61
+ if (!hasWriteStage || ismaster.maxWireVersion >= MIN_WIRE_VERSION_$OUT_READ_CONCERN_SUPPORT) {
56
62
  decorateWithReadConcern(command, target, options);
57
63
  }
58
64
 
59
- if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out'] && takesWriteConcern) {
65
+ if (hasWriteStage && takesWriteConcern) {
60
66
  applyWriteConcern(command, optionSources, options);
61
67
  }
62
68
 
@@ -79,7 +85,9 @@ function aggregate(db, coll, pipeline, options, callback) {
79
85
  options = Object.assign({}, options);
80
86
 
81
87
  // Ensure we have the right read preference inheritance
82
- options.readPreference = resolveReadPreference(options, optionSources);
88
+ options.readPreference = hasWriteStage
89
+ ? ReadPreference.primary
90
+ : resolveReadPreference(isDbAggregate ? db : coll, options);
83
91
 
84
92
  if (options.explain) {
85
93
  if (command.readConcern || command.writeConcern) {
@@ -96,7 +104,10 @@ function aggregate(db, coll, pipeline, options, callback) {
96
104
  }
97
105
 
98
106
  options.cursor = options.cursor || {};
99
- if (options.batchSize && !hasOutStage) options.cursor.batchSize = options.batchSize;
107
+ if (options.batchSize && !hasWriteStage) {
108
+ options.cursor.batchSize = options.batchSize;
109
+ }
110
+
100
111
  command.cursor = options.cursor;
101
112
 
102
113
  // promiseLibrary
@@ -110,10 +121,10 @@ function aggregate(db, coll, pipeline, options, callback) {
110
121
  throw new MongoError('cannot connect to server');
111
122
  }
112
123
 
113
- return topology.cursor(namespace, command, options);
124
+ return topology.cursor(namespace.toString(), command, options);
114
125
  }
115
126
 
116
- return handleCallback(callback, null, topology.cursor(namespace, command, options));
127
+ return handleCallback(callback, null, topology.cursor(namespace.toString(), command, options));
117
128
  }
118
129
 
119
130
  module.exports = {
@@ -0,0 +1,127 @@
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;