diff options
Diffstat (limited to 'common/src/main/webapp/usageguide/appserver/node_modules/mongodb/lib/mongo_client.js')
-rw-r--r-- | common/src/main/webapp/usageguide/appserver/node_modules/mongodb/lib/mongo_client.js | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/mongodb/lib/mongo_client.js b/common/src/main/webapp/usageguide/appserver/node_modules/mongodb/lib/mongo_client.js new file mode 100644 index 0000000..55421d9 --- /dev/null +++ b/common/src/main/webapp/usageguide/appserver/node_modules/mongodb/lib/mongo_client.js @@ -0,0 +1,327 @@ +"use strict"; + +var parse = require('./url_parser') + , Server = require('./server') + , Mongos = require('./mongos') + , ReplSet = require('./replset') + , Define = require('./metadata') + , ReadPreference = require('./read_preference') + , Logger = require('mongodb-core').Logger + , MongoError = require('mongodb-core').MongoError + , Db = require('./db') + , f = require('util').format + , shallowClone = require('./utils').shallowClone; + +/** + * @fileOverview The **MongoClient** class is a class that allows for making Connections to MongoDB. + * + * @example + * var MongoClient = require('mongodb').MongoClient, + * test = require('assert'); + * // Connection url + * var url = 'mongodb://localhost:27017/test'; + * // Connect using MongoClient + * MongoClient.connect(url, function(err, db) { + * // Get an additional db + * db.close(); + * }); + */ + +/** + * Creates a new MongoClient instance + * @class + * @return {MongoClient} a MongoClient instance. + */ +function MongoClient() { + /** + * The callback format for results + * @callback MongoClient~connectCallback + * @param {MongoError} error An error instance representing the error during the execution. + * @param {Db} db The connected database. + */ + + /** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Note that for replicasets the replicaSet query parameter is required in the 2.0 driver + * + * @method + * @param {string} url The connection URI string + * @param {object} [options=null] Optional settings. + * @param {boolean} [options.uri_decode_auth=false] Uri decode the user name and password for authentication + * @param {object} [options.db=null] A hash of options to set on the db object, see **Db constructor** + * @param {object} [options.server=null] A hash of options to set on the server objects, see **Server** constructor** + * @param {object} [options.replSet=null] A hash of options to set on the replSet object, see **ReplSet** constructor** + * @param {object} [options.mongos=null] A hash of options to set on the mongos object, see **Mongos** constructor** + * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible + * @param {MongoClient~connectCallback} [callback] The command result callback + * @return {Promise} returns Promise if no callback passed + */ + this.connect = MongoClient.connect; +} + +var define = MongoClient.define = new Define('MongoClient', MongoClient, false); + +/** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Note that for replicasets the replicaSet query parameter is required in the 2.0 driver + * + * @method + * @static + * @param {string} url The connection URI string + * @param {object} [options=null] Optional settings. + * @param {boolean} [options.uri_decode_auth=false] Uri decode the user name and password for authentication + * @param {object} [options.db=null] A hash of options to set on the db object, see **Db constructor** + * @param {object} [options.server=null] A hash of options to set on the server objects, see **Server** constructor** + * @param {object} [options.replSet=null] A hash of options to set on the replSet object, see **ReplSet** constructor** + * @param {object} [options.mongos=null] A hash of options to set on the mongos object, see **Mongos** constructor** + * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible + * @param {MongoClient~connectCallback} [callback] The command result callback + * @return {Promise} returns Promise if no callback passed + */ +MongoClient.connect = function(url, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = typeof args[args.length - 1] == 'function' ? args.pop() : null; + options = args.length ? args.shift() : null; + options = options || {}; + + // Get the promiseLibrary + var promiseLibrary = options.promiseLibrary; + + // No promise library selected fall back + if(!promiseLibrary) { + promiseLibrary = typeof global.Promise == 'function' ? + global.Promise : require('es6-promise').Promise; + } + + // Return a promise + if(typeof callback != 'function') { + return new promiseLibrary(function(resolve, reject) { + connect(url, options, function(err, db) { + if(err) return reject(err); + resolve(db); + }); + }); + } + + // Fallback to callback based connect + connect(url, options, callback); +} + +define.staticMethod('connect', {callback: true, promise:true}); + +var mergeOptions = function(target, source, flatten) { + for(var name in source) { + if(source[name] && typeof source[name] == 'object' && flatten) { + target = mergeOptions(target, source[name], flatten); + } else { + target[name] = source[name]; + } + } + + return target; +} + +var createUnifiedOptions = function(finalOptions, options) { + var childOptions = ['mongos', 'server', 'db' + , 'replset', 'db_options', 'server_options', 'rs_options', 'mongos_options']; + var noMerge = []; + + for(var name in options) { + if(noMerge.indexOf(name.toLowerCase()) != -1) { + finalOptions[name] = options[name]; + } else if(childOptions.indexOf(name.toLowerCase()) != -1) { + finalOptions = mergeOptions(finalOptions, options[name], false); + } else { + if(options[name] && typeof options[name] == 'object' && !Buffer.isBuffer(options[name]) && !Array.isArray(options[name])) { + finalOptions = mergeOptions(finalOptions, options[name], true); + } else { + finalOptions[name] = options[name]; + } + } + } + + return finalOptions; +} + +function translateOptions(options) { + // If we have a readPreference passed in by the db options + if(typeof options.readPreference == 'string' || typeof options.read_preference == 'string') { + options.readPreference = new ReadPreference(options.readPreference || options.read_preference); + } + + // Do we have readPreference tags, add them + if(options.readPreference && (options.readPreferenceTags || options.read_preference_tags)) { + options.readPreference.tags = options.readPreferenceTags || options.read_preference_tags; + } + + // Do we have maxStalenessSeconds + if(options.maxStalenessSeconds) { + options.readPreference.maxStalenessSeconds = options.maxStalenessSeconds; + } + + // Set the socket and connection timeouts + if(options.socketTimeoutMS == null) options.socketTimeoutMS = 30000; + if(options.connectTimeoutMS == null) options.connectTimeoutMS = 30000; + + // Create server instances + return options.servers.map(function(serverObj) { + return serverObj.domain_socket ? + new Server(serverObj.domain_socket, 27017, options) + : new Server(serverObj.host, serverObj.port, options); + }); +} + +function createReplicaset(options, callback) { + // Set default options + var servers = translateOptions(options); + // Create Db instance + new Db(options.dbName, new ReplSet(servers, options), options).open(callback); +} + +function createMongos(options, callback) { + // Set default options + var servers = translateOptions(options); + // Create Db instance + new Db(options.dbName, new Mongos(servers, options), options).open(callback); +} + +function createServer(options, callback) { + // Set default options + var servers = translateOptions(options); + // Create Db instance + new Db(options.dbName, servers[0], options).open(function(err, db) { + if(err) return callback(err); + // Check if we are really speaking to a mongos + var ismaster = db.serverConfig.lastIsMaster(); + + // Do we actually have a mongos + if(ismaster && ismaster.msg == 'isdbgrid') { + // Destroy the current connection + db.close(); + // Create mongos connection instead + return createMongos(options, callback); + } + + // Otherwise callback + callback(err, db); + }); +} + +function connectHandler(options, callback) { + return function (err, db) { + if(err) { + return process.nextTick(function() { + try { + callback(err, null); + } catch (err) { + if(db) db.close(); + throw err + } + }); + } + + // No authentication just reconnect + if(!options.auth) { + return process.nextTick(function() { + try { + callback(err, db); + } catch (err) { + if(db) db.close(); + throw err + } + }) + } + + // What db to authenticate against + var authentication_db = db; + if(options.authSource) { + authentication_db = db.db(options.authSource); + } + + // Authenticate + authentication_db.authenticate(options.user, options.password, options, function(err, success){ + if(success){ + process.nextTick(function() { + try { + callback(null, db); + } catch (err) { + if(db) db.close(); + throw err + } + }); + } else { + if(db) db.close(); + process.nextTick(function() { + try { + callback(err ? err : new Error('Could not authenticate user ' + options.auth[0]), null); + } catch (err) { + if(db) db.close(); + throw err + } + }); + } + }); + } +} + +/* + * Connect using MongoClient + */ +var connect = function(url, options, callback) { + options = options || {}; + options = shallowClone(options); + + // If callback is null throw an exception + if(callback == null) { + throw new Error("no callback function provided"); + } + + // Get a logger for MongoClient + var logger = Logger('MongoClient', options); + + // Parse the string + var object = parse(url, options); + var _finalOptions = createUnifiedOptions({}, object); + _finalOptions = mergeOptions(_finalOptions, object, false); + _finalOptions = createUnifiedOptions(_finalOptions, options); + + // Check if we have connection and socket timeout set + if(_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 30000; + if(_finalOptions.connectTimeoutMS == null) _finalOptions.connectTimeoutMS = 30000; + + // Failure modes + if(object.servers.length == 0) { + throw new Error("connection string must contain at least one seed host"); + } + + function connectCallback(err, db) { + if(err && err.message == 'no mongos proxies found in seed list') { + if(logger.isWarn()) { + logger.warn(f('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')); + } + + // Return a more specific error message for MongoClient.connect + return callback(new MongoError('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')); + } + + // Return the error and db instance + callback(err, db); + } + + // Do we have a replicaset then skip discovery and go straight to connectivity + if(_finalOptions.replicaSet || _finalOptions.rs_name) { + return createReplicaset(_finalOptions, connectHandler(_finalOptions, connectCallback)); + } else if(object.servers.length > 1) { + return createMongos(_finalOptions, connectHandler(_finalOptions, connectCallback)); + } else { + return createServer(_finalOptions, connectHandler(_finalOptions, connectCallback)); + } +} + +module.exports = MongoClient |