| "use strict"; |
| |
| var MongoError = require('mongodb-core').MongoError, |
| f = require('util').format; |
| |
| var shallowClone = function(obj) { |
| var copy = {}; |
| for(var name in obj) copy[name] = obj[name]; |
| return copy; |
| } |
| |
| // Set simple property |
| var getSingleProperty = function(obj, name, value) { |
| Object.defineProperty(obj, name, { |
| enumerable:true, |
| get: function() { |
| return value |
| } |
| }); |
| } |
| |
| var formatSortValue = exports.formatSortValue = function(sortDirection) { |
| var value = ("" + sortDirection).toLowerCase(); |
| |
| switch (value) { |
| case 'ascending': |
| case 'asc': |
| case '1': |
| return 1; |
| case 'descending': |
| case 'desc': |
| case '-1': |
| return -1; |
| default: |
| throw new Error("Illegal sort clause, must be of the form " |
| + "[['field1', '(ascending|descending)'], " |
| + "['field2', '(ascending|descending)']]"); |
| } |
| }; |
| |
| var formattedOrderClause = exports.formattedOrderClause = function(sortValue) { |
| var orderBy = {}; |
| if(sortValue == null) return null; |
| if (Array.isArray(sortValue)) { |
| if(sortValue.length === 0) { |
| return null; |
| } |
| |
| for(var i = 0; i < sortValue.length; i++) { |
| if(sortValue[i].constructor == String) { |
| orderBy[sortValue[i]] = 1; |
| } else { |
| orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]); |
| } |
| } |
| } else if(sortValue != null && typeof sortValue == 'object') { |
| orderBy = sortValue; |
| } else if (typeof sortValue == 'string') { |
| orderBy[sortValue] = 1; |
| } else { |
| throw new Error("Illegal sort clause, must be of the form " + |
| "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"); |
| } |
| |
| return orderBy; |
| }; |
| |
| var checkCollectionName = function checkCollectionName (collectionName) { |
| if('string' !== typeof collectionName) { |
| throw Error("collection name must be a String"); |
| } |
| |
| if(!collectionName || collectionName.indexOf('..') != -1) { |
| throw Error("collection names cannot be empty"); |
| } |
| |
| if(collectionName.indexOf('$') != -1 && |
| collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null) { |
| throw Error("collection names must not contain '$'"); |
| } |
| |
| if(collectionName.match(/^\.|\.$/) != null) { |
| throw Error("collection names must not start or end with '.'"); |
| } |
| |
| // Validate that we are not passing 0x00 in the colletion name |
| if(!!~collectionName.indexOf("\x00")) { |
| throw new Error("collection names cannot contain a null character"); |
| } |
| }; |
| |
| var handleCallback = function(callback, err, value1, value2) { |
| try { |
| if(callback == null) return; |
| if(value2) return callback(err, value1, value2); |
| return callback(err, value1); |
| } catch(err) { |
| process.nextTick(function() { throw err; }); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Wrap a Mongo error document in an Error instance |
| * @ignore |
| * @api private |
| */ |
| var toError = function(error) { |
| if (error instanceof Error) return error; |
| |
| var msg = error.err || error.errmsg || error.errMessage || error; |
| var e = MongoError.create({message: msg, driver:true}); |
| |
| // Get all object keys |
| var keys = typeof error == 'object' |
| ? Object.keys(error) |
| : []; |
| |
| for(var i = 0; i < keys.length; i++) { |
| e[keys[i]] = error[keys[i]]; |
| } |
| |
| return e; |
| } |
| |
| /** |
| * @ignore |
| */ |
| var normalizeHintField = function normalizeHintField(hint) { |
| var finalHint = null; |
| |
| if(typeof hint == 'string') { |
| finalHint = hint; |
| } else if(Array.isArray(hint)) { |
| finalHint = {}; |
| |
| hint.forEach(function(param) { |
| finalHint[param] = 1; |
| }); |
| } else if(hint != null && typeof hint == 'object') { |
| finalHint = {}; |
| for (var name in hint) { |
| finalHint[name] = hint[name]; |
| } |
| } |
| |
| return finalHint; |
| }; |
| |
| /** |
| * Create index name based on field spec |
| * |
| * @ignore |
| * @api private |
| */ |
| var parseIndexOptions = function(fieldOrSpec) { |
| var fieldHash = {}; |
| var indexes = []; |
| var keys; |
| |
| // Get all the fields accordingly |
| if('string' == typeof fieldOrSpec) { |
| // 'type' |
| indexes.push(fieldOrSpec + '_' + 1); |
| fieldHash[fieldOrSpec] = 1; |
| } else if(Array.isArray(fieldOrSpec)) { |
| fieldOrSpec.forEach(function(f) { |
| if('string' == typeof f) { |
| // [{location:'2d'}, 'type'] |
| indexes.push(f + '_' + 1); |
| fieldHash[f] = 1; |
| } else if(Array.isArray(f)) { |
| // [['location', '2d'],['type', 1]] |
| indexes.push(f[0] + '_' + (f[1] || 1)); |
| fieldHash[f[0]] = f[1] || 1; |
| } else if(isObject(f)) { |
| // [{location:'2d'}, {type:1}] |
| keys = Object.keys(f); |
| keys.forEach(function(k) { |
| indexes.push(k + '_' + f[k]); |
| fieldHash[k] = f[k]; |
| }); |
| } else { |
| // undefined (ignore) |
| } |
| }); |
| } else if(isObject(fieldOrSpec)) { |
| // {location:'2d', type:1} |
| keys = Object.keys(fieldOrSpec); |
| keys.forEach(function(key) { |
| indexes.push(key + '_' + fieldOrSpec[key]); |
| fieldHash[key] = fieldOrSpec[key]; |
| }); |
| } |
| |
| return { |
| name: indexes.join("_"), keys: keys, fieldHash: fieldHash |
| } |
| } |
| |
| var isObject = exports.isObject = function (arg) { |
| return '[object Object]' == toString.call(arg) |
| } |
| |
| var debugOptions = function(debugFields, options) { |
| var finaloptions = {}; |
| debugFields.forEach(function(n) { |
| finaloptions[n] = options[n]; |
| }); |
| |
| return finaloptions; |
| } |
| |
| var decorateCommand = function(command, options, exclude) { |
| for(var name in options) { |
| if(exclude[name] == null) command[name] = options[name]; |
| } |
| |
| return command; |
| } |
| |
| exports.shallowClone = shallowClone; |
| exports.getSingleProperty = getSingleProperty; |
| exports.checkCollectionName = checkCollectionName; |
| exports.toError = toError; |
| exports.formattedOrderClause = formattedOrderClause; |
| exports.parseIndexOptions = parseIndexOptions; |
| exports.normalizeHintField = normalizeHintField; |
| exports.handleCallback = handleCallback; |
| exports.decorateCommand = decorateCommand; |
| exports.isObject = isObject; |
| exports.debugOptions = debugOptions; |