summaryrefslogtreecommitdiffstats
path: root/node_modules/mongodb/lib/operations
diff options
context:
space:
mode:
authorGravatar Piotr Russ <mail@pruss.it> 2020-11-16 00:10:28 +0100
committerGravatar Piotr Russ <mail@pruss.it> 2020-11-16 00:10:28 +0100
commite06ec920f7a5d784e674c4c4b4e6d1da3dc7391d (patch)
tree55713f725f77b44ebfec86e4eec3ce33e71458ca /node_modules/mongodb/lib/operations
downloadwebsite_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.gz
website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.bz2
website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.zip
api, login, auth
Diffstat (limited to 'node_modules/mongodb/lib/operations')
-rw-r--r--node_modules/mongodb/lib/operations/add_user.js98
-rw-r--r--node_modules/mongodb/lib/operations/admin_ops.js62
-rw-r--r--node_modules/mongodb/lib/operations/aggregate.js106
-rw-r--r--node_modules/mongodb/lib/operations/bulk_write.js104
-rw-r--r--node_modules/mongodb/lib/operations/collection_ops.js353
-rw-r--r--node_modules/mongodb/lib/operations/collections.js55
-rw-r--r--node_modules/mongodb/lib/operations/command.js119
-rw-r--r--node_modules/mongodb/lib/operations/command_v2.js110
-rw-r--r--node_modules/mongodb/lib/operations/common_functions.js412
-rw-r--r--node_modules/mongodb/lib/operations/connect.js806
-rw-r--r--node_modules/mongodb/lib/operations/count.js68
-rw-r--r--node_modules/mongodb/lib/operations/count_documents.js41
-rw-r--r--node_modules/mongodb/lib/operations/create_collection.js102
-rw-r--r--node_modules/mongodb/lib/operations/create_indexes.js137
-rw-r--r--node_modules/mongodb/lib/operations/cursor_ops.js167
-rw-r--r--node_modules/mongodb/lib/operations/db_ops.js467
-rw-r--r--node_modules/mongodb/lib/operations/delete_many.js25
-rw-r--r--node_modules/mongodb/lib/operations/delete_one.js25
-rw-r--r--node_modules/mongodb/lib/operations/distinct.js85
-rw-r--r--node_modules/mongodb/lib/operations/drop.js53
-rw-r--r--node_modules/mongodb/lib/operations/drop_index.js42
-rw-r--r--node_modules/mongodb/lib/operations/drop_indexes.js23
-rw-r--r--node_modules/mongodb/lib/operations/estimated_document_count.js58
-rw-r--r--node_modules/mongodb/lib/operations/execute_db_admin_command.js34
-rw-r--r--node_modules/mongodb/lib/operations/execute_operation.js186
-rw-r--r--node_modules/mongodb/lib/operations/find.js40
-rw-r--r--node_modules/mongodb/lib/operations/find_and_modify.js115
-rw-r--r--node_modules/mongodb/lib/operations/find_one.js37
-rw-r--r--node_modules/mongodb/lib/operations/find_one_and_delete.js21
-rw-r--r--node_modules/mongodb/lib/operations/find_one_and_replace.js31
-rw-r--r--node_modules/mongodb/lib/operations/find_one_and_update.js32
-rw-r--r--node_modules/mongodb/lib/operations/geo_haystack_search.js79
-rw-r--r--node_modules/mongodb/lib/operations/index_exists.js39
-rw-r--r--node_modules/mongodb/lib/operations/index_information.js23
-rw-r--r--node_modules/mongodb/lib/operations/indexes.js22
-rw-r--r--node_modules/mongodb/lib/operations/insert_many.js63
-rw-r--r--node_modules/mongodb/lib/operations/insert_one.js39
-rw-r--r--node_modules/mongodb/lib/operations/is_capped.js19
-rw-r--r--node_modules/mongodb/lib/operations/list_collections.js106
-rw-r--r--node_modules/mongodb/lib/operations/list_databases.js38
-rw-r--r--node_modules/mongodb/lib/operations/list_indexes.js42
-rw-r--r--node_modules/mongodb/lib/operations/map_reduce.js190
-rw-r--r--node_modules/mongodb/lib/operations/operation.js66
-rw-r--r--node_modules/mongodb/lib/operations/options_operation.js32
-rw-r--r--node_modules/mongodb/lib/operations/profiling_level.js31
-rw-r--r--node_modules/mongodb/lib/operations/re_index.js33
-rw-r--r--node_modules/mongodb/lib/operations/remove_user.js52
-rw-r--r--node_modules/mongodb/lib/operations/rename.js61
-rw-r--r--node_modules/mongodb/lib/operations/replace_one.js54
-rw-r--r--node_modules/mongodb/lib/operations/run_command.js19
-rw-r--r--node_modules/mongodb/lib/operations/set_profiling_level.js48
-rw-r--r--node_modules/mongodb/lib/operations/stats.js45
-rw-r--r--node_modules/mongodb/lib/operations/update_many.js34
-rw-r--r--node_modules/mongodb/lib/operations/update_one.js49
-rw-r--r--node_modules/mongodb/lib/operations/validate_collection.js39
55 files changed, 5237 insertions, 0 deletions
diff --git a/node_modules/mongodb/lib/operations/add_user.js b/node_modules/mongodb/lib/operations/add_user.js
new file mode 100644
index 0000000..9c02510
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/add_user.js
@@ -0,0 +1,98 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const CommandOperation = require('./command');
+const defineAspects = require('./operation').defineAspects;
+const crypto = require('crypto');
+const handleCallback = require('../utils').handleCallback;
+const toError = require('../utils').toError;
+
+class AddUserOperation extends CommandOperation {
+ constructor(db, username, password, options) {
+ super(db, options);
+
+ this.username = username;
+ this.password = password;
+ }
+
+ _buildCommand() {
+ const db = this.db;
+ const username = this.username;
+ const password = this.password;
+ const options = this.options;
+
+ // Get additional values
+ let roles = [];
+ if (Array.isArray(options.roles)) roles = options.roles;
+ if (typeof options.roles === 'string') roles = [options.roles];
+
+ // If not roles defined print deprecated message
+ // TODO: handle deprecation properly
+ if (roles.length === 0) {
+ console.log('Creating a user without roles is deprecated in MongoDB >= 2.6');
+ }
+
+ // Check the db name and add roles if needed
+ if (
+ (db.databaseName.toLowerCase() === 'admin' || options.dbName === 'admin') &&
+ !Array.isArray(options.roles)
+ ) {
+ roles = ['root'];
+ } else if (!Array.isArray(options.roles)) {
+ roles = ['dbOwner'];
+ }
+
+ const digestPassword = db.s.topology.lastIsMaster().maxWireVersion >= 7;
+
+ let userPassword = password;
+
+ if (!digestPassword) {
+ // Use node md5 generator
+ const md5 = crypto.createHash('md5');
+ // Generate keys used for authentication
+ md5.update(username + ':mongo:' + password);
+ userPassword = md5.digest('hex');
+ }
+
+ // Build the command to execute
+ const command = {
+ createUser: username,
+ customData: options.customData || {},
+ roles: roles,
+ digestPassword
+ };
+
+ // No password
+ if (typeof password === 'string') {
+ command.pwd = userPassword;
+ }
+
+ return command;
+ }
+
+ execute(callback) {
+ const options = this.options;
+
+ // Error out if digestPassword set
+ if (options.digestPassword != null) {
+ return callback(
+ toError(
+ "The digestPassword option is not supported via add_user. Please use db.command('createUser', ...) instead for this option."
+ )
+ );
+ }
+
+ // Attempt to execute auth command
+ super.execute((err, r) => {
+ if (!err) {
+ return handleCallback(callback, err, r);
+ }
+
+ return handleCallback(callback, err, null);
+ });
+ }
+}
+
+defineAspects(AddUserOperation, Aspect.WRITE_OPERATION);
+
+module.exports = AddUserOperation;
diff --git a/node_modules/mongodb/lib/operations/admin_ops.js b/node_modules/mongodb/lib/operations/admin_ops.js
new file mode 100644
index 0000000..d5f3516
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/admin_ops.js
@@ -0,0 +1,62 @@
+'use strict';
+
+const executeCommand = require('./db_ops').executeCommand;
+const executeDbAdminCommand = require('./db_ops').executeDbAdminCommand;
+
+/**
+ * Get ReplicaSet status
+ *
+ * @param {Admin} a collection instance.
+ * @param {Object} [options] Optional settings. See Admin.prototype.replSetGetStatus for a list of options.
+ * @param {Admin~resultCallback} [callback] The command result callback.
+ */
+function replSetGetStatus(admin, options, callback) {
+ executeDbAdminCommand(admin.s.db, { replSetGetStatus: 1 }, options, callback);
+}
+
+/**
+ * Retrieve this db's server status.
+ *
+ * @param {Admin} a collection instance.
+ * @param {Object} [options] Optional settings. See Admin.prototype.serverStatus for a list of options.
+ * @param {Admin~resultCallback} [callback] The command result callback
+ */
+function serverStatus(admin, options, callback) {
+ executeDbAdminCommand(admin.s.db, { serverStatus: 1 }, options, callback);
+}
+
+/**
+ * Validate an existing collection
+ *
+ * @param {Admin} a collection instance.
+ * @param {string} collectionName The name of the collection to validate.
+ * @param {Object} [options] Optional settings. See Admin.prototype.validateCollection for a list of options.
+ * @param {Admin~resultCallback} [callback] The command result callback.
+ */
+function validateCollection(admin, collectionName, options, callback) {
+ const command = { validate: collectionName };
+ const keys = Object.keys(options);
+
+ // Decorate command with extra options
+ for (let i = 0; i < keys.length; i++) {
+ if (Object.prototype.hasOwnProperty.call(options, keys[i]) && keys[i] !== 'session') {
+ command[keys[i]] = options[keys[i]];
+ }
+ }
+
+ executeCommand(admin.s.db, command, options, (err, doc) => {
+ if (err != null) return callback(err, null);
+
+ if (doc.ok === 0) return callback(new Error('Error with validate command'), null);
+ if (doc.result != null && doc.result.constructor !== String)
+ return callback(new Error('Error with validation data'), null);
+ if (doc.result != null && doc.result.match(/exception|corrupt/) != null)
+ return callback(new Error('Error: invalid collection ' + collectionName), null);
+ if (doc.valid != null && !doc.valid)
+ return callback(new Error('Error: invalid collection ' + collectionName), null);
+
+ return callback(null, doc);
+ });
+}
+
+module.exports = { replSetGetStatus, serverStatus, validateCollection };
diff --git a/node_modules/mongodb/lib/operations/aggregate.js b/node_modules/mongodb/lib/operations/aggregate.js
new file mode 100644
index 0000000..e0f2da8
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/aggregate.js
@@ -0,0 +1,106 @@
+'use strict';
+
+const CommandOperationV2 = require('./command_v2');
+const MongoError = require('../core').MongoError;
+const maxWireVersion = require('../core/utils').maxWireVersion;
+const ReadPreference = require('../core').ReadPreference;
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+
+const DB_AGGREGATE_COLLECTION = 1;
+const MIN_WIRE_VERSION_$OUT_READ_CONCERN_SUPPORT = 8;
+
+class AggregateOperation extends CommandOperationV2 {
+ constructor(parent, pipeline, options) {
+ super(parent, options, { fullResponse: true });
+
+ this.target =
+ parent.s.namespace && parent.s.namespace.collection
+ ? parent.s.namespace.collection
+ : DB_AGGREGATE_COLLECTION;
+
+ this.pipeline = pipeline;
+
+ // determine if we have a write stage, override read preference if so
+ this.hasWriteStage = false;
+ if (typeof options.out === 'string') {
+ this.pipeline = this.pipeline.concat({ $out: options.out });
+ this.hasWriteStage = true;
+ } else if (pipeline.length > 0) {
+ const finalStage = pipeline[pipeline.length - 1];
+ if (finalStage.$out || finalStage.$merge) {
+ this.hasWriteStage = true;
+ }
+ }
+
+ if (this.hasWriteStage) {
+ this.readPreference = ReadPreference.primary;
+ }
+
+ if (options.explain && (this.readConcern || this.writeConcern)) {
+ throw new MongoError(
+ '"explain" cannot be used on an aggregate call with readConcern/writeConcern'
+ );
+ }
+
+ if (options.cursor != null && typeof options.cursor !== 'object') {
+ throw new MongoError('cursor options must be an object');
+ }
+ }
+
+ get canRetryRead() {
+ return !this.hasWriteStage;
+ }
+
+ addToPipeline(stage) {
+ this.pipeline.push(stage);
+ }
+
+ execute(server, callback) {
+ const options = this.options;
+ const serverWireVersion = maxWireVersion(server);
+ const command = { aggregate: this.target, pipeline: this.pipeline };
+
+ if (this.hasWriteStage && serverWireVersion < MIN_WIRE_VERSION_$OUT_READ_CONCERN_SUPPORT) {
+ this.readConcern = null;
+ }
+
+ if (serverWireVersion >= 5) {
+ if (this.hasWriteStage && this.writeConcern) {
+ Object.assign(command, { writeConcern: this.writeConcern });
+ }
+ }
+
+ if (options.bypassDocumentValidation === true) {
+ command.bypassDocumentValidation = options.bypassDocumentValidation;
+ }
+
+ if (typeof options.allowDiskUse === 'boolean') {
+ command.allowDiskUse = options.allowDiskUse;
+ }
+
+ if (options.hint) {
+ command.hint = options.hint;
+ }
+
+ if (options.explain) {
+ options.full = false;
+ command.explain = options.explain;
+ }
+
+ command.cursor = options.cursor || {};
+ if (options.batchSize && !this.hasWriteStage) {
+ command.cursor.batchSize = options.batchSize;
+ }
+
+ super.executeCommand(server, command, callback);
+ }
+}
+
+defineAspects(AggregateOperation, [
+ Aspect.READ_OPERATION,
+ Aspect.RETRYABLE,
+ Aspect.EXECUTE_WITH_SELECTION
+]);
+
+module.exports = AggregateOperation;
diff --git a/node_modules/mongodb/lib/operations/bulk_write.js b/node_modules/mongodb/lib/operations/bulk_write.js
new file mode 100644
index 0000000..8f14f02
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/bulk_write.js
@@ -0,0 +1,104 @@
+'use strict';
+
+const applyRetryableWrites = require('../utils').applyRetryableWrites;
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const MongoError = require('../core').MongoError;
+const OperationBase = require('./operation').OperationBase;
+
+class BulkWriteOperation extends OperationBase {
+ constructor(collection, operations, options) {
+ super(options);
+
+ this.collection = collection;
+ this.operations = operations;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const operations = this.operations;
+ let options = this.options;
+
+ // Add ignoreUndfined
+ if (coll.s.options.ignoreUndefined) {
+ options = Object.assign({}, options);
+ options.ignoreUndefined = coll.s.options.ignoreUndefined;
+ }
+
+ // Create the bulk operation
+ const bulk =
+ options.ordered === true || options.ordered == null
+ ? coll.initializeOrderedBulkOp(options)
+ : coll.initializeUnorderedBulkOp(options);
+
+ // Do we have a collation
+ let collation = false;
+
+ // for each op go through and add to the bulk
+ try {
+ for (let i = 0; i < operations.length; i++) {
+ // Get the operation type
+ const key = Object.keys(operations[i])[0];
+ // Check if we have a collation
+ if (operations[i][key].collation) {
+ collation = true;
+ }
+
+ // Pass to the raw bulk
+ bulk.raw(operations[i]);
+ }
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ // Final options for retryable writes and write concern
+ let finalOptions = Object.assign({}, options);
+ finalOptions = applyRetryableWrites(finalOptions, coll.s.db);
+ finalOptions = applyWriteConcern(finalOptions, { db: coll.s.db, collection: coll }, options);
+
+ const writeCon = finalOptions.writeConcern ? finalOptions.writeConcern : {};
+ const capabilities = coll.s.topology.capabilities();
+
+ // Did the user pass in a collation, check if our write server supports it
+ if (collation && capabilities && !capabilities.commandsTakeCollation) {
+ return callback(new MongoError('server/primary/mongos does not support collation'));
+ }
+
+ // Execute the bulk
+ bulk.execute(writeCon, finalOptions, (err, r) => {
+ // We have connection level error
+ if (!r && err) {
+ return callback(err, null);
+ }
+
+ r.insertedCount = r.nInserted;
+ r.matchedCount = r.nMatched;
+ r.modifiedCount = r.nModified || 0;
+ r.deletedCount = r.nRemoved;
+ r.upsertedCount = r.getUpsertedIds().length;
+ r.upsertedIds = {};
+ r.insertedIds = {};
+
+ // Update the n
+ r.n = r.insertedCount;
+
+ // Inserted documents
+ const inserted = r.getInsertedIds();
+ // Map inserted ids
+ for (let i = 0; i < inserted.length; i++) {
+ r.insertedIds[inserted[i].index] = inserted[i]._id;
+ }
+
+ // Upserted documents
+ const upserted = r.getUpsertedIds();
+ // Map upserted ids
+ for (let i = 0; i < upserted.length; i++) {
+ r.upsertedIds[upserted[i].index] = upserted[i]._id;
+ }
+
+ // Return the results
+ callback(null, r);
+ });
+ }
+}
+
+module.exports = BulkWriteOperation;
diff --git a/node_modules/mongodb/lib/operations/collection_ops.js b/node_modules/mongodb/lib/operations/collection_ops.js
new file mode 100644
index 0000000..655bd70
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/collection_ops.js
@@ -0,0 +1,353 @@
+'use strict';
+
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const Code = require('../core').BSON.Code;
+const createIndexDb = require('./db_ops').createIndex;
+const decorateWithCollation = require('../utils').decorateWithCollation;
+const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
+const ensureIndexDb = require('./db_ops').ensureIndex;
+const evaluate = require('./db_ops').evaluate;
+const executeCommand = require('./db_ops').executeCommand;
+const handleCallback = require('../utils').handleCallback;
+const indexInformationDb = require('./db_ops').indexInformation;
+const Long = require('../core').BSON.Long;
+const MongoError = require('../core').MongoError;
+const ReadPreference = require('../core').ReadPreference;
+const insertDocuments = require('./common_functions').insertDocuments;
+const updateDocuments = require('./common_functions').updateDocuments;
+
+/**
+ * Group function helper
+ * @ignore
+ */
+// var groupFunction = function () {
+// var c = db[ns].find(condition);
+// var map = new Map();
+// var reduce_function = reduce;
+//
+// while (c.hasNext()) {
+// var obj = c.next();
+// var key = {};
+//
+// for (var i = 0, len = keys.length; i < len; ++i) {
+// var k = keys[i];
+// key[k] = obj[k];
+// }
+//
+// var aggObj = map.get(key);
+//
+// if (aggObj == null) {
+// var newObj = Object.extend({}, key);
+// aggObj = Object.extend(newObj, initial);
+// map.put(key, aggObj);
+// }
+//
+// reduce_function(obj, aggObj);
+// }
+//
+// return { "result": map.values() };
+// }.toString();
+const groupFunction =
+ 'function () {\nvar c = db[ns].find(condition);\nvar map = new Map();\nvar reduce_function = reduce;\n\nwhile (c.hasNext()) {\nvar obj = c.next();\nvar key = {};\n\nfor (var i = 0, len = keys.length; i < len; ++i) {\nvar k = keys[i];\nkey[k] = obj[k];\n}\n\nvar aggObj = map.get(key);\n\nif (aggObj == null) {\nvar newObj = Object.extend({}, key);\naggObj = Object.extend(newObj, initial);\nmap.put(key, aggObj);\n}\n\nreduce_function(obj, aggObj);\n}\n\nreturn { "result": map.values() };\n}';
+
+/**
+ * Create an index on the db and collection.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {(string|object)} fieldOrSpec Defines the index.
+ * @param {object} [options] Optional settings. See Collection.prototype.createIndex for a list of options.
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+function createIndex(coll, fieldOrSpec, options, callback) {
+ createIndexDb(coll.s.db, coll.collectionName, fieldOrSpec, options, callback);
+}
+
+/**
+ * Create multiple indexes in the collection. This method is only supported for
+ * MongoDB 2.6 or higher. Earlier version of MongoDB will throw a command not supported
+ * error. Index specifications are defined at http://docs.mongodb.org/manual/reference/command/createIndexes/.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {array} indexSpecs An array of index specifications to be created
+ * @param {Object} [options] Optional settings. See Collection.prototype.createIndexes for a list of options.
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+function createIndexes(coll, indexSpecs, options, callback) {
+ const capabilities = coll.s.topology.capabilities();
+
+ // Ensure we generate the correct name if the parameter is not set
+ for (let i = 0; i < indexSpecs.length; i++) {
+ if (indexSpecs[i].name == null) {
+ const keys = [];
+
+ // Did the user pass in a collation, check if our write server supports it
+ if (indexSpecs[i].collation && capabilities && !capabilities.commandsTakeCollation) {
+ return callback(new MongoError('server/primary/mongos does not support collation'));
+ }
+
+ for (let name in indexSpecs[i].key) {
+ keys.push(`${name}_${indexSpecs[i].key[name]}`);
+ }
+
+ // Set the name
+ indexSpecs[i].name = keys.join('_');
+ }
+ }
+
+ options = Object.assign({}, options, { readPreference: ReadPreference.PRIMARY });
+
+ // Execute the index
+ executeCommand(
+ coll.s.db,
+ {
+ createIndexes: coll.collectionName,
+ indexes: indexSpecs
+ },
+ options,
+ callback
+ );
+}
+
+/**
+ * Ensure that an index exists. If the index does not exist, this function creates it.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {(string|object)} fieldOrSpec Defines the index.
+ * @param {object} [options] Optional settings. See Collection.prototype.ensureIndex for a list of options.
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+function ensureIndex(coll, fieldOrSpec, options, callback) {
+ ensureIndexDb(coll.s.db, coll.collectionName, fieldOrSpec, options, callback);
+}
+
+/**
+ * Run a group command across a collection.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {(object|array|function|code)} keys An object, array or function expressing the keys to group by.
+ * @param {object} condition An optional condition that must be true for a row to be considered.
+ * @param {object} initial Initial value of the aggregation counter object.
+ * @param {(function|Code)} reduce The reduce function aggregates (reduces) the objects iterated
+ * @param {(function|Code)} finalize An optional function to be run on each item in the result set just before the item is returned.
+ * @param {boolean} command Specify if you wish to run using the internal group command or using eval, default is true.
+ * @param {object} [options] Optional settings. See Collection.prototype.group for a list of options.
+ * @param {Collection~resultCallback} [callback] The command result callback
+ * @deprecated MongoDB 3.6 or higher will no longer support the group command. We recommend rewriting using the aggregation framework.
+ */
+function group(coll, keys, condition, initial, reduce, finalize, command, options, callback) {
+ // Execute using the command
+ if (command) {
+ const reduceFunction = reduce && reduce._bsontype === 'Code' ? reduce : new Code(reduce);
+
+ const selector = {
+ group: {
+ ns: coll.collectionName,
+ $reduce: reduceFunction,
+ cond: condition,
+ initial: initial,
+ out: 'inline'
+ }
+ };
+
+ // if finalize is defined
+ if (finalize != null) selector.group['finalize'] = finalize;
+ // Set up group selector
+ if ('function' === typeof keys || (keys && keys._bsontype === 'Code')) {
+ selector.group.$keyf = keys && keys._bsontype === 'Code' ? keys : new Code(keys);
+ } else {
+ const hash = {};
+ keys.forEach(key => {
+ hash[key] = 1;
+ });
+ selector.group.key = hash;
+ }
+
+ options = Object.assign({}, options);
+ // Ensure we have the right read preference inheritance
+ options.readPreference = ReadPreference.resolve(coll, options);
+
+ // Do we have a readConcern specified
+ decorateWithReadConcern(selector, coll, options);
+
+ // Have we specified collation
+ try {
+ decorateWithCollation(selector, coll, options);
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ // Execute command
+ executeCommand(coll.s.db, selector, options, (err, result) => {
+ if (err) return handleCallback(callback, err, null);
+ handleCallback(callback, null, result.retval);
+ });
+ } else {
+ // Create execution scope
+ const scope = reduce != null && reduce._bsontype === 'Code' ? reduce.scope : {};
+
+ scope.ns = coll.collectionName;
+ scope.keys = keys;
+ scope.condition = condition;
+ scope.initial = initial;
+
+ // Pass in the function text to execute within mongodb.
+ const groupfn = groupFunction.replace(/ reduce;/, reduce.toString() + ';');
+
+ evaluate(coll.s.db, new Code(groupfn, scope), null, options, (err, results) => {
+ if (err) return handleCallback(callback, err, null);
+ handleCallback(callback, null, results.result || results);
+ });
+ }
+}
+
+/**
+ * Retrieve all the indexes on the collection.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {Object} [options] Optional settings. See Collection.prototype.indexes for a list of options.
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+function indexes(coll, options, callback) {
+ options = Object.assign({}, { full: true }, options);
+ indexInformationDb(coll.s.db, coll.collectionName, options, callback);
+}
+
+/**
+ * Check if one or more indexes exist on the collection. This fails on the first index that doesn't exist.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {(string|array)} indexes One or more index names to check.
+ * @param {Object} [options] Optional settings. See Collection.prototype.indexExists for a list of options.
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+function indexExists(coll, indexes, options, callback) {
+ indexInformation(coll, options, (err, indexInformation) => {
+ // If we have an error return
+ if (err != null) return handleCallback(callback, err, null);
+ // Let's check for the index names
+ if (!Array.isArray(indexes))
+ return handleCallback(callback, null, indexInformation[indexes] != null);
+ // Check in list of indexes
+ for (let i = 0; i < indexes.length; i++) {
+ if (indexInformation[indexes[i]] == null) {
+ return handleCallback(callback, null, false);
+ }
+ }
+
+ // All keys found return true
+ return handleCallback(callback, null, true);
+ });
+}
+
+/**
+ * Retrieve this collection's index info.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {object} [options] Optional settings. See Collection.prototype.indexInformation for a list of options.
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+function indexInformation(coll, options, callback) {
+ indexInformationDb(coll.s.db, coll.collectionName, options, callback);
+}
+
+/**
+ * Return N parallel cursors for a collection to allow parallel reading of the entire collection. There are
+ * no ordering guarantees for returned results.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {object} [options] Optional settings. See Collection.prototype.parallelCollectionScan for a list of options.
+ * @param {Collection~parallelCollectionScanCallback} [callback] The command result callback
+ */
+function parallelCollectionScan(coll, options, callback) {
+ // Create command object
+ const commandObject = {
+ parallelCollectionScan: coll.collectionName,
+ numCursors: options.numCursors
+ };
+
+ // Do we have a readConcern specified
+ decorateWithReadConcern(commandObject, coll, options);
+
+ // Store the raw value
+ const raw = options.raw;
+ delete options['raw'];
+
+ // Execute the command
+ executeCommand(coll.s.db, commandObject, options, (err, result) => {
+ if (err) return handleCallback(callback, err, null);
+ if (result == null)
+ return handleCallback(
+ callback,
+ new Error('no result returned for parallelCollectionScan'),
+ null
+ );
+
+ options = Object.assign({ explicitlyIgnoreSession: true }, options);
+
+ const cursors = [];
+ // Add the raw back to the option
+ if (raw) options.raw = raw;
+ // Create command cursors for each item
+ for (let i = 0; i < result.cursors.length; i++) {
+ const rawId = result.cursors[i].cursor.id;
+ // Convert cursorId to Long if needed
+ const cursorId = typeof rawId === 'number' ? Long.fromNumber(rawId) : rawId;
+ // Add a command cursor
+ cursors.push(coll.s.topology.cursor(coll.namespace, cursorId, options));
+ }
+
+ handleCallback(callback, null, cursors);
+ });
+}
+
+/**
+ * Save a document.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {object} doc Document to save
+ * @param {object} [options] Optional settings. See Collection.prototype.save for a list of options.
+ * @param {Collection~writeOpCallback} [callback] The command result callback
+ * @deprecated use insertOne, insertMany, updateOne or updateMany
+ */
+function save(coll, doc, options, callback) {
+ // Get the write concern options
+ const finalOptions = applyWriteConcern(
+ Object.assign({}, options),
+ { db: coll.s.db, collection: coll },
+ options
+ );
+ // Establish if we need to perform an insert or update
+ if (doc._id != null) {
+ finalOptions.upsert = true;
+ return updateDocuments(coll, { _id: doc._id }, doc, finalOptions, callback);
+ }
+
+ // Insert the document
+ insertDocuments(coll, [doc], finalOptions, (err, result) => {
+ if (callback == null) return;
+ if (doc == null) return handleCallback(callback, null, null);
+ if (err) return handleCallback(callback, err, null);
+ handleCallback(callback, null, result);
+ });
+}
+
+module.exports = {
+ createIndex,
+ createIndexes,
+ ensureIndex,
+ group,
+ indexes,
+ indexExists,
+ indexInformation,
+ parallelCollectionScan,
+ save
+};
diff --git a/node_modules/mongodb/lib/operations/collections.js b/node_modules/mongodb/lib/operations/collections.js
new file mode 100644
index 0000000..eac690a
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/collections.js
@@ -0,0 +1,55 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const handleCallback = require('../utils').handleCallback;
+
+let collection;
+function loadCollection() {
+ if (!collection) {
+ collection = require('../collection');
+ }
+ return collection;
+}
+
+class CollectionsOperation extends OperationBase {
+ constructor(db, options) {
+ super(options);
+
+ this.db = db;
+ }
+
+ execute(callback) {
+ const db = this.db;
+ let options = this.options;
+
+ let Collection = loadCollection();
+
+ options = Object.assign({}, options, { nameOnly: true });
+ // Let's get the collection names
+ db.listCollections({}, options).toArray((err, documents) => {
+ if (err != null) return handleCallback(callback, err, null);
+ // Filter collections removing any illegal ones
+ documents = documents.filter(doc => {
+ return doc.name.indexOf('$') === -1;
+ });
+
+ // Return the collection objects
+ handleCallback(
+ callback,
+ null,
+ documents.map(d => {
+ return new Collection(
+ db,
+ db.s.topology,
+ db.databaseName,
+ d.name,
+ db.s.pkFactory,
+ db.s.options
+ );
+ })
+ );
+ });
+ }
+}
+
+module.exports = CollectionsOperation;
diff --git a/node_modules/mongodb/lib/operations/command.js b/node_modules/mongodb/lib/operations/command.js
new file mode 100644
index 0000000..fd18a54
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/command.js
@@ -0,0 +1,119 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const OperationBase = require('./operation').OperationBase;
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const debugOptions = require('../utils').debugOptions;
+const handleCallback = require('../utils').handleCallback;
+const MongoError = require('../core').MongoError;
+const ReadPreference = require('../core').ReadPreference;
+const MongoDBNamespace = require('../utils').MongoDBNamespace;
+
+const debugFields = [
+ 'authSource',
+ 'w',
+ 'wtimeout',
+ 'j',
+ 'native_parser',
+ 'forceServerObjectId',
+ 'serializeFunctions',
+ 'raw',
+ 'promoteLongs',
+ 'promoteValues',
+ 'promoteBuffers',
+ 'bufferMaxEntries',
+ 'numberOfRetries',
+ 'retryMiliSeconds',
+ 'readPreference',
+ 'pkFactory',
+ 'parentDb',
+ 'promiseLibrary',
+ 'noListener'
+];
+
+class CommandOperation extends OperationBase {
+ constructor(db, options, collection, command) {
+ super(options);
+
+ if (!this.hasAspect(Aspect.WRITE_OPERATION)) {
+ if (collection != null) {
+ this.options.readPreference = ReadPreference.resolve(collection, options);
+ } else {
+ this.options.readPreference = ReadPreference.resolve(db, options);
+ }
+ } else {
+ if (collection != null) {
+ applyWriteConcern(this.options, { db, coll: collection }, this.options);
+ } else {
+ applyWriteConcern(this.options, { db }, this.options);
+ }
+ this.options.readPreference = ReadPreference.primary;
+ }
+
+ this.db = db;
+
+ if (command != null) {
+ this.command = command;
+ }
+
+ if (collection != null) {
+ this.collection = collection;
+ }
+ }
+
+ _buildCommand() {
+ if (this.command != null) {
+ return this.command;
+ }
+ }
+
+ execute(callback) {
+ const db = this.db;
+ const options = Object.assign({}, this.options);
+
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed()) {
+ return callback(new MongoError('topology was destroyed'));
+ }
+
+ let command;
+ try {
+ command = this._buildCommand();
+ } catch (e) {
+ return callback(e);
+ }
+
+ // Get the db name we are executing against
+ const dbName = options.dbName || options.authdb || db.databaseName;
+
+ // Convert the readPreference if its not a write
+ if (this.hasAspect(Aspect.WRITE_OPERATION)) {
+ if (options.writeConcern && (!options.session || !options.session.inTransaction())) {
+ command.writeConcern = options.writeConcern;
+ }
+ }
+
+ // Debug information
+ if (db.s.logger.isDebug()) {
+ db.s.logger.debug(
+ `executing command ${JSON.stringify(
+ command
+ )} against ${dbName}.$cmd with options [${JSON.stringify(
+ debugOptions(debugFields, options)
+ )}]`
+ );
+ }
+
+ const namespace =
+ this.namespace != null ? this.namespace : new MongoDBNamespace(dbName, '$cmd');
+
+ // Execute command
+ db.s.topology.command(namespace, command, options, (err, result) => {
+ if (err) return handleCallback(callback, err);
+ if (options.full) return handleCallback(callback, null, result);
+ handleCallback(callback, null, result.result);
+ });
+ }
+}
+
+module.exports = CommandOperation;
diff --git a/node_modules/mongodb/lib/operations/command_v2.js b/node_modules/mongodb/lib/operations/command_v2.js
new file mode 100644
index 0000000..e59122a
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/command_v2.js
@@ -0,0 +1,110 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const OperationBase = require('./operation').OperationBase;
+const ReadPreference = require('../core').ReadPreference;
+const ReadConcern = require('../read_concern');
+const WriteConcern = require('../write_concern');
+const maxWireVersion = require('../core/utils').maxWireVersion;
+const commandSupportsReadConcern = require('../core/sessions').commandSupportsReadConcern;
+const MongoError = require('../core/error').MongoError;
+
+const SUPPORTS_WRITE_CONCERN_AND_COLLATION = 5;
+
+class CommandOperationV2 extends OperationBase {
+ constructor(parent, options, operationOptions) {
+ super(options);
+
+ this.ns = parent.s.namespace.withCollection('$cmd');
+ const propertyProvider = this.hasAspect(Aspect.NO_INHERIT_OPTIONS) ? undefined : parent;
+ this.readPreference = this.hasAspect(Aspect.WRITE_OPERATION)
+ ? ReadPreference.primary
+ : ReadPreference.resolve(propertyProvider, this.options);
+ this.readConcern = resolveReadConcern(propertyProvider, this.options);
+ this.writeConcern = resolveWriteConcern(propertyProvider, this.options);
+ this.explain = false;
+
+ if (operationOptions && typeof operationOptions.fullResponse === 'boolean') {
+ this.fullResponse = true;
+ }
+
+ // TODO: A lot of our code depends on having the read preference in the options. This should
+ // go away, but also requires massive test rewrites.
+ this.options.readPreference = this.readPreference;
+
+ // TODO(NODE-2056): make logger another "inheritable" property
+ if (parent.s.logger) {
+ this.logger = parent.s.logger;
+ } else if (parent.s.db && parent.s.db.logger) {
+ this.logger = parent.s.db.logger;
+ }
+ }
+
+ executeCommand(server, cmd, callback) {
+ // TODO: consider making this a non-enumerable property
+ this.server = server;
+
+ const options = this.options;
+ const serverWireVersion = maxWireVersion(server);
+ const inTransaction = this.session && this.session.inTransaction();
+
+ if (this.readConcern && commandSupportsReadConcern(cmd) && !inTransaction) {
+ Object.assign(cmd, { readConcern: this.readConcern });
+ }
+
+ if (options.collation && serverWireVersion < SUPPORTS_WRITE_CONCERN_AND_COLLATION) {
+ callback(
+ new MongoError(
+ `Server ${server.name}, which reports wire version ${serverWireVersion}, does not support collation`
+ )
+ );
+ return;
+ }
+
+ if (serverWireVersion >= SUPPORTS_WRITE_CONCERN_AND_COLLATION) {
+ if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION)) {
+ Object.assign(cmd, { writeConcern: this.writeConcern });
+ }
+
+ if (options.collation && typeof options.collation === 'object') {
+ Object.assign(cmd, { collation: options.collation });
+ }
+ }
+
+ if (typeof options.maxTimeMS === 'number') {
+ cmd.maxTimeMS = options.maxTimeMS;
+ }
+
+ if (typeof options.comment === 'string') {
+ cmd.comment = options.comment;
+ }
+
+ if (this.logger && this.logger.isDebug()) {
+ this.logger.debug(`executing command ${JSON.stringify(cmd)} against ${this.ns}`);
+ }
+
+ server.command(this.ns.toString(), cmd, this.options, (err, result) => {
+ if (err) {
+ callback(err, null);
+ return;
+ }
+
+ if (this.fullResponse) {
+ callback(null, result);
+ return;
+ }
+
+ callback(null, result.result);
+ });
+ }
+}
+
+function resolveWriteConcern(parent, options) {
+ return WriteConcern.fromOptions(options) || (parent && parent.writeConcern);
+}
+
+function resolveReadConcern(parent, options) {
+ return ReadConcern.fromOptions(options) || (parent && parent.readConcern);
+}
+
+module.exports = CommandOperationV2;
diff --git a/node_modules/mongodb/lib/operations/common_functions.js b/node_modules/mongodb/lib/operations/common_functions.js
new file mode 100644
index 0000000..a02c53d
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/common_functions.js
@@ -0,0 +1,412 @@
+'use strict';
+
+const applyRetryableWrites = require('../utils').applyRetryableWrites;
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const decorateWithCollation = require('../utils').decorateWithCollation;
+const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
+const executeCommand = require('./db_ops').executeCommand;
+const formattedOrderClause = require('../utils').formattedOrderClause;
+const handleCallback = require('../utils').handleCallback;
+const MongoError = require('../core').MongoError;
+const ReadPreference = require('../core').ReadPreference;
+const toError = require('../utils').toError;
+const CursorState = require('../core/cursor').CursorState;
+
+/**
+ * Build the count command.
+ *
+ * @method
+ * @param {collectionOrCursor} an instance of a collection or cursor
+ * @param {object} query The query for the count.
+ * @param {object} [options] Optional settings. See Collection.prototype.count and Cursor.prototype.count for a list of options.
+ */
+function buildCountCommand(collectionOrCursor, query, options) {
+ const skip = options.skip;
+ const limit = options.limit;
+ let hint = options.hint;
+ const maxTimeMS = options.maxTimeMS;
+ query = query || {};
+
+ // Final query
+ const cmd = {
+ count: options.collectionName,
+ query: query
+ };
+
+ if (collectionOrCursor.s.numberOfRetries) {
+ // collectionOrCursor is a cursor
+ if (collectionOrCursor.options.hint) {
+ hint = collectionOrCursor.options.hint;
+ } else if (collectionOrCursor.cmd.hint) {
+ hint = collectionOrCursor.cmd.hint;
+ }
+ decorateWithCollation(cmd, collectionOrCursor, collectionOrCursor.cmd);
+ } else {
+ decorateWithCollation(cmd, collectionOrCursor, options);
+ }
+
+ // Add limit, skip and maxTimeMS if defined
+ if (typeof skip === 'number') cmd.skip = skip;
+ if (typeof limit === 'number') cmd.limit = limit;
+ if (typeof maxTimeMS === 'number') cmd.maxTimeMS = maxTimeMS;
+ if (hint) cmd.hint = hint;
+
+ // Do we have a readConcern specified
+ decorateWithReadConcern(cmd, collectionOrCursor);
+
+ return cmd;
+}
+
+function deleteCallback(err, r, callback) {
+ if (callback == null) return;
+ if (err && callback) return callback(err);
+ if (r == null) return callback(null, { result: { ok: 1 } });
+ r.deletedCount = r.result.n;
+ if (callback) callback(null, r);
+}
+
+/**
+ * Find and update a document.
+ *
+ * @method
+ * @param {Collection} a Collection instance.
+ * @param {object} query Query object to locate the object to modify.
+ * @param {array} sort If multiple docs match, choose the first one in the specified sort order as the object to manipulate.
+ * @param {object} doc The fields/vals to be updated.
+ * @param {object} [options] Optional settings. See Collection.prototype.findAndModify for a list of options.
+ * @param {Collection~findAndModifyCallback} [callback] The command result callback
+ * @deprecated use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead
+ */
+function findAndModify(coll, query, sort, doc, options, callback) {
+ // Create findAndModify command object
+ const queryObject = {
+ findAndModify: coll.collectionName,
+ query: query
+ };
+
+ sort = formattedOrderClause(sort);
+ if (sort) {
+ queryObject.sort = sort;
+ }
+
+ queryObject.new = options.new ? true : false;
+ queryObject.remove = options.remove ? true : false;
+ queryObject.upsert = options.upsert ? true : false;
+
+ const projection = options.projection || options.fields;
+
+ if (projection) {
+ queryObject.fields = projection;
+ }
+
+ if (options.arrayFilters) {
+ queryObject.arrayFilters = options.arrayFilters;
+ delete options.arrayFilters;
+ }
+
+ if (doc && !options.remove) {
+ queryObject.update = doc;
+ }
+
+ if (options.maxTimeMS) queryObject.maxTimeMS = options.maxTimeMS;
+
+ // Either use override on the function, or go back to default on either the collection
+ // level or db
+ options.serializeFunctions = options.serializeFunctions || coll.s.serializeFunctions;
+
+ // No check on the documents
+ options.checkKeys = false;
+
+ // Final options for retryable writes and write concern
+ let finalOptions = Object.assign({}, options);
+ finalOptions = applyRetryableWrites(finalOptions, coll.s.db);
+ finalOptions = applyWriteConcern(finalOptions, { db: coll.s.db, collection: coll }, options);
+
+ // Decorate the findAndModify command with the write Concern
+ if (finalOptions.writeConcern) {
+ queryObject.writeConcern = finalOptions.writeConcern;
+ }
+
+ // Have we specified bypassDocumentValidation
+ if (finalOptions.bypassDocumentValidation === true) {
+ queryObject.bypassDocumentValidation = finalOptions.bypassDocumentValidation;
+ }
+
+ finalOptions.readPreference = ReadPreference.primary;
+
+ // Have we specified collation
+ try {
+ decorateWithCollation(queryObject, coll, finalOptions);
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ // Execute the command
+ executeCommand(coll.s.db, queryObject, finalOptions, (err, result) => {
+ if (err) return handleCallback(callback, err, null);
+
+ return handleCallback(callback, null, result);
+ });
+}
+
+/**
+ * Retrieves this collections index info.
+ *
+ * @method
+ * @param {Db} db The Db instance on which to retrieve the index info.
+ * @param {string} name The name of the collection.
+ * @param {object} [options] Optional settings. See Db.prototype.indexInformation for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback
+ */
+function indexInformation(db, name, options, callback) {
+ // If we specified full information
+ const full = options['full'] == null ? false : options['full'];
+
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed())
+ return callback(new MongoError('topology was destroyed'));
+ // Process all the results from the index command and collection
+ function processResults(indexes) {
+ // Contains all the information
+ let info = {};
+ // Process all the indexes
+ for (let i = 0; i < indexes.length; i++) {
+ const index = indexes[i];
+ // Let's unpack the object
+ info[index.name] = [];
+ for (let name in index.key) {
+ info[index.name].push([name, index.key[name]]);
+ }
+ }
+
+ return info;
+ }
+
+ // Get the list of indexes of the specified collection
+ db.collection(name)
+ .listIndexes(options)
+ .toArray((err, indexes) => {
+ if (err) return callback(toError(err));
+ if (!Array.isArray(indexes)) return handleCallback(callback, null, []);
+ if (full) return handleCallback(callback, null, indexes);
+ handleCallback(callback, null, processResults(indexes));
+ });
+}
+
+function prepareDocs(coll, docs, options) {
+ const forceServerObjectId =
+ typeof options.forceServerObjectId === 'boolean'
+ ? options.forceServerObjectId
+ : coll.s.db.options.forceServerObjectId;
+
+ // no need to modify the docs if server sets the ObjectId
+ if (forceServerObjectId === true) {
+ return docs;
+ }
+
+ return docs.map(doc => {
+ if (forceServerObjectId !== true && doc._id == null) {
+ doc._id = coll.s.pkFactory.createPk();
+ }
+
+ return doc;
+ });
+}
+
+// Get the next available document from the cursor, returns null if no more documents are available.
+function nextObject(cursor, callback) {
+ if (cursor.s.state === CursorState.CLOSED || (cursor.isDead && cursor.isDead())) {
+ return handleCallback(
+ callback,
+ MongoError.create({ message: 'Cursor is closed', driver: true })
+ );
+ }
+
+ if (cursor.s.state === CursorState.INIT && cursor.cmd && cursor.cmd.sort) {
+ try {
+ cursor.cmd.sort = formattedOrderClause(cursor.cmd.sort);
+ } catch (err) {
+ return handleCallback(callback, err);
+ }
+ }
+
+ // Get the next object
+ cursor._next((err, doc) => {
+ cursor.s.state = CursorState.OPEN;
+ if (err) return handleCallback(callback, err);
+ handleCallback(callback, null, doc);
+ });
+}
+
+function insertDocuments(coll, docs, options, callback) {
+ if (typeof options === 'function') (callback = options), (options = {});
+ options = options || {};
+ // Ensure we are operating on an array op docs
+ docs = Array.isArray(docs) ? docs : [docs];
+
+ // Final options for retryable writes and write concern
+ let finalOptions = Object.assign({}, options);
+ finalOptions = applyRetryableWrites(finalOptions, coll.s.db);
+ finalOptions = applyWriteConcern(finalOptions, { db: coll.s.db, collection: coll }, options);
+
+ // If keep going set unordered
+ if (finalOptions.keepGoing === true) finalOptions.ordered = false;
+ finalOptions.serializeFunctions = options.serializeFunctions || coll.s.serializeFunctions;
+
+ docs = prepareDocs(coll, docs, options);
+
+ // File inserts
+ coll.s.topology.insert(coll.s.namespace, docs, finalOptions, (err, result) => {
+ if (callback == null) return;
+ if (err) return handleCallback(callback, err);
+ if (result == null) return handleCallback(callback, null, null);
+ if (result.result.code) return handleCallback(callback, toError(result.result));
+ if (result.result.writeErrors)
+ return handleCallback(callback, toError(result.result.writeErrors[0]));
+ // Add docs to the list
+ result.ops = docs;
+ // Return the results
+ handleCallback(callback, null, result);
+ });
+}
+
+function removeDocuments(coll, selector, options, callback) {
+ if (typeof options === 'function') {
+ (callback = options), (options = {});
+ } else if (typeof selector === 'function') {
+ callback = selector;
+ options = {};
+ selector = {};
+ }
+
+ // Create an empty options object if the provided one is null
+ options = options || {};
+
+ // Final options for retryable writes and write concern
+ let finalOptions = Object.assign({}, options);
+ finalOptions = applyRetryableWrites(finalOptions, coll.s.db);
+ finalOptions = applyWriteConcern(finalOptions, { db: coll.s.db, collection: coll }, options);
+
+ // If selector is null set empty
+ if (selector == null) selector = {};
+
+ // Build the op
+ const op = { q: selector, limit: 0 };
+ if (options.single) {
+ op.limit = 1;
+ } else if (finalOptions.retryWrites) {
+ finalOptions.retryWrites = false;
+ }
+ if (options.hint) {
+ op.hint = options.hint;
+ }
+
+ // Have we specified collation
+ try {
+ decorateWithCollation(finalOptions, coll, options);
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ // Execute the remove
+ coll.s.topology.remove(coll.s.namespace, [op], finalOptions, (err, result) => {
+ if (callback == null) return;
+ if (err) return handleCallback(callback, err, null);
+ if (result == null) return handleCallback(callback, null, null);
+ if (result.result.code) return handleCallback(callback, toError(result.result));
+ if (result.result.writeErrors) {
+ return handleCallback(callback, toError(result.result.writeErrors[0]));
+ }
+
+ // Return the results
+ handleCallback(callback, null, result);
+ });
+}
+
+function updateDocuments(coll, selector, document, options, callback) {
+ if ('function' === typeof options) (callback = options), (options = null);
+ if (options == null) options = {};
+ if (!('function' === typeof callback)) callback = null;
+
+ // If we are not providing a selector or document throw
+ if (selector == null || typeof selector !== 'object')
+ return callback(toError('selector must be a valid JavaScript object'));
+ if (document == null || typeof document !== 'object')
+ return callback(toError('document must be a valid JavaScript object'));
+
+ // Final options for retryable writes and write concern
+ let finalOptions = Object.assign({}, options);
+ finalOptions = applyRetryableWrites(finalOptions, coll.s.db);
+ finalOptions = applyWriteConcern(finalOptions, { db: coll.s.db, collection: coll }, options);
+
+ // Do we return the actual result document
+ // Either use override on the function, or go back to default on either the collection
+ // level or db
+ finalOptions.serializeFunctions = options.serializeFunctions || coll.s.serializeFunctions;
+
+ // Execute the operation
+ const op = { q: selector, u: document };
+ op.upsert = options.upsert !== void 0 ? !!options.upsert : false;
+ op.multi = options.multi !== void 0 ? !!options.multi : false;
+
+ if (options.hint) {
+ op.hint = options.hint;
+ }
+
+ if (finalOptions.arrayFilters) {
+ op.arrayFilters = finalOptions.arrayFilters;
+ delete finalOptions.arrayFilters;
+ }
+
+ if (finalOptions.retryWrites && op.multi) {
+ finalOptions.retryWrites = false;
+ }
+
+ // Have we specified collation
+ try {
+ decorateWithCollation(finalOptions, coll, options);
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ // Update options
+ coll.s.topology.update(coll.s.namespace, [op], finalOptions, (err, result) => {
+ if (callback == null) return;
+ if (err) return handleCallback(callback, err, null);
+ if (result == null) return handleCallback(callback, null, null);
+ if (result.result.code) return handleCallback(callback, toError(result.result));
+ if (result.result.writeErrors)
+ return handleCallback(callback, toError(result.result.writeErrors[0]));
+ // Return the results
+ handleCallback(callback, null, result);
+ });
+}
+
+function updateCallback(err, r, callback) {
+ if (callback == null) return;
+ if (err) return callback(err);
+ if (r == null) return callback(null, { result: { ok: 1 } });
+ r.modifiedCount = r.result.nModified != null ? r.result.nModified : r.result.n;
+ r.upsertedId =
+ Array.isArray(r.result.upserted) && r.result.upserted.length > 0
+ ? r.result.upserted[0] // FIXME(major): should be `r.result.upserted[0]._id`
+ : null;
+ r.upsertedCount =
+ Array.isArray(r.result.upserted) && r.result.upserted.length ? r.result.upserted.length : 0;
+ r.matchedCount =
+ Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? 0 : r.result.n;
+ callback(null, r);
+}
+
+module.exports = {
+ buildCountCommand,
+ deleteCallback,
+ findAndModify,
+ indexInformation,
+ nextObject,
+ prepareDocs,
+ insertDocuments,
+ removeDocuments,
+ updateDocuments,
+ updateCallback
+};
diff --git a/node_modules/mongodb/lib/operations/connect.js b/node_modules/mongodb/lib/operations/connect.js
new file mode 100644
index 0000000..2c3e8bd
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/connect.js
@@ -0,0 +1,806 @@
+'use strict';
+
+const deprecate = require('util').deprecate;
+const Logger = require('../core').Logger;
+const MongoCredentials = require('../core').MongoCredentials;
+const MongoError = require('../core').MongoError;
+const Mongos = require('../topologies/mongos');
+const NativeTopology = require('../topologies/native_topology');
+const parse = require('../core').parseConnectionString;
+const ReadConcern = require('../read_concern');
+const ReadPreference = require('../core').ReadPreference;
+const ReplSet = require('../topologies/replset');
+const Server = require('../topologies/server');
+const ServerSessionPool = require('../core').Sessions.ServerSessionPool;
+const emitDeprecationWarning = require('../utils').emitDeprecationWarning;
+const fs = require('fs');
+const BSON = require('../core/connection/utils').retrieveBSON();
+const CMAP_EVENT_NAMES = require('../cmap/events').CMAP_EVENT_NAMES;
+
+let client;
+function loadClient() {
+ if (!client) {
+ client = require('../mongo_client');
+ }
+ return client;
+}
+
+const legacyParse = deprecate(
+ require('../url_parser'),
+ 'current URL string parser is deprecated, and will be removed in a future version. ' +
+ 'To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.'
+);
+
+const AUTH_MECHANISM_INTERNAL_MAP = {
+ DEFAULT: 'default',
+ PLAIN: 'plain',
+ GSSAPI: 'gssapi',
+ 'MONGODB-CR': 'mongocr',
+ 'MONGODB-X509': 'x509',
+ 'MONGODB-AWS': 'mongodb-aws',
+ 'SCRAM-SHA-1': 'scram-sha-1',
+ 'SCRAM-SHA-256': 'scram-sha-256'
+};
+
+const monitoringEvents = [
+ 'timeout',
+ 'close',
+ 'serverOpening',
+ 'serverDescriptionChanged',
+ 'serverHeartbeatStarted',
+ 'serverHeartbeatSucceeded',
+ 'serverHeartbeatFailed',
+ 'serverClosed',
+ 'topologyOpening',
+ 'topologyClosed',
+ 'topologyDescriptionChanged',
+ 'commandStarted',
+ 'commandSucceeded',
+ 'commandFailed',
+ 'joined',
+ 'left',
+ 'ping',
+ 'ha',
+ 'all',
+ 'fullsetup',
+ 'open'
+];
+
+const VALID_AUTH_MECHANISMS = new Set([
+ 'DEFAULT',
+ 'PLAIN',
+ 'GSSAPI',
+ 'MONGODB-CR',
+ 'MONGODB-X509',
+ 'MONGODB-AWS',
+ 'SCRAM-SHA-1',
+ 'SCRAM-SHA-256'
+]);
+
+const validOptionNames = [
+ 'poolSize',
+ 'ssl',
+ 'sslValidate',
+ 'sslCA',
+ 'sslCert',
+ 'sslKey',
+ 'sslPass',
+ 'sslCRL',
+ 'autoReconnect',
+ 'noDelay',
+ 'keepAlive',
+ 'keepAliveInitialDelay',
+ 'connectTimeoutMS',
+ 'family',
+ 'socketTimeoutMS',
+ 'reconnectTries',
+ 'reconnectInterval',
+ 'ha',
+ 'haInterval',
+ 'replicaSet',
+ 'secondaryAcceptableLatencyMS',
+ 'acceptableLatencyMS',
+ 'connectWithNoPrimary',
+ 'authSource',
+ 'w',
+ 'wtimeout',
+ 'j',
+ 'forceServerObjectId',
+ 'serializeFunctions',
+ 'ignoreUndefined',
+ 'raw',
+ 'bufferMaxEntries',
+ 'readPreference',
+ 'pkFactory',
+ 'promiseLibrary',
+ 'readConcern',
+ 'maxStalenessSeconds',
+ 'loggerLevel',
+ 'logger',
+ 'promoteValues',
+ 'promoteBuffers',
+ 'promoteLongs',
+ 'domainsEnabled',
+ 'checkServerIdentity',
+ 'validateOptions',
+ 'appname',
+ 'auth',
+ 'user',
+ 'password',
+ 'authMechanism',
+ 'compression',
+ 'fsync',
+ 'readPreferenceTags',
+ 'numberOfRetries',
+ 'auto_reconnect',
+ 'minSize',
+ 'monitorCommands',
+ 'retryWrites',
+ 'retryReads',
+ 'useNewUrlParser',
+ 'useUnifiedTopology',
+ 'serverSelectionTimeoutMS',
+ 'useRecoveryToken',
+ 'autoEncryption',
+ 'driverInfo',
+ 'tls',
+ 'tlsInsecure',
+ 'tlsinsecure',
+ 'tlsAllowInvalidCertificates',
+ 'tlsAllowInvalidHostnames',
+ 'tlsCAFile',
+ 'tlsCertificateFile',
+ 'tlsCertificateKeyFile',
+ 'tlsCertificateKeyFilePassword',
+ 'minHeartbeatFrequencyMS',
+ 'heartbeatFrequencyMS',
+ 'directConnection',
+ 'appName',
+
+ // CMAP options
+ 'maxPoolSize',
+ 'minPoolSize',
+ 'maxIdleTimeMS',
+ 'waitQueueTimeoutMS'
+];
+
+const ignoreOptionNames = ['native_parser'];
+const legacyOptionNames = ['server', 'replset', 'replSet', 'mongos', 'db'];
+
+// Validate options object
+function validOptions(options) {
+ const _validOptions = validOptionNames.concat(legacyOptionNames);
+
+ for (const name in options) {
+ if (ignoreOptionNames.indexOf(name) !== -1) {
+ continue;
+ }
+
+ if (_validOptions.indexOf(name) === -1) {
+ if (options.validateOptions) {
+ return new MongoError(`option ${name} is not supported`);
+ } else {
+ console.warn(`the options [${name}] is not supported`);
+ }
+ }
+
+ if (legacyOptionNames.indexOf(name) !== -1) {
+ console.warn(
+ `the server/replset/mongos/db options are deprecated, ` +
+ `all their options are supported at the top level of the options object [${validOptionNames}]`
+ );
+ }
+ }
+}
+
+const LEGACY_OPTIONS_MAP = validOptionNames.reduce((obj, name) => {
+ obj[name.toLowerCase()] = name;
+ return obj;
+}, {});
+
+function addListeners(mongoClient, topology) {
+ topology.on('authenticated', createListener(mongoClient, 'authenticated'));
+ topology.on('error', createListener(mongoClient, 'error'));
+ topology.on('timeout', createListener(mongoClient, 'timeout'));
+ topology.on('close', createListener(mongoClient, 'close'));
+ topology.on('parseError', createListener(mongoClient, 'parseError'));
+ topology.once('open', createListener(mongoClient, 'open'));
+ topology.once('fullsetup', createListener(mongoClient, 'fullsetup'));
+ topology.once('all', createListener(mongoClient, 'all'));
+ topology.on('reconnect', createListener(mongoClient, 'reconnect'));
+}
+
+function assignTopology(client, topology) {
+ client.topology = topology;
+
+ if (!(topology instanceof NativeTopology)) {
+ topology.s.sessionPool = new ServerSessionPool(topology.s.coreTopology);
+ }
+}
+
+// Clear out all events
+function clearAllEvents(topology) {
+ monitoringEvents.forEach(event => topology.removeAllListeners(event));
+}
+
+// Collect all events in order from SDAM
+function collectEvents(mongoClient, topology) {
+ let MongoClient = loadClient();
+ const collectedEvents = [];
+
+ if (mongoClient instanceof MongoClient) {
+ monitoringEvents.forEach(event => {
+ topology.on(event, (object1, object2) => {
+ if (event === 'open') {
+ collectedEvents.push({ event: event, object1: mongoClient });
+ } else {
+ collectedEvents.push({ event: event, object1: object1, object2: object2 });
+ }
+ });
+ });
+ }
+
+ return collectedEvents;
+}
+
+function resolveTLSOptions(options) {
+ if (options.tls == null) {
+ return;
+ }
+
+ ['sslCA', 'sslKey', 'sslCert'].forEach(optionName => {
+ if (options[optionName]) {
+ options[optionName] = fs.readFileSync(options[optionName]);
+ }
+ });
+}
+
+const emitDeprecationForNonUnifiedTopology = deprecate(() => {},
+'current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. ' + 'To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.');
+
+function connect(mongoClient, url, options, callback) {
+ options = Object.assign({}, options);
+
+ // If callback is null throw an exception
+ if (callback == null) {
+ throw new Error('no callback function provided');
+ }
+
+ let didRequestAuthentication = false;
+ const logger = Logger('MongoClient', options);
+
+ // Did we pass in a Server/ReplSet/Mongos
+ if (url instanceof Server || url instanceof ReplSet || url instanceof Mongos) {
+ return connectWithUrl(mongoClient, url, options, connectCallback);
+ }
+
+ const useNewUrlParser = options.useNewUrlParser !== false;
+
+ const parseFn = useNewUrlParser ? parse : legacyParse;
+ const transform = useNewUrlParser ? transformUrlOptions : legacyTransformUrlOptions;
+
+ parseFn(url, options, (err, _object) => {
+ // Do not attempt to connect if parsing error
+ if (err) return callback(err);
+
+ // Flatten
+ const object = transform(_object);
+
+ // Parse the string
+ const _finalOptions = createUnifiedOptions(object, options);
+
+ // Check if we have connection and socket timeout set
+ if (_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 0;
+ if (_finalOptions.connectTimeoutMS == null) _finalOptions.connectTimeoutMS = 10000;
+ if (_finalOptions.retryWrites == null) _finalOptions.retryWrites = true;
+ if (_finalOptions.useRecoveryToken == null) _finalOptions.useRecoveryToken = true;
+ if (_finalOptions.readPreference == null) _finalOptions.readPreference = 'primary';
+
+ if (_finalOptions.db_options && _finalOptions.db_options.auth) {
+ delete _finalOptions.db_options.auth;
+ }
+
+ // `journal` should be translated to `j` for the driver
+ if (_finalOptions.journal != null) {
+ _finalOptions.j = _finalOptions.journal;
+ _finalOptions.journal = undefined;
+ }
+
+ // resolve tls options if needed
+ resolveTLSOptions(_finalOptions);
+
+ // Store the merged options object
+ mongoClient.s.options = _finalOptions;
+
+ // Failure modes
+ if (object.servers.length === 0) {
+ return callback(new Error('connection string must contain at least one seed host'));
+ }
+
+ if (_finalOptions.auth && !_finalOptions.credentials) {
+ try {
+ didRequestAuthentication = true;
+ _finalOptions.credentials = generateCredentials(
+ mongoClient,
+ _finalOptions.auth.user,
+ _finalOptions.auth.password,
+ _finalOptions
+ );
+ } catch (err) {
+ return callback(err);
+ }
+ }
+
+ if (_finalOptions.useUnifiedTopology) {
+ return createTopology(mongoClient, 'unified', _finalOptions, connectCallback);
+ }
+
+ emitDeprecationForNonUnifiedTopology();
+
+ // Do we have a replicaset then skip discovery and go straight to connectivity
+ if (_finalOptions.replicaSet || _finalOptions.rs_name) {
+ return createTopology(mongoClient, 'replicaset', _finalOptions, connectCallback);
+ } else if (object.servers.length > 1) {
+ return createTopology(mongoClient, 'mongos', _finalOptions, connectCallback);
+ } else {
+ return createServer(mongoClient, _finalOptions, connectCallback);
+ }
+ });
+
+ function connectCallback(err, topology) {
+ const warningMessage = `seed list contains no mongos proxies, replicaset connections requires the parameter replicaSet to be supplied in the URI or options object, mongodb://server:port/db?replicaSet=name`;
+ if (err && err.message === 'no mongos proxies found in seed list') {
+ if (logger.isWarn()) {
+ logger.warn(warningMessage);
+ }
+
+ // Return a more specific error message for MongoClient.connect
+ return callback(new MongoError(warningMessage));
+ }
+
+ if (didRequestAuthentication) {
+ mongoClient.emit('authenticated', null, true);
+ }
+
+ // Return the error and db instance
+ callback(err, topology);
+ }
+}
+
+function connectWithUrl(mongoClient, url, options, connectCallback) {
+ // Set the topology
+ assignTopology(mongoClient, url);
+
+ // Add listeners
+ addListeners(mongoClient, url);
+
+ // Propagate the events to the client
+ relayEvents(mongoClient, url);
+
+ let finalOptions = Object.assign({}, options);
+
+ // If we have a readPreference passed in by the db options, convert it from a string
+ if (typeof options.readPreference === 'string' || typeof options.read_preference === 'string') {
+ finalOptions.readPreference = new ReadPreference(
+ options.readPreference || options.read_preference
+ );
+ }
+
+ const isDoingAuth = finalOptions.user || finalOptions.password || finalOptions.authMechanism;
+ if (isDoingAuth && !finalOptions.credentials) {
+ try {
+ finalOptions.credentials = generateCredentials(
+ mongoClient,
+ finalOptions.user,
+ finalOptions.password,
+ finalOptions
+ );
+ } catch (err) {
+ return connectCallback(err, url);
+ }
+ }
+
+ return url.connect(finalOptions, connectCallback);
+}
+
+function createListener(mongoClient, event) {
+ const eventSet = new Set(['all', 'fullsetup', 'open', 'reconnect']);
+ return (v1, v2) => {
+ if (eventSet.has(event)) {
+ return mongoClient.emit(event, mongoClient);
+ }
+
+ mongoClient.emit(event, v1, v2);
+ };
+}
+
+function createServer(mongoClient, options, callback) {
+ // Pass in the promise library
+ options.promiseLibrary = mongoClient.s.promiseLibrary;
+
+ // Set default options
+ const servers = translateOptions(options);
+
+ const server = servers[0];
+
+ // Propagate the events to the client
+ const collectedEvents = collectEvents(mongoClient, server);
+
+ // Connect to topology
+ server.connect(options, (err, topology) => {
+ if (err) {
+ server.close(true);
+ return callback(err);
+ }
+ // Clear out all the collected event listeners
+ clearAllEvents(server);
+
+ // Relay all the events
+ relayEvents(mongoClient, server);
+ // Add listeners
+ addListeners(mongoClient, server);
+ // Check if we are really speaking to a mongos
+ const ismaster = topology.lastIsMaster();
+
+ // Set the topology
+ assignTopology(mongoClient, topology);
+
+ // Do we actually have a mongos
+ if (ismaster && ismaster.msg === 'isdbgrid') {
+ // Destroy the current connection
+ topology.close();
+ // Create mongos connection instead
+ return createTopology(mongoClient, 'mongos', options, callback);
+ }
+
+ // Fire all the events
+ replayEvents(mongoClient, collectedEvents);
+ // Otherwise callback
+ callback(err, topology);
+ });
+}
+
+const DEPRECATED_UNIFIED_EVENTS = new Set([
+ 'reconnect',
+ 'reconnectFailed',
+ 'attemptReconnect',
+ 'joined',
+ 'left',
+ 'ping',
+ 'ha',
+ 'all',
+ 'fullsetup',
+ 'open'
+]);
+
+function registerDeprecatedEventNotifiers(client) {
+ client.on('newListener', eventName => {
+ if (DEPRECATED_UNIFIED_EVENTS.has(eventName)) {
+ emitDeprecationWarning(
+ `The \`${eventName}\` event is no longer supported by the unified topology, please read more by visiting http://bit.ly/2D8WfT6`,
+ 'DeprecationWarning'
+ );
+ }
+ });
+}
+
+function createTopology(mongoClient, topologyType, options, callback) {
+ // Pass in the promise library
+ options.promiseLibrary = mongoClient.s.promiseLibrary;
+
+ const translationOptions = {};
+ if (topologyType === 'unified') translationOptions.createServers = false;
+
+ // Set default options
+ const servers = translateOptions(options, translationOptions);
+
+ // determine CSFLE support
+ if (options.autoEncryption != null) {
+ let AutoEncrypter;
+ try {
+ require.resolve('mongodb-client-encryption');
+ } catch (err) {
+ callback(
+ new MongoError(
+ 'Auto-encryption requested, but the module is not installed. Please add `mongodb-client-encryption` as a dependency of your project'
+ )
+ );
+ return;
+ }
+
+ try {
+ let mongodbClientEncryption = require('mongodb-client-encryption');
+ if (typeof mongodbClientEncryption.extension !== 'function') {
+ callback(
+ new MongoError(
+ 'loaded version of `mongodb-client-encryption` does not have property `extension`. Please make sure you are loading the correct version of `mongodb-client-encryption`'
+ )
+ );
+ }
+ AutoEncrypter = mongodbClientEncryption.extension(require('../../index')).AutoEncrypter;
+ } catch (err) {
+ callback(err);
+ return;
+ }
+
+ const mongoCryptOptions = Object.assign(
+ {
+ bson:
+ options.bson ||
+ new BSON([
+ BSON.Binary,
+ BSON.Code,
+ BSON.DBRef,
+ BSON.Decimal128,
+ BSON.Double,
+ BSON.Int32,
+ BSON.Long,
+ BSON.Map,
+ BSON.MaxKey,
+ BSON.MinKey,
+ BSON.ObjectId,
+ BSON.BSONRegExp,
+ BSON.Symbol,
+ BSON.Timestamp
+ ])
+ },
+ options.autoEncryption
+ );
+
+ options.autoEncrypter = new AutoEncrypter(mongoClient, mongoCryptOptions);
+ }
+
+ // Create the topology
+ let topology;
+ if (topologyType === 'mongos') {
+ topology = new Mongos(servers, options);
+ } else if (topologyType === 'replicaset') {
+ topology = new ReplSet(servers, options);
+ } else if (topologyType === 'unified') {
+ topology = new NativeTopology(options.servers, options);
+ registerDeprecatedEventNotifiers(mongoClient);
+ }
+
+ // Add listeners
+ addListeners(mongoClient, topology);
+
+ // Propagate the events to the client
+ relayEvents(mongoClient, topology);
+
+ // Open the connection
+ assignTopology(mongoClient, topology);
+
+ // initialize CSFLE if requested
+ if (options.autoEncrypter) {
+ options.autoEncrypter.init(err => {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ topology.connect(options, err => {
+ if (err) {
+ topology.close(true);
+ callback(err);
+ return;
+ }
+
+ callback(undefined, topology);
+ });
+ });
+
+ return;
+ }
+
+ // otherwise connect normally
+ topology.connect(options, err => {
+ if (err) {
+ topology.close(true);
+ return callback(err);
+ }
+
+ callback(undefined, topology);
+ return;
+ });
+}
+
+function createUnifiedOptions(finalOptions, options) {
+ const childOptions = [
+ 'mongos',
+ 'server',
+ 'db',
+ 'replset',
+ 'db_options',
+ 'server_options',
+ 'rs_options',
+ 'mongos_options'
+ ];
+ const noMerge = ['readconcern', 'compression', 'autoencryption'];
+
+ for (const name in options) {
+ if (noMerge.indexOf(name.toLowerCase()) !== -1) {
+ finalOptions[name] = options[name];
+ } else if (childOptions.indexOf(name.toLowerCase()) !== -1) {
+ finalOptions = mergeOptions(finalOptions, options[name], false);
+ } else {
+ if (
+ options[name] &&
+ typeof options[name] === 'object' &&
+ !Buffer.isBuffer(options[name]) &&
+ !Array.isArray(options[name])
+ ) {
+ finalOptions = mergeOptions(finalOptions, options[name], true);
+ } else {
+ finalOptions[name] = options[name];
+ }
+ }
+ }
+
+ return finalOptions;
+}
+
+function generateCredentials(client, username, password, options) {
+ options = Object.assign({}, options);
+
+ // the default db to authenticate against is 'self'
+ // if authententicate is called from a retry context, it may be another one, like admin
+ const source = options.authSource || options.authdb || options.dbName;
+
+ // authMechanism
+ const authMechanismRaw = options.authMechanism || 'DEFAULT';
+ const authMechanism = authMechanismRaw.toUpperCase();
+ const mechanismProperties = options.authMechanismProperties;
+
+ if (!VALID_AUTH_MECHANISMS.has(authMechanism)) {
+ throw MongoError.create({
+ message: `authentication mechanism ${authMechanismRaw} not supported', options.authMechanism`,
+ driver: true
+ });
+ }
+
+ return new MongoCredentials({
+ mechanism: AUTH_MECHANISM_INTERNAL_MAP[authMechanism],
+ mechanismProperties,
+ source,
+ username,
+ password
+ });
+}
+
+function legacyTransformUrlOptions(object) {
+ return mergeOptions(createUnifiedOptions({}, object), object, false);
+}
+
+function mergeOptions(target, source, flatten) {
+ for (const name in source) {
+ if (source[name] && typeof source[name] === 'object' && flatten) {
+ target = mergeOptions(target, source[name], flatten);
+ } else {
+ target[name] = source[name];
+ }
+ }
+
+ return target;
+}
+
+function relayEvents(mongoClient, topology) {
+ const serverOrCommandEvents = [
+ // APM
+ 'commandStarted',
+ 'commandSucceeded',
+ 'commandFailed',
+
+ // SDAM
+ 'serverOpening',
+ 'serverClosed',
+ 'serverDescriptionChanged',
+ 'serverHeartbeatStarted',
+ 'serverHeartbeatSucceeded',
+ 'serverHeartbeatFailed',
+ 'topologyOpening',
+ 'topologyClosed',
+ 'topologyDescriptionChanged',
+
+ // Legacy
+ 'joined',
+ 'left',
+ 'ping',
+ 'ha'
+ ].concat(CMAP_EVENT_NAMES);
+
+ serverOrCommandEvents.forEach(event => {
+ topology.on(event, (object1, object2) => {
+ mongoClient.emit(event, object1, object2);
+ });
+ });
+}
+
+//
+// Replay any events due to single server connection switching to Mongos
+//
+function replayEvents(mongoClient, events) {
+ for (let i = 0; i < events.length; i++) {
+ mongoClient.emit(events[i].event, events[i].object1, events[i].object2);
+ }
+}
+
+function transformUrlOptions(_object) {
+ let object = Object.assign({ servers: _object.hosts }, _object.options);
+ for (let name in object) {
+ const camelCaseName = LEGACY_OPTIONS_MAP[name];
+ if (camelCaseName) {
+ object[camelCaseName] = object[name];
+ }
+ }
+
+ const hasUsername = _object.auth && _object.auth.username;
+ const hasAuthMechanism = _object.options && _object.options.authMechanism;
+ if (hasUsername || hasAuthMechanism) {
+ object.auth = Object.assign({}, _object.auth);
+ if (object.auth.db) {
+ object.authSource = object.authSource || object.auth.db;
+ }
+
+ if (object.auth.username) {
+ object.auth.user = object.auth.username;
+ }
+ }
+
+ if (_object.defaultDatabase) {
+ object.dbName = _object.defaultDatabase;
+ }
+
+ if (object.maxPoolSize) {
+ object.poolSize = object.maxPoolSize;
+ }
+
+ if (object.readConcernLevel) {
+ object.readConcern = new ReadConcern(object.readConcernLevel);
+ }
+
+ if (object.wTimeoutMS) {
+ object.wtimeout = object.wTimeoutMS;
+ }
+
+ if (_object.srvHost) {
+ object.srvHost = _object.srvHost;
+ }
+
+ return object;
+}
+
+function translateOptions(options, translationOptions) {
+ translationOptions = Object.assign({}, { createServers: true }, translationOptions);
+
+ // If we have a readPreference passed in by the db options
+ if (typeof options.readPreference === 'string' || typeof options.read_preference === 'string') {
+ options.readPreference = new ReadPreference(options.readPreference || options.read_preference);
+ }
+
+ // Do we have readPreference tags, add them
+ if (options.readPreference && (options.readPreferenceTags || options.read_preference_tags)) {
+ options.readPreference.tags = options.readPreferenceTags || options.read_preference_tags;
+ }
+
+ // Do we have maxStalenessSeconds
+ if (options.maxStalenessSeconds) {
+ options.readPreference.maxStalenessSeconds = options.maxStalenessSeconds;
+ }
+
+ // Set the socket and connection timeouts
+ if (options.socketTimeoutMS == null) options.socketTimeoutMS = 0;
+ if (options.connectTimeoutMS == null) options.connectTimeoutMS = 10000;
+
+ if (!translationOptions.createServers) {
+ return;
+ }
+
+ // Create server instances
+ return options.servers.map(serverObj => {
+ return serverObj.domain_socket
+ ? new Server(serverObj.domain_socket, 27017, options)
+ : new Server(serverObj.host, serverObj.port, options);
+ });
+}
+
+module.exports = { validOptions, connect };
diff --git a/node_modules/mongodb/lib/operations/count.js b/node_modules/mongodb/lib/operations/count.js
new file mode 100644
index 0000000..a7216d6
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/count.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const buildCountCommand = require('./common_functions').buildCountCommand;
+const OperationBase = require('./operation').OperationBase;
+
+class CountOperation extends OperationBase {
+ constructor(cursor, applySkipLimit, options) {
+ super(options);
+
+ this.cursor = cursor;
+ this.applySkipLimit = applySkipLimit;
+ }
+
+ execute(callback) {
+ const cursor = this.cursor;
+ const applySkipLimit = this.applySkipLimit;
+ const options = this.options;
+
+ if (applySkipLimit) {
+ if (typeof cursor.cursorSkip() === 'number') options.skip = cursor.cursorSkip();
+ if (typeof cursor.cursorLimit() === 'number') options.limit = cursor.cursorLimit();
+ }
+
+ // Ensure we have the right read preference inheritance
+ if (options.readPreference) {
+ cursor.setReadPreference(options.readPreference);
+ }
+
+ if (
+ typeof options.maxTimeMS !== 'number' &&
+ cursor.cmd &&
+ typeof cursor.cmd.maxTimeMS === 'number'
+ ) {
+ options.maxTimeMS = cursor.cmd.maxTimeMS;
+ }
+
+ let finalOptions = {};
+ finalOptions.skip = options.skip;
+ finalOptions.limit = options.limit;
+ finalOptions.hint = options.hint;
+ finalOptions.maxTimeMS = options.maxTimeMS;
+
+ // Command
+ finalOptions.collectionName = cursor.namespace.collection;
+
+ let command;
+ try {
+ command = buildCountCommand(cursor, cursor.cmd.query, finalOptions);
+ } catch (err) {
+ return callback(err);
+ }
+
+ // Set cursor server to the same as the topology
+ cursor.server = cursor.topology.s.coreTopology;
+
+ // Execute the command
+ cursor.topology.command(
+ cursor.namespace.withCollection('$cmd'),
+ command,
+ cursor.options,
+ (err, result) => {
+ callback(err, result ? result.result.n : null);
+ }
+ );
+ }
+}
+
+module.exports = CountOperation;
diff --git a/node_modules/mongodb/lib/operations/count_documents.js b/node_modules/mongodb/lib/operations/count_documents.js
new file mode 100644
index 0000000..d043abf
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/count_documents.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const AggregateOperation = require('./aggregate');
+
+class CountDocumentsOperation extends AggregateOperation {
+ constructor(collection, query, options) {
+ const pipeline = [{ $match: query }];
+ if (typeof options.skip === 'number') {
+ pipeline.push({ $skip: options.skip });
+ }
+
+ if (typeof options.limit === 'number') {
+ pipeline.push({ $limit: options.limit });
+ }
+
+ pipeline.push({ $group: { _id: 1, n: { $sum: 1 } } });
+
+ super(collection, pipeline, options);
+ }
+
+ execute(server, callback) {
+ super.execute(server, (err, result) => {
+ if (err) {
+ callback(err, null);
+ return;
+ }
+
+ // NOTE: We're avoiding creating a cursor here to reduce the callstack.
+ const response = result.result;
+ if (response.cursor == null || response.cursor.firstBatch == null) {
+ callback(null, 0);
+ return;
+ }
+
+ const docs = response.cursor.firstBatch;
+ callback(null, docs.length ? docs[0].n : 0);
+ });
+ }
+}
+
+module.exports = CountDocumentsOperation;
diff --git a/node_modules/mongodb/lib/operations/create_collection.js b/node_modules/mongodb/lib/operations/create_collection.js
new file mode 100644
index 0000000..c84adb0
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/create_collection.js
@@ -0,0 +1,102 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const CommandOperation = require('./command');
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const loadCollection = require('../dynamic_loaders').loadCollection;
+const MongoError = require('../core').MongoError;
+const ReadPreference = require('../core').ReadPreference;
+
+const ILLEGAL_COMMAND_FIELDS = new Set([
+ 'w',
+ 'wtimeout',
+ 'j',
+ 'fsync',
+ 'autoIndexId',
+ 'strict',
+ 'serializeFunctions',
+ 'pkFactory',
+ 'raw',
+ 'readPreference',
+ 'session',
+ 'readConcern',
+ 'writeConcern'
+]);
+
+class CreateCollectionOperation extends CommandOperation {
+ constructor(db, name, options) {
+ super(db, options);
+ this.name = name;
+ }
+
+ _buildCommand() {
+ const name = this.name;
+ const options = this.options;
+
+ const cmd = { create: name };
+ for (let n in options) {
+ if (
+ options[n] != null &&
+ typeof options[n] !== 'function' &&
+ !ILLEGAL_COMMAND_FIELDS.has(n)
+ ) {
+ cmd[n] = options[n];
+ }
+ }
+
+ return cmd;
+ }
+
+ execute(callback) {
+ const db = this.db;
+ const name = this.name;
+ const options = this.options;
+ const Collection = loadCollection();
+
+ let listCollectionOptions = Object.assign({ nameOnly: true, strict: false }, options);
+ listCollectionOptions = applyWriteConcern(listCollectionOptions, { db }, listCollectionOptions);
+
+ function done(err) {
+ if (err) {
+ return callback(err);
+ }
+
+ try {
+ callback(
+ null,
+ new Collection(db, db.s.topology, db.databaseName, name, db.s.pkFactory, options)
+ );
+ } catch (err) {
+ callback(err);
+ }
+ }
+
+ const strictMode = listCollectionOptions.strict;
+ if (strictMode) {
+ db.listCollections({ name }, listCollectionOptions)
+ .setReadPreference(ReadPreference.PRIMARY)
+ .toArray((err, collections) => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (collections.length > 0) {
+ return callback(
+ new MongoError(`Collection ${name} already exists. Currently in strict mode.`)
+ );
+ }
+
+ super.execute(done);
+ });
+
+ return;
+ }
+
+ // otherwise just execute the command
+ super.execute(done);
+ }
+}
+
+defineAspects(CreateCollectionOperation, Aspect.WRITE_OPERATION);
+module.exports = CreateCollectionOperation;
diff --git a/node_modules/mongodb/lib/operations/create_indexes.js b/node_modules/mongodb/lib/operations/create_indexes.js
new file mode 100644
index 0000000..211b43c
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/create_indexes.js
@@ -0,0 +1,137 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const CommandOperationV2 = require('./command_v2');
+const MongoError = require('../core').MongoError;
+const parseIndexOptions = require('../utils').parseIndexOptions;
+const maxWireVersion = require('../core/utils').maxWireVersion;
+
+const VALID_INDEX_OPTIONS = new Set([
+ 'background',
+ 'unique',
+ 'name',
+ 'partialFilterExpression',
+ 'sparse',
+ 'expireAfterSeconds',
+ 'storageEngine',
+ 'collation',
+
+ // text indexes
+ 'weights',
+ 'default_language',
+ 'language_override',
+ 'textIndexVersion',
+
+ // 2d-sphere indexes
+ '2dsphereIndexVersion',
+
+ // 2d indexes
+ 'bits',
+ 'min',
+ 'max',
+
+ // geoHaystack Indexes
+ 'bucketSize',
+
+ // wildcard indexes
+ 'wildcardProjection'
+]);
+
+class CreateIndexesOperation extends CommandOperationV2 {
+ /**
+ * @ignore
+ */
+ constructor(parent, collection, indexes, options) {
+ super(parent, options);
+ this.collection = collection;
+
+ // createIndex can be called with a variety of styles:
+ // coll.createIndex('a');
+ // coll.createIndex({ a: 1 });
+ // coll.createIndex([['a', 1]]);
+ // createIndexes is always called with an array of index spec objects
+ if (!Array.isArray(indexes) || Array.isArray(indexes[0])) {
+ this.onlyReturnNameOfCreatedIndex = true;
+ // TODO: remove in v4 (breaking change); make createIndex return full response as createIndexes does
+
+ const indexParameters = parseIndexOptions(indexes);
+ // Generate the index name
+ const name = typeof options.name === 'string' ? options.name : indexParameters.name;
+ // Set up the index
+ const indexSpec = { name, key: indexParameters.fieldHash };
+ // merge valid index options into the index spec
+ for (let optionName in options) {
+ if (VALID_INDEX_OPTIONS.has(optionName)) {
+ indexSpec[optionName] = options[optionName];
+ }
+ }
+ this.indexes = [indexSpec];
+ return;
+ }
+
+ this.indexes = indexes;
+ }
+
+ /**
+ * @ignore
+ */
+ execute(server, callback) {
+ const options = this.options;
+ const indexes = this.indexes;
+
+ const serverWireVersion = maxWireVersion(server);
+
+ // Ensure we generate the correct name if the parameter is not set
+ for (let i = 0; i < indexes.length; i++) {
+ // Did the user pass in a collation, check if our write server supports it
+ if (indexes[i].collation && serverWireVersion < 5) {
+ callback(
+ new MongoError(
+ `Server ${server.name}, which reports wire version ${serverWireVersion}, does not support collation`
+ )
+ );
+ return;
+ }
+
+ if (indexes[i].name == null) {
+ const keys = [];
+
+ for (let name in indexes[i].key) {
+ keys.push(`${name}_${indexes[i].key[name]}`);
+ }
+
+ // Set the name
+ indexes[i].name = keys.join('_');
+ }
+ }
+
+ const cmd = { createIndexes: this.collection, indexes };
+
+ if (options.commitQuorum != null) {
+ if (serverWireVersion < 9) {
+ callback(
+ new MongoError('`commitQuorum` option for `createIndexes` not supported on servers < 4.4')
+ );
+ return;
+ }
+ cmd.commitQuorum = options.commitQuorum;
+ }
+
+ // collation is set on each index, it should not be defined at the root
+ this.options.collation = undefined;
+
+ super.executeCommand(server, cmd, (err, result) => {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ callback(null, this.onlyReturnNameOfCreatedIndex ? indexes[0].name : result);
+ });
+ }
+}
+
+defineAspects(CreateIndexesOperation, [Aspect.WRITE_OPERATION, Aspect.EXECUTE_WITH_SELECTION]);
+
+module.exports = CreateIndexesOperation;
diff --git a/node_modules/mongodb/lib/operations/cursor_ops.js b/node_modules/mongodb/lib/operations/cursor_ops.js
new file mode 100644
index 0000000..fda4c91
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/cursor_ops.js
@@ -0,0 +1,167 @@
+'use strict';
+
+const buildCountCommand = require('./collection_ops').buildCountCommand;
+const handleCallback = require('../utils').handleCallback;
+const MongoError = require('../core').MongoError;
+const push = Array.prototype.push;
+const CursorState = require('../core/cursor').CursorState;
+
+/**
+ * Get the count of documents for this cursor.
+ *
+ * @method
+ * @param {Cursor} cursor The Cursor instance on which to count.
+ * @param {boolean} [applySkipLimit=true] Specifies whether the count command apply limit and skip settings should be applied on the cursor or in the provided options.
+ * @param {object} [options] Optional settings. See Cursor.prototype.count for a list of options.
+ * @param {Cursor~countResultCallback} [callback] The result callback.
+ */
+function count(cursor, applySkipLimit, opts, callback) {
+ if (applySkipLimit) {
+ if (typeof cursor.cursorSkip() === 'number') opts.skip = cursor.cursorSkip();
+ if (typeof cursor.cursorLimit() === 'number') opts.limit = cursor.cursorLimit();
+ }
+
+ // Ensure we have the right read preference inheritance
+ if (opts.readPreference) {
+ cursor.setReadPreference(opts.readPreference);
+ }
+
+ if (
+ typeof opts.maxTimeMS !== 'number' &&
+ cursor.cmd &&
+ typeof cursor.cmd.maxTimeMS === 'number'
+ ) {
+ opts.maxTimeMS = cursor.cmd.maxTimeMS;
+ }
+
+ let options = {};
+ options.skip = opts.skip;
+ options.limit = opts.limit;
+ options.hint = opts.hint;
+ options.maxTimeMS = opts.maxTimeMS;
+
+ // Command
+ options.collectionName = cursor.namespace.collection;
+
+ let command;
+ try {
+ command = buildCountCommand(cursor, cursor.cmd.query, options);
+ } catch (err) {
+ return callback(err);
+ }
+
+ // Set cursor server to the same as the topology
+ cursor.server = cursor.topology.s.coreTopology;
+
+ // Execute the command
+ cursor.topology.command(
+ cursor.namespace.withCollection('$cmd'),
+ command,
+ cursor.options,
+ (err, result) => {
+ callback(err, result ? result.result.n : null);
+ }
+ );
+}
+
+/**
+ * Iterates over all the documents for this cursor. See Cursor.prototype.each for more information.
+ *
+ * @method
+ * @deprecated
+ * @param {Cursor} cursor The Cursor instance on which to run.
+ * @param {Cursor~resultCallback} callback The result callback.
+ */
+function each(cursor, callback) {
+ if (!callback) throw MongoError.create({ message: 'callback is mandatory', driver: true });
+ if (cursor.isNotified()) return;
+ if (cursor.s.state === CursorState.CLOSED || cursor.isDead()) {
+ return handleCallback(
+ callback,
+ MongoError.create({ message: 'Cursor is closed', driver: true })
+ );
+ }
+
+ if (cursor.s.state === CursorState.INIT) {
+ cursor.s.state = CursorState.OPEN;
+ }
+
+ // Define function to avoid global scope escape
+ let fn = null;
+ // Trampoline all the entries
+ if (cursor.bufferedCount() > 0) {
+ while ((fn = loop(cursor, callback))) fn(cursor, callback);
+ each(cursor, callback);
+ } else {
+ cursor.next((err, item) => {
+ if (err) return handleCallback(callback, err);
+ if (item == null) {
+ return cursor.close({ skipKillCursors: true }, () => handleCallback(callback, null, null));
+ }
+
+ if (handleCallback(callback, null, item) === false) return;
+ each(cursor, callback);
+ });
+ }
+}
+
+// Trampoline emptying the number of retrieved items
+// without incurring a nextTick operation
+function loop(cursor, callback) {
+ // No more items we are done
+ if (cursor.bufferedCount() === 0) return;
+ // Get the next document
+ cursor._next(callback);
+ // Loop
+ return loop;
+}
+
+/**
+ * Returns an array of documents. See Cursor.prototype.toArray for more information.
+ *
+ * @method
+ * @param {Cursor} cursor The Cursor instance from which to get the next document.
+ * @param {Cursor~toArrayResultCallback} [callback] The result callback.
+ */
+function toArray(cursor, callback) {
+ const items = [];
+
+ // Reset cursor
+ cursor.rewind();
+ cursor.s.state = CursorState.INIT;
+
+ // Fetch all the documents
+ const fetchDocs = () => {
+ cursor._next((err, doc) => {
+ if (err) {
+ return handleCallback(callback, err);
+ }
+
+ if (doc == null) {
+ return cursor.close({ skipKillCursors: true }, () => handleCallback(callback, null, items));
+ }
+
+ // Add doc to items
+ items.push(doc);
+
+ // Get all buffered objects
+ if (cursor.bufferedCount() > 0) {
+ let docs = cursor.readBufferedDocuments(cursor.bufferedCount());
+
+ // Transform the doc if transform method added
+ if (cursor.s.transforms && typeof cursor.s.transforms.doc === 'function') {
+ docs = docs.map(cursor.s.transforms.doc);
+ }
+
+ push.apply(items, docs);
+ }
+
+ // Attempt a fetch
+ fetchDocs();
+ });
+ };
+
+ fetchDocs();
+}
+
+module.exports = { count, each, toArray };
diff --git a/node_modules/mongodb/lib/operations/db_ops.js b/node_modules/mongodb/lib/operations/db_ops.js
new file mode 100644
index 0000000..8f9b890
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/db_ops.js
@@ -0,0 +1,467 @@
+'use strict';
+
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const Code = require('../core').BSON.Code;
+const debugOptions = require('../utils').debugOptions;
+const handleCallback = require('../utils').handleCallback;
+const MongoError = require('../core').MongoError;
+const parseIndexOptions = require('../utils').parseIndexOptions;
+const ReadPreference = require('../core').ReadPreference;
+const toError = require('../utils').toError;
+const CONSTANTS = require('../constants');
+const MongoDBNamespace = require('../utils').MongoDBNamespace;
+
+const debugFields = [
+ 'authSource',
+ 'w',
+ 'wtimeout',
+ 'j',
+ 'native_parser',
+ 'forceServerObjectId',
+ 'serializeFunctions',
+ 'raw',
+ 'promoteLongs',
+ 'promoteValues',
+ 'promoteBuffers',
+ 'bufferMaxEntries',
+ 'numberOfRetries',
+ 'retryMiliSeconds',
+ 'readPreference',
+ 'pkFactory',
+ 'parentDb',
+ 'promiseLibrary',
+ 'noListener'
+];
+
+/**
+ * Creates an index on the db and collection.
+ * @method
+ * @param {Db} db The Db instance on which to create an index.
+ * @param {string} name Name of the collection to create the index on.
+ * @param {(string|object)} fieldOrSpec Defines the index.
+ * @param {object} [options] Optional settings. See Db.prototype.createIndex for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback
+ */
+function createIndex(db, name, fieldOrSpec, options, callback) {
+ // Get the write concern options
+ let finalOptions = Object.assign({}, { readPreference: ReadPreference.PRIMARY }, options);
+ finalOptions = applyWriteConcern(finalOptions, { db }, options);
+
+ // Ensure we have a callback
+ if (finalOptions.writeConcern && typeof callback !== 'function') {
+ throw MongoError.create({
+ message: 'Cannot use a writeConcern without a provided callback',
+ driver: true
+ });
+ }
+
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed())
+ return callback(new MongoError('topology was destroyed'));
+
+ // Attempt to run using createIndexes command
+ createIndexUsingCreateIndexes(db, name, fieldOrSpec, finalOptions, (err, result) => {
+ if (err == null) return handleCallback(callback, err, result);
+
+ /**
+ * The following errors mean that the server recognized `createIndex` as a command so we don't need to fallback to an insert:
+ * 67 = 'CannotCreateIndex' (malformed index options)
+ * 85 = 'IndexOptionsConflict' (index already exists with different options)
+ * 86 = 'IndexKeySpecsConflict' (index already exists with the same name)
+ * 11000 = 'DuplicateKey' (couldn't build unique index because of dupes)
+ * 11600 = 'InterruptedAtShutdown' (interrupted at shutdown)
+ * 197 = 'InvalidIndexSpecificationOption' (`_id` with `background: true`)
+ */
+ if (
+ err.code === 67 ||
+ err.code === 11000 ||
+ err.code === 85 ||
+ err.code === 86 ||
+ err.code === 11600 ||
+ err.code === 197
+ ) {
+ return handleCallback(callback, err, result);
+ }
+
+ // Create command
+ const doc = createCreateIndexCommand(db, name, fieldOrSpec, options);
+ // Set no key checking
+ finalOptions.checkKeys = false;
+ // Insert document
+ db.s.topology.insert(
+ db.s.namespace.withCollection(CONSTANTS.SYSTEM_INDEX_COLLECTION),
+ doc,
+ finalOptions,
+ (err, result) => {
+ if (callback == null) return;
+ if (err) return handleCallback(callback, err);
+ if (result == null) return handleCallback(callback, null, null);
+ if (result.result.writeErrors)
+ return handleCallback(callback, MongoError.create(result.result.writeErrors[0]), null);
+ handleCallback(callback, null, doc.name);
+ }
+ );
+ });
+}
+
+// Add listeners to topology
+function createListener(db, e, object) {
+ function listener(err) {
+ if (object.listeners(e).length > 0) {
+ object.emit(e, err, db);
+
+ // Emit on all associated db's if available
+ for (let i = 0; i < db.s.children.length; i++) {
+ db.s.children[i].emit(e, err, db.s.children[i]);
+ }
+ }
+ }
+ return listener;
+}
+
+/**
+ * Ensures that an index exists. If it does not, creates it.
+ *
+ * @method
+ * @param {Db} db The Db instance on which to ensure the index.
+ * @param {string} name The index name
+ * @param {(string|object)} fieldOrSpec Defines the index.
+ * @param {object} [options] Optional settings. See Db.prototype.ensureIndex for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback
+ */
+function ensureIndex(db, name, fieldOrSpec, options, callback) {
+ // Get the write concern options
+ const finalOptions = applyWriteConcern({}, { db }, options);
+ // Create command
+ const selector = createCreateIndexCommand(db, name, fieldOrSpec, options);
+ const index_name = selector.name;
+
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed())
+ return callback(new MongoError('topology was destroyed'));
+
+ // Merge primary readPreference
+ finalOptions.readPreference = ReadPreference.PRIMARY;
+
+ // Check if the index already exists
+ indexInformation(db, name, finalOptions, (err, indexInformation) => {
+ if (err != null && err.code !== 26) return handleCallback(callback, err, null);
+ // If the index does not exist, create it
+ if (indexInformation == null || !indexInformation[index_name]) {
+ createIndex(db, name, fieldOrSpec, options, callback);
+ } else {
+ if (typeof callback === 'function') return handleCallback(callback, null, index_name);
+ }
+ });
+}
+
+/**
+ * Evaluate JavaScript on the server
+ *
+ * @method
+ * @param {Db} db The Db instance.
+ * @param {Code} code JavaScript to execute on server.
+ * @param {(object|array)} parameters The parameters for the call.
+ * @param {object} [options] Optional settings. See Db.prototype.eval for a list of options.
+ * @param {Db~resultCallback} [callback] The results callback
+ * @deprecated Eval is deprecated on MongoDB 3.2 and forward
+ */
+function evaluate(db, code, parameters, options, callback) {
+ let finalCode = code;
+ let finalParameters = [];
+
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed())
+ return callback(new MongoError('topology was destroyed'));
+
+ // If not a code object translate to one
+ if (!(finalCode && finalCode._bsontype === 'Code')) finalCode = new Code(finalCode);
+ // Ensure the parameters are correct
+ if (parameters != null && !Array.isArray(parameters) && typeof parameters !== 'function') {
+ finalParameters = [parameters];
+ } else if (parameters != null && Array.isArray(parameters) && typeof parameters !== 'function') {
+ finalParameters = parameters;
+ }
+
+ // Create execution selector
+ let cmd = { $eval: finalCode, args: finalParameters };
+ // Check if the nolock parameter is passed in
+ if (options['nolock']) {
+ cmd['nolock'] = options['nolock'];
+ }
+
+ // Set primary read preference
+ options.readPreference = new ReadPreference(ReadPreference.PRIMARY);
+
+ // Execute the command
+ executeCommand(db, cmd, options, (err, result) => {
+ if (err) return handleCallback(callback, err, null);
+ if (result && result.ok === 1) return handleCallback(callback, null, result.retval);
+ if (result)
+ return handleCallback(
+ callback,
+ MongoError.create({ message: `eval failed: ${result.errmsg}`, driver: true }),
+ null
+ );
+ handleCallback(callback, err, result);
+ });
+}
+
+/**
+ * Execute a command
+ *
+ * @method
+ * @param {Db} db The Db instance on which to execute the command.
+ * @param {object} command The command hash
+ * @param {object} [options] Optional settings. See Db.prototype.command for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback
+ */
+function executeCommand(db, command, options, callback) {
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed())
+ return callback(new MongoError('topology was destroyed'));
+ // Get the db name we are executing against
+ const dbName = options.dbName || options.authdb || db.databaseName;
+
+ // Convert the readPreference if its not a write
+ options.readPreference = ReadPreference.resolve(db, options);
+
+ // Debug information
+ if (db.s.logger.isDebug())
+ db.s.logger.debug(
+ `executing command ${JSON.stringify(
+ command
+ )} against ${dbName}.$cmd with options [${JSON.stringify(
+ debugOptions(debugFields, options)
+ )}]`
+ );
+
+ // Execute command
+ db.s.topology.command(db.s.namespace.withCollection('$cmd'), command, options, (err, result) => {
+ if (err) return handleCallback(callback, err);
+ if (options.full) return handleCallback(callback, null, result);
+ handleCallback(callback, null, result.result);
+ });
+}
+
+/**
+ * Runs a command on the database as admin.
+ *
+ * @method
+ * @param {Db} db The Db instance on which to execute the command.
+ * @param {object} command The command hash
+ * @param {object} [options] Optional settings. See Db.prototype.executeDbAdminCommand for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback
+ */
+function executeDbAdminCommand(db, command, options, callback) {
+ const namespace = new MongoDBNamespace('admin', '$cmd');
+
+ db.s.topology.command(namespace, command, options, (err, result) => {
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed()) {
+ return callback(new MongoError('topology was destroyed'));
+ }
+
+ if (err) return handleCallback(callback, err);
+ handleCallback(callback, null, result.result);
+ });
+}
+
+/**
+ * Retrieves this collections index info.
+ *
+ * @method
+ * @param {Db} db The Db instance on which to retrieve the index info.
+ * @param {string} name The name of the collection.
+ * @param {object} [options] Optional settings. See Db.prototype.indexInformation for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback
+ */
+function indexInformation(db, name, options, callback) {
+ // If we specified full information
+ const full = options['full'] == null ? false : options['full'];
+
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed())
+ return callback(new MongoError('topology was destroyed'));
+ // Process all the results from the index command and collection
+ function processResults(indexes) {
+ // Contains all the information
+ let info = {};
+ // Process all the indexes
+ for (let i = 0; i < indexes.length; i++) {
+ const index = indexes[i];
+ // Let's unpack the object
+ info[index.name] = [];
+ for (let name in index.key) {
+ info[index.name].push([name, index.key[name]]);
+ }
+ }
+
+ return info;
+ }
+
+ // Get the list of indexes of the specified collection
+ db.collection(name)
+ .listIndexes(options)
+ .toArray((err, indexes) => {
+ if (err) return callback(toError(err));
+ if (!Array.isArray(indexes)) return handleCallback(callback, null, []);
+ if (full) return handleCallback(callback, null, indexes);
+ handleCallback(callback, null, processResults(indexes));
+ });
+}
+
+/**
+ * Retrieve the current profiling information for MongoDB
+ *
+ * @method
+ * @param {Db} db The Db instance on which to retrieve the profiling info.
+ * @param {Object} [options] Optional settings. See Db.protoype.profilingInfo for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback.
+ * @deprecated Query the system.profile collection directly.
+ */
+function profilingInfo(db, options, callback) {
+ try {
+ db.collection('system.profile')
+ .find({}, options)
+ .toArray(callback);
+ } catch (err) {
+ return callback(err, null);
+ }
+}
+
+// Validate the database name
+function validateDatabaseName(databaseName) {
+ if (typeof databaseName !== 'string')
+ throw MongoError.create({ message: 'database name must be a string', driver: true });
+ if (databaseName.length === 0)
+ throw MongoError.create({ message: 'database name cannot be the empty string', driver: true });
+ if (databaseName === '$external') return;
+
+ const invalidChars = [' ', '.', '$', '/', '\\'];
+ for (let i = 0; i < invalidChars.length; i++) {
+ if (databaseName.indexOf(invalidChars[i]) !== -1)
+ throw MongoError.create({
+ message: "database names cannot contain the character '" + invalidChars[i] + "'",
+ driver: true
+ });
+ }
+}
+
+/**
+ * Create the command object for Db.prototype.createIndex.
+ *
+ * @param {Db} db The Db instance on which to create the command.
+ * @param {string} name Name of the collection to create the index on.
+ * @param {(string|object)} fieldOrSpec Defines the index.
+ * @param {Object} [options] Optional settings. See Db.prototype.createIndex for a list of options.
+ * @return {Object} The insert command object.
+ */
+function createCreateIndexCommand(db, name, fieldOrSpec, options) {
+ const indexParameters = parseIndexOptions(fieldOrSpec);
+ const fieldHash = indexParameters.fieldHash;
+
+ // Generate the index name
+ const indexName = typeof options.name === 'string' ? options.name : indexParameters.name;
+ const selector = {
+ ns: db.s.namespace.withCollection(name).toString(),
+ key: fieldHash,
+ name: indexName
+ };
+
+ // Ensure we have a correct finalUnique
+ const finalUnique = options == null || 'object' === typeof options ? false : options;
+ // Set up options
+ options = options == null || typeof options === 'boolean' ? {} : options;
+
+ // Add all the options
+ const keysToOmit = Object.keys(selector);
+ for (let optionName in options) {
+ if (keysToOmit.indexOf(optionName) === -1) {
+ selector[optionName] = options[optionName];
+ }
+ }
+
+ if (selector['unique'] == null) selector['unique'] = finalUnique;
+
+ // Remove any write concern operations
+ const removeKeys = ['w', 'wtimeout', 'j', 'fsync', 'readPreference', 'session'];
+ for (let i = 0; i < removeKeys.length; i++) {
+ delete selector[removeKeys[i]];
+ }
+
+ // Return the command creation selector
+ return selector;
+}
+
+/**
+ * Create index using the createIndexes command.
+ *
+ * @param {Db} db The Db instance on which to execute the command.
+ * @param {string} name Name of the collection to create the index on.
+ * @param {(string|object)} fieldOrSpec Defines the index.
+ * @param {Object} [options] Optional settings. See Db.prototype.createIndex for a list of options.
+ * @param {Db~resultCallback} [callback] The command result callback.
+ */
+function createIndexUsingCreateIndexes(db, name, fieldOrSpec, options, callback) {
+ // Build the index
+ const indexParameters = parseIndexOptions(fieldOrSpec);
+ // Generate the index name
+ const indexName = typeof options.name === 'string' ? options.name : indexParameters.name;
+ // Set up the index
+ const indexes = [{ name: indexName, key: indexParameters.fieldHash }];
+ // merge all the options
+ const keysToOmit = Object.keys(indexes[0]).concat([
+ 'writeConcern',
+ 'w',
+ 'wtimeout',
+ 'j',
+ 'fsync',
+ 'readPreference',
+ 'session'
+ ]);
+
+ for (let optionName in options) {
+ if (keysToOmit.indexOf(optionName) === -1) {
+ indexes[0][optionName] = options[optionName];
+ }
+ }
+
+ // Get capabilities
+ const capabilities = db.s.topology.capabilities();
+
+ // Did the user pass in a collation, check if our write server supports it
+ if (indexes[0].collation && capabilities && !capabilities.commandsTakeCollation) {
+ // Create a new error
+ const error = new MongoError('server/primary/mongos does not support collation');
+ error.code = 67;
+ // Return the error
+ return callback(error);
+ }
+
+ // Create command, apply write concern to command
+ const cmd = applyWriteConcern({ createIndexes: name, indexes }, { db }, options);
+
+ // ReadPreference primary
+ options.readPreference = ReadPreference.PRIMARY;
+
+ // Build the command
+ executeCommand(db, cmd, options, (err, result) => {
+ if (err) return handleCallback(callback, err, null);
+ if (result.ok === 0) return handleCallback(callback, toError(result), null);
+ // Return the indexName for backward compatibility
+ handleCallback(callback, null, indexName);
+ });
+}
+
+module.exports = {
+ createListener,
+ createIndex,
+ ensureIndex,
+ evaluate,
+ executeCommand,
+ executeDbAdminCommand,
+ indexInformation,
+ profilingInfo,
+ validateDatabaseName
+};
diff --git a/node_modules/mongodb/lib/operations/delete_many.js b/node_modules/mongodb/lib/operations/delete_many.js
new file mode 100644
index 0000000..d881f67
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/delete_many.js
@@ -0,0 +1,25 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const deleteCallback = require('./common_functions').deleteCallback;
+const removeDocuments = require('./common_functions').removeDocuments;
+
+class DeleteManyOperation extends OperationBase {
+ constructor(collection, filter, options) {
+ super(options);
+
+ this.collection = collection;
+ this.filter = filter;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const filter = this.filter;
+ const options = this.options;
+
+ options.single = false;
+ removeDocuments(coll, filter, options, (err, r) => deleteCallback(err, r, callback));
+ }
+}
+
+module.exports = DeleteManyOperation;
diff --git a/node_modules/mongodb/lib/operations/delete_one.js b/node_modules/mongodb/lib/operations/delete_one.js
new file mode 100644
index 0000000..b05597f
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/delete_one.js
@@ -0,0 +1,25 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const deleteCallback = require('./common_functions').deleteCallback;
+const removeDocuments = require('./common_functions').removeDocuments;
+
+class DeleteOneOperation extends OperationBase {
+ constructor(collection, filter, options) {
+ super(options);
+
+ this.collection = collection;
+ this.filter = filter;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const filter = this.filter;
+ const options = this.options;
+
+ options.single = true;
+ removeDocuments(coll, filter, options, (err, r) => deleteCallback(err, r, callback));
+ }
+}
+
+module.exports = DeleteOneOperation;
diff --git a/node_modules/mongodb/lib/operations/distinct.js b/node_modules/mongodb/lib/operations/distinct.js
new file mode 100644
index 0000000..dcf4f7e
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/distinct.js
@@ -0,0 +1,85 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const CommandOperationV2 = require('./command_v2');
+const decorateWithCollation = require('../utils').decorateWithCollation;
+const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
+
+/**
+ * Return a list of distinct values for the given key across a collection.
+ *
+ * @class
+ * @property {Collection} a Collection instance.
+ * @property {string} key Field of the document to find distinct values for.
+ * @property {object} query The query for filtering the set of documents to which we apply the distinct filter.
+ * @property {object} [options] Optional settings. See Collection.prototype.distinct for a list of options.
+ */
+class DistinctOperation extends CommandOperationV2 {
+ /**
+ * Construct a Distinct operation.
+ *
+ * @param {Collection} a Collection instance.
+ * @param {string} key Field of the document to find distinct values for.
+ * @param {object} query The query for filtering the set of documents to which we apply the distinct filter.
+ * @param {object} [options] Optional settings. See Collection.prototype.distinct for a list of options.
+ */
+ constructor(collection, key, query, options) {
+ super(collection, options);
+
+ this.collection = collection;
+ this.key = key;
+ this.query = query;
+ }
+
+ /**
+ * Execute the operation.
+ *
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+ execute(server, callback) {
+ const coll = this.collection;
+ const key = this.key;
+ const query = this.query;
+ const options = this.options;
+
+ // Distinct command
+ const cmd = {
+ distinct: coll.collectionName,
+ key: key,
+ query: query
+ };
+
+ // Add maxTimeMS if defined
+ if (typeof options.maxTimeMS === 'number') {
+ cmd.maxTimeMS = options.maxTimeMS;
+ }
+
+ // Do we have a readConcern specified
+ decorateWithReadConcern(cmd, coll, options);
+
+ // Have we specified collation
+ try {
+ decorateWithCollation(cmd, coll, options);
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ super.executeCommand(server, cmd, (err, result) => {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ callback(null, this.options.full ? result : result.values);
+ });
+ }
+}
+
+defineAspects(DistinctOperation, [
+ Aspect.READ_OPERATION,
+ Aspect.RETRYABLE,
+ Aspect.EXECUTE_WITH_SELECTION
+]);
+
+module.exports = DistinctOperation;
diff --git a/node_modules/mongodb/lib/operations/drop.js b/node_modules/mongodb/lib/operations/drop.js
new file mode 100644
index 0000000..be03716
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/drop.js
@@ -0,0 +1,53 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const CommandOperation = require('./command');
+const defineAspects = require('./operation').defineAspects;
+const handleCallback = require('../utils').handleCallback;
+
+class DropOperation extends CommandOperation {
+ constructor(db, options) {
+ const finalOptions = Object.assign({}, options, db.s.options);
+
+ if (options.session) {
+ finalOptions.session = options.session;
+ }
+
+ super(db, finalOptions);
+ }
+
+ execute(callback) {
+ super.execute((err, result) => {
+ if (err) return handleCallback(callback, err);
+ if (result.ok) return handleCallback(callback, null, true);
+ handleCallback(callback, null, false);
+ });
+ }
+}
+
+defineAspects(DropOperation, Aspect.WRITE_OPERATION);
+
+class DropCollectionOperation extends DropOperation {
+ constructor(db, name, options) {
+ super(db, options);
+
+ this.name = name;
+ this.namespace = `${db.namespace}.${name}`;
+ }
+
+ _buildCommand() {
+ return { drop: this.name };
+ }
+}
+
+class DropDatabaseOperation extends DropOperation {
+ _buildCommand() {
+ return { dropDatabase: 1 };
+ }
+}
+
+module.exports = {
+ DropOperation,
+ DropCollectionOperation,
+ DropDatabaseOperation
+};
diff --git a/node_modules/mongodb/lib/operations/drop_index.js b/node_modules/mongodb/lib/operations/drop_index.js
new file mode 100644
index 0000000..a6ca783
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/drop_index.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const CommandOperation = require('./command');
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const handleCallback = require('../utils').handleCallback;
+
+class DropIndexOperation extends CommandOperation {
+ constructor(collection, indexName, options) {
+ super(collection.s.db, options, collection);
+
+ this.collection = collection;
+ this.indexName = indexName;
+ }
+
+ _buildCommand() {
+ const collection = this.collection;
+ const indexName = this.indexName;
+ const options = this.options;
+
+ let cmd = { dropIndexes: collection.collectionName, index: indexName };
+
+ // Decorate command with writeConcern if supported
+ cmd = applyWriteConcern(cmd, { db: collection.s.db, collection }, options);
+
+ return cmd;
+ }
+
+ execute(callback) {
+ // Execute command
+ super.execute((err, result) => {
+ if (typeof callback !== 'function') return;
+ if (err) return handleCallback(callback, err, null);
+ handleCallback(callback, null, result);
+ });
+ }
+}
+
+defineAspects(DropIndexOperation, Aspect.WRITE_OPERATION);
+
+module.exports = DropIndexOperation;
diff --git a/node_modules/mongodb/lib/operations/drop_indexes.js b/node_modules/mongodb/lib/operations/drop_indexes.js
new file mode 100644
index 0000000..ed404ee
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/drop_indexes.js
@@ -0,0 +1,23 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const DropIndexOperation = require('./drop_index');
+const handleCallback = require('../utils').handleCallback;
+
+class DropIndexesOperation extends DropIndexOperation {
+ constructor(collection, options) {
+ super(collection, '*', options);
+ }
+
+ execute(callback) {
+ super.execute(err => {
+ if (err) return handleCallback(callback, err, false);
+ handleCallback(callback, null, true);
+ });
+ }
+}
+
+defineAspects(DropIndexesOperation, Aspect.WRITE_OPERATION);
+
+module.exports = DropIndexesOperation;
diff --git a/node_modules/mongodb/lib/operations/estimated_document_count.js b/node_modules/mongodb/lib/operations/estimated_document_count.js
new file mode 100644
index 0000000..e2d6556
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/estimated_document_count.js
@@ -0,0 +1,58 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const CommandOperationV2 = require('./command_v2');
+
+class EstimatedDocumentCountOperation extends CommandOperationV2 {
+ constructor(collection, query, options) {
+ if (typeof options === 'undefined') {
+ options = query;
+ query = undefined;
+ }
+
+ super(collection, options);
+ this.collectionName = collection.s.namespace.collection;
+ if (query) {
+ this.query = query;
+ }
+ }
+
+ execute(server, callback) {
+ const options = this.options;
+ const cmd = { count: this.collectionName };
+
+ if (this.query) {
+ cmd.query = this.query;
+ }
+
+ if (typeof options.skip === 'number') {
+ cmd.skip = options.skip;
+ }
+
+ if (typeof options.limit === 'number') {
+ cmd.limit = options.limit;
+ }
+
+ if (options.hint) {
+ cmd.hint = options.hint;
+ }
+
+ super.executeCommand(server, cmd, (err, response) => {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ callback(null, response.n);
+ });
+ }
+}
+
+defineAspects(EstimatedDocumentCountOperation, [
+ Aspect.READ_OPERATION,
+ Aspect.RETRYABLE,
+ Aspect.EXECUTE_WITH_SELECTION
+]);
+
+module.exports = EstimatedDocumentCountOperation;
diff --git a/node_modules/mongodb/lib/operations/execute_db_admin_command.js b/node_modules/mongodb/lib/operations/execute_db_admin_command.js
new file mode 100644
index 0000000..d15fc8e
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/execute_db_admin_command.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const handleCallback = require('../utils').handleCallback;
+const MongoError = require('../core').MongoError;
+const MongoDBNamespace = require('../utils').MongoDBNamespace;
+
+class ExecuteDbAdminCommandOperation extends OperationBase {
+ constructor(db, selector, options) {
+ super(options);
+
+ this.db = db;
+ this.selector = selector;
+ }
+
+ execute(callback) {
+ const db = this.db;
+ const selector = this.selector;
+ const options = this.options;
+
+ const namespace = new MongoDBNamespace('admin', '$cmd');
+ db.s.topology.command(namespace, selector, options, (err, result) => {
+ // Did the user destroy the topology
+ if (db.serverConfig && db.serverConfig.isDestroyed()) {
+ return callback(new MongoError('topology was destroyed'));
+ }
+
+ if (err) return handleCallback(callback, err);
+ handleCallback(callback, null, result.result);
+ });
+ }
+}
+
+module.exports = ExecuteDbAdminCommandOperation;
diff --git a/node_modules/mongodb/lib/operations/execute_operation.js b/node_modules/mongodb/lib/operations/execute_operation.js
new file mode 100644
index 0000000..80d5785
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/execute_operation.js
@@ -0,0 +1,186 @@
+'use strict';
+
+const MongoError = require('../core/error').MongoError;
+const Aspect = require('./operation').Aspect;
+const OperationBase = require('./operation').OperationBase;
+const ReadPreference = require('../core/topologies/read_preference');
+const isRetryableError = require('../core/error').isRetryableError;
+const maxWireVersion = require('../core/utils').maxWireVersion;
+const isUnifiedTopology = require('../core/utils').isUnifiedTopology;
+
+/**
+ * Executes the given operation with provided arguments.
+ *
+ * This method reduces large amounts of duplication in the entire codebase by providing
+ * a single point for determining whether callbacks or promises should be used. Additionally
+ * it allows for a single point of entry to provide features such as implicit sessions, which
+ * are required by the Driver Sessions specification in the event that a ClientSession is
+ * not provided
+ *
+ * @param {object} topology The topology to execute this operation on
+ * @param {Operation} operation The operation to execute
+ * @param {function} callback The command result callback
+ */
+function executeOperation(topology, operation, callback) {
+ if (topology == null) {
+ throw new TypeError('This method requires a valid topology instance');
+ }
+
+ if (!(operation instanceof OperationBase)) {
+ throw new TypeError('This method requires a valid operation instance');
+ }
+
+ if (isUnifiedTopology(topology) && topology.shouldCheckForSessionSupport()) {
+ return selectServerForSessionSupport(topology, operation, callback);
+ }
+
+ const Promise = topology.s.promiseLibrary;
+
+ // The driver sessions spec mandates that we implicitly create sessions for operations
+ // that are not explicitly provided with a session.
+ let session, owner;
+ if (topology.hasSessionSupport()) {
+ if (operation.session == null) {
+ owner = Symbol();
+ session = topology.startSession({ owner });
+ operation.session = session;
+ } else if (operation.session.hasEnded) {
+ throw new MongoError('Use of expired sessions is not permitted');
+ }
+ }
+
+ let result;
+ if (typeof callback !== 'function') {
+ result = new Promise((resolve, reject) => {
+ callback = (err, res) => {
+ if (err) return reject(err);
+ resolve(res);
+ };
+ });
+ }
+
+ function executeCallback(err, result) {
+ if (session && session.owner === owner) {
+ session.endSession();
+ if (operation.session === session) {
+ operation.clearSession();
+ }
+ }
+
+ callback(err, result);
+ }
+
+ try {
+ if (operation.hasAspect(Aspect.EXECUTE_WITH_SELECTION)) {
+ executeWithServerSelection(topology, operation, executeCallback);
+ } else {
+ operation.execute(executeCallback);
+ }
+ } catch (e) {
+ if (session && session.owner === owner) {
+ session.endSession();
+ if (operation.session === session) {
+ operation.clearSession();
+ }
+ }
+
+ throw e;
+ }
+
+ return result;
+}
+
+function supportsRetryableReads(server) {
+ return maxWireVersion(server) >= 6;
+}
+
+function executeWithServerSelection(topology, operation, callback) {
+ const readPreference = operation.readPreference || ReadPreference.primary;
+ const inTransaction = operation.session && operation.session.inTransaction();
+
+ if (inTransaction && !readPreference.equals(ReadPreference.primary)) {
+ callback(
+ new MongoError(
+ `Read preference in a transaction must be primary, not: ${readPreference.mode}`
+ )
+ );
+
+ return;
+ }
+
+ const serverSelectionOptions = {
+ readPreference,
+ session: operation.session
+ };
+
+ function callbackWithRetry(err, result) {
+ if (err == null) {
+ return callback(null, result);
+ }
+
+ if (!isRetryableError(err)) {
+ return callback(err);
+ }
+
+ // select a new server, and attempt to retry the operation
+ topology.selectServer(serverSelectionOptions, (err, server) => {
+ if (err || !supportsRetryableReads(server)) {
+ callback(err, null);
+ return;
+ }
+
+ operation.execute(server, callback);
+ });
+ }
+
+ // select a server, and execute the operation against it
+ topology.selectServer(serverSelectionOptions, (err, server) => {
+ if (err) {
+ callback(err, null);
+ return;
+ }
+
+ const shouldRetryReads =
+ topology.s.options.retryReads !== false &&
+ operation.session &&
+ !inTransaction &&
+ supportsRetryableReads(server) &&
+ operation.canRetryRead;
+
+ if (operation.hasAspect(Aspect.RETRYABLE) && shouldRetryReads) {
+ operation.execute(server, callbackWithRetry);
+ return;
+ }
+
+ operation.execute(server, callback);
+ });
+}
+
+// TODO: This is only supported for unified topology, it should go away once
+// we remove support for legacy topology types.
+function selectServerForSessionSupport(topology, operation, callback) {
+ const Promise = topology.s.promiseLibrary;
+
+ let result;
+ if (typeof callback !== 'function') {
+ result = new Promise((resolve, reject) => {
+ callback = (err, result) => {
+ if (err) return reject(err);
+ resolve(result);
+ };
+ });
+ }
+
+ topology.selectServer(ReadPreference.primaryPreferred, err => {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ executeOperation(topology, operation, callback);
+ });
+
+ return result;
+}
+
+module.exports = executeOperation;
diff --git a/node_modules/mongodb/lib/operations/find.js b/node_modules/mongodb/lib/operations/find.js
new file mode 100644
index 0000000..09cb9a9
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/find.js
@@ -0,0 +1,40 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const ReadPreference = require('../core').ReadPreference;
+const maxWireVersion = require('../core/utils').maxWireVersion;
+const MongoError = require('../core/error').MongoError;
+
+class FindOperation extends OperationBase {
+ constructor(collection, ns, command, options) {
+ super(options);
+
+ this.ns = ns;
+ this.cmd = command;
+ this.readPreference = ReadPreference.resolve(collection, this.options);
+ }
+
+ execute(server, callback) {
+ // copied from `CommandOperationV2`, to be subclassed in the future
+ this.server = server;
+
+ if (typeof this.cmd.allowDiskUse !== 'undefined' && maxWireVersion(server) < 4) {
+ callback(new MongoError('The `allowDiskUse` option is not supported on MongoDB < 3.2'));
+ return;
+ }
+
+ // TOOD: use `MongoDBNamespace` through and through
+ const cursorState = this.cursorState || {};
+ server.query(this.ns.toString(), this.cmd, cursorState, this.options, callback);
+ }
+}
+
+defineAspects(FindOperation, [
+ Aspect.READ_OPERATION,
+ Aspect.RETRYABLE,
+ Aspect.EXECUTE_WITH_SELECTION
+]);
+
+module.exports = FindOperation;
diff --git a/node_modules/mongodb/lib/operations/find_and_modify.js b/node_modules/mongodb/lib/operations/find_and_modify.js
new file mode 100644
index 0000000..03711ee
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/find_and_modify.js
@@ -0,0 +1,115 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const applyRetryableWrites = require('../utils').applyRetryableWrites;
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const decorateWithCollation = require('../utils').decorateWithCollation;
+const executeCommand = require('./db_ops').executeCommand;
+const formattedOrderClause = require('../utils').formattedOrderClause;
+const handleCallback = require('../utils').handleCallback;
+const ReadPreference = require('../core').ReadPreference;
+const maxWireVersion = require('../core/utils').maxWireVersion;
+const MongoError = require('../error').MongoError;
+
+class FindAndModifyOperation extends OperationBase {
+ constructor(collection, query, sort, doc, options) {
+ super(options);
+
+ this.collection = collection;
+ this.query = query;
+ this.sort = sort;
+ this.doc = doc;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const query = this.query;
+ const sort = formattedOrderClause(this.sort);
+ const doc = this.doc;
+ let options = this.options;
+
+ // Create findAndModify command object
+ const queryObject = {
+ findAndModify: coll.collectionName,
+ query: query
+ };
+
+ if (sort) {
+ queryObject.sort = sort;
+ }
+
+ queryObject.new = options.new ? true : false;
+ queryObject.remove = options.remove ? true : false;
+ queryObject.upsert = options.upsert ? true : false;
+
+ const projection = options.projection || options.fields;
+
+ if (projection) {
+ queryObject.fields = projection;
+ }
+
+ if (options.arrayFilters) {
+ queryObject.arrayFilters = options.arrayFilters;
+ }
+
+ if (doc && !options.remove) {
+ queryObject.update = doc;
+ }
+
+ if (options.maxTimeMS) queryObject.maxTimeMS = options.maxTimeMS;
+
+ // Either use override on the function, or go back to default on either the collection
+ // level or db
+ options.serializeFunctions = options.serializeFunctions || coll.s.serializeFunctions;
+
+ // No check on the documents
+ options.checkKeys = false;
+
+ // Final options for retryable writes and write concern
+ options = applyRetryableWrites(options, coll.s.db);
+ options = applyWriteConcern(options, { db: coll.s.db, collection: coll }, options);
+
+ // Decorate the findAndModify command with the write Concern
+ if (options.writeConcern) {
+ queryObject.writeConcern = options.writeConcern;
+ }
+
+ // Have we specified bypassDocumentValidation
+ if (options.bypassDocumentValidation === true) {
+ queryObject.bypassDocumentValidation = options.bypassDocumentValidation;
+ }
+
+ options.readPreference = ReadPreference.primary;
+
+ // Have we specified collation
+ try {
+ decorateWithCollation(queryObject, coll, options);
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ if (options.hint) {
+ // TODO: once this method becomes a CommandOperationV2 we will have the server
+ // in place to check.
+ const unacknowledgedWrite = options.writeConcern && options.writeConcern.w === 0;
+ if (unacknowledgedWrite || maxWireVersion(coll.s.topology) < 8) {
+ callback(
+ new MongoError('The current topology does not support a hint on findAndModify commands')
+ );
+
+ return;
+ }
+
+ queryObject.hint = options.hint;
+ }
+
+ // Execute the command
+ executeCommand(coll.s.db, queryObject, options, (err, result) => {
+ if (err) return handleCallback(callback, err, null);
+
+ return handleCallback(callback, null, result);
+ });
+ }
+}
+
+module.exports = FindAndModifyOperation;
diff --git a/node_modules/mongodb/lib/operations/find_one.js b/node_modules/mongodb/lib/operations/find_one.js
new file mode 100644
index 0000000..b584db6
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/find_one.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const handleCallback = require('../utils').handleCallback;
+const OperationBase = require('./operation').OperationBase;
+const toError = require('../utils').toError;
+
+class FindOneOperation extends OperationBase {
+ constructor(collection, query, options) {
+ super(options);
+
+ this.collection = collection;
+ this.query = query;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const query = this.query;
+ const options = this.options;
+
+ try {
+ const cursor = coll
+ .find(query, options)
+ .limit(-1)
+ .batchSize(1);
+
+ // Return the item
+ cursor.next((err, item) => {
+ if (err != null) return handleCallback(callback, toError(err), null);
+ handleCallback(callback, null, item);
+ });
+ } catch (e) {
+ callback(e);
+ }
+ }
+}
+
+module.exports = FindOneOperation;
diff --git a/node_modules/mongodb/lib/operations/find_one_and_delete.js b/node_modules/mongodb/lib/operations/find_one_and_delete.js
new file mode 100644
index 0000000..eaf3287
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/find_one_and_delete.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const FindAndModifyOperation = require('./find_and_modify');
+
+class FindOneAndDeleteOperation extends FindAndModifyOperation {
+ constructor(collection, filter, options) {
+ // Final options
+ const finalOptions = Object.assign({}, options);
+ finalOptions.fields = options.projection;
+ finalOptions.remove = true;
+
+ // Basic validation
+ if (filter == null || typeof filter !== 'object') {
+ throw new TypeError('Filter parameter must be an object');
+ }
+
+ super(collection, filter, finalOptions.sort, null, finalOptions);
+ }
+}
+
+module.exports = FindOneAndDeleteOperation;
diff --git a/node_modules/mongodb/lib/operations/find_one_and_replace.js b/node_modules/mongodb/lib/operations/find_one_and_replace.js
new file mode 100644
index 0000000..f068cdf
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/find_one_and_replace.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const FindAndModifyOperation = require('./find_and_modify');
+const hasAtomicOperators = require('../utils').hasAtomicOperators;
+
+class FindOneAndReplaceOperation extends FindAndModifyOperation {
+ constructor(collection, filter, replacement, options) {
+ // Final options
+ const finalOptions = Object.assign({}, options);
+ finalOptions.fields = options.projection;
+ finalOptions.update = true;
+ finalOptions.new = options.returnOriginal !== void 0 ? !options.returnOriginal : false;
+ finalOptions.upsert = options.upsert !== void 0 ? !!options.upsert : false;
+
+ if (filter == null || typeof filter !== 'object') {
+ throw new TypeError('Filter parameter must be an object');
+ }
+
+ if (replacement == null || typeof replacement !== 'object') {
+ throw new TypeError('Replacement parameter must be an object');
+ }
+
+ if (hasAtomicOperators(replacement)) {
+ throw new TypeError('Replacement document must not contain atomic operators');
+ }
+
+ super(collection, filter, finalOptions.sort, replacement, finalOptions);
+ }
+}
+
+module.exports = FindOneAndReplaceOperation;
diff --git a/node_modules/mongodb/lib/operations/find_one_and_update.js b/node_modules/mongodb/lib/operations/find_one_and_update.js
new file mode 100644
index 0000000..5ec8be5
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/find_one_and_update.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const FindAndModifyOperation = require('./find_and_modify');
+const hasAtomicOperators = require('../utils').hasAtomicOperators;
+
+class FindOneAndUpdateOperation extends FindAndModifyOperation {
+ constructor(collection, filter, update, options) {
+ // Final options
+ const finalOptions = Object.assign({}, options);
+ finalOptions.fields = options.projection;
+ finalOptions.update = true;
+ finalOptions.new =
+ typeof options.returnOriginal === 'boolean' ? !options.returnOriginal : false;
+ finalOptions.upsert = typeof options.upsert === 'boolean' ? options.upsert : false;
+
+ if (filter == null || typeof filter !== 'object') {
+ throw new TypeError('Filter parameter must be an object');
+ }
+
+ if (update == null || typeof update !== 'object') {
+ throw new TypeError('Update parameter must be an object');
+ }
+
+ if (!hasAtomicOperators(update)) {
+ throw new TypeError('Update document requires atomic operators');
+ }
+
+ super(collection, filter, finalOptions.sort, update, finalOptions);
+ }
+}
+
+module.exports = FindOneAndUpdateOperation;
diff --git a/node_modules/mongodb/lib/operations/geo_haystack_search.js b/node_modules/mongodb/lib/operations/geo_haystack_search.js
new file mode 100644
index 0000000..7c8654d
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/geo_haystack_search.js
@@ -0,0 +1,79 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const OperationBase = require('./operation').OperationBase;
+const decorateCommand = require('../utils').decorateCommand;
+const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
+const executeCommand = require('./db_ops').executeCommand;
+const handleCallback = require('../utils').handleCallback;
+const ReadPreference = require('../core').ReadPreference;
+const toError = require('../utils').toError;
+
+/**
+ * Execute a geo search using a geo haystack index on a collection.
+ *
+ * @class
+ * @property {Collection} a Collection instance.
+ * @property {number} x Point to search on the x axis, ensure the indexes are ordered in the same order.
+ * @property {number} y Point to search on the y axis, ensure the indexes are ordered in the same order.
+ * @property {object} [options] Optional settings. See Collection.prototype.geoHaystackSearch for a list of options.
+ */
+class GeoHaystackSearchOperation extends OperationBase {
+ /**
+ * Construct a GeoHaystackSearch operation.
+ *
+ * @param {Collection} a Collection instance.
+ * @param {number} x Point to search on the x axis, ensure the indexes are ordered in the same order.
+ * @param {number} y Point to search on the y axis, ensure the indexes are ordered in the same order.
+ * @param {object} [options] Optional settings. See Collection.prototype.geoHaystackSearch for a list of options.
+ */
+ constructor(collection, x, y, options) {
+ super(options);
+
+ this.collection = collection;
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Execute the operation.
+ *
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+ execute(callback) {
+ const coll = this.collection;
+ const x = this.x;
+ const y = this.y;
+ let options = this.options;
+
+ // Build command object
+ let commandObject = {
+ geoSearch: coll.collectionName,
+ near: [x, y]
+ };
+
+ // Remove read preference from hash if it exists
+ commandObject = decorateCommand(commandObject, options, ['readPreference', 'session']);
+
+ options = Object.assign({}, options);
+ // Ensure we have the right read preference inheritance
+ options.readPreference = ReadPreference.resolve(coll, options);
+
+ // Do we have a readConcern specified
+ decorateWithReadConcern(commandObject, coll, options);
+
+ // Execute the command
+ executeCommand(coll.s.db, commandObject, options, (err, res) => {
+ if (err) return handleCallback(callback, err);
+ if (res.err || res.errmsg) handleCallback(callback, toError(res));
+ // should we only be returning res.results here? Not sure if the user
+ // should see the other return information
+ handleCallback(callback, null, res);
+ });
+ }
+}
+
+defineAspects(GeoHaystackSearchOperation, Aspect.READ_OPERATION);
+
+module.exports = GeoHaystackSearchOperation;
diff --git a/node_modules/mongodb/lib/operations/index_exists.js b/node_modules/mongodb/lib/operations/index_exists.js
new file mode 100644
index 0000000..bd9dc0e
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/index_exists.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const handleCallback = require('../utils').handleCallback;
+const indexInformationDb = require('./db_ops').indexInformation;
+
+class IndexExistsOperation extends OperationBase {
+ constructor(collection, indexes, options) {
+ super(options);
+
+ this.collection = collection;
+ this.indexes = indexes;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const indexes = this.indexes;
+ const options = this.options;
+
+ indexInformationDb(coll.s.db, coll.collectionName, options, (err, indexInformation) => {
+ // If we have an error return
+ if (err != null) return handleCallback(callback, err, null);
+ // Let's check for the index names
+ if (!Array.isArray(indexes))
+ return handleCallback(callback, null, indexInformation[indexes] != null);
+ // Check in list of indexes
+ for (let i = 0; i < indexes.length; i++) {
+ if (indexInformation[indexes[i]] == null) {
+ return handleCallback(callback, null, false);
+ }
+ }
+
+ // All keys found return true
+ return handleCallback(callback, null, true);
+ });
+ }
+}
+
+module.exports = IndexExistsOperation;
diff --git a/node_modules/mongodb/lib/operations/index_information.js b/node_modules/mongodb/lib/operations/index_information.js
new file mode 100644
index 0000000..b18a603
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/index_information.js
@@ -0,0 +1,23 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const indexInformation = require('./common_functions').indexInformation;
+
+class IndexInformationOperation extends OperationBase {
+ constructor(db, name, options) {
+ super(options);
+
+ this.db = db;
+ this.name = name;
+ }
+
+ execute(callback) {
+ const db = this.db;
+ const name = this.name;
+ const options = this.options;
+
+ indexInformation(db, name, options, callback);
+ }
+}
+
+module.exports = IndexInformationOperation;
diff --git a/node_modules/mongodb/lib/operations/indexes.js b/node_modules/mongodb/lib/operations/indexes.js
new file mode 100644
index 0000000..e29a88a
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/indexes.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const indexInformation = require('./common_functions').indexInformation;
+
+class IndexesOperation extends OperationBase {
+ constructor(collection, options) {
+ super(options);
+
+ this.collection = collection;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ let options = this.options;
+
+ options = Object.assign({}, { full: true }, options);
+ indexInformation(coll.s.db, coll.collectionName, options, callback);
+ }
+}
+
+module.exports = IndexesOperation;
diff --git a/node_modules/mongodb/lib/operations/insert_many.js b/node_modules/mongodb/lib/operations/insert_many.js
new file mode 100644
index 0000000..460a535
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/insert_many.js
@@ -0,0 +1,63 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const BulkWriteOperation = require('./bulk_write');
+const MongoError = require('../core').MongoError;
+const prepareDocs = require('./common_functions').prepareDocs;
+
+class InsertManyOperation extends OperationBase {
+ constructor(collection, docs, options) {
+ super(options);
+
+ this.collection = collection;
+ this.docs = docs;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ let docs = this.docs;
+ const options = this.options;
+
+ if (!Array.isArray(docs)) {
+ return callback(
+ MongoError.create({ message: 'docs parameter must be an array of documents', driver: true })
+ );
+ }
+
+ // If keep going set unordered
+ options['serializeFunctions'] = options['serializeFunctions'] || coll.s.serializeFunctions;
+
+ docs = prepareDocs(coll, docs, options);
+
+ // Generate the bulk write operations
+ const operations = [
+ {
+ insertMany: docs
+ }
+ ];
+
+ const bulkWriteOperation = new BulkWriteOperation(coll, operations, options);
+
+ bulkWriteOperation.execute((err, result) => {
+ if (err) return callback(err, null);
+ callback(null, mapInsertManyResults(docs, result));
+ });
+ }
+}
+
+function mapInsertManyResults(docs, r) {
+ const finalResult = {
+ result: { ok: 1, n: r.insertedCount },
+ ops: docs,
+ insertedCount: r.insertedCount,
+ insertedIds: r.insertedIds
+ };
+
+ if (r.getLastOp()) {
+ finalResult.result.opTime = r.getLastOp();
+ }
+
+ return finalResult;
+}
+
+module.exports = InsertManyOperation;
diff --git a/node_modules/mongodb/lib/operations/insert_one.js b/node_modules/mongodb/lib/operations/insert_one.js
new file mode 100644
index 0000000..5e70880
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/insert_one.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const MongoError = require('../core').MongoError;
+const OperationBase = require('./operation').OperationBase;
+const insertDocuments = require('./common_functions').insertDocuments;
+
+class InsertOneOperation extends OperationBase {
+ constructor(collection, doc, options) {
+ super(options);
+
+ this.collection = collection;
+ this.doc = doc;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const doc = this.doc;
+ const options = this.options;
+
+ if (Array.isArray(doc)) {
+ return callback(
+ MongoError.create({ message: 'doc parameter must be an object', driver: true })
+ );
+ }
+
+ insertDocuments(coll, [doc], options, (err, r) => {
+ if (callback == null) return;
+ if (err && callback) return callback(err);
+ // Workaround for pre 2.6 servers
+ if (r == null) return callback(null, { result: { ok: 1 } });
+ // Add values to top level to ensure crud spec compatibility
+ r.insertedCount = r.result.n;
+ r.insertedId = doc._id;
+ if (callback) callback(null, r);
+ });
+ }
+}
+
+module.exports = InsertOneOperation;
diff --git a/node_modules/mongodb/lib/operations/is_capped.js b/node_modules/mongodb/lib/operations/is_capped.js
new file mode 100644
index 0000000..3bfd9ff
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/is_capped.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const OptionsOperation = require('./options_operation');
+const handleCallback = require('../utils').handleCallback;
+
+class IsCappedOperation extends OptionsOperation {
+ constructor(collection, options) {
+ super(collection, options);
+ }
+
+ execute(callback) {
+ super.execute((err, document) => {
+ if (err) return handleCallback(callback, err);
+ handleCallback(callback, null, !!(document && document.capped));
+ });
+ }
+}
+
+module.exports = IsCappedOperation;
diff --git a/node_modules/mongodb/lib/operations/list_collections.js b/node_modules/mongodb/lib/operations/list_collections.js
new file mode 100644
index 0000000..ee01d31
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/list_collections.js
@@ -0,0 +1,106 @@
+'use strict';
+
+const CommandOperationV2 = require('./command_v2');
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const maxWireVersion = require('../core/utils').maxWireVersion;
+const CONSTANTS = require('../constants');
+
+const LIST_COLLECTIONS_WIRE_VERSION = 3;
+
+function listCollectionsTransforms(databaseName) {
+ const matching = `${databaseName}.`;
+
+ return {
+ doc: doc => {
+ const index = doc.name.indexOf(matching);
+ // Remove database name if available
+ if (doc.name && index === 0) {
+ doc.name = doc.name.substr(index + matching.length);
+ }
+
+ return doc;
+ }
+ };
+}
+
+class ListCollectionsOperation extends CommandOperationV2 {
+ constructor(db, filter, options) {
+ super(db, options, { fullResponse: true });
+
+ this.db = db;
+ this.filter = filter;
+ this.nameOnly = !!this.options.nameOnly;
+
+ if (typeof this.options.batchSize === 'number') {
+ this.batchSize = this.options.batchSize;
+ }
+ }
+
+ execute(server, callback) {
+ if (maxWireVersion(server) < LIST_COLLECTIONS_WIRE_VERSION) {
+ let filter = this.filter;
+ const databaseName = this.db.s.namespace.db;
+
+ // If we have legacy mode and have not provided a full db name filter it
+ if (
+ typeof filter.name === 'string' &&
+ !new RegExp('^' + databaseName + '\\.').test(filter.name)
+ ) {
+ filter = Object.assign({}, filter);
+ filter.name = this.db.s.namespace.withCollection(filter.name).toString();
+ }
+
+ // No filter, filter by current database
+ if (filter == null) {
+ filter.name = `/${databaseName}/`;
+ }
+
+ // Rewrite the filter to use $and to filter out indexes
+ if (filter.name) {
+ filter = { $and: [{ name: filter.name }, { name: /^((?!\$).)*$/ }] };
+ } else {
+ filter = { name: /^((?!\$).)*$/ };
+ }
+
+ const transforms = listCollectionsTransforms(databaseName);
+ server.query(
+ `${databaseName}.${CONSTANTS.SYSTEM_NAMESPACE_COLLECTION}`,
+ { query: filter },
+ { batchSize: this.batchSize || 1000 },
+ {},
+ (err, result) => {
+ if (
+ result &&
+ result.message &&
+ result.message.documents &&
+ Array.isArray(result.message.documents)
+ ) {
+ result.message.documents = result.message.documents.map(transforms.doc);
+ }
+
+ callback(err, result);
+ }
+ );
+
+ return;
+ }
+
+ const command = {
+ listCollections: 1,
+ filter: this.filter,
+ cursor: this.batchSize ? { batchSize: this.batchSize } : {},
+ nameOnly: this.nameOnly
+ };
+
+ return super.executeCommand(server, command, callback);
+ }
+}
+
+defineAspects(ListCollectionsOperation, [
+ Aspect.READ_OPERATION,
+ Aspect.RETRYABLE,
+ Aspect.EXECUTE_WITH_SELECTION
+]);
+
+module.exports = ListCollectionsOperation;
diff --git a/node_modules/mongodb/lib/operations/list_databases.js b/node_modules/mongodb/lib/operations/list_databases.js
new file mode 100644
index 0000000..62b2606
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/list_databases.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const CommandOperationV2 = require('./command_v2');
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const MongoDBNamespace = require('../utils').MongoDBNamespace;
+
+class ListDatabasesOperation extends CommandOperationV2 {
+ constructor(db, options) {
+ super(db, options);
+ this.ns = new MongoDBNamespace('admin', '$cmd');
+ }
+
+ execute(server, callback) {
+ const cmd = { listDatabases: 1 };
+ if (this.options.nameOnly) {
+ cmd.nameOnly = Number(cmd.nameOnly);
+ }
+
+ if (this.options.filter) {
+ cmd.filter = this.options.filter;
+ }
+
+ if (typeof this.options.authorizedDatabases === 'boolean') {
+ cmd.authorizedDatabases = this.options.authorizedDatabases;
+ }
+
+ super.executeCommand(server, cmd, callback);
+ }
+}
+
+defineAspects(ListDatabasesOperation, [
+ Aspect.READ_OPERATION,
+ Aspect.RETRYABLE,
+ Aspect.EXECUTE_WITH_SELECTION
+]);
+
+module.exports = ListDatabasesOperation;
diff --git a/node_modules/mongodb/lib/operations/list_indexes.js b/node_modules/mongodb/lib/operations/list_indexes.js
new file mode 100644
index 0000000..302a31b
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/list_indexes.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const CommandOperationV2 = require('./command_v2');
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const maxWireVersion = require('../core/utils').maxWireVersion;
+
+const LIST_INDEXES_WIRE_VERSION = 3;
+
+class ListIndexesOperation extends CommandOperationV2 {
+ constructor(collection, options) {
+ super(collection, options, { fullResponse: true });
+
+ this.collectionNamespace = collection.s.namespace;
+ }
+
+ execute(server, callback) {
+ const serverWireVersion = maxWireVersion(server);
+ if (serverWireVersion < LIST_INDEXES_WIRE_VERSION) {
+ const systemIndexesNS = this.collectionNamespace.withCollection('system.indexes').toString();
+ const collectionNS = this.collectionNamespace.toString();
+
+ server.query(systemIndexesNS, { query: { ns: collectionNS } }, {}, this.options, callback);
+ return;
+ }
+
+ const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {};
+ super.executeCommand(
+ server,
+ { listIndexes: this.collectionNamespace.collection, cursor },
+ callback
+ );
+ }
+}
+
+defineAspects(ListIndexesOperation, [
+ Aspect.READ_OPERATION,
+ Aspect.RETRYABLE,
+ Aspect.EXECUTE_WITH_SELECTION
+]);
+
+module.exports = ListIndexesOperation;
diff --git a/node_modules/mongodb/lib/operations/map_reduce.js b/node_modules/mongodb/lib/operations/map_reduce.js
new file mode 100644
index 0000000..febba58
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/map_reduce.js
@@ -0,0 +1,190 @@
+'use strict';
+
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const Code = require('../core').BSON.Code;
+const decorateWithCollation = require('../utils').decorateWithCollation;
+const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
+const executeCommand = require('./db_ops').executeCommand;
+const handleCallback = require('../utils').handleCallback;
+const isObject = require('../utils').isObject;
+const loadDb = require('../dynamic_loaders').loadDb;
+const OperationBase = require('./operation').OperationBase;
+const ReadPreference = require('../core').ReadPreference;
+const toError = require('../utils').toError;
+
+const exclusionList = [
+ 'readPreference',
+ 'session',
+ 'bypassDocumentValidation',
+ 'w',
+ 'wtimeout',
+ 'j',
+ 'writeConcern'
+];
+
+/**
+ * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection.
+ *
+ * @class
+ * @property {Collection} a Collection instance.
+ * @property {(function|string)} map The mapping function.
+ * @property {(function|string)} reduce The reduce function.
+ * @property {object} [options] Optional settings. See Collection.prototype.mapReduce for a list of options.
+ */
+class MapReduceOperation extends OperationBase {
+ /**
+ * Constructs a MapReduce operation.
+ *
+ * @param {Collection} a Collection instance.
+ * @param {(function|string)} map The mapping function.
+ * @param {(function|string)} reduce The reduce function.
+ * @param {object} [options] Optional settings. See Collection.prototype.mapReduce for a list of options.
+ */
+ constructor(collection, map, reduce, options) {
+ super(options);
+
+ this.collection = collection;
+ this.map = map;
+ this.reduce = reduce;
+ }
+
+ /**
+ * Execute the operation.
+ *
+ * @param {Collection~resultCallback} [callback] The command result callback
+ */
+ execute(callback) {
+ const coll = this.collection;
+ const map = this.map;
+ const reduce = this.reduce;
+ let options = this.options;
+
+ const mapCommandHash = {
+ mapReduce: coll.collectionName,
+ map: map,
+ reduce: reduce
+ };
+
+ // Add any other options passed in
+ for (let n in options) {
+ if ('scope' === n) {
+ mapCommandHash[n] = processScope(options[n]);
+ } else {
+ // Only include if not in exclusion list
+ if (exclusionList.indexOf(n) === -1) {
+ mapCommandHash[n] = options[n];
+ }
+ }
+ }
+
+ options = Object.assign({}, options);
+
+ // Ensure we have the right read preference inheritance
+ options.readPreference = ReadPreference.resolve(coll, options);
+
+ // If we have a read preference and inline is not set as output fail hard
+ if (
+ options.readPreference !== false &&
+ options.readPreference !== 'primary' &&
+ options['out'] &&
+ options['out'].inline !== 1 &&
+ options['out'] !== 'inline'
+ ) {
+ // Force readPreference to primary
+ options.readPreference = 'primary';
+ // Decorate command with writeConcern if supported
+ applyWriteConcern(mapCommandHash, { db: coll.s.db, collection: coll }, options);
+ } else {
+ decorateWithReadConcern(mapCommandHash, coll, options);
+ }
+
+ // Is bypassDocumentValidation specified
+ if (options.bypassDocumentValidation === true) {
+ mapCommandHash.bypassDocumentValidation = options.bypassDocumentValidation;
+ }
+
+ // Have we specified collation
+ try {
+ decorateWithCollation(mapCommandHash, coll, options);
+ } catch (err) {
+ return callback(err, null);
+ }
+
+ // Execute command
+ executeCommand(coll.s.db, mapCommandHash, options, (err, result) => {
+ if (err) return handleCallback(callback, err);
+ // Check if we have an error
+ if (1 !== result.ok || result.err || result.errmsg) {
+ return handleCallback(callback, toError(result));
+ }
+
+ // Create statistics value
+ const stats = {};
+ if (result.timeMillis) stats['processtime'] = result.timeMillis;
+ if (result.counts) stats['counts'] = result.counts;
+ if (result.timing) stats['timing'] = result.timing;
+
+ // invoked with inline?
+ if (result.results) {
+ // If we wish for no verbosity
+ if (options['verbose'] == null || !options['verbose']) {
+ return handleCallback(callback, null, result.results);
+ }
+
+ return handleCallback(callback, null, { results: result.results, stats: stats });
+ }
+
+ // The returned collection
+ let collection = null;
+
+ // If we have an object it's a different db
+ if (result.result != null && typeof result.result === 'object') {
+ const doc = result.result;
+ // Return a collection from another db
+ let Db = loadDb();
+ collection = new Db(doc.db, coll.s.db.s.topology, coll.s.db.s.options).collection(
+ doc.collection
+ );
+ } else {
+ // Create a collection object that wraps the result collection
+ collection = coll.s.db.collection(result.result);
+ }
+
+ // If we wish for no verbosity
+ if (options['verbose'] == null || !options['verbose']) {
+ return handleCallback(callback, err, collection);
+ }
+
+ // Return stats as third set of values
+ handleCallback(callback, err, { collection: collection, stats: stats });
+ });
+ }
+}
+
+/**
+ * Functions that are passed as scope args must
+ * be converted to Code instances.
+ * @ignore
+ */
+function processScope(scope) {
+ if (!isObject(scope) || scope._bsontype === 'ObjectID') {
+ return scope;
+ }
+
+ const keys = Object.keys(scope);
+ let key;
+ const new_scope = {};
+
+ for (let i = keys.length - 1; i >= 0; i--) {
+ key = keys[i];
+ if ('function' === typeof scope[key]) {
+ new_scope[key] = new Code(String(scope[key]));
+ } else {
+ new_scope[key] = processScope(scope[key]);
+ }
+ }
+
+ return new_scope;
+}
+
+module.exports = MapReduceOperation;
diff --git a/node_modules/mongodb/lib/operations/operation.js b/node_modules/mongodb/lib/operations/operation.js
new file mode 100644
index 0000000..28a9d05
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/operation.js
@@ -0,0 +1,66 @@
+'use strict';
+
+const Aspect = {
+ READ_OPERATION: Symbol('READ_OPERATION'),
+ WRITE_OPERATION: Symbol('WRITE_OPERATION'),
+ RETRYABLE: Symbol('RETRYABLE'),
+ EXECUTE_WITH_SELECTION: Symbol('EXECUTE_WITH_SELECTION'),
+ NO_INHERIT_OPTIONS: Symbol('NO_INHERIT_OPTIONS')
+};
+
+/**
+ * This class acts as a parent class for any operation and is responsible for setting this.options,
+ * as well as setting and getting a session.
+ * Additionally, this class implements `hasAspect`, which determines whether an operation has
+ * a specific aspect.
+ */
+class OperationBase {
+ constructor(options) {
+ this.options = Object.assign({}, options);
+ }
+
+ hasAspect(aspect) {
+ if (this.constructor.aspects == null) {
+ return false;
+ }
+ return this.constructor.aspects.has(aspect);
+ }
+
+ set session(session) {
+ Object.assign(this.options, { session });
+ }
+
+ get session() {
+ return this.options.session;
+ }
+
+ clearSession() {
+ delete this.options.session;
+ }
+
+ get canRetryRead() {
+ return true;
+ }
+
+ execute() {
+ throw new TypeError('`execute` must be implemented for OperationBase subclasses');
+ }
+}
+
+function defineAspects(operation, aspects) {
+ if (!Array.isArray(aspects) && !(aspects instanceof Set)) {
+ aspects = [aspects];
+ }
+ aspects = new Set(aspects);
+ Object.defineProperty(operation, 'aspects', {
+ value: aspects,
+ writable: false
+ });
+ return aspects;
+}
+
+module.exports = {
+ Aspect,
+ defineAspects,
+ OperationBase
+};
diff --git a/node_modules/mongodb/lib/operations/options_operation.js b/node_modules/mongodb/lib/operations/options_operation.js
new file mode 100644
index 0000000..9a739a5
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/options_operation.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const handleCallback = require('../utils').handleCallback;
+const MongoError = require('../core').MongoError;
+
+class OptionsOperation extends OperationBase {
+ constructor(collection, options) {
+ super(options);
+
+ this.collection = collection;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const opts = this.options;
+
+ coll.s.db.listCollections({ name: coll.collectionName }, opts).toArray((err, collections) => {
+ if (err) return handleCallback(callback, err);
+ if (collections.length === 0) {
+ return handleCallback(
+ callback,
+ MongoError.create({ message: `collection ${coll.namespace} not found`, driver: true })
+ );
+ }
+
+ handleCallback(callback, err, collections[0].options || null);
+ });
+ }
+}
+
+module.exports = OptionsOperation;
diff --git a/node_modules/mongodb/lib/operations/profiling_level.js b/node_modules/mongodb/lib/operations/profiling_level.js
new file mode 100644
index 0000000..3f7639b
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/profiling_level.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const CommandOperation = require('./command');
+
+class ProfilingLevelOperation extends CommandOperation {
+ constructor(db, command, options) {
+ super(db, options);
+ }
+
+ _buildCommand() {
+ const command = { profile: -1 };
+
+ return command;
+ }
+
+ execute(callback) {
+ super.execute((err, doc) => {
+ if (err == null && doc.ok === 1) {
+ const was = doc.was;
+ if (was === 0) return callback(null, 'off');
+ if (was === 1) return callback(null, 'slow_only');
+ if (was === 2) return callback(null, 'all');
+ return callback(new Error('Error: illegal profiling level value ' + was), null);
+ } else {
+ err != null ? callback(err, null) : callback(new Error('Error with profile command'), null);
+ }
+ });
+ }
+}
+
+module.exports = ProfilingLevelOperation;
diff --git a/node_modules/mongodb/lib/operations/re_index.js b/node_modules/mongodb/lib/operations/re_index.js
new file mode 100644
index 0000000..dc44522
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/re_index.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const defineAspects = require('./operation').defineAspects;
+const CommandOperationV2 = require('./command_v2');
+const serverType = require('../core/sdam/common').serverType;
+const ServerType = require('../core/sdam/common').ServerType;
+const MongoError = require('../core').MongoError;
+
+class ReIndexOperation extends CommandOperationV2 {
+ constructor(collection, options) {
+ super(collection, options);
+ this.collectionName = collection.collectionName;
+ }
+
+ execute(server, callback) {
+ if (serverType(server) !== ServerType.Standalone) {
+ callback(new MongoError(`reIndex can only be executed on standalone servers.`));
+ return;
+ }
+ super.executeCommand(server, { reIndex: this.collectionName }, (err, result) => {
+ if (err) {
+ callback(err);
+ return;
+ }
+ callback(null, !!result.ok);
+ });
+ }
+}
+
+defineAspects(ReIndexOperation, [Aspect.EXECUTE_WITH_SELECTION]);
+
+module.exports = ReIndexOperation;
diff --git a/node_modules/mongodb/lib/operations/remove_user.js b/node_modules/mongodb/lib/operations/remove_user.js
new file mode 100644
index 0000000..9e8376b
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/remove_user.js
@@ -0,0 +1,52 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const CommandOperation = require('./command');
+const defineAspects = require('./operation').defineAspects;
+const handleCallback = require('../utils').handleCallback;
+const WriteConcern = require('../write_concern');
+
+class RemoveUserOperation extends CommandOperation {
+ constructor(db, username, options) {
+ const commandOptions = {};
+
+ const writeConcern = WriteConcern.fromOptions(options);
+ if (writeConcern != null) {
+ commandOptions.writeConcern = writeConcern;
+ }
+
+ if (options.dbName) {
+ commandOptions.dbName = options.dbName;
+ }
+
+ // Add maxTimeMS to options if set
+ if (typeof options.maxTimeMS === 'number') {
+ commandOptions.maxTimeMS = options.maxTimeMS;
+ }
+
+ super(db, commandOptions);
+
+ this.username = username;
+ }
+
+ _buildCommand() {
+ const username = this.username;
+
+ // Build the command to execute
+ const command = { dropUser: username };
+
+ return command;
+ }
+
+ execute(callback) {
+ // Attempt to execute command
+ super.execute((err, result) => {
+ if (err) return handleCallback(callback, err, null);
+ handleCallback(callback, err, result.ok ? true : false);
+ });
+ }
+}
+
+defineAspects(RemoveUserOperation, Aspect.WRITE_OPERATION);
+
+module.exports = RemoveUserOperation;
diff --git a/node_modules/mongodb/lib/operations/rename.js b/node_modules/mongodb/lib/operations/rename.js
new file mode 100644
index 0000000..8098fe6
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/rename.js
@@ -0,0 +1,61 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const applyWriteConcern = require('../utils').applyWriteConcern;
+const checkCollectionName = require('../utils').checkCollectionName;
+const executeDbAdminCommand = require('./db_ops').executeDbAdminCommand;
+const handleCallback = require('../utils').handleCallback;
+const loadCollection = require('../dynamic_loaders').loadCollection;
+const toError = require('../utils').toError;
+
+class RenameOperation extends OperationBase {
+ constructor(collection, newName, options) {
+ super(options);
+
+ this.collection = collection;
+ this.newName = newName;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const newName = this.newName;
+ const options = this.options;
+
+ let Collection = loadCollection();
+ // Check the collection name
+ checkCollectionName(newName);
+ // Build the command
+ const renameCollection = coll.namespace;
+ const toCollection = coll.s.namespace.withCollection(newName).toString();
+ const dropTarget = typeof options.dropTarget === 'boolean' ? options.dropTarget : false;
+ const cmd = { renameCollection: renameCollection, to: toCollection, dropTarget: dropTarget };
+
+ // Decorate command with writeConcern if supported
+ applyWriteConcern(cmd, { db: coll.s.db, collection: coll }, options);
+
+ // Execute against admin
+ executeDbAdminCommand(coll.s.db.admin().s.db, cmd, options, (err, doc) => {
+ if (err) return handleCallback(callback, err, null);
+ // We have an error
+ if (doc.errmsg) return handleCallback(callback, toError(doc), null);
+ try {
+ return handleCallback(
+ callback,
+ null,
+ new Collection(
+ coll.s.db,
+ coll.s.topology,
+ coll.s.namespace.db,
+ newName,
+ coll.s.pkFactory,
+ coll.s.options
+ )
+ );
+ } catch (err) {
+ return handleCallback(callback, toError(err), null);
+ }
+ });
+ }
+}
+
+module.exports = RenameOperation;
diff --git a/node_modules/mongodb/lib/operations/replace_one.js b/node_modules/mongodb/lib/operations/replace_one.js
new file mode 100644
index 0000000..93ec0ef
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/replace_one.js
@@ -0,0 +1,54 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const updateDocuments = require('./common_functions').updateDocuments;
+const hasAtomicOperators = require('../utils').hasAtomicOperators;
+
+class ReplaceOneOperation extends OperationBase {
+ constructor(collection, filter, replacement, options) {
+ super(options);
+
+ if (hasAtomicOperators(replacement)) {
+ throw new TypeError('Replacement document must not contain atomic operators');
+ }
+
+ this.collection = collection;
+ this.filter = filter;
+ this.replacement = replacement;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const filter = this.filter;
+ const replacement = this.replacement;
+ const options = this.options;
+
+ // Set single document update
+ options.multi = false;
+
+ // Execute update
+ updateDocuments(coll, filter, replacement, options, (err, r) =>
+ replaceCallback(err, r, replacement, callback)
+ );
+ }
+}
+
+function replaceCallback(err, r, doc, callback) {
+ if (callback == null) return;
+ if (err && callback) return callback(err);
+ if (r == null) return callback(null, { result: { ok: 1 } });
+
+ r.modifiedCount = r.result.nModified != null ? r.result.nModified : r.result.n;
+ r.upsertedId =
+ Array.isArray(r.result.upserted) && r.result.upserted.length > 0
+ ? r.result.upserted[0] // FIXME(major): should be `r.result.upserted[0]._id`
+ : null;
+ r.upsertedCount =
+ Array.isArray(r.result.upserted) && r.result.upserted.length ? r.result.upserted.length : 0;
+ r.matchedCount =
+ Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? 0 : r.result.n;
+ r.ops = [doc]; // TODO: Should we still have this?
+ if (callback) callback(null, r);
+}
+
+module.exports = ReplaceOneOperation;
diff --git a/node_modules/mongodb/lib/operations/run_command.js b/node_modules/mongodb/lib/operations/run_command.js
new file mode 100644
index 0000000..5525ba2
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/run_command.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const CommandOperationV2 = require('./command_v2');
+const defineAspects = require('./operation').defineAspects;
+const Aspect = require('./operation').Aspect;
+
+class RunCommandOperation extends CommandOperationV2 {
+ constructor(parent, command, options) {
+ super(parent, options);
+ this.command = command;
+ }
+ execute(server, callback) {
+ const command = this.command;
+ this.executeCommand(server, command, callback);
+ }
+}
+defineAspects(RunCommandOperation, [Aspect.EXECUTE_WITH_SELECTION, Aspect.NO_INHERIT_OPTIONS]);
+
+module.exports = RunCommandOperation;
diff --git a/node_modules/mongodb/lib/operations/set_profiling_level.js b/node_modules/mongodb/lib/operations/set_profiling_level.js
new file mode 100644
index 0000000..b31cc13
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/set_profiling_level.js
@@ -0,0 +1,48 @@
+'use strict';
+
+const CommandOperation = require('./command');
+const levelValues = new Set(['off', 'slow_only', 'all']);
+
+class SetProfilingLevelOperation extends CommandOperation {
+ constructor(db, level, options) {
+ let profile = 0;
+
+ if (level === 'off') {
+ profile = 0;
+ } else if (level === 'slow_only') {
+ profile = 1;
+ } else if (level === 'all') {
+ profile = 2;
+ }
+
+ super(db, options);
+ this.level = level;
+ this.profile = profile;
+ }
+
+ _buildCommand() {
+ const profile = this.profile;
+
+ // Set up the profile number
+ const command = { profile };
+
+ return command;
+ }
+
+ execute(callback) {
+ const level = this.level;
+
+ if (!levelValues.has(level)) {
+ return callback(new Error('Error: illegal profiling level value ' + level));
+ }
+
+ super.execute((err, doc) => {
+ if (err == null && doc.ok === 1) return callback(null, level);
+ return err != null
+ ? callback(err, null)
+ : callback(new Error('Error with profile command'), null);
+ });
+ }
+}
+
+module.exports = SetProfilingLevelOperation;
diff --git a/node_modules/mongodb/lib/operations/stats.js b/node_modules/mongodb/lib/operations/stats.js
new file mode 100644
index 0000000..ff79126
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/stats.js
@@ -0,0 +1,45 @@
+'use strict';
+
+const Aspect = require('./operation').Aspect;
+const CommandOperation = require('./command');
+const defineAspects = require('./operation').defineAspects;
+
+/**
+ * Get all the collection statistics.
+ *
+ * @class
+ * @property {Collection} a Collection instance.
+ * @property {object} [options] Optional settings. See Collection.prototype.stats for a list of options.
+ */
+class StatsOperation extends CommandOperation {
+ /**
+ * Construct a Stats operation.
+ *
+ * @param {Collection} a Collection instance.
+ * @param {object} [options] Optional settings. See Collection.prototype.stats for a list of options.
+ */
+ constructor(collection, options) {
+ super(collection.s.db, options, collection);
+ }
+
+ _buildCommand() {
+ const collection = this.collection;
+ const options = this.options;
+
+ // Build command object
+ const command = {
+ collStats: collection.collectionName
+ };
+
+ // Check if we have the scale value
+ if (options['scale'] != null) {
+ command['scale'] = options['scale'];
+ }
+
+ return command;
+ }
+}
+
+defineAspects(StatsOperation, Aspect.READ_OPERATION);
+
+module.exports = StatsOperation;
diff --git a/node_modules/mongodb/lib/operations/update_many.js b/node_modules/mongodb/lib/operations/update_many.js
new file mode 100644
index 0000000..725ed28
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/update_many.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const updateCallback = require('./common_functions').updateCallback;
+const updateDocuments = require('./common_functions').updateDocuments;
+const hasAtomicOperators = require('../utils').hasAtomicOperators;
+
+class UpdateManyOperation extends OperationBase {
+ constructor(collection, filter, update, options) {
+ super(options);
+
+ if (!hasAtomicOperators(update)) {
+ throw new TypeError('Update document requires atomic operators');
+ }
+
+ this.collection = collection;
+ this.filter = filter;
+ this.update = update;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const filter = this.filter;
+ const update = this.update;
+ const options = this.options;
+
+ // Set single document update
+ options.multi = true;
+ // Execute update
+ updateDocuments(coll, filter, update, options, (err, r) => updateCallback(err, r, callback));
+ }
+}
+
+module.exports = UpdateManyOperation;
diff --git a/node_modules/mongodb/lib/operations/update_one.js b/node_modules/mongodb/lib/operations/update_one.js
new file mode 100644
index 0000000..eea12a8
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/update_one.js
@@ -0,0 +1,49 @@
+'use strict';
+
+const OperationBase = require('./operation').OperationBase;
+const updateDocuments = require('./common_functions').updateDocuments;
+const hasAtomicOperators = require('../utils').hasAtomicOperators;
+
+class UpdateOneOperation extends OperationBase {
+ constructor(collection, filter, update, options) {
+ super(options);
+
+ if (!hasAtomicOperators(update)) {
+ throw new TypeError('Update document requires atomic operators');
+ }
+
+ this.collection = collection;
+ this.filter = filter;
+ this.update = update;
+ }
+
+ execute(callback) {
+ const coll = this.collection;
+ const filter = this.filter;
+ const update = this.update;
+ const options = this.options;
+
+ // Set single document update
+ options.multi = false;
+ // Execute update
+ updateDocuments(coll, filter, update, options, (err, r) => updateCallback(err, r, callback));
+ }
+}
+
+function updateCallback(err, r, callback) {
+ if (callback == null) return;
+ if (err) return callback(err);
+ if (r == null) return callback(null, { result: { ok: 1 } });
+ r.modifiedCount = r.result.nModified != null ? r.result.nModified : r.result.n;
+ r.upsertedId =
+ Array.isArray(r.result.upserted) && r.result.upserted.length > 0
+ ? r.result.upserted[0] // FIXME(major): should be `r.result.upserted[0]._id`
+ : null;
+ r.upsertedCount =
+ Array.isArray(r.result.upserted) && r.result.upserted.length ? r.result.upserted.length : 0;
+ r.matchedCount =
+ Array.isArray(r.result.upserted) && r.result.upserted.length > 0 ? 0 : r.result.n;
+ callback(null, r);
+}
+
+module.exports = UpdateOneOperation;
diff --git a/node_modules/mongodb/lib/operations/validate_collection.js b/node_modules/mongodb/lib/operations/validate_collection.js
new file mode 100644
index 0000000..bc16cd2
--- /dev/null
+++ b/node_modules/mongodb/lib/operations/validate_collection.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const CommandOperation = require('./command');
+
+class ValidateCollectionOperation extends CommandOperation {
+ constructor(admin, collectionName, options) {
+ // Decorate command with extra options
+ let command = { validate: collectionName };
+ const keys = Object.keys(options);
+ for (let i = 0; i < keys.length; i++) {
+ if (Object.prototype.hasOwnProperty.call(options, keys[i]) && keys[i] !== 'session') {
+ command[keys[i]] = options[keys[i]];
+ }
+ }
+
+ super(admin.s.db, options, null, command);
+ this.collectionName = collectionName;
+ }
+
+ execute(callback) {
+ const collectionName = this.collectionName;
+
+ super.execute((err, doc) => {
+ if (err != null) return callback(err, null);
+
+ if (doc.ok === 0) return callback(new Error('Error with validate command'), null);
+ if (doc.result != null && doc.result.constructor !== String)
+ return callback(new Error('Error with validation data'), null);
+ if (doc.result != null && doc.result.match(/exception|corrupt/) != null)
+ return callback(new Error('Error: invalid collection ' + collectionName), null);
+ if (doc.valid != null && !doc.valid)
+ return callback(new Error('Error: invalid collection ' + collectionName), null);
+
+ return callback(null, doc);
+ });
+ }
+}
+
+module.exports = ValidateCollectionOperation;