123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- 'use strict';
- const ChangeStream = require('./change_stream');
- const Db = require('./db');
- const EventEmitter = require('events').EventEmitter;
- const inherits = require('util').inherits;
- const MongoError = require('./core').MongoError;
- const deprecate = require('util').deprecate;
- const WriteConcern = require('./write_concern');
- const MongoDBNamespace = require('./utils').MongoDBNamespace;
- const ReadPreference = require('./core/topologies/read_preference');
- const maybePromise = require('./utils').maybePromise;
- const NativeTopology = require('./topologies/native_topology');
- const connect = require('./operations/connect').connect;
- const validOptions = require('./operations/connect').validOptions;
- function MongoClient(url, options) {
- if (!(this instanceof MongoClient)) return new MongoClient(url, options);
-
- EventEmitter.call(this);
- if (options && options.autoEncryption) require('./encrypter');
-
- this.s = {
- url: url,
- options: options || {},
- promiseLibrary: (options && options.promiseLibrary) || Promise,
- dbCache: new Map(),
- sessions: new Set(),
- writeConcern: WriteConcern.fromOptions(options),
- readPreference: ReadPreference.fromOptions(options) || ReadPreference.primary,
- namespace: new MongoDBNamespace('admin')
- };
- }
- inherits(MongoClient, EventEmitter);
- Object.defineProperty(MongoClient.prototype, 'writeConcern', {
- enumerable: true,
- get: function() {
- return this.s.writeConcern;
- }
- });
- Object.defineProperty(MongoClient.prototype, 'readPreference', {
- enumerable: true,
- get: function() {
- return this.s.readPreference;
- }
- });
- MongoClient.prototype.connect = function(callback) {
- if (typeof callback === 'string') {
- throw new TypeError('`connect` only accepts a callback');
- }
- const client = this;
- return maybePromise(this, callback, cb => {
- const err = validOptions(client.s.options);
- if (err) return cb(err);
- connect(client, client.s.url, client.s.options, err => {
- if (err) return cb(err);
- cb(null, client);
- });
- });
- };
- MongoClient.prototype.logout = deprecate(function(options, callback) {
- if (typeof options === 'function') (callback = options), (options = {});
- if (typeof callback === 'function') callback(null, true);
- }, 'Multiple authentication is prohibited on a connected client, please only authenticate once per MongoClient');
- MongoClient.prototype.close = function(force, callback) {
- if (typeof force === 'function') {
- callback = force;
- force = false;
- }
- const client = this;
- return maybePromise(this, callback, cb => {
- const completeClose = err => {
- client.emit('close', client);
- if (!(client.topology instanceof NativeTopology)) {
- for (const item of client.s.dbCache) {
- item[1].emit('close', client);
- }
- }
- client.removeAllListeners('close');
- cb(err);
- };
- if (client.topology == null) {
- completeClose();
- return;
- }
- client.topology.close(force, err => {
- const encrypter = client.topology.s.options.encrypter;
- if (encrypter) {
- return encrypter.close(client, force, err2 => {
- completeClose(err || err2);
- });
- }
- completeClose(err);
- });
- });
- };
- MongoClient.prototype.db = function(dbName, options) {
- options = options || {};
-
- if (!dbName) {
- dbName = this.s.options.dbName;
- }
-
- const finalOptions = Object.assign({}, this.s.options, options);
-
- if (this.s.dbCache.has(dbName) && finalOptions.returnNonCachedInstance !== true) {
- return this.s.dbCache.get(dbName);
- }
-
- finalOptions.promiseLibrary = this.s.promiseLibrary;
-
- if (!this.topology) {
- throw new MongoError('MongoClient must be connected before calling MongoClient.prototype.db');
- }
-
- const db = new Db(dbName, this.topology, finalOptions);
-
- this.s.dbCache.set(dbName, db);
-
- return db;
- };
- MongoClient.prototype.isConnected = function(options) {
- options = options || {};
- if (!this.topology) return false;
- return this.topology.isConnected(options);
- };
- MongoClient.connect = function(url, options, callback) {
- const args = Array.prototype.slice.call(arguments, 1);
- callback = typeof args[args.length - 1] === 'function' ? args.pop() : undefined;
- options = args.length ? args.shift() : null;
- options = options || {};
-
- const mongoClient = new MongoClient(url, options);
-
- return mongoClient.connect(callback);
- };
- MongoClient.prototype.startSession = function(options) {
- options = Object.assign({ explicit: true }, options);
- if (!this.topology) {
- throw new MongoError('Must connect to a server before calling this method');
- }
- return this.topology.startSession(options, this.s.options);
- };
- MongoClient.prototype.withSession = function(options, operation) {
- if (typeof options === 'function') (operation = options), (options = undefined);
- const session = this.startSession(options);
- let cleanupHandler = (err, result, opts) => {
-
- cleanupHandler = () => {
- throw new ReferenceError('cleanupHandler was called too many times');
- };
- opts = Object.assign({ throw: true }, opts);
- session.endSession();
- if (err) {
- if (opts.throw) throw err;
- return Promise.reject(err);
- }
- };
- try {
- const result = operation(session);
- return Promise.resolve(result)
- .then(result => cleanupHandler(null, result))
- .catch(err => cleanupHandler(err, null, { throw: true }));
- } catch (err) {
- return cleanupHandler(err, null, { throw: false });
- }
- };
- MongoClient.prototype.watch = function(pipeline, options) {
- pipeline = pipeline || [];
- options = options || {};
-
- if (!Array.isArray(pipeline)) {
- options = pipeline;
- pipeline = [];
- }
- return new ChangeStream(this, pipeline, options);
- };
- MongoClient.prototype.getLogger = function() {
- return this.s.options.logger;
- };
- module.exports = MongoClient;
|