123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- 'use strict';
- 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 connectOp = require('./operations/mongo_client_ops').connectOp;
- const logout = require('./operations/mongo_client_ops').logout;
- const validOptions = require('./operations/mongo_client_ops').validOptions;
- function MongoClient(url, options) {
- if (!(this instanceof MongoClient)) return new MongoClient(url, options);
-
- EventEmitter.call(this);
-
- this.s = {
- url: url,
- options: options || {},
- promiseLibrary: null,
- dbCache: {},
- sessions: []
- };
-
- const promiseLibrary = this.s.options.promiseLibrary || Promise;
-
- this.s.promiseLibrary = promiseLibrary;
- }
- inherits(MongoClient, EventEmitter);
- MongoClient.prototype.connect = function(callback) {
-
- const err = validOptions(this.s.options);
- if (typeof callback === 'string') {
- throw new TypeError('`connect` only accepts a callback');
- }
- return executeOperation(this, connectOp, [this, err, callback], {
- skipSessions: true
- });
- };
- MongoClient.prototype.logout = function(options, callback) {
- if (typeof options === 'function') (callback = options), (options = {});
- options = options || {};
-
- const dbName = this.s.options.authSource ? this.s.options.authSource : this.s.options.dbName;
- return executeOperation(this, logout, [this, dbName, callback], {
- skipSessions: true
- });
- };
- MongoClient.prototype.close = function(force, callback) {
- if (typeof force === 'function') (callback = force), (force = false);
-
- if (this.topology) {
- this.topology.close(force);
- }
-
- this.emit('close', this);
-
- for (const name in this.s.dbCache) {
- this.s.dbCache[name].emit('close');
- }
-
- this.removeAllListeners('close');
-
- if (typeof callback === 'function')
- return process.nextTick(() => {
- handleCallback(callback, null);
- });
-
- return new this.s.promiseLibrary(resolve => {
- resolve();
- });
- };
- 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[dbName] && finalOptions.returnNonCachedInstance !== true) {
- return this.s.dbCache[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[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');
- }
- if (!this.topology.hasSessionSupport()) {
- throw new MongoError('Current topology does not support sessions');
- }
- 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;
|