Update Node_modules
This commit is contained in:
+166
@@ -2,6 +2,159 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
<a name="3.2.7"></a>
|
||||
## [3.2.7](https://github.com/mongodb/node-mongodb-native/compare/v3.2.6...v3.2.7) (2019-06-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** updating core to version 3.2.7 ([2f91466](https://github.com/mongodb/node-mongodb-native/commit/2f91466))
|
||||
* **findOneAndReplace:** throw error if atomic operators provided for findOneAndReplace ([6a860a3](https://github.com/mongodb/node-mongodb-native/commit/6a860a3))
|
||||
|
||||
|
||||
|
||||
<a name="3.2.6"></a>
|
||||
## [3.2.6](https://github.com/mongodb/node-mongodb-native/compare/v3.2.5...v3.2.6) (2019-05-24)
|
||||
|
||||
|
||||
|
||||
<a name="3.2.5"></a>
|
||||
## [3.2.5](https://github.com/mongodb/node-mongodb-native/compare/v3.2.4...v3.2.5) (2019-05-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** updating core to 3.2.5 ([a2766c1](https://github.com/mongodb/node-mongodb-native/commit/a2766c1))
|
||||
|
||||
|
||||
|
||||
<a name="3.2.4"></a>
|
||||
## [3.2.4](https://github.com/mongodb/node-mongodb-native/compare/v3.2.2...v3.2.4) (2019-05-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **aggregation:** fix field name typo ([4235d04](https://github.com/mongodb/node-mongodb-native/commit/4235d04))
|
||||
* **async:** rewrote asyncGenerator in node < 10 syntax ([49c8cef](https://github.com/mongodb/node-mongodb-native/commit/49c8cef))
|
||||
* **BulkOp:** run unordered bulk ops in serial ([f548bd7](https://github.com/mongodb/node-mongodb-native/commit/f548bd7))
|
||||
* **bulkWrite:** fix issue with bulkWrite continuing w/ callback ([2a4a42c](https://github.com/mongodb/node-mongodb-native/commit/2a4a42c))
|
||||
* **docs:** correctly document that default for `sslValidate` is false ([1f8e7fa](https://github.com/mongodb/node-mongodb-native/commit/1f8e7fa))
|
||||
* **gridfs-stream:** honor chunk size ([9eeb114](https://github.com/mongodb/node-mongodb-native/commit/9eeb114))
|
||||
* **unified-topology:** only clone pool size if provided ([8dc2416](https://github.com/mongodb/node-mongodb-native/commit/8dc2416))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update to mongodb-core v3.2.3 ([1c5357a](https://github.com/mongodb/node-mongodb-native/commit/1c5357a))
|
||||
* **core:** update to mongodb-core v3.2.4 ([2059260](https://github.com/mongodb/node-mongodb-native/commit/2059260))
|
||||
* **lib:** implement executeOperationV2 ([67d4edf](https://github.com/mongodb/node-mongodb-native/commit/67d4edf))
|
||||
|
||||
|
||||
|
||||
<a name="3.2.3"></a>
|
||||
## [3.2.3](https://github.com/mongodb/node-mongodb-native/compare/v3.2.2...v3.2.3) (2019-04-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **aggregation:** fix field name typo ([4235d04](https://github.com/mongodb/node-mongodb-native/commit/4235d04))
|
||||
* **async:** rewrote asyncGenerator in node < 10 syntax ([49c8cef](https://github.com/mongodb/node-mongodb-native/commit/49c8cef))
|
||||
* **bulkWrite:** fix issue with bulkWrite continuing w/ callback ([2a4a42c](https://github.com/mongodb/node-mongodb-native/commit/2a4a42c))
|
||||
* **docs:** correctly document that default for `sslValidate` is false ([1f8e7fa](https://github.com/mongodb/node-mongodb-native/commit/1f8e7fa))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update to mongodb-core v3.2.3 ([1c5357a](https://github.com/mongodb/node-mongodb-native/commit/1c5357a))
|
||||
|
||||
|
||||
|
||||
<a name="3.2.2"></a>
|
||||
## [3.2.2](https://github.com/mongodb/node-mongodb-native/compare/v3.2.1...v3.2.2) (2019-03-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **asyncIterator:** stronger guard against importing async generator ([e0826fb](https://github.com/mongodb/node-mongodb-native/commit/e0826fb))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update to mongodb-core v3.2.2 ([868cfc3](https://github.com/mongodb/node-mongodb-native/commit/868cfc3))
|
||||
|
||||
|
||||
|
||||
<a name="3.2.1"></a>
|
||||
## [3.2.1](https://github.com/mongodb/node-mongodb-native/compare/v3.2.0...v3.2.1) (2019-03-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** update to mongodb-core v3.2.1 ([30b0100](https://github.com/mongodb/node-mongodb-native/commit/30b0100))
|
||||
|
||||
|
||||
|
||||
<a name="3.2.0"></a>
|
||||
# [3.2.0](https://github.com/mongodb/node-mongodb-native/compare/v3.1.13...v3.2.0) (2019-03-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **aggregate:** do not send batchSize for aggregation with $out ([ddb8d90](https://github.com/mongodb/node-mongodb-native/commit/ddb8d90))
|
||||
* **bulkWrite:** always count undefined values in bson size for bulk ([436d340](https://github.com/mongodb/node-mongodb-native/commit/436d340))
|
||||
* **db_ops:** rename db to add user on ([79931af](https://github.com/mongodb/node-mongodb-native/commit/79931af))
|
||||
* **mongo_client_ops:** only skip authentication if no authMechanism is specified ([3b6957d](https://github.com/mongodb/node-mongodb-native/commit/3b6957d))
|
||||
* **mongo-client:** ensure close callback is called with client ([f39e881](https://github.com/mongodb/node-mongodb-native/commit/f39e881))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** pin to mongodb-core v3.2.0 ([22af15a](https://github.com/mongodb/node-mongodb-native/commit/22af15a))
|
||||
* **Cursor:** adds support for AsyncIterator in cursors ([b972c1e](https://github.com/mongodb/node-mongodb-native/commit/b972c1e))
|
||||
* **db:** add database-level aggregation ([b629b21](https://github.com/mongodb/node-mongodb-native/commit/b629b21))
|
||||
* **mongo-client:** remove deprecated `logout` and print warning ([542859d](https://github.com/mongodb/node-mongodb-native/commit/542859d))
|
||||
* **topology-base:** support passing callbacks to `close` method ([7c111e0](https://github.com/mongodb/node-mongodb-native/commit/7c111e0))
|
||||
* **transactions:** support pinning mongos for sharded txns ([3886127](https://github.com/mongodb/node-mongodb-native/commit/3886127))
|
||||
* **unified-sdam:** backport unified SDAM to master for v3.2.0 ([79f33ca](https://github.com/mongodb/node-mongodb-native/commit/79f33ca))
|
||||
|
||||
|
||||
|
||||
<a name="3.1.13"></a>
|
||||
## [3.1.13](https://github.com/mongodb/node-mongodb-native/compare/v3.1.12...v3.1.13) (2019-01-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* restore ability to webpack by removing `makeLazyLoader` ([050267d](https://github.com/mongodb/node-mongodb-native/commit/050267d))
|
||||
* **bulk:** honor ignoreUndefined in initializeUnorderedBulkOp ([e806be4](https://github.com/mongodb/node-mongodb-native/commit/e806be4))
|
||||
* **changeStream:** properly handle changeStream event mid-close ([#1902](https://github.com/mongodb/node-mongodb-native/issues/1902)) ([5ad9fa9](https://github.com/mongodb/node-mongodb-native/commit/5ad9fa9))
|
||||
* **db_ops:** ensure we async resolve errors in createCollection ([210c71d](https://github.com/mongodb/node-mongodb-native/commit/210c71d))
|
||||
|
||||
|
||||
|
||||
<a name="3.1.12"></a>
|
||||
## [3.1.12](https://github.com/mongodb/node-mongodb-native/compare/v3.1.11...v3.1.12) (2019-01-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** update to mongodb-core v3.1.11 ([9bef6e7](https://github.com/mongodb/node-mongodb-native/commit/9bef6e7))
|
||||
|
||||
|
||||
|
||||
<a name="3.1.11"></a>
|
||||
## [3.1.11](https://github.com/mongodb/node-mongodb-native/compare/v3.1.10...v3.1.11) (2019-01-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bulk:** fix error propagation in empty bulk.execute ([a3adb3f](https://github.com/mongodb/node-mongodb-native/commit/a3adb3f))
|
||||
* **bulk:** make sure that any error in bulk write is propagated ([bedc2d2](https://github.com/mongodb/node-mongodb-native/commit/bedc2d2))
|
||||
* **bulk:** properly calculate batch size for bulk writes ([aafe71b](https://github.com/mongodb/node-mongodb-native/commit/aafe71b))
|
||||
* **operations:** do not call require in a hot path ([ff82ff4](https://github.com/mongodb/node-mongodb-native/commit/ff82ff4))
|
||||
|
||||
|
||||
|
||||
<a name="3.1.10"></a>
|
||||
## [3.1.10](https://github.com/mongodb/node-mongodb-native/compare/v3.1.9...v3.1.10) (2018-11-16)
|
||||
|
||||
@@ -186,6 +339,19 @@ All notable changes to this project will be documented in this file. See [standa
|
||||
|
||||
|
||||
|
||||
<a name="3.1.1"></a>
|
||||
## [3.1.1](https://github.com/mongodb/node-mongodb-native/compare/v3.1.0...v3.1.1) (2018-07-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **client-ops:** return transform map to map rather than function ([b8b4bfa](https://github.com/mongodb/node-mongodb-native/commit/b8b4bfa))
|
||||
* **collection:** correctly shallow clone passed in options ([2e6c4fa](https://github.com/mongodb/node-mongodb-native/commit/2e6c4fa))
|
||||
* **collection:** countDocuments throws error when query doesn't match docs ([4e83556](https://github.com/mongodb/node-mongodb-native/commit/4e83556))
|
||||
* **server:** remove unnecessary print statement ([20e11b3](https://github.com/mongodb/node-mongodb-native/commit/20e11b3))
|
||||
|
||||
|
||||
|
||||
<a name="3.1.0"></a>
|
||||
# [3.1.0](https://github.com/mongodb/node-mongodb-native/compare/v3.0.6...v3.1.0) (2018-06-27)
|
||||
|
||||
|
||||
+9
-3
@@ -31,15 +31,21 @@ case in our issue management tool, JIRA:
|
||||
Bug reports in JIRA for all driver projects (i.e. NODE, PYTHON, CSHARP, JAVA) and the
|
||||
Core Server (i.e. SERVER) project are **public**.
|
||||
|
||||
### Questions and Bug Reports
|
||||
### Support / Feedback
|
||||
|
||||
* Mailing List: [groups.google.com/forum/#!forum/node-mongodb-native](https://groups.google.com/forum/#!forum/node-mongodb-native)
|
||||
* JIRA: [jira.mongodb.org](http://jira.mongodb.org)
|
||||
For issues with, questions about, or feedback for the Node.js driver, please look into our [support channels](http://www.mongodb.org/about/support). Please do not email any of the driver developers directly with issues or questions - you're more likely to get an answer on the [mongodb-user](http://groups.google.com/group/mongodb-user>) list on Google Groups.
|
||||
|
||||
### Change Log
|
||||
|
||||
Change history can be found in [`HISTORY.md`](HISTORY.md).
|
||||
|
||||
### Compatibility
|
||||
|
||||
For version compatibility matrices, please refer to the following links:
|
||||
|
||||
* [MongoDB](https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#reference-compatibility-mongodb-node)
|
||||
* [NodeJS](https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#reference-compatibility-language-node)
|
||||
|
||||
# Installation
|
||||
|
||||
The recommended way to get started using the Node.js 3.0 driver is by using the `npm` (Node Package Manager) to install the dependency in your project.
|
||||
|
||||
+12
-5
@@ -4,6 +4,8 @@ const inherits = require('util').inherits;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const Readable = require('stream').Readable;
|
||||
const CoreCursor = require('./cursor');
|
||||
const deprecate = require('util').deprecate;
|
||||
const SUPPORTS = require('./utils').SUPPORTS;
|
||||
|
||||
/**
|
||||
* @fileOverview The **AggregationCursor** class is an internal class that embodies an aggregation cursor on MongoDB
|
||||
@@ -129,6 +131,11 @@ inherits(AggregationCursor, Readable);
|
||||
for (var name in CoreCursor.prototype) {
|
||||
AggregationCursor.prototype[name] = CoreCursor.prototype[name];
|
||||
}
|
||||
if (SUPPORTS.ASYNC_ITERATOR) {
|
||||
AggregationCursor.prototype[
|
||||
Symbol.asyncIterator
|
||||
] = require('./async/async_iterator').asyncIterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the batch size for the cursor.
|
||||
@@ -141,7 +148,7 @@ AggregationCursor.prototype.batchSize = function(value) {
|
||||
if (this.s.state === AggregationCursor.CLOSED || this.isDead())
|
||||
throw MongoError.create({ message: 'Cursor is closed', driver: true });
|
||||
if (typeof value !== 'number')
|
||||
throw MongoError.create({ message: 'batchSize requires an integer', drvier: true });
|
||||
throw MongoError.create({ message: 'batchSize requires an integer', driver: true });
|
||||
if (this.s.cmd.cursor) this.s.cmd.cursor.batchSize = value;
|
||||
this.setCursorBatchSize(value);
|
||||
return this;
|
||||
@@ -153,10 +160,10 @@ AggregationCursor.prototype.batchSize = function(value) {
|
||||
* @param {object} document The geoNear stage document.
|
||||
* @return {AggregationCursor}
|
||||
*/
|
||||
AggregationCursor.prototype.geoNear = function(document) {
|
||||
AggregationCursor.prototype.geoNear = deprecate(function(document) {
|
||||
this.s.cmd.pipeline.push({ $geoNear: document });
|
||||
return this;
|
||||
};
|
||||
}, 'The `$geoNear` stage is deprecated in MongoDB 4.0, and removed in version 4.2.');
|
||||
|
||||
/**
|
||||
* Add a group stage to the aggregation pipeline
|
||||
@@ -319,7 +326,7 @@ AggregationCursor.prototype.get = AggregationCursor.prototype.toArray;
|
||||
/**
|
||||
* Returns an array of documents. The caller is responsible for making sure that there
|
||||
* is enough memory to store the results. Note that the array only contain partial
|
||||
* results when this cursor had been previouly accessed. In that case,
|
||||
* results when this cursor had been previously accessed. In that case,
|
||||
* cursor.rewind() can be used to reset the cursor.
|
||||
* @method AggregationCursor.prototype.toArray
|
||||
* @param {AggregationCursor~toArrayResultCallback} [callback] The result callback.
|
||||
@@ -336,7 +343,7 @@ AggregationCursor.prototype.get = AggregationCursor.prototype.toArray;
|
||||
|
||||
/**
|
||||
* Iterates over all the documents for this cursor. As with **{cursor.toArray}**,
|
||||
* not all of the elements will be iterated if this cursor had been previouly accessed.
|
||||
* not all of the elements will be iterated if this cursor had been previously accessed.
|
||||
* In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike
|
||||
* **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements
|
||||
* at any given time if batch size is specified. Otherwise, the caller is responsible
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
// async function* asyncIterator() {
|
||||
// while (true) {
|
||||
// const value = await this.next();
|
||||
// if (!value) {
|
||||
// await this.close();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// yield value;
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: change this to the async generator function above
|
||||
function asyncIterator() {
|
||||
const cursor = this;
|
||||
|
||||
return {
|
||||
next: function() {
|
||||
return Promise.resolve()
|
||||
.then(() => cursor.next())
|
||||
.then(value => {
|
||||
if (!value) {
|
||||
return cursor.close().then(() => ({ value, done: true }));
|
||||
}
|
||||
return { value, done: false };
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.asyncIterator = asyncIterator;
|
||||
-136
@@ -1,136 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var shallowClone = require('./utils').shallowClone,
|
||||
handleCallback = require('./utils').handleCallback,
|
||||
MongoError = require('mongodb-core').MongoError,
|
||||
f = require('util').format;
|
||||
|
||||
var authenticate = function(client, username, password, options, callback) {
|
||||
// Did the user destroy the topology
|
||||
if (client.topology && client.topology.isDestroyed())
|
||||
return callback(new MongoError('topology was destroyed'));
|
||||
|
||||
// the default db to authenticate against is 'self'
|
||||
// if authententicate is called from a retry context, it may be another one, like admin
|
||||
var authdb = options.dbName;
|
||||
authdb = options.authdb ? options.authdb : authdb;
|
||||
authdb = options.authSource ? options.authSource : authdb;
|
||||
|
||||
// Callback
|
||||
var _callback = function(err, result) {
|
||||
if (client.listeners('authenticated').length > 0) {
|
||||
client.emit('authenticated', err, result);
|
||||
}
|
||||
|
||||
// Return to caller
|
||||
handleCallback(callback, err, result);
|
||||
};
|
||||
|
||||
// authMechanism
|
||||
var authMechanism = options.authMechanism || '';
|
||||
authMechanism = authMechanism.toUpperCase();
|
||||
|
||||
// If classic auth delegate to auth command
|
||||
if (authMechanism === 'MONGODB-CR') {
|
||||
client.topology.auth('mongocr', authdb, username, password, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
} else if (authMechanism === 'PLAIN') {
|
||||
client.topology.auth('plain', authdb, username, password, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
} else if (authMechanism === 'MONGODB-X509') {
|
||||
client.topology.auth('x509', authdb, username, password, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
} else if (authMechanism === 'SCRAM-SHA-1') {
|
||||
client.topology.auth('scram-sha-1', authdb, username, password, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
} else if (authMechanism === 'SCRAM-SHA-256') {
|
||||
client.topology.auth('scram-sha-256', authdb, username, password, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
} else if (authMechanism === 'GSSAPI') {
|
||||
if (process.platform === 'win32') {
|
||||
client.topology.auth('sspi', authdb, username, password, options, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
} else {
|
||||
client.topology.auth('gssapi', authdb, username, password, options, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
}
|
||||
} else if (authMechanism === 'DEFAULT') {
|
||||
client.topology.auth('default', authdb, username, password, function(err) {
|
||||
if (err) return handleCallback(callback, err, false);
|
||||
_callback(null, true);
|
||||
});
|
||||
} else {
|
||||
handleCallback(
|
||||
callback,
|
||||
MongoError.create({
|
||||
message: f('authentication mechanism %s not supported', options.authMechanism),
|
||||
driver: true
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function(self, username, password, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
// Shallow copy the options
|
||||
options = shallowClone(options);
|
||||
|
||||
// Set default mechanism
|
||||
if (!options.authMechanism) {
|
||||
options.authMechanism = 'DEFAULT';
|
||||
} else if (
|
||||
options.authMechanism !== 'GSSAPI' &&
|
||||
options.authMechanism !== 'DEFAULT' &&
|
||||
options.authMechanism !== 'MONGODB-CR' &&
|
||||
options.authMechanism !== 'MONGODB-X509' &&
|
||||
options.authMechanism !== 'SCRAM-SHA-1' &&
|
||||
options.authMechanism !== 'SCRAM-SHA-256' &&
|
||||
options.authMechanism !== 'PLAIN'
|
||||
) {
|
||||
return handleCallback(
|
||||
callback,
|
||||
MongoError.create({
|
||||
message:
|
||||
'only DEFAULT, GSSAPI, PLAIN, MONGODB-X509, or SCRAM-SHA-1 is supported by authMechanism',
|
||||
driver: true
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// If we have a callback fallback
|
||||
if (typeof callback === 'function')
|
||||
return authenticate(self, username, password, options, function(err, r) {
|
||||
// Support failed auth method
|
||||
if (err && err.message && err.message.indexOf('saslStart') !== -1) err.code = 59;
|
||||
// Reject error
|
||||
if (err) return callback(err, r);
|
||||
callback(null, r);
|
||||
});
|
||||
|
||||
// Return a promise
|
||||
return new self.s.promiseLibrary(function(resolve, reject) {
|
||||
authenticate(self, username, password, options, function(err, r) {
|
||||
// Support failed auth method
|
||||
if (err && err.message && err.message.indexOf('saslStart') !== -1) err.code = 59;
|
||||
// Reject error
|
||||
if (err) return reject(err);
|
||||
resolve(r);
|
||||
});
|
||||
});
|
||||
};
|
||||
+100
-48
@@ -2,18 +2,18 @@
|
||||
|
||||
const Long = require('mongodb-core').BSON.Long;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const ObjectID = require('mongodb-core').BSON.ObjectID;
|
||||
const BSON = require('mongodb-core').BSON;
|
||||
const MongoWriteConcernError = require('mongodb-core').MongoWriteConcernError;
|
||||
const toError = require('../utils').toError;
|
||||
const handleCallback = require('../utils').handleCallback;
|
||||
const applyRetryableWrites = require('../utils').applyRetryableWrites;
|
||||
const applyWriteConcern = require('../utils').applyWriteConcern;
|
||||
const ObjectID = require('mongodb-core').BSON.ObjectID;
|
||||
const BSON = require('mongodb-core').BSON;
|
||||
const executeOperation = require('../utils').executeOperation;
|
||||
const isPromiseLike = require('../utils').isPromiseLike;
|
||||
|
||||
// Error codes
|
||||
const UNKNOWN_ERROR = 8;
|
||||
const INVALID_BSON_ERROR = 22;
|
||||
const WRITE_CONCERN_ERROR = 64;
|
||||
const MULTIPLE_ERROR = 65;
|
||||
|
||||
// Insert types
|
||||
const INSERT = 1;
|
||||
@@ -54,18 +54,6 @@ class Batch {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a legacy operation so we can correctly rewrite it's error
|
||||
* @ignore
|
||||
*/
|
||||
class LegacyOp {
|
||||
constructor(batchType, operation, index) {
|
||||
this.batchType = batchType;
|
||||
this.index = index;
|
||||
this.operation = operation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new BulkWriteResult instance (INTERNAL TYPE, do not instantiate directly)
|
||||
*
|
||||
@@ -352,7 +340,7 @@ class WriteError {
|
||||
* Merges results into shared data structure
|
||||
* @ignore
|
||||
*/
|
||||
function mergeBatchResults(ordered, batch, bulkResult, err, result) {
|
||||
function mergeBatchResults(batch, bulkResult, err, result) {
|
||||
// If we have an error set the result to be the err object
|
||||
if (err) {
|
||||
result = err;
|
||||
@@ -484,6 +472,41 @@ function mergeBatchResults(ordered, batch, bulkResult, err, result) {
|
||||
}
|
||||
}
|
||||
|
||||
function executeCommands(bulkOperation, options, callback) {
|
||||
if (bulkOperation.s.batches.length === 0) {
|
||||
return handleCallback(callback, null, new BulkWriteResult(bulkOperation.s.bulkResult));
|
||||
}
|
||||
|
||||
const batch = bulkOperation.s.batches.shift();
|
||||
|
||||
function resultHandler(err, result) {
|
||||
// Error is a driver related error not a bulk op error, terminate
|
||||
if (((err && err.driver) || (err && err.message)) && !(err instanceof MongoWriteConcernError)) {
|
||||
return handleCallback(callback, err);
|
||||
}
|
||||
|
||||
// If we have and error
|
||||
if (err) err.ok = 0;
|
||||
if (err instanceof MongoWriteConcernError) {
|
||||
return handleMongoWriteConcernError(batch, bulkOperation.s.bulkResult, err, callback);
|
||||
}
|
||||
|
||||
// Merge the results together
|
||||
const writeResult = new BulkWriteResult(bulkOperation.s.bulkResult);
|
||||
const mergeResult = mergeBatchResults(batch, bulkOperation.s.bulkResult, err, result);
|
||||
if (mergeResult != null) {
|
||||
return handleCallback(callback, null, writeResult);
|
||||
}
|
||||
|
||||
if (bulkOperation.handleWriteError(callback, writeResult)) return;
|
||||
|
||||
// Execute the next command in line
|
||||
executeCommands(bulkOperation, options, callback);
|
||||
}
|
||||
|
||||
bulkOperation.finalOptionsHandler({ options, batch, resultHandler }, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* handles write concern error
|
||||
*
|
||||
@@ -493,8 +516,8 @@ function mergeBatchResults(ordered, batch, bulkResult, err, result) {
|
||||
* @param {WriteConcernError} err
|
||||
* @param {function} callback
|
||||
*/
|
||||
function handleMongoWriteConcernError(batch, bulkResult, ordered, err, callback) {
|
||||
mergeBatchResults(ordered, batch, bulkResult, null, err.result);
|
||||
function handleMongoWriteConcernError(batch, bulkResult, err, callback) {
|
||||
mergeBatchResults(batch, bulkResult, null, err.result);
|
||||
|
||||
const wrappedWriteConcernError = new WriteConcernError({
|
||||
errmsg: err.result.writeConcernError.errmsg,
|
||||
@@ -702,6 +725,13 @@ class BulkOperationBase {
|
||||
const maxWriteBatchSize =
|
||||
isMaster && isMaster.maxWriteBatchSize ? isMaster.maxWriteBatchSize : 1000;
|
||||
|
||||
// Calculates the largest possible size of an Array key, represented as a BSON string
|
||||
// element. This calculation:
|
||||
// 1 byte for BSON type
|
||||
// # of bytes = length of (string representation of (maxWriteBatchSize - 1))
|
||||
// + 1 bytes for null terminator
|
||||
const maxKeySize = (maxWriteBatchSize - 1).toString(10).length + 2;
|
||||
|
||||
// Final options for retryable writes and write concern
|
||||
let finalOptions = Object.assign({}, options);
|
||||
finalOptions = applyRetryableWrites(finalOptions, collection.s.db);
|
||||
@@ -745,6 +775,7 @@ class BulkOperationBase {
|
||||
// Max batch size options
|
||||
maxBatchSizeBytes: maxBatchSizeBytes,
|
||||
maxWriteBatchSize: maxWriteBatchSize,
|
||||
maxKeySize,
|
||||
// Namespace
|
||||
namespace: namespace,
|
||||
// BSON
|
||||
@@ -898,6 +929,15 @@ class BulkOperationBase {
|
||||
);
|
||||
}
|
||||
|
||||
_handleEarlyError(err, callback) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(err, null);
|
||||
return;
|
||||
}
|
||||
|
||||
return this.s.promiseLibrary.reject(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute next write command in a chain
|
||||
*
|
||||
@@ -911,19 +951,17 @@ class BulkOperationBase {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
if (this.s.executed) {
|
||||
const executedError = toError('batch cannot be re-executed');
|
||||
return typeof callback === 'function'
|
||||
? callback(executedError, null)
|
||||
: this.s.promiseLibrary.reject(executedError);
|
||||
}
|
||||
|
||||
if (typeof _writeConcern === 'function') {
|
||||
callback = _writeConcern;
|
||||
} else if (_writeConcern && typeof _writeConcern === 'object') {
|
||||
this.s.writeConcern = _writeConcern;
|
||||
}
|
||||
|
||||
if (this.s.executed) {
|
||||
const executedError = toError('batch cannot be re-executed');
|
||||
return this._handleEarlyError(executedError, callback);
|
||||
}
|
||||
|
||||
// If we have current batch
|
||||
if (this.isOrdered) {
|
||||
if (this.s.currentBatch) this.s.batches.push(this.s.currentBatch);
|
||||
@@ -935,13 +973,43 @@ class BulkOperationBase {
|
||||
// If we have no operations in the bulk raise an error
|
||||
if (this.s.batches.length === 0) {
|
||||
const emptyBatchError = toError('Invalid Operation, no operations specified');
|
||||
return typeof callback === 'function'
|
||||
? callback(emptyBatchError, null)
|
||||
: this.s.promiseLibrary.reject(emptyBatchError);
|
||||
return this._handleEarlyError(emptyBatchError, callback);
|
||||
}
|
||||
return { options, callback };
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback format for results
|
||||
* @callback BulkOperationBase~resultCallback
|
||||
* @param {MongoError} error An error instance representing the error during the execution.
|
||||
* @param {BulkWriteResult} result The bulk write result.
|
||||
*/
|
||||
/**
|
||||
* Execute the ordered bulk operation
|
||||
*
|
||||
* @method
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {(number|string)} [options.w] The write concern.
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
* @param {boolean} [options.j=false] Specify a journal write concern.
|
||||
* @param {boolean} [options.fsync=false] Specify a file sync write concern.
|
||||
* @param {BulkOperationBase~resultCallback} [callback] The result callback
|
||||
* @throws {MongoError} Throws error if the bulk object has already been executed
|
||||
* @throws {MongoError} Throws error if the bulk object does not have any operations
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
execute(_writeConcern, options, callback) {
|
||||
const ret = this.bulkExecute(_writeConcern, options, callback);
|
||||
if (!ret || isPromiseLike(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
options = ret.options;
|
||||
callback = ret.callback;
|
||||
|
||||
return executeOperation(this.s.topology, executeCommands, [this, options, callback]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles final options before executing command
|
||||
*
|
||||
@@ -1025,11 +1093,7 @@ class BulkOperationBase {
|
||||
// Force top level error
|
||||
err.ok = 0;
|
||||
// Merge top level error and return
|
||||
handleCallback(
|
||||
callback,
|
||||
null,
|
||||
mergeBatchResults(false, config.batch, this.s.bulkResult, err, null)
|
||||
);
|
||||
handleCallback(callback, null, mergeBatchResults(config.batch, this.s.bulkResult, err, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1086,20 +1150,8 @@ Object.defineProperty(BulkOperationBase.prototype, 'length', {
|
||||
module.exports = {
|
||||
Batch,
|
||||
BulkOperationBase,
|
||||
BulkWriteError,
|
||||
BulkWriteResult,
|
||||
bson,
|
||||
FindOperators,
|
||||
handleMongoWriteConcernError,
|
||||
LegacyOp,
|
||||
mergeBatchResults,
|
||||
INVALID_BSON_ERROR: INVALID_BSON_ERROR,
|
||||
MULTIPLE_ERROR: MULTIPLE_ERROR,
|
||||
UNKNOWN_ERROR: UNKNOWN_ERROR,
|
||||
WRITE_CONCERN_ERROR: WRITE_CONCERN_ERROR,
|
||||
INSERT: INSERT,
|
||||
UPDATE: UPDATE,
|
||||
REMOVE: REMOVE,
|
||||
WriteError,
|
||||
WriteConcernError
|
||||
REMOVE: REMOVE
|
||||
};
|
||||
|
||||
+17
-90
@@ -2,16 +2,10 @@
|
||||
|
||||
const common = require('./common');
|
||||
const BulkOperationBase = common.BulkOperationBase;
|
||||
const Batch = common.Batch;
|
||||
const bson = common.bson;
|
||||
const utils = require('../utils');
|
||||
const toError = utils.toError;
|
||||
const handleCallback = utils.handleCallback;
|
||||
const BulkWriteResult = common.BulkWriteResult;
|
||||
const Batch = common.Batch;
|
||||
const mergeBatchResults = common.mergeBatchResults;
|
||||
const executeOperation = utils.executeOperation;
|
||||
const MongoWriteConcernError = require('mongodb-core').MongoWriteConcernError;
|
||||
const handleMongoWriteConcernError = require('./common').handleMongoWriteConcernError;
|
||||
const bson = common.bson;
|
||||
|
||||
/**
|
||||
* Add to internal list of Operations
|
||||
@@ -24,7 +18,11 @@ const bson = common.bson;
|
||||
function addToOperationsList(bulkOperation, docType, document) {
|
||||
// Get the bsonSize
|
||||
const bsonSize = bson.calculateObjectSize(document, {
|
||||
checkKeys: false
|
||||
checkKeys: false,
|
||||
|
||||
// Since we don't know what the user selected for BSON options here,
|
||||
// err on the safe side, and check the size with ignoreUndefined: false.
|
||||
ignoreUndefined: false
|
||||
});
|
||||
|
||||
// Throw error if the doc is bigger than the max BSON size
|
||||
@@ -35,10 +33,12 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
if (bulkOperation.s.currentBatch == null)
|
||||
bulkOperation.s.currentBatch = new Batch(docType, bulkOperation.s.currentIndex);
|
||||
|
||||
const maxKeySize = bulkOperation.s.maxKeySize;
|
||||
|
||||
// Check if we need to create a new batch
|
||||
if (
|
||||
bulkOperation.s.currentBatchSize + 1 >= bulkOperation.s.maxWriteBatchSize ||
|
||||
bulkOperation.s.currentBatchSizeBytes + bulkOperation.s.currentBatchSizeBytes >=
|
||||
bulkOperation.s.currentBatchSizeBytes + maxKeySize + bsonSize >=
|
||||
bulkOperation.s.maxBatchSizeBytes ||
|
||||
bulkOperation.s.currentBatch.batchType !== docType
|
||||
) {
|
||||
@@ -51,10 +51,6 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
// Reset the current size trackers
|
||||
bulkOperation.s.currentBatchSize = 0;
|
||||
bulkOperation.s.currentBatchSizeBytes = 0;
|
||||
} else {
|
||||
// Update current batch size
|
||||
bulkOperation.s.currentBatchSize = bulkOperation.s.currentBatchSize + 1;
|
||||
bulkOperation.s.currentBatchSizeBytes = bulkOperation.s.currentBatchSizeBytes + bsonSize;
|
||||
}
|
||||
|
||||
if (docType === common.INSERT) {
|
||||
@@ -67,13 +63,14 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
// We have an array of documents
|
||||
if (Array.isArray(document)) {
|
||||
throw toError('operation passed in cannot be an Array');
|
||||
} else {
|
||||
bulkOperation.s.currentBatch.originalIndexes.push(bulkOperation.s.currentIndex);
|
||||
bulkOperation.s.currentBatch.operations.push(document);
|
||||
bulkOperation.s.currentBatchSizeBytes = bulkOperation.s.currentBatchSizeBytes + bsonSize;
|
||||
bulkOperation.s.currentIndex = bulkOperation.s.currentIndex + 1;
|
||||
}
|
||||
|
||||
bulkOperation.s.currentBatch.originalIndexes.push(bulkOperation.s.currentIndex);
|
||||
bulkOperation.s.currentBatch.operations.push(document);
|
||||
bulkOperation.s.currentBatchSize += 1;
|
||||
bulkOperation.s.currentBatchSizeBytes += maxKeySize + bsonSize;
|
||||
bulkOperation.s.currentIndex += 1;
|
||||
|
||||
// Return bulkOperation
|
||||
return bulkOperation;
|
||||
}
|
||||
@@ -81,6 +78,7 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
/**
|
||||
* Create a new OrderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly)
|
||||
* @class
|
||||
* @extends BulkOperationBase
|
||||
* @property {number} length Get the number of operations in the bulk.
|
||||
* @return {OrderedBulkOperation} a OrderedBulkOperation instance.
|
||||
*/
|
||||
@@ -92,77 +90,6 @@ class OrderedBulkOperation extends BulkOperationBase {
|
||||
|
||||
super(topology, collection, options, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback format for results
|
||||
* @callback OrderedBulkOperation~resultCallback
|
||||
* @param {MongoError} error An error instance representing the error during the execution.
|
||||
* @param {BulkWriteResult} result The bulk write result.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Execute the ordered bulk operation
|
||||
*
|
||||
* @method
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {(number|string)} [options.w] The write concern.
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
* @param {boolean} [options.j=false] Specify a journal write concern.
|
||||
* @param {boolean} [options.fsync=false] Specify a file sync write concern.
|
||||
* @param {OrderedBulkOperation~resultCallback} [callback] The result callback
|
||||
* @throws {MongoError}
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
execute(_writeConcern, options, callback) {
|
||||
const ret = this.bulkExecute(_writeConcern, options, callback);
|
||||
options = ret.options;
|
||||
callback = ret.callback;
|
||||
|
||||
return executeOperation(this.s.topology, executeCommands, [this, options, callback]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute next write command in a chain
|
||||
*
|
||||
* @param {OrderedBulkOperation} bulkOperation
|
||||
* @param {object} options
|
||||
* @param {function} callback
|
||||
*/
|
||||
function executeCommands(bulkOperation, options, callback) {
|
||||
if (bulkOperation.s.batches.length === 0) {
|
||||
return handleCallback(callback, null, new BulkWriteResult(bulkOperation.s.bulkResult));
|
||||
}
|
||||
|
||||
// Ordered execution of the command
|
||||
const batch = bulkOperation.s.batches.shift();
|
||||
|
||||
function resultHandler(err, result) {
|
||||
// Error is a driver related error not a bulk op error, terminate
|
||||
if (((err && err.driver) || (err && err.message)) && !(err instanceof MongoWriteConcernError)) {
|
||||
return handleCallback(callback, err);
|
||||
}
|
||||
|
||||
// If we have and error
|
||||
if (err) err.ok = 0;
|
||||
if (err instanceof MongoWriteConcernError) {
|
||||
return handleMongoWriteConcernError(batch, bulkOperation.s.bulkResult, true, err, callback);
|
||||
}
|
||||
|
||||
// Merge the results together
|
||||
const writeResult = new BulkWriteResult(bulkOperation.s.bulkResult);
|
||||
const mergeResult = mergeBatchResults(true, batch, bulkOperation.s.bulkResult, err, result);
|
||||
if (mergeResult != null) {
|
||||
return handleCallback(callback, null, writeResult);
|
||||
}
|
||||
|
||||
if (bulkOperation.handleWriteError(callback, writeResult)) return;
|
||||
|
||||
// Execute the next command in line
|
||||
executeCommands(bulkOperation, options, callback);
|
||||
}
|
||||
|
||||
bulkOperation.finalOptionsHandler({ options, batch, resultHandler }, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
-103
@@ -2,16 +2,10 @@
|
||||
|
||||
const common = require('./common');
|
||||
const BulkOperationBase = common.BulkOperationBase;
|
||||
const Batch = common.Batch;
|
||||
const bson = common.bson;
|
||||
const utils = require('../utils');
|
||||
const toError = utils.toError;
|
||||
const handleCallback = utils.handleCallback;
|
||||
const BulkWriteResult = common.BulkWriteResult;
|
||||
const Batch = common.Batch;
|
||||
const mergeBatchResults = common.mergeBatchResults;
|
||||
const executeOperation = utils.executeOperation;
|
||||
const MongoWriteConcernError = require('mongodb-core').MongoWriteConcernError;
|
||||
const handleMongoWriteConcernError = require('./common').handleMongoWriteConcernError;
|
||||
const bson = common.bson;
|
||||
|
||||
/**
|
||||
* Add to internal list of Operations
|
||||
@@ -24,7 +18,11 @@ const bson = common.bson;
|
||||
function addToOperationsList(bulkOperation, docType, document) {
|
||||
// Get the bsonSize
|
||||
const bsonSize = bson.calculateObjectSize(document, {
|
||||
checkKeys: false
|
||||
checkKeys: false,
|
||||
|
||||
// Since we don't know what the user selected for BSON options here,
|
||||
// err on the safe side, and check the size with ignoreUndefined: false.
|
||||
ignoreUndefined: false
|
||||
});
|
||||
// Throw error if the doc is bigger than the max BSON size
|
||||
if (bsonSize >= bulkOperation.s.maxBatchSizeBytes)
|
||||
@@ -40,6 +38,8 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
bulkOperation.s.currentBatch = bulkOperation.s.currentRemoveBatch;
|
||||
}
|
||||
|
||||
const maxKeySize = bulkOperation.s.maxKeySize;
|
||||
|
||||
// Create a new batch object if we don't have a current one
|
||||
if (bulkOperation.s.currentBatch == null)
|
||||
bulkOperation.s.currentBatch = new Batch(docType, bulkOperation.s.currentIndex);
|
||||
@@ -47,7 +47,8 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
// Check if we need to create a new batch
|
||||
if (
|
||||
bulkOperation.s.currentBatch.size + 1 >= bulkOperation.s.maxWriteBatchSize ||
|
||||
bulkOperation.s.currentBatch.sizeBytes + bsonSize >= bulkOperation.s.maxBatchSizeBytes ||
|
||||
bulkOperation.s.currentBatch.sizeBytes + maxKeySize + bsonSize >=
|
||||
bulkOperation.s.maxBatchSizeBytes ||
|
||||
bulkOperation.s.currentBatch.batchType !== docType
|
||||
) {
|
||||
// Save the batch to the execution stack
|
||||
@@ -60,12 +61,12 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
// We have an array of documents
|
||||
if (Array.isArray(document)) {
|
||||
throw toError('operation passed in cannot be an Array');
|
||||
} else {
|
||||
bulkOperation.s.currentBatch.operations.push(document);
|
||||
bulkOperation.s.currentBatch.originalIndexes.push(bulkOperation.s.currentIndex);
|
||||
bulkOperation.s.currentIndex = bulkOperation.s.currentIndex + 1;
|
||||
}
|
||||
|
||||
bulkOperation.s.currentBatch.operations.push(document);
|
||||
bulkOperation.s.currentBatch.originalIndexes.push(bulkOperation.s.currentIndex);
|
||||
bulkOperation.s.currentIndex = bulkOperation.s.currentIndex + 1;
|
||||
|
||||
// Save back the current Batch to the right type
|
||||
if (docType === common.INSERT) {
|
||||
bulkOperation.s.currentInsertBatch = bulkOperation.s.currentBatch;
|
||||
@@ -80,8 +81,8 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
}
|
||||
|
||||
// Update current batch size
|
||||
bulkOperation.s.currentBatch.size = bulkOperation.s.currentBatch.size + 1;
|
||||
bulkOperation.s.currentBatch.sizeBytes = bulkOperation.s.currentBatch.sizeBytes + bsonSize;
|
||||
bulkOperation.s.currentBatch.size += 1;
|
||||
bulkOperation.s.currentBatch.sizeBytes += maxKeySize + bsonSize;
|
||||
|
||||
// Return bulkOperation
|
||||
return bulkOperation;
|
||||
@@ -90,6 +91,7 @@ function addToOperationsList(bulkOperation, docType, document) {
|
||||
/**
|
||||
* Create a new UnorderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly)
|
||||
* @class
|
||||
* @extends BulkOperationBase
|
||||
* @property {number} length Get the number of operations in the bulk.
|
||||
* @return {UnorderedBulkOperation} a UnorderedBulkOperation instance.
|
||||
*/
|
||||
@@ -100,93 +102,6 @@ class UnorderedBulkOperation extends BulkOperationBase {
|
||||
|
||||
super(topology, collection, options, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback format for results
|
||||
* @callback UnorderedBulkOperation~resultCallback
|
||||
* @param {MongoError} error An error instance representing the error during the execution.
|
||||
* @param {BulkWriteResult} result The bulk write result.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Execute the ordered bulk operation
|
||||
*
|
||||
* @method
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {(number|string)} [options.w] The write concern.
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
* @param {boolean} [options.j=false] Specify a journal write concern.
|
||||
* @param {boolean} [options.fsync=false] Specify a file sync write concern.
|
||||
* @param {UnorderedBulkOperation~resultCallback} [callback] The result callback
|
||||
* @throws {MongoError}
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
execute(_writeConcern, options, callback) {
|
||||
const ret = this.bulkExecute(_writeConcern, options, callback);
|
||||
options = ret.options;
|
||||
callback = ret.callback;
|
||||
|
||||
return executeOperation(this.s.topology, executeBatches, [this, options, callback]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the command
|
||||
*
|
||||
* @param {UnorderedBulkOperation} bulkOperation
|
||||
* @param {object} batch
|
||||
* @param {object} options
|
||||
* @param {function} callback
|
||||
*/
|
||||
function executeBatch(bulkOperation, batch, options, callback) {
|
||||
function resultHandler(err, result) {
|
||||
// Error is a driver related error not a bulk op error, terminate
|
||||
if (((err && err.driver) || (err && err.message)) && !(err instanceof MongoWriteConcernError)) {
|
||||
return handleCallback(callback, err);
|
||||
}
|
||||
|
||||
// If we have and error
|
||||
if (err) err.ok = 0;
|
||||
if (err instanceof MongoWriteConcernError) {
|
||||
return handleMongoWriteConcernError(batch, bulkOperation.s.bulkResult, false, err, callback);
|
||||
}
|
||||
handleCallback(
|
||||
callback,
|
||||
null,
|
||||
mergeBatchResults(false, batch, bulkOperation.s.bulkResult, err, result)
|
||||
);
|
||||
}
|
||||
|
||||
bulkOperation.finalOptionsHandler({ options, batch, resultHandler }, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all the commands
|
||||
*
|
||||
* @param {UnorderedBulkOperation} bulkOperation
|
||||
* @param {object} options
|
||||
* @param {function} callback
|
||||
*/
|
||||
function executeBatches(bulkOperation, options, callback) {
|
||||
let numberOfCommandsToExecute = bulkOperation.s.batches.length;
|
||||
// Execute over all the batches
|
||||
for (let i = 0; i < bulkOperation.s.batches.length; i++) {
|
||||
executeBatch(bulkOperation, bulkOperation.s.batches[i], options, function(err) {
|
||||
// Count down the number of commands left to execute
|
||||
numberOfCommandsToExecute = numberOfCommandsToExecute - 1;
|
||||
|
||||
// Execute
|
||||
if (numberOfCommandsToExecute === 0) {
|
||||
// Driver level error
|
||||
if (err) return handleCallback(callback, err);
|
||||
|
||||
const writeResult = new BulkWriteResult(bulkOperation.s.bulkResult);
|
||||
if (bulkOperation.handleWriteError(callback, writeResult)) return;
|
||||
|
||||
return handleCallback(callback, null, writeResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+14
@@ -368,6 +368,20 @@ function processNewChange(args) {
|
||||
const change = args.change;
|
||||
const callback = args.callback;
|
||||
const eventEmitter = args.eventEmitter || false;
|
||||
|
||||
// If the changeStream is closed, then it should not process a change.
|
||||
if (changeStream.isClosed()) {
|
||||
// We do not error in the eventEmitter case.
|
||||
if (eventEmitter) {
|
||||
return;
|
||||
}
|
||||
|
||||
const error = new MongoError('ChangeStream is closed');
|
||||
return typeof callback === 'function'
|
||||
? callback(error, null)
|
||||
: changeStream.promiseLibrary.reject(error);
|
||||
}
|
||||
|
||||
const topology = changeStream.topology;
|
||||
const options = changeStream.cursor.options;
|
||||
|
||||
|
||||
+57
-159
@@ -4,7 +4,6 @@ const deprecate = require('util').deprecate;
|
||||
const deprecateOptions = require('./utils').deprecateOptions;
|
||||
const checkCollectionName = require('./utils').checkCollectionName;
|
||||
const ObjectID = require('mongodb-core').BSON.ObjectID;
|
||||
const AggregationCursor = require('./aggregation_cursor');
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const toError = require('./utils').toError;
|
||||
const normalizeHintField = require('./utils').normalizeHintField;
|
||||
@@ -19,10 +18,10 @@ const unordered = require('./bulk/unordered');
|
||||
const ordered = require('./bulk/ordered');
|
||||
const ChangeStream = require('./change_stream');
|
||||
const executeOperation = require('./utils').executeOperation;
|
||||
const applyWriteConcern = require('./utils').applyWriteConcern;
|
||||
const resolveReadPreference = require('./utils').resolveReadPreference;
|
||||
|
||||
// Operations
|
||||
const aggregate = require('./operations/aggregate').aggregate;
|
||||
const bulkWrite = require('./operations/collection_ops').bulkWrite;
|
||||
const checkForAtomicOperators = require('./operations/collection_ops').checkForAtomicOperators;
|
||||
const count = require('./operations/collection_ops').count;
|
||||
@@ -46,12 +45,12 @@ const group = require('./operations/collection_ops').group;
|
||||
const indexes = require('./operations/collection_ops').indexes;
|
||||
const indexExists = require('./operations/collection_ops').indexExists;
|
||||
const indexInformation = require('./operations/collection_ops').indexInformation;
|
||||
const insertMany = require('./operations/collection_ops').insertMany;
|
||||
const insertOne = require('./operations/collection_ops').insertOne;
|
||||
const isCapped = require('./operations/collection_ops').isCapped;
|
||||
const mapReduce = require('./operations/collection_ops').mapReduce;
|
||||
const optionsOp = require('./operations/collection_ops').optionsOp;
|
||||
const parallelCollectionScan = require('./operations/collection_ops').parallelCollectionScan;
|
||||
const prepareDocs = require('./operations/collection_ops').prepareDocs;
|
||||
const reIndex = require('./operations/collection_ops').reIndex;
|
||||
const removeDocuments = require('./operations/collection_ops').removeDocuments;
|
||||
const rename = require('./operations/collection_ops').rename;
|
||||
@@ -269,7 +268,7 @@ const DEPRECATED_FIND_OPTIONS = ['maxScan', 'fields', 'snapshot'];
|
||||
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
|
||||
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
||||
* @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
|
||||
* @param {number} [options.maxTimeMS] Number of miliseconds to wait before aborting the query.
|
||||
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
||||
* @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @throws {MongoError}
|
||||
@@ -455,7 +454,7 @@ Collection.prototype.insertOne = function(doc, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -464,21 +463,6 @@ Collection.prototype.insertOne = function(doc, options, callback) {
|
||||
return executeOperation(this.s.topology, insertOne, [this, doc, options, callback]);
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an array of documents into MongoDB. If documents passed in do not contain the **_id** field,
|
||||
* one will be added to each of the documents missing it by the driver, mutating the document. This behavior
|
||||
@@ -502,33 +486,7 @@ Collection.prototype.insertMany = function(docs, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options ? Object.assign({}, options) : { ordered: true };
|
||||
|
||||
if (!Array.isArray(docs) && typeof callback === 'function') {
|
||||
return callback(
|
||||
MongoError.create({ message: 'docs parameter must be an array of documents', driver: true })
|
||||
);
|
||||
} else if (!Array.isArray(docs)) {
|
||||
return new this.s.promiseLibrary((resolve, reject) => {
|
||||
reject(
|
||||
MongoError.create({ message: 'docs parameter must be an array of documents', driver: true })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// If keep going set unordered
|
||||
options['serializeFunctions'] = options['serializeFunctions'] || this.s.serializeFunctions;
|
||||
|
||||
docs = prepareDocs(this, docs, options);
|
||||
|
||||
// Generate the bulk write operations
|
||||
const operations = [
|
||||
{
|
||||
insertMany: docs
|
||||
}
|
||||
];
|
||||
|
||||
return executeOperation(this.s.topology, bulkWrite, [this, operations, options, callback], {
|
||||
resultMutator: result => mapInsertManyResults(docs, result)
|
||||
});
|
||||
return executeOperation(this.s.topology, insertMany, [this, docs, options, callback]);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -727,7 +685,7 @@ Collection.prototype.updateOne = function(filter, update, options, callback) {
|
||||
|
||||
options = Object.assign({}, options);
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -755,7 +713,7 @@ Collection.prototype.replaceOne = function(filter, doc, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = Object.assign({}, options);
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -791,7 +749,7 @@ Collection.prototype.updateMany = function(filter, update, options, callback) {
|
||||
|
||||
options = Object.assign({}, options);
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -804,7 +762,7 @@ Collection.prototype.updateMany = function(filter, update, options, callback) {
|
||||
* Updates documents.
|
||||
* @method
|
||||
* @param {object} selector The selector for the update operation.
|
||||
* @param {object} document The update document.
|
||||
* @param {object} update The update operations to be applied to the documents
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {(number|string)} [options.w] The write concern.
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
@@ -820,11 +778,11 @@ Collection.prototype.updateMany = function(filter, update, options, callback) {
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
* @deprecated use updateOne, updateMany or bulkWrite
|
||||
*/
|
||||
Collection.prototype.update = deprecate(function(selector, document, options, callback) {
|
||||
Collection.prototype.update = deprecate(function(selector, update, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -833,7 +791,7 @@ Collection.prototype.update = deprecate(function(selector, document, options, ca
|
||||
return executeOperation(this.s.topology, updateDocuments, [
|
||||
this,
|
||||
selector,
|
||||
document,
|
||||
update,
|
||||
options,
|
||||
callback
|
||||
]);
|
||||
@@ -871,7 +829,7 @@ Collection.prototype.deleteOne = function(filter, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = Object.assign({}, options);
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -898,7 +856,7 @@ Collection.prototype.deleteMany = function(filter, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = Object.assign({}, options);
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -927,7 +885,7 @@ Collection.prototype.remove = deprecate(function(selector, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -954,7 +912,7 @@ Collection.prototype.save = deprecate(function(doc, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (this.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
@@ -1005,7 +963,7 @@ Collection.prototype.save = deprecate(function(doc, options, callback) {
|
||||
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
|
||||
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
||||
* @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
|
||||
* @param {number} [options.maxTimeMS] Number of miliseconds to wait before aborting the query.
|
||||
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
||||
* @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {Collection~resultCallback} [callback] The command result callback
|
||||
@@ -1168,7 +1126,7 @@ Collection.prototype.createIndexes = function(indexSpecs, options, callback) {
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
* @param {boolean} [options.j=false] Specify a journal write concern.
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {number} [options.maxTimeMS] Number of miliseconds to wait before aborting the query.
|
||||
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
||||
* @param {Collection~resultCallback} [callback] The command result callback
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
@@ -1188,7 +1146,7 @@ Collection.prototype.dropIndex = function(indexName, options, callback) {
|
||||
* @method
|
||||
* @param {Object} [options] Optional settings
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {number} [options.maxTimeMS] Number of miliseconds to wait before aborting the query.
|
||||
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
||||
* @param {Collection~resultCallback} [callback] The command result callback
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
@@ -1360,7 +1318,7 @@ Collection.prototype.indexInformation = function(options, callback) {
|
||||
* @param {boolean} [options.skip] The number of documents to skip for the count.
|
||||
* @param {string} [options.hint] An index name hint for the query.
|
||||
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
||||
* @param {number} [options.maxTimeMS] Number of miliseconds to wait before aborting the query.
|
||||
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {Collection~countCallback} [callback] The command result callback
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
@@ -1434,13 +1392,13 @@ Collection.prototype.countDocuments = function(query, options, callback) {
|
||||
};
|
||||
|
||||
/**
|
||||
* The distinct command returns returns a list of distinct values for the given key across a collection.
|
||||
* The distinct command returns a list of distinct values for the given key across a collection.
|
||||
* @method
|
||||
* @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.
|
||||
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
||||
* @param {number} [options.maxTimeMS] Number of miliseconds to wait before aborting the query.
|
||||
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {Collection~resultCallback} [callback] The command result callback
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
@@ -1557,6 +1515,13 @@ Collection.prototype.findOneAndReplace = function(filter, replacement, options,
|
||||
if (replacement == null || typeof replacement !== 'object')
|
||||
throw toError('replacement parameter must be an object');
|
||||
|
||||
// Check that there are no atomic operators
|
||||
const keys = Object.keys(replacement);
|
||||
|
||||
if (keys[0] && keys[0][0] === '$') {
|
||||
throw toError('The replacement document must not contain atomic operators.');
|
||||
}
|
||||
|
||||
return executeOperation(this.s.topology, findOneAndReplace, [
|
||||
this,
|
||||
filter,
|
||||
@@ -1629,7 +1594,18 @@ Collection.prototype.findOneAndUpdate = function(filter, update, options, callba
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
* @deprecated use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead
|
||||
*/
|
||||
Collection.prototype.findAndModify = deprecate(function(query, sort, doc, options, callback) {
|
||||
Collection.prototype.findAndModify = deprecate(
|
||||
_findAndModify,
|
||||
'collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.'
|
||||
);
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
Collection.prototype._findAndModify = _findAndModify;
|
||||
|
||||
function _findAndModify(query, sort, doc, options, callback) {
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
|
||||
sort = args.length ? args.shift() || [] : [];
|
||||
@@ -1649,7 +1625,7 @@ Collection.prototype.findAndModify = deprecate(function(query, sort, doc, option
|
||||
options,
|
||||
callback
|
||||
]);
|
||||
}, 'collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and remove a document.
|
||||
@@ -1692,6 +1668,7 @@ Collection.prototype.findAndRemove = deprecate(function(query, sort, options, ca
|
||||
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
|
||||
* @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
|
||||
* @param {string} [options.comment] Add a comment to an aggregation command
|
||||
* @param {string|object} [options.hint] Add an index selection hint to an aggregation command
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {Collection~aggregationCallback} callback The command result callback
|
||||
* @return {(null|AggregationCursor)}
|
||||
@@ -1732,97 +1709,7 @@ Collection.prototype.aggregate = function(pipeline, options, callback) {
|
||||
pipeline = args;
|
||||
}
|
||||
|
||||
// Ignore readConcern option
|
||||
let ignoreReadConcern = false;
|
||||
|
||||
// Build the command
|
||||
const command = { aggregate: this.s.name, pipeline: pipeline };
|
||||
|
||||
// If out was specified
|
||||
if (typeof options.out === 'string') {
|
||||
pipeline.push({ $out: options.out });
|
||||
// Ignore read concern
|
||||
ignoreReadConcern = true;
|
||||
} else if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out']) {
|
||||
ignoreReadConcern = true;
|
||||
}
|
||||
|
||||
// Decorate command with writeConcern if out has been specified
|
||||
if (
|
||||
pipeline.length > 0 &&
|
||||
pipeline[pipeline.length - 1]['$out'] &&
|
||||
this.s.topology.capabilities().commandsTakeWriteConcern
|
||||
) {
|
||||
applyWriteConcern(command, { db: this.s.db, collection: this }, options);
|
||||
}
|
||||
|
||||
// Have we specified collation
|
||||
try {
|
||||
decorateWithCollation(command, this, options);
|
||||
} catch (err) {
|
||||
if (typeof callback === 'function') return callback(err, null);
|
||||
throw err;
|
||||
}
|
||||
|
||||
// If we have bypassDocumentValidation set
|
||||
if (options.bypassDocumentValidation === true) {
|
||||
command.bypassDocumentValidation = options.bypassDocumentValidation;
|
||||
}
|
||||
|
||||
// Do we have a readConcern specified
|
||||
if (!ignoreReadConcern) {
|
||||
decorateWithReadConcern(command, this, options);
|
||||
}
|
||||
|
||||
// If we have allowDiskUse defined
|
||||
if (options.allowDiskUse) command.allowDiskUse = options.allowDiskUse;
|
||||
if (typeof options.maxTimeMS === 'number') command.maxTimeMS = options.maxTimeMS;
|
||||
|
||||
// If we are giving a hint
|
||||
if (options.hint) command.hint = options.hint;
|
||||
|
||||
options = Object.assign({}, options);
|
||||
// Ensure we have the right read preference inheritance
|
||||
options.readPreference = resolveReadPreference(options, { db: this.s.db, collection: this });
|
||||
|
||||
// If explain has been specified add it
|
||||
if (options.explain) {
|
||||
if (command.readConcern || command.writeConcern) {
|
||||
throw toError('"explain" cannot be used on an aggregate call with readConcern/writeConcern');
|
||||
}
|
||||
command.explain = options.explain;
|
||||
}
|
||||
|
||||
if (typeof options.comment === 'string') command.comment = options.comment;
|
||||
|
||||
// Validate that cursor options is valid
|
||||
if (options.cursor != null && typeof options.cursor !== 'object') {
|
||||
throw toError('cursor options must be an object');
|
||||
}
|
||||
|
||||
options.cursor = options.cursor || {};
|
||||
if (options.batchSize) options.cursor.batchSize = options.batchSize;
|
||||
command.cursor = options.cursor;
|
||||
|
||||
// promiseLibrary
|
||||
options.promiseLibrary = this.s.promiseLibrary;
|
||||
|
||||
// Set the AggregationCursor constructor
|
||||
options.cursorFactory = AggregationCursor;
|
||||
if (typeof callback !== 'function') {
|
||||
if (!this.s.topology.capabilities()) {
|
||||
throw new MongoError('cannot connect to server');
|
||||
}
|
||||
|
||||
// Allow disk usage command
|
||||
if (typeof options.allowDiskUse === 'boolean') command.allowDiskUse = options.allowDiskUse;
|
||||
if (typeof options.maxTimeMS === 'number') command.maxTimeMS = options.maxTimeMS;
|
||||
|
||||
// Execute the cursor
|
||||
return this.s.topology.cursor(this.s.namespace, command, options);
|
||||
}
|
||||
|
||||
return handleCallback(callback, null, this.s.topology.cursor(this.s.namespace, command, options));
|
||||
return aggregate(this.s.db, this, pipeline, options, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1873,7 +1760,7 @@ Collection.prototype.watch = function(pipeline, options) {
|
||||
* @param {Collection~parallelCollectionScanCallback} [callback] The command result callback
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
Collection.prototype.parallelCollectionScan = function(options, callback) {
|
||||
Collection.prototype.parallelCollectionScan = deprecate(function(options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = { numCursors: 1 });
|
||||
// Set number of cursors to 1
|
||||
options.numCursors = options.numCursors || 1;
|
||||
@@ -1893,7 +1780,7 @@ Collection.prototype.parallelCollectionScan = function(options, callback) {
|
||||
return executeOperation(this.s.topology, parallelCollectionScan, [this, options, callback], {
|
||||
skipSessions: true
|
||||
});
|
||||
};
|
||||
}, 'parallelCollectionScan is deprecated in MongoDB v4.1');
|
||||
|
||||
/**
|
||||
* Execute a geo search using a geo haystack index on a collection.
|
||||
@@ -2047,11 +1934,17 @@ Collection.prototype.mapReduce = function(map, reduce, options, callback) {
|
||||
* @param {(number|string)} [options.w] The write concern.
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
* @param {boolean} [options.j=false] Specify a journal write concern.
|
||||
* @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @return {UnorderedBulkOperation}
|
||||
*/
|
||||
Collection.prototype.initializeUnorderedBulkOp = function(options) {
|
||||
options = options || {};
|
||||
// Give function's options precedence over session options.
|
||||
if (options.ignoreUndefined == null) {
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
}
|
||||
|
||||
options.promiseLibrary = this.s.promiseLibrary;
|
||||
return unordered(this.s.topology, this, options);
|
||||
};
|
||||
@@ -2065,11 +1958,16 @@ Collection.prototype.initializeUnorderedBulkOp = function(options) {
|
||||
* @param {number} [options.wtimeout] The write concern timeout.
|
||||
* @param {boolean} [options.j=false] Specify a journal write concern.
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
||||
* @param {OrderedBulkOperation} callback The command result callback
|
||||
* @return {null}
|
||||
*/
|
||||
Collection.prototype.initializeOrderedBulkOp = function(options) {
|
||||
options = options || {};
|
||||
// Give function's options precedence over session's options.
|
||||
if (options.ignoreUndefined == null) {
|
||||
options.ignoreUndefined = this.s.options.ignoreUndefined;
|
||||
}
|
||||
options.promiseLibrary = this.s.promiseLibrary;
|
||||
return ordered(this.s.topology, this, options);
|
||||
};
|
||||
|
||||
+7
-2
@@ -5,6 +5,7 @@ const ReadPreference = require('mongodb-core').ReadPreference;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const Readable = require('stream').Readable;
|
||||
const CoreCursor = require('./cursor');
|
||||
const SUPPORTS = require('./utils').SUPPORTS;
|
||||
|
||||
/**
|
||||
* @fileOverview The **CommandCursor** class is an internal class that embodies a
|
||||
@@ -156,6 +157,10 @@ for (var i = 0; i < methodsToInherit.length; i++) {
|
||||
CommandCursor.prototype[methodsToInherit[i]] = CoreCursor.prototype[methodsToInherit[i]];
|
||||
}
|
||||
|
||||
if (SUPPORTS.ASYNC_ITERATOR) {
|
||||
CommandCursor.prototype[Symbol.asyncIterator] = require('./async/async_iterator').asyncIterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ReadPreference for the cursor.
|
||||
* @method
|
||||
@@ -254,7 +259,7 @@ CommandCursor.prototype.get = CommandCursor.prototype.toArray;
|
||||
/**
|
||||
* Returns an array of documents. The caller is responsible for making sure that there
|
||||
* is enough memory to store the results. Note that the array only contain partial
|
||||
* results when this cursor had been previouly accessed.
|
||||
* results when this cursor had been previously accessed.
|
||||
* @method CommandCursor.prototype.toArray
|
||||
* @param {CommandCursor~toArrayResultCallback} [callback] The result callback.
|
||||
* @throws {MongoError}
|
||||
@@ -270,7 +275,7 @@ CommandCursor.prototype.get = CommandCursor.prototype.toArray;
|
||||
|
||||
/**
|
||||
* Iterates over all the documents for this cursor. As with **{cursor.toArray}**,
|
||||
* not all of the elements will be iterated if this cursor had been previouly accessed.
|
||||
* not all of the elements will be iterated if this cursor had been previously accessed.
|
||||
* In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike
|
||||
* **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements
|
||||
* at any given time if batch size is specified. Otherwise, the caller is responsible
|
||||
|
||||
+8
-3
@@ -5,6 +5,7 @@ const PassThrough = require('stream').PassThrough;
|
||||
const inherits = require('util').inherits;
|
||||
const deprecate = require('util').deprecate;
|
||||
const handleCallback = require('./utils').handleCallback;
|
||||
const SUPPORTS = require('./utils').SUPPORTS;
|
||||
const ReadPreference = require('mongodb-core').ReadPreference;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const Readable = require('stream').Readable;
|
||||
@@ -203,6 +204,10 @@ function Cursor(bson, ns, cmd, options, topology, topologyOptions) {
|
||||
// Inherit from Readable
|
||||
inherits(Cursor, Readable);
|
||||
|
||||
if (SUPPORTS.ASYNC_ITERATOR) {
|
||||
Cursor.prototype[Symbol.asyncIterator] = require('./async/async_iterator').asyncIterator;
|
||||
}
|
||||
|
||||
// Map core cursor _next method so we can apply mapping
|
||||
Cursor.prototype._next = function() {
|
||||
if (this._initImplicitSession) {
|
||||
@@ -688,7 +693,7 @@ Cursor.prototype.skip = function(value) {
|
||||
|
||||
/**
|
||||
* Iterates over all the documents for this cursor. As with **{cursor.toArray}**,
|
||||
* not all of the elements will be iterated if this cursor had been previouly accessed.
|
||||
* not all of the elements will be iterated if this cursor had been previously accessed.
|
||||
* In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike
|
||||
* **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements
|
||||
* at any given time if batch size is specified. Otherwise, the caller is responsible
|
||||
@@ -806,7 +811,7 @@ Cursor.prototype.setReadPreference = function(readPreference) {
|
||||
/**
|
||||
* Returns an array of documents. The caller is responsible for making sure that there
|
||||
* is enough memory to store the results. Note that the array only contains partial
|
||||
* results when this cursor had been previouly accessed. In that case,
|
||||
* results when this cursor had been previously accessed. In that case,
|
||||
* cursor.rewind() can be used to reset the cursor.
|
||||
* @method
|
||||
* @param {Cursor~toArrayResultCallback} [callback] The result callback.
|
||||
@@ -840,7 +845,7 @@ Cursor.prototype.toArray = function(callback) {
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {number} [options.skip] The number of documents to skip.
|
||||
* @param {number} [options.limit] The maximum amounts to count before aborting.
|
||||
* @param {number} [options.maxTimeMS] Number of miliseconds to wait before aborting the query.
|
||||
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
||||
* @param {string} [options.hint] An index name hint for the query.
|
||||
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
||||
* @param {Cursor~countResultCallback} [callback] The result callback.
|
||||
|
||||
+50
-4
@@ -23,6 +23,7 @@ const CONSTANTS = require('./constants');
|
||||
|
||||
// Operations
|
||||
const addUser = require('./operations/db_ops').addUser;
|
||||
const aggregate = require('./operations/aggregate').aggregate;
|
||||
const collections = require('./operations/db_ops').collections;
|
||||
const createCollection = require('./operations/db_ops').createCollection;
|
||||
const createIndex = require('./operations/db_ops').createIndex;
|
||||
@@ -112,7 +113,7 @@ const legalOptionNames = [
|
||||
* @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys.
|
||||
* @param {object} [options.promiseLibrary] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
|
||||
* @param {object} [options.readConcern] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
|
||||
* @param {object} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
|
||||
* @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
|
||||
* @property {(Server|ReplSet|Mongos)} serverConfig Get the current db topology.
|
||||
* @property {number} bufferMaxEntries Current bufferMaxEntries value for the database
|
||||
* @property {string} databaseName The name of the database this instance represents.
|
||||
@@ -263,6 +264,44 @@ Db.prototype.command = function(command, options, callback) {
|
||||
return executeOperation(this.s.topology, executeCommand, [this, command, options, callback]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute an aggregation framework pipeline against the database, needs MongoDB >= 3.6
|
||||
* @method
|
||||
* @param {object} [pipeline=[]] Array containing all the aggregation framework commands for the execution.
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
||||
* @param {object} [options.cursor] Return the query as cursor, on 2.6 > it returns as a real cursor on pre 2.6 it returns as an emulated cursor.
|
||||
* @param {number} [options.cursor.batchSize] The batchSize for the cursor
|
||||
* @param {boolean} [options.explain=false] Explain returns the aggregation execution plan (requires mongodb 2.6 >).
|
||||
* @param {boolean} [options.allowDiskUse=false] allowDiskUse lets the server know if it can use disk to store temporary results for the aggregation (requires mongodb 2.6 >).
|
||||
* @param {number} [options.maxTimeMS] maxTimeMS specifies a cumulative time limit in milliseconds for processing operations on the cursor. MongoDB interrupts the operation at the earliest following interrupt point.
|
||||
* @param {boolean} [options.bypassDocumentValidation=false] Allow driver to bypass schema validation in MongoDB 3.2 or higher.
|
||||
* @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
|
||||
* @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
|
||||
* @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
|
||||
* @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
|
||||
* @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
|
||||
* @param {string} [options.comment] Add a comment to an aggregation command
|
||||
* @param {string|object} [options.hint] Add an index selection hint to an aggregation command
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {Database~aggregationCallback} callback The command result callback
|
||||
* @return {(null|AggregationCursor)}
|
||||
*/
|
||||
Db.prototype.aggregate = function(pipeline, options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
// If we have no options or callback we are doing
|
||||
// a cursor based aggregation
|
||||
if (options == null && callback == null) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
return aggregate(this, '1', pipeline, options, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the Admin db instance
|
||||
* @method
|
||||
@@ -281,6 +320,13 @@ Db.prototype.admin = function() {
|
||||
* @param {Collection} collection The collection instance.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The callback format for an aggregation call
|
||||
* @callback Database~aggregationCallback
|
||||
* @param {MongoError} error An error instance representing the error during the execution.
|
||||
* @param {AggregationCursor} cursor The cursor if the aggregation command was executed successfully.
|
||||
*/
|
||||
|
||||
const collectionKeys = [
|
||||
'pkFactory',
|
||||
'readPreference',
|
||||
@@ -309,7 +355,7 @@ const collectionKeys = [
|
||||
* @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
|
||||
* @param {boolean} [options.strict=false] Returns an error if the collection does not exist
|
||||
* @param {object} [options.readConcern] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
|
||||
* @param {object} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
|
||||
* @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
|
||||
* @param {Db~collectionResultCallback} [callback] The collection result callback
|
||||
* @return {Collection} return the new Collection instance if not in strict mode
|
||||
*/
|
||||
@@ -549,7 +595,7 @@ Db.prototype.listCollections = function(filter, options) {
|
||||
* @param {Code} code JavaScript to execute on server.
|
||||
* @param {(object|array)} parameters The parameters for the call.
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {boolean} [options.nolock=false] Tell MongoDB not to block on the evaulation of the javascript.
|
||||
* @param {boolean} [options.nolock=false] Tell MongoDB not to block on the evaluation of the javascript.
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
* @param {Db~resultCallback} [callback] The results callback
|
||||
* @deprecated Eval is deprecated on MongoDB 3.2 and forward
|
||||
@@ -821,7 +867,7 @@ Db.prototype.setProfilingLevel = function(level, options, callback) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrive the current profiling information for MongoDB
|
||||
* Retrieve the current profiling information for MongoDB
|
||||
*
|
||||
* @param {Object} [options] Optional settings
|
||||
* @param {ClientSession} [options.session] optional session to use for this operation
|
||||
|
||||
+6
-7
@@ -234,13 +234,12 @@ function doRead(_this) {
|
||||
_this.s.bytesToSkip = 0;
|
||||
}
|
||||
|
||||
if (expectedN === _this.s.expectedEnd && _this.s.bytesToTrim != null) {
|
||||
sliceEnd = _this.s.bytesToTrim;
|
||||
}
|
||||
|
||||
// If the remaining amount of data left is < chunkSize read the right amount of data
|
||||
if (_this.s.options.end && _this.s.options.end - _this.s.bytesToSkip < buf.length) {
|
||||
sliceEnd = _this.s.options.end - _this.s.bytesToSkip;
|
||||
const atEndOfStream = expectedN === _this.s.expectedEnd - 1;
|
||||
const bytesLeftToRead = _this.s.options.end - _this.s.bytesToSkip;
|
||||
if (atEndOfStream && _this.s.bytesToTrim != null) {
|
||||
sliceEnd = _this.s.file.chunkSize - _this.s.bytesToTrim;
|
||||
} else if (_this.s.options.end && bytesLeftToRead < doc.data.length()) {
|
||||
sliceEnd = bytesLeftToRead;
|
||||
}
|
||||
|
||||
if (sliceStart != null || sliceEnd != null) {
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ const deprecationFn = deprecate(() => {},
|
||||
*
|
||||
* Modes
|
||||
* - **"r"** - read only. This is the default mode.
|
||||
* - **"w"** - write in truncate mode. Existing data will be overwriten.
|
||||
* - **"w"** - write in truncate mode. Existing data will be overwritten.
|
||||
*
|
||||
* @class
|
||||
* @param {Db} db A database instance to interact with.
|
||||
|
||||
+19
-50
@@ -4,14 +4,14 @@ const ChangeStream = require('./change_stream');
|
||||
const Db = require('./db');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const executeOperation = require('./utils').executeOperation;
|
||||
const handleCallback = require('./utils').handleCallback;
|
||||
const inherits = require('util').inherits;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const deprecate = require('util').deprecate;
|
||||
|
||||
// Operations
|
||||
const connectOp = require('./operations/mongo_client_ops').connectOp;
|
||||
const logout = require('./operations/mongo_client_ops').logout;
|
||||
const validOptions = require('./operations/mongo_client_ops').validOptions;
|
||||
const closeOperation = require('./operations/mongo_client_ops').closeOperation;
|
||||
|
||||
/**
|
||||
* @fileOverview The **MongoClient** class is a class that allows for making Connections to MongoDB.
|
||||
@@ -46,6 +46,12 @@ const validOptions = require('./operations/mongo_client_ops').validOptions;
|
||||
* });
|
||||
*/
|
||||
|
||||
/**
|
||||
* A string specifying the level of a ReadConcern
|
||||
* @typedef {'local'|'available'|'majority'|'linearizable'|'snapshot'} ReadConcernLevel
|
||||
* @see https://docs.mongodb.com/manual/reference/read-concern/index.html#read-concern-levels
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new MongoClient instance
|
||||
* @class
|
||||
@@ -53,7 +59,7 @@ const validOptions = require('./operations/mongo_client_ops').validOptions;
|
||||
* @param {object} [options] Optional settings
|
||||
* @param {number} [options.poolSize=5] The maximum size of the individual server pool
|
||||
* @param {boolean} [options.ssl=false] Enable SSL connection.
|
||||
* @param {boolean} [options.sslValidate=true] Validate mongod server certificate against Certificate Authority
|
||||
* @param {boolean} [options.sslValidate=false] Validate mongod server certificate against Certificate Authority
|
||||
* @param {buffer} [options.sslCA=undefined] SSL Certificate store binary buffer
|
||||
* @param {buffer} [options.sslCert=undefined] SSL Certificate binary buffer
|
||||
* @param {buffer} [options.sslKey=undefined] SSL Key file binary buffer
|
||||
@@ -88,7 +94,7 @@ const validOptions = require('./operations/mongo_client_ops').validOptions;
|
||||
* @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys
|
||||
* @param {object} [options.promiseLibrary] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
|
||||
* @param {object} [options.readConcern] Specify a read concern for the collection (only MongoDB 3.2 or higher supported)
|
||||
* @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
|
||||
* @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
|
||||
* @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed)
|
||||
* @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
|
||||
* @param {object} [options.logger=undefined] Custom logger object
|
||||
@@ -110,6 +116,7 @@ const validOptions = require('./operations/mongo_client_ops').validOptions;
|
||||
* @param {boolean} [options.monitorCommands=false] Enable command monitoring for this client
|
||||
* @param {number} [options.minSize] If present, the connection pool will be initialized with minSize connections, and will never dip below minSize connections
|
||||
* @param {boolean} [options.useNewUrlParser=false] Determines whether or not to use the new url parser. Enables the new, spec-compliant, url parser shipped in the core driver. This url parser fixes a number of problems with the original parser, and aims to outright replace that parser in the near future.
|
||||
* @param {boolean} [options.useUnifiedTopology] Enables the new unified topology layer
|
||||
* @param {MongoClient~connectCallback} [callback] The command result callback
|
||||
* @return {MongoClient} a MongoClient instance
|
||||
*/
|
||||
@@ -170,60 +177,22 @@ MongoClient.prototype.connect = function(callback) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Logout user from server, fire off on all connections and remove all auth info
|
||||
* @method
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {string} [options.dbName] Logout against different database than current.
|
||||
* @param {Db~resultCallback} [callback] The command result callback
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
MongoClient.prototype.logout = function(options, callback) {
|
||||
MongoClient.prototype.logout = deprecate(function(options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
// Establish the correct database name
|
||||
const dbName = this.s.options.authSource ? this.s.options.authSource : this.s.options.dbName;
|
||||
|
||||
return executeOperation(this, logout, [this, dbName, callback], {
|
||||
skipSessions: true
|
||||
});
|
||||
};
|
||||
if (typeof callback === 'function') callback(null, true);
|
||||
}, 'Multiple authentication is prohibited on a connected client, please only authenticate once per MongoClient');
|
||||
|
||||
/**
|
||||
* Close the db and its underlying connections
|
||||
* @method
|
||||
* @param {boolean} force Force close, emitting no events
|
||||
* @param {boolean} [force=false] Force close, emitting no events
|
||||
* @param {Db~noResultCallback} [callback] The result callback
|
||||
* @return {Promise} returns Promise if no callback passed
|
||||
*/
|
||||
MongoClient.prototype.close = function(force, callback) {
|
||||
if (typeof force === 'function') (callback = force), (force = false);
|
||||
|
||||
// Close the topology connection
|
||||
if (this.topology) {
|
||||
this.topology.close(force);
|
||||
}
|
||||
// Emit close event
|
||||
this.emit('close', this);
|
||||
|
||||
// Fire close event on any cached db instances
|
||||
for (const name in this.s.dbCache) {
|
||||
this.s.dbCache[name].emit('close');
|
||||
}
|
||||
|
||||
// Remove listeners after emit
|
||||
this.removeAllListeners('close');
|
||||
|
||||
// Callback after next event loop tick
|
||||
if (typeof callback === 'function')
|
||||
return process.nextTick(() => {
|
||||
handleCallback(callback, null);
|
||||
});
|
||||
|
||||
// Return dummy promise
|
||||
return new this.s.promiseLibrary(resolve => {
|
||||
resolve();
|
||||
return executeOperation(this, closeOperation, [this, force, callback], {
|
||||
skipSessions: true
|
||||
});
|
||||
};
|
||||
|
||||
@@ -302,7 +271,7 @@ MongoClient.prototype.isConnected = function(options) {
|
||||
* @param {object} [options] Optional settings
|
||||
* @param {number} [options.poolSize=5] The maximum size of the individual server pool
|
||||
* @param {boolean} [options.ssl=false] Enable SSL connection.
|
||||
* @param {boolean} [options.sslValidate=true] Validate mongod server certificate against Certificate Authority
|
||||
* @param {boolean} [options.sslValidate=false] Validate mongod server certificate against Certificate Authority
|
||||
* @param {buffer} [options.sslCA=undefined] SSL Certificate store binary buffer
|
||||
* @param {buffer} [options.sslCert=undefined] SSL Certificate binary buffer
|
||||
* @param {buffer} [options.sslKey=undefined] SSL Key file binary buffer
|
||||
@@ -337,7 +306,7 @@ MongoClient.prototype.isConnected = function(options) {
|
||||
* @param {object} [options.pkFactory] A primary key factory object for generation of custom _id keys
|
||||
* @param {object} [options.promiseLibrary] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
|
||||
* @param {object} [options.readConcern] Specify a read concern for the collection (only MongoDB 3.2 or higher supported)
|
||||
* @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
|
||||
* @param {ReadConcernLevel} [options.readConcern.level='local'] Specify a read concern level for the collection operations (only MongoDB 3.2 or higher supported)
|
||||
* @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed)
|
||||
* @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
|
||||
* @param {object} [options.logger=undefined] Custom logger object
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
'use strict';
|
||||
|
||||
const AggregationCursor = require('../aggregation_cursor');
|
||||
const applyWriteConcern = require('../utils').applyWriteConcern;
|
||||
const decorateWithCollation = require('../utils').decorateWithCollation;
|
||||
const decorateWithReadConcern = require('../utils').decorateWithReadConcern;
|
||||
const handleCallback = require('../utils').handleCallback;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const resolveReadPreference = require('../utils').resolveReadPreference;
|
||||
const toError = require('../utils').toError;
|
||||
|
||||
const DB_AGGREGATE_COLLECTION = 1;
|
||||
|
||||
/**
|
||||
* Perform an aggregate operation. See Collection.prototype.aggregate or Db.prototype.aggregate for more information.
|
||||
*
|
||||
* @method
|
||||
* @param {Db} db A Db instance.
|
||||
* @param {Collection|string} coll A collection instance or the string '1', used for db.aggregate.
|
||||
* @param {object} [pipeline=[]] Array containing all the aggregation framework commands for the execution.
|
||||
* @param {object} [options] Optional settings. See Collection.prototype.aggregate or Db.prototype.aggregate for a list of options.
|
||||
* @param {Db~aggregationCallback|Collection~aggregationCallback} callback The command result callback
|
||||
*/
|
||||
function aggregate(db, coll, pipeline, options, callback) {
|
||||
const isDbAggregate = typeof coll === 'string';
|
||||
const target = isDbAggregate ? db : coll;
|
||||
const topology = target.s.topology;
|
||||
let hasOutStage = false;
|
||||
|
||||
if (typeof options.out === 'string') {
|
||||
pipeline = pipeline.concat({ $out: options.out });
|
||||
hasOutStage = true;
|
||||
} else if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out']) {
|
||||
hasOutStage = true;
|
||||
}
|
||||
|
||||
let command;
|
||||
let namespace;
|
||||
let optionSources;
|
||||
|
||||
if (isDbAggregate) {
|
||||
command = { aggregate: DB_AGGREGATE_COLLECTION, pipeline: pipeline };
|
||||
namespace = `${db.s.databaseName}.${DB_AGGREGATE_COLLECTION}`;
|
||||
|
||||
optionSources = { db };
|
||||
} else {
|
||||
command = { aggregate: coll.s.name, pipeline: pipeline };
|
||||
namespace = coll.s.namespace;
|
||||
|
||||
optionSources = { db: coll.s.db, collection: coll };
|
||||
}
|
||||
|
||||
const takesWriteConcern = topology.capabilities().commandsTakeWriteConcern;
|
||||
|
||||
if (!hasOutStage) {
|
||||
decorateWithReadConcern(command, target, options);
|
||||
}
|
||||
|
||||
if (pipeline.length > 0 && pipeline[pipeline.length - 1]['$out'] && takesWriteConcern) {
|
||||
applyWriteConcern(command, optionSources, options);
|
||||
}
|
||||
|
||||
try {
|
||||
decorateWithCollation(command, target, options);
|
||||
} catch (err) {
|
||||
if (typeof callback === 'function') return callback(err, null);
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (options.bypassDocumentValidation === true) {
|
||||
command.bypassDocumentValidation = options.bypassDocumentValidation;
|
||||
}
|
||||
|
||||
if (typeof options.allowDiskUse === 'boolean') command.allowDiskUse = options.allowDiskUse;
|
||||
if (typeof options.maxTimeMS === 'number') command.maxTimeMS = options.maxTimeMS;
|
||||
|
||||
if (options.hint) command.hint = options.hint;
|
||||
|
||||
options = Object.assign({}, options);
|
||||
|
||||
// Ensure we have the right read preference inheritance
|
||||
options.readPreference = resolveReadPreference(options, optionSources);
|
||||
|
||||
if (options.explain) {
|
||||
if (command.readConcern || command.writeConcern) {
|
||||
throw toError('"explain" cannot be used on an aggregate call with readConcern/writeConcern');
|
||||
}
|
||||
command.explain = options.explain;
|
||||
}
|
||||
|
||||
if (typeof options.comment === 'string') command.comment = options.comment;
|
||||
|
||||
// Validate that cursor options is valid
|
||||
if (options.cursor != null && typeof options.cursor !== 'object') {
|
||||
throw toError('cursor options must be an object');
|
||||
}
|
||||
|
||||
options.cursor = options.cursor || {};
|
||||
if (options.batchSize && !hasOutStage) options.cursor.batchSize = options.batchSize;
|
||||
command.cursor = options.cursor;
|
||||
|
||||
// promiseLibrary
|
||||
options.promiseLibrary = target.s.promiseLibrary;
|
||||
|
||||
// Set the AggregationCursor constructor
|
||||
options.cursorFactory = AggregationCursor;
|
||||
|
||||
if (typeof callback !== 'function') {
|
||||
if (!topology.capabilities()) {
|
||||
throw new MongoError('cannot connect to server');
|
||||
}
|
||||
|
||||
return topology.cursor(namespace, command, options);
|
||||
}
|
||||
|
||||
return handleCallback(callback, null, topology.cursor(namespace, command, options));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
aggregate
|
||||
};
|
||||
+71
-4
@@ -22,6 +22,21 @@ const MongoError = require('mongodb-core').MongoError;
|
||||
const ReadPreference = require('mongodb-core').ReadPreference;
|
||||
const toError = require('../utils').toError;
|
||||
|
||||
let collection;
|
||||
function loadCollection() {
|
||||
if (!collection) {
|
||||
collection = require('../collection');
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
let db;
|
||||
function loadDb() {
|
||||
if (!db) {
|
||||
db = require('../db');
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group function helper
|
||||
* @ignore
|
||||
@@ -66,7 +81,7 @@ const groupFunction =
|
||||
* @param {Collection~bulkWriteOpCallback} [callback] The command result callback
|
||||
*/
|
||||
function bulkWrite(coll, operations, options, callback) {
|
||||
// Add ignoreUndfined
|
||||
// Add ignoreUndefined
|
||||
if (coll.s.options.ignoreUndefined) {
|
||||
options = Object.assign({}, options);
|
||||
options.ignoreUndefined = coll.s.options.ignoreUndefined;
|
||||
@@ -210,7 +225,7 @@ function countDocuments(coll, query, options, callback) {
|
||||
pipeline.push({ $limit: limit });
|
||||
}
|
||||
|
||||
pipeline.push({ $group: { _id: null, n: { $sum: 1 } } });
|
||||
pipeline.push({ $group: { _id: 1, n: { $sum: 1 } } });
|
||||
|
||||
delete options.limit;
|
||||
delete options.skip;
|
||||
@@ -877,6 +892,57 @@ function insertOne(coll, doc, options, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an array of documents into MongoDB. If documents passed in do not contain the **_id** field,
|
||||
* one will be added to each of the documents missing it by the driver, mutating the document. This behavior
|
||||
* can be overridden by setting the **forceServerObjectId** flag.
|
||||
*
|
||||
* @method
|
||||
* @param {Collection} a Collection instance.
|
||||
* @param {object[]} docs Documents to insert.
|
||||
* @param {number} [options] Optional settings. See Collection.prototype.insertMany for a list of options.
|
||||
* @param {Collection~insertWriteOpCallback} [callback] The command result callback
|
||||
*/
|
||||
function insertMany(coll, docs, options, callback) {
|
||||
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
|
||||
}
|
||||
];
|
||||
|
||||
bulkWrite(coll, operations, options, (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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the collection is a capped collection.
|
||||
*
|
||||
@@ -987,7 +1053,7 @@ function mapReduce(coll, map, reduce, options, callback) {
|
||||
if (result.result != null && typeof result.result === 'object') {
|
||||
const doc = result.result;
|
||||
// Return a collection from another db
|
||||
const Db = require('../db');
|
||||
let Db = loadDb();
|
||||
collection = new Db(doc.db, coll.s.db.s.topology, coll.s.db.s.options).collection(
|
||||
doc.collection
|
||||
);
|
||||
@@ -1204,7 +1270,7 @@ function removeDocuments(coll, selector, options, callback) {
|
||||
* @param {Collection~collectionResultCallback} [callback] The results callback
|
||||
*/
|
||||
function rename(coll, newName, options, callback) {
|
||||
const Collection = require('../collection');
|
||||
let Collection = loadCollection();
|
||||
// Check the collection name
|
||||
checkCollectionName(newName);
|
||||
// Build the command
|
||||
@@ -1461,6 +1527,7 @@ module.exports = {
|
||||
indexes,
|
||||
indexExists,
|
||||
indexInformation,
|
||||
insertMany,
|
||||
insertOne,
|
||||
isCapped,
|
||||
mapReduce,
|
||||
|
||||
+12
-4
@@ -6,6 +6,14 @@ const handleCallback = require('../utils').handleCallback;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
const push = Array.prototype.push;
|
||||
|
||||
let cursor;
|
||||
function loadCursor() {
|
||||
if (!cursor) {
|
||||
cursor = require('../cursor');
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of documents for this cursor.
|
||||
*
|
||||
@@ -74,7 +82,7 @@ function count(cursor, applySkipLimit, opts, callback) {
|
||||
* @param {Cursor~resultCallback} callback The result callback.
|
||||
*/
|
||||
function each(cursor, callback) {
|
||||
const Cursor = require('../cursor');
|
||||
let Cursor = loadCursor();
|
||||
|
||||
if (!callback) throw MongoError.create({ message: 'callback is mandatory', driver: true });
|
||||
if (cursor.isNotified()) return;
|
||||
@@ -114,7 +122,7 @@ function each(cursor, callback) {
|
||||
* @param {Cursor~resultCallback} [callback] The result callback.
|
||||
*/
|
||||
function hasNext(cursor, callback) {
|
||||
const Cursor = require('../cursor');
|
||||
let Cursor = loadCursor();
|
||||
|
||||
if (cursor.s.currentDoc) {
|
||||
return callback(null, true);
|
||||
@@ -165,7 +173,7 @@ function next(cursor, callback) {
|
||||
|
||||
// Get the next available document from the cursor, returns null if no more documents are available.
|
||||
function nextObject(cursor, callback) {
|
||||
const Cursor = require('../cursor');
|
||||
let Cursor = loadCursor();
|
||||
|
||||
if (cursor.s.state === Cursor.CLOSED || (cursor.isDead && cursor.isDead()))
|
||||
return handleCallback(
|
||||
@@ -196,7 +204,7 @@ function nextObject(cursor, callback) {
|
||||
* @param {Cursor~toArrayResultCallback} [callback] The result callback.
|
||||
*/
|
||||
function toArray(cursor, callback) {
|
||||
const Cursor = require('../cursor');
|
||||
let Cursor = loadCursor();
|
||||
|
||||
const items = [];
|
||||
|
||||
|
||||
+32
-12
@@ -17,6 +17,21 @@ const findOne = require('./collection_ops').findOne;
|
||||
const remove = require('./collection_ops').remove;
|
||||
const updateOne = require('./collection_ops').updateOne;
|
||||
|
||||
let collection;
|
||||
function loadCollection() {
|
||||
if (!collection) {
|
||||
collection = require('../collection');
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
let db;
|
||||
function loadDb() {
|
||||
if (!db) {
|
||||
db = require('../db');
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
const debugFields = [
|
||||
'authSource',
|
||||
'w',
|
||||
@@ -64,7 +79,7 @@ const illegalCommandFields = [
|
||||
* @param {Db~resultCallback} [callback] The command result callback
|
||||
*/
|
||||
function addUser(db, username, password, options, callback) {
|
||||
const Db = require('../db');
|
||||
let Db = loadDb();
|
||||
|
||||
// Did the user destroy the topology
|
||||
if (db.serverConfig && db.serverConfig.isDestroyed())
|
||||
@@ -82,10 +97,10 @@ function addUser(db, username, password, options, callback) {
|
||||
const userPassword = md5.digest('hex');
|
||||
|
||||
// If we have another db set
|
||||
const db = options.dbName ? new Db(options.dbName, db.s.topology, db.s.options) : db;
|
||||
const dbToUse = options.dbName ? new Db(options.dbName, db.s.topology, db.s.options) : db;
|
||||
|
||||
// Fetch a user collection
|
||||
const collection = db.collection(CONSTANTS.SYSTEM_USER_COLLECTION);
|
||||
const collection = dbToUse.collection(CONSTANTS.SYSTEM_USER_COLLECTION);
|
||||
|
||||
// Check if we are inserting the first user
|
||||
count(collection, {}, finalOptions, (err, count) => {
|
||||
@@ -132,7 +147,7 @@ function addUser(db, username, password, options, callback) {
|
||||
* @param {Db~collectionsResultCallback} [callback] The results callback
|
||||
*/
|
||||
function collections(db, options, callback) {
|
||||
const Collection = require('../collection');
|
||||
let Collection = loadCollection();
|
||||
|
||||
options = Object.assign({}, options, { nameOnly: true });
|
||||
// Let's get the collection names
|
||||
@@ -172,7 +187,7 @@ function collections(db, options, callback) {
|
||||
* @param {Db~collectionResultCallback} [callback] The results callback
|
||||
*/
|
||||
function createCollection(db, name, options, callback) {
|
||||
const Collection = require('../collection');
|
||||
let Collection = loadCollection();
|
||||
|
||||
// Get the write concern options
|
||||
const finalOptions = applyWriteConcern(Object.assign({}, options), { db }, options);
|
||||
@@ -233,11 +248,16 @@ function createCollection(db, name, options, callback) {
|
||||
// Execute command
|
||||
executeCommand(db, cmd, finalOptions, err => {
|
||||
if (err) return handleCallback(callback, err);
|
||||
handleCallback(
|
||||
callback,
|
||||
null,
|
||||
new Collection(db, db.s.topology, db.s.databaseName, name, db.s.pkFactory, options)
|
||||
);
|
||||
|
||||
try {
|
||||
return handleCallback(
|
||||
callback,
|
||||
null,
|
||||
new Collection(db, db.s.topology, db.s.databaseName, name, db.s.pkFactory, options)
|
||||
);
|
||||
} catch (err) {
|
||||
return handleCallback(callback, err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -581,7 +601,7 @@ function listCollectionsTransforms(databaseName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive the current profiling information for MongoDB
|
||||
* Retrieve the current profiling information for MongoDB
|
||||
*
|
||||
* @method
|
||||
* @param {Db} db The Db instance on which to retrieve the profiling info.
|
||||
@@ -632,7 +652,7 @@ function profilingLevel(db, options, callback) {
|
||||
* @param {Db~resultCallback} [callback] The command result callback
|
||||
*/
|
||||
function removeUser(db, username, options, callback) {
|
||||
const Db = require('../db');
|
||||
let Db = loadDb();
|
||||
|
||||
// Attempt to execute command
|
||||
executeAuthRemoveUserCommand(db, username, options, (err, result) => {
|
||||
|
||||
+152
-110
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const authenticate = require('../authenticate');
|
||||
const deprecate = require('util').deprecate;
|
||||
const Logger = require('mongodb-core').Logger;
|
||||
const MongoError = require('mongodb-core').MongoError;
|
||||
@@ -10,6 +9,16 @@ const ReadPreference = require('mongodb-core').ReadPreference;
|
||||
const ReplSet = require('../topologies/replset');
|
||||
const Server = require('../topologies/server');
|
||||
const ServerSessionPool = require('mongodb-core').Sessions.ServerSessionPool;
|
||||
const NativeTopology = require('../topologies/native_topology');
|
||||
const MongoCredentials = require('mongodb-core').MongoCredentials;
|
||||
|
||||
let client;
|
||||
function loadClient() {
|
||||
if (!client) {
|
||||
client = require('../mongo_client');
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
const monitoringEvents = [
|
||||
'timeout',
|
||||
@@ -100,7 +109,10 @@ const validOptionNames = [
|
||||
'minSize',
|
||||
'monitorCommands',
|
||||
'retryWrites',
|
||||
'useNewUrlParser'
|
||||
'useNewUrlParser',
|
||||
'useUnifiedTopology',
|
||||
'serverSelectionTimeoutMS',
|
||||
'useRecoveryToken'
|
||||
];
|
||||
|
||||
function addListeners(mongoClient, topology) {
|
||||
@@ -117,7 +129,10 @@ function addListeners(mongoClient, topology) {
|
||||
|
||||
function assignTopology(client, topology) {
|
||||
client.topology = topology;
|
||||
topology.s.sessionPool = new ServerSessionPool(topology.s.coreTopology);
|
||||
topology.s.sessionPool =
|
||||
topology instanceof NativeTopology
|
||||
? new ServerSessionPool(topology)
|
||||
: new ServerSessionPool(topology.s.coreTopology);
|
||||
}
|
||||
|
||||
// Clear out all events
|
||||
@@ -127,7 +142,7 @@ function clearAllEvents(topology) {
|
||||
|
||||
// Collect all events in order from SDAM
|
||||
function collectEvents(mongoClient, topology) {
|
||||
const MongoClient = require('../mongo_client');
|
||||
let MongoClient = loadClient();
|
||||
const collectedEvents = [];
|
||||
|
||||
if (mongoClient instanceof MongoClient) {
|
||||
@@ -166,7 +181,7 @@ function connect(mongoClient, url, options, callback) {
|
||||
throw new Error('no callback function provided');
|
||||
}
|
||||
|
||||
// Get a logger for MongoClient
|
||||
let didRequestAuthentication = false;
|
||||
const logger = Logger('MongoClient', options);
|
||||
|
||||
// Did we pass in a Server/ReplSet/Mongos
|
||||
@@ -203,29 +218,34 @@ function connect(mongoClient, url, options, callback) {
|
||||
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);
|
||||
}
|
||||
|
||||
// Do we have a replicaset then skip discovery and go straight to connectivity
|
||||
if (_finalOptions.replicaSet || _finalOptions.rs_name) {
|
||||
return createTopology(
|
||||
mongoClient,
|
||||
'replicaset',
|
||||
_finalOptions,
|
||||
connectHandler(mongoClient, _finalOptions, connectCallback)
|
||||
);
|
||||
return createTopology(mongoClient, 'replicaset', _finalOptions, connectCallback);
|
||||
} else if (object.servers.length > 1) {
|
||||
return createTopology(
|
||||
mongoClient,
|
||||
'mongos',
|
||||
_finalOptions,
|
||||
connectHandler(mongoClient, _finalOptions, connectCallback)
|
||||
);
|
||||
return createTopology(mongoClient, 'mongos', _finalOptions, connectCallback);
|
||||
} else {
|
||||
return createServer(
|
||||
mongoClient,
|
||||
_finalOptions,
|
||||
connectHandler(mongoClient, _finalOptions, connectCallback)
|
||||
);
|
||||
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') {
|
||||
@@ -237,35 +257,15 @@ function connect(mongoClient, url, options, callback) {
|
||||
return callback(new MongoError(warningMessage));
|
||||
}
|
||||
|
||||
if (didRequestAuthentication) {
|
||||
mongoClient.emit('authenticated', null, true);
|
||||
}
|
||||
|
||||
// Return the error and db instance
|
||||
callback(err, topology);
|
||||
}
|
||||
}
|
||||
|
||||
function connectHandler(client, options, callback) {
|
||||
return (err, topology) => {
|
||||
if (err) {
|
||||
return handleConnectCallback(err, topology, callback);
|
||||
}
|
||||
|
||||
// No authentication just reconnect
|
||||
if (!options.auth) {
|
||||
return handleConnectCallback(err, topology, callback);
|
||||
}
|
||||
|
||||
// Authenticate
|
||||
authenticate(client, options.user, options.password, options, (err, success) => {
|
||||
if (success) {
|
||||
handleConnectCallback(null, topology, callback);
|
||||
} else {
|
||||
if (topology) topology.close();
|
||||
const authError = err ? err : new Error('Could not authenticate user ' + options.auth[0]);
|
||||
handleConnectCallback(authError, topology, callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to MongoDB using a url as documented at
|
||||
*
|
||||
@@ -306,27 +306,21 @@ function connectWithUrl(mongoClient, url, options, connectCallback) {
|
||||
);
|
||||
}
|
||||
|
||||
// Connect
|
||||
return url.connect(
|
||||
finalOptions,
|
||||
connectHandler(mongoClient, finalOptions, (err, topology) => {
|
||||
if (err) return connectCallback(err, topology);
|
||||
if (finalOptions.user || finalOptions.password || finalOptions.authMechanism) {
|
||||
return authenticate(
|
||||
mongoClient,
|
||||
finalOptions.user,
|
||||
finalOptions.password,
|
||||
finalOptions,
|
||||
err => {
|
||||
if (err) return connectCallback(err, topology);
|
||||
connectCallback(err, topology);
|
||||
}
|
||||
);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
connectCallback(err, topology);
|
||||
})
|
||||
);
|
||||
return url.connect(finalOptions, connectCallback);
|
||||
}
|
||||
|
||||
function createListener(mongoClient, event) {
|
||||
@@ -402,6 +396,8 @@ function createTopology(mongoClient, topologyType, options, callback) {
|
||||
topology = new Mongos(servers, options);
|
||||
} else if (topologyType === 'replicaset') {
|
||||
topology = new ReplSet(servers, options);
|
||||
} else if (topologyType === 'unified') {
|
||||
topology = new NativeTopology(options.servers, options);
|
||||
}
|
||||
|
||||
// Add listeners
|
||||
@@ -457,36 +453,10 @@ function createUnifiedOptions(finalOptions, options) {
|
||||
return finalOptions;
|
||||
}
|
||||
|
||||
function handleConnectCallback(err, topology, callback) {
|
||||
return process.nextTick(() => {
|
||||
try {
|
||||
callback(err, topology);
|
||||
} catch (err) {
|
||||
if (topology) topology.close();
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function legacyTransformUrlOptions(object) {
|
||||
return mergeOptions(createUnifiedOptions({}, object), object, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout user from server, fire off on all connections and remove all auth info.
|
||||
*
|
||||
* @method
|
||||
* @param {MongoClient} mongoClient The MongoClient instance on which to logout.
|
||||
* @param {object} [options] Optional settings. See MongoClient.prototype.logout for a list of options.
|
||||
* @param {Db~resultCallback} [callback] The command result callback
|
||||
*/
|
||||
function logout(mongoClient, dbName, callback) {
|
||||
mongoClient.topology.logout(dbName, err => {
|
||||
if (err) return callback(err);
|
||||
callback(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
function mergeOptions(target, source, flatten) {
|
||||
for (const name in source) {
|
||||
if (source[name] && typeof source[name] === 'object' && flatten) {
|
||||
@@ -548,21 +518,17 @@ function transformUrlOptions(_object) {
|
||||
object[camelCaseName] = object[name];
|
||||
}
|
||||
}
|
||||
if (_object.auth) {
|
||||
const auth = _object.auth;
|
||||
for (let i in auth) {
|
||||
if (auth[i]) {
|
||||
object[i] = auth[i];
|
||||
}
|
||||
|
||||
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 (auth.username) {
|
||||
object.auth = auth;
|
||||
object.user = auth.username;
|
||||
}
|
||||
|
||||
if (auth.db) {
|
||||
object.authSource = object.authSource || auth.db;
|
||||
if (object.auth.username) {
|
||||
object.auth.user = object.auth.username;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,10 +594,12 @@ function validOptions(options) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_validOptions.indexOf(name) === -1 && options.validateOptions) {
|
||||
return new MongoError(`option ${name} is not supported`);
|
||||
} else if (_validOptions.indexOf(name) === -1) {
|
||||
console.warn(`the options [${name}] is not supported`);
|
||||
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) {
|
||||
@@ -643,4 +611,78 @@ function validOptions(options) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { connectOp, logout, validOptions };
|
||||
const VALID_AUTH_MECHANISMS = new Set([
|
||||
'DEFAULT',
|
||||
'MONGODB-CR',
|
||||
'PLAIN',
|
||||
'MONGODB-X509',
|
||||
'SCRAM-SHA-1',
|
||||
'SCRAM-SHA-256',
|
||||
'GSSAPI'
|
||||
]);
|
||||
|
||||
const AUTH_MECHANISM_INTERNAL_MAP = {
|
||||
DEFAULT: 'default',
|
||||
'MONGODB-CR': 'mongocr',
|
||||
PLAIN: 'plain',
|
||||
'MONGODB-X509': 'x509',
|
||||
'SCRAM-SHA-1': 'scram-sha-1',
|
||||
'SCRAM-SHA-256': 'scram-sha-256'
|
||||
};
|
||||
|
||||
function generateCredentials(client, username, password, options) {
|
||||
options = Object.assign({}, options);
|
||||
|
||||
// the default db to authenticate against is 'self'
|
||||
// if authenticate 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();
|
||||
|
||||
if (!VALID_AUTH_MECHANISMS.has(authMechanism)) {
|
||||
throw MongoError.create({
|
||||
message: `authentication mechanism ${authMechanismRaw} not supported', options.authMechanism`,
|
||||
driver: true
|
||||
});
|
||||
}
|
||||
|
||||
if (authMechanism === 'GSSAPI') {
|
||||
return new MongoCredentials({
|
||||
mechanism: process.platform === 'win32' ? 'sspi' : 'gssapi',
|
||||
mechanismProperties: options,
|
||||
source,
|
||||
username,
|
||||
password
|
||||
});
|
||||
}
|
||||
|
||||
return new MongoCredentials({
|
||||
mechanism: AUTH_MECHANISM_INTERNAL_MAP[authMechanism],
|
||||
source,
|
||||
username,
|
||||
password
|
||||
});
|
||||
}
|
||||
|
||||
function closeOperation(client, force, callback) {
|
||||
const completeClose = err => {
|
||||
client.emit('close', client);
|
||||
for (const name in client.s.dbCache) {
|
||||
client.s.dbCache[name].emit('close', client);
|
||||
}
|
||||
|
||||
client.removeAllListeners('close');
|
||||
callback(err, null);
|
||||
};
|
||||
|
||||
if (client.topology == null) {
|
||||
completeClose();
|
||||
return;
|
||||
}
|
||||
|
||||
client.topology.close(force, completeClose);
|
||||
}
|
||||
|
||||
module.exports = { connectOp, validOptions, closeOperation };
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ var legalOptionNames = [
|
||||
* @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for MongoS proxy selection
|
||||
* @param {boolean} [options.ssl=false] Use ssl connection (needs to have a mongod server with ssl support)
|
||||
* @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function.
|
||||
* @param {boolean} [options.sslValidate=true] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {boolean} [options.sslValidate=false] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {array} [options.sslCA] Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {array} [options.sslCRL] Array of revocation certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {string} [options.ciphers] Passed directly through to tls.createSecureContext. See https://nodejs.org/dist/latest-v9.x/docs/api/tls.html#tls_tls_createsecurecontext_options for more info.
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const Topology = require('mongodb-core').Topology;
|
||||
const ServerCapabilities = require('./topology_base').ServerCapabilities;
|
||||
const Cursor = require('../cursor');
|
||||
const translateOptions = require('../utils').translateOptions;
|
||||
|
||||
class NativeTopology extends Topology {
|
||||
constructor(servers, options) {
|
||||
options = options || {};
|
||||
|
||||
let clonedOptions = Object.assign(
|
||||
{},
|
||||
{
|
||||
cursorFactory: Cursor,
|
||||
reconnect: false,
|
||||
emitError: typeof options.emitError === 'boolean' ? options.emitError : true,
|
||||
size: typeof options.poolSize === 'number' ? options.poolSize : 5,
|
||||
monitorCommands:
|
||||
typeof options.monitorCommands === 'boolean' ? options.monitorCommands : false
|
||||
}
|
||||
);
|
||||
|
||||
// Translate any SSL options and other connectivity options
|
||||
clonedOptions = translateOptions(clonedOptions, options);
|
||||
|
||||
// Socket options
|
||||
var socketOptions =
|
||||
options.socketOptions && Object.keys(options.socketOptions).length > 0
|
||||
? options.socketOptions
|
||||
: options;
|
||||
|
||||
// Translate all the options to the mongodb-core ones
|
||||
clonedOptions = translateOptions(clonedOptions, socketOptions);
|
||||
|
||||
super(servers, clonedOptions);
|
||||
|
||||
// Do we have an application specific string
|
||||
if (options.appname) {
|
||||
this.s.clientInfo.application = { name: options.appname };
|
||||
}
|
||||
}
|
||||
|
||||
capabilities() {
|
||||
if (this.s.sCapabilities) return this.s.sCapabilities;
|
||||
if (this.lastIsMaster() == null) return null;
|
||||
this.s.sCapabilities = new ServerCapabilities(this.lastIsMaster());
|
||||
return this.s.sCapabilities;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NativeTopology;
|
||||
+3
-4
@@ -80,7 +80,7 @@ var legalOptionNames = [
|
||||
* @param {number} [options.poolSize=5] Number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons.
|
||||
* @param {boolean} [options.ssl=false] Use ssl connection (needs to have a mongod server with ssl support)
|
||||
* @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function.
|
||||
* @param {boolean} [options.sslValidate=true] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {boolean} [options.sslValidate=false] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {array} [options.sslCA] Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {array} [options.sslCRL] Array of revocation certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {(Buffer|string)} [options.sslCert] String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher.
|
||||
@@ -381,10 +381,9 @@ class ReplSet extends TopologyBase {
|
||||
self.s.coreTopology.connect(_options);
|
||||
}
|
||||
|
||||
close(forceClosed) {
|
||||
super.close(forceClosed);
|
||||
|
||||
close(forceClosed, callback) {
|
||||
['timeout', 'error', 'close', 'joined', 'left'].forEach(e => this.removeAllListeners(e));
|
||||
super.close(forceClosed, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ var legalOptionNames = [
|
||||
* @param {object} [options] Optional settings.
|
||||
* @param {number} [options.poolSize=5] Number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons.
|
||||
* @param {boolean} [options.ssl=false] Use ssl connection (needs to have a mongod server with ssl support)
|
||||
* @param {boolean} [options.sslValidate=true] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {boolean} [options.sslValidate=false] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function.
|
||||
* @param {array} [options.sslCA] Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* @param {array} [options.sslCRL] Array of revocation certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
|
||||
+8
-15
@@ -370,16 +370,6 @@ class TopologyBase extends EventEmitter {
|
||||
return this.s.coreTopology.unref();
|
||||
}
|
||||
|
||||
auth() {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
this.s.coreTopology.auth.apply(this.s.coreTopology, args);
|
||||
}
|
||||
|
||||
logout() {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
this.s.coreTopology.logout.apply(this.s.coreTopology, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* All raw connections
|
||||
* @method
|
||||
@@ -389,7 +379,7 @@ class TopologyBase extends EventEmitter {
|
||||
return this.s.coreTopology.connections();
|
||||
}
|
||||
|
||||
close(forceClosed) {
|
||||
close(forceClosed, callback) {
|
||||
// If we have sessions, we want to individually move them to the session pool,
|
||||
// and then send a single endSessions call.
|
||||
if (this.s.sessions.length) {
|
||||
@@ -400,15 +390,18 @@ class TopologyBase extends EventEmitter {
|
||||
this.s.sessionPool.endAllPooledSessions();
|
||||
}
|
||||
|
||||
this.s.coreTopology.destroy({
|
||||
force: typeof forceClosed === 'boolean' ? forceClosed : false
|
||||
});
|
||||
|
||||
// We need to wash out all stored processes
|
||||
if (forceClosed === true) {
|
||||
this.s.storeOptions.force = forceClosed;
|
||||
this.s.store.flush();
|
||||
}
|
||||
|
||||
this.s.coreTopology.destroy(
|
||||
{
|
||||
force: typeof forceClosed === 'boolean' ? forceClosed : false
|
||||
},
|
||||
callback
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@ function parseConnectionString(url, options) {
|
||||
if (_host.indexOf('?') !== -1) _host = _host.split(/\?/)[0];
|
||||
}
|
||||
|
||||
// No entry returned for duplicate servr
|
||||
// No entry returned for duplicate server
|
||||
if (deduplicatedServers[_host + '_' + _port]) return null;
|
||||
deduplicatedServers[_host + '_' + _port] = 1;
|
||||
|
||||
|
||||
+18
-9
@@ -114,7 +114,7 @@ var checkCollectionName = function checkCollectionName(collectionName) {
|
||||
throw new MongoError("collection names must not start or end with '.'");
|
||||
}
|
||||
|
||||
// Validate that we are not passing 0x00 in the colletion name
|
||||
// Validate that we are not passing 0x00 in the collection name
|
||||
if (collectionName.indexOf('\x00') !== -1) {
|
||||
throw new MongoError('collection names cannot contain a null character');
|
||||
}
|
||||
@@ -360,7 +360,6 @@ var mergeOptionsAndWriteConcern = function(targetOptions, sourceOptions, keys, m
|
||||
* @param {function} operation The operation to execute
|
||||
* @param {array} args Arguments to apply the provided operation
|
||||
* @param {object} [options] Options that modify the behavior of the method
|
||||
* @param {function]} [options.resultMutator] Allows for the result of the operation to be changed for custom return types
|
||||
*/
|
||||
const executeOperation = (topology, operation, args, options) => {
|
||||
if (topology == null) {
|
||||
@@ -373,7 +372,6 @@ const executeOperation = (topology, operation, args, options) => {
|
||||
|
||||
options = options || {};
|
||||
const Promise = topology.s.promiseLibrary;
|
||||
let resultMutator = options.resultMutator;
|
||||
let callback = args[args.length - 1];
|
||||
|
||||
// The driver sessions spec mandates that we implicitly create sessions for operations
|
||||
@@ -397,12 +395,10 @@ const executeOperation = (topology, operation, args, options) => {
|
||||
session.endSession(() => {
|
||||
delete opOptions.session;
|
||||
if (err) return reject(err);
|
||||
if (resultMutator) return resolve(resultMutator(result));
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (err) return reject(err);
|
||||
if (resultMutator) return resolve(resultMutator(result));
|
||||
resolve(result);
|
||||
}
|
||||
};
|
||||
@@ -588,12 +584,12 @@ function decorateWithCollation(command, target, options) {
|
||||
throw new TypeError('parameter "target" is missing a topology');
|
||||
}
|
||||
|
||||
const capabilities = target.s.topology.capabilities();
|
||||
const capabilities = topology.capabilities();
|
||||
if (options.collation && typeof options.collation === 'object') {
|
||||
if (capabilities && capabilities.commandsTakeCollation) {
|
||||
command.collation = options.collation;
|
||||
} else {
|
||||
throw new MongoError(`server ${topology.s.coreTopology.name} does not support collation`);
|
||||
throw new MongoError(`Current topology does not support collation`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -604,7 +600,10 @@ function decorateWithCollation(command, target, options) {
|
||||
* @param {object} command the command on which to apply the read concern
|
||||
* @param {Collection} coll the parent collection of the operation calling this method
|
||||
*/
|
||||
function decorateWithReadConcern(command, coll) {
|
||||
function decorateWithReadConcern(command, coll, options) {
|
||||
if (options && options.session && options.session.inTransaction()) {
|
||||
return;
|
||||
}
|
||||
let readConcern = Object.assign({}, command.readConcern || {});
|
||||
if (coll.s.readConcern) {
|
||||
Object.assign(readConcern, coll.s.readConcern);
|
||||
@@ -691,6 +690,15 @@ function deprecateOptions(config, fn) {
|
||||
return deprecated;
|
||||
}
|
||||
|
||||
const SUPPORTS = {};
|
||||
// Test asyncIterator support
|
||||
try {
|
||||
require('./async/async_iterator');
|
||||
SUPPORTS.ASYNC_ITERATOR = true;
|
||||
} catch (e) {
|
||||
SUPPORTS.ASYNC_ITERATOR = false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
filterOptions,
|
||||
mergeOptions,
|
||||
@@ -716,5 +724,6 @@ module.exports = {
|
||||
isPromiseLike,
|
||||
decorateWithCollation,
|
||||
decorateWithReadConcern,
|
||||
deprecateOptions
|
||||
deprecateOptions,
|
||||
SUPPORTS
|
||||
};
|
||||
|
||||
+16
-15
@@ -1,35 +1,35 @@
|
||||
{
|
||||
"_from": "mongodb",
|
||||
"_id": "mongodb@3.1.10",
|
||||
"_from": "mongodb@^3.2.7",
|
||||
"_id": "mongodb@3.2.7",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-Uml42GeFxhTGQVml1XQ4cD0o/rp7J2ROy0fdYUcVitoE7vFqEhKH4TYVqRDpQr/bXtCJVxJdNQC1ntRxNREkPQ==",
|
||||
"_integrity": "sha512-2YdWrdf1PJgxcCrT1tWoL6nHuk6hCxhddAAaEh8QJL231ci4+P9FLyqopbTm2Z2sAU6mhCri+wd9r1hOcHdoMw==",
|
||||
"_location": "/mongodb",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "mongodb",
|
||||
"raw": "mongodb@^3.2.7",
|
||||
"name": "mongodb",
|
||||
"escapedName": "mongodb",
|
||||
"rawSpec": "",
|
||||
"rawSpec": "^3.2.7",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
"fetchSpec": "^3.2.7"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/",
|
||||
"/connect-mongo",
|
||||
"/mongoose"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.1.10.tgz",
|
||||
"_shasum": "45ad9b74ea376f4122d0881b75e5489b9e504ed7",
|
||||
"_spec": "mongodb",
|
||||
"_where": "D:\\Gitterra\\om",
|
||||
"_resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.2.7.tgz",
|
||||
"_shasum": "8ba149e4be708257cad0dea72aebb2bbb311a7ac",
|
||||
"_spec": "mongodb@^3.2.7",
|
||||
"_where": "/home/erik/Documents/workspace_brackets/a1_BME_Project_Ohm/om",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mongodb/node-mongodb-native/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"mongodb-core": "3.1.9",
|
||||
"mongodb-core": "3.2.7",
|
||||
"safe-buffer": "^5.1.2"
|
||||
},
|
||||
"deprecated": false,
|
||||
@@ -48,7 +48,7 @@
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"mocha-sinon": "^2.1.0",
|
||||
"mongodb-extjson": "^2.1.1",
|
||||
"mongodb-mock-server": "^1.0.0",
|
||||
"mongodb-mock-server": "^1.0.1",
|
||||
"mongodb-test-runner": "^1.1.18",
|
||||
"prettier": "~1.12.0",
|
||||
"semver": "^5.5.0",
|
||||
@@ -78,6 +78,7 @@
|
||||
"url": "git+ssh://git@github.com/mongodb/node-mongodb-native.git"
|
||||
},
|
||||
"scripts": {
|
||||
"atlas": "node ./test/atlas_connectivity_tests.js",
|
||||
"bench": "node test/driverBench/",
|
||||
"coverage": "istanbul cover mongodb-test-runner -- -t 60000 test/unit test/functional",
|
||||
"format": "prettier --print-width 100 --tab-width 2 --single-quote --write 'test/**/*.js' 'lib/**/*.js'",
|
||||
@@ -86,5 +87,5 @@
|
||||
"release": "standard-version -i HISTORY.md",
|
||||
"test": "npm run lint && mongodb-test-runner -t 60000 test/unit test/functional"
|
||||
},
|
||||
"version": "3.1.10"
|
||||
"version": "3.2.7"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user