utils.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. "use strict";
  2. var MongoError = require('mongodb-core').MongoError,
  3. f = require('util').format;
  4. var shallowClone = function(obj) {
  5. var copy = {};
  6. for(var name in obj) copy[name] = obj[name];
  7. return copy;
  8. }
  9. // Set simple property
  10. var getSingleProperty = function(obj, name, value) {
  11. Object.defineProperty(obj, name, {
  12. enumerable:true,
  13. get: function() {
  14. return value
  15. }
  16. });
  17. }
  18. var formatSortValue = exports.formatSortValue = function(sortDirection) {
  19. var value = ("" + sortDirection).toLowerCase();
  20. switch (value) {
  21. case 'ascending':
  22. case 'asc':
  23. case '1':
  24. return 1;
  25. case 'descending':
  26. case 'desc':
  27. case '-1':
  28. return -1;
  29. default:
  30. throw new Error("Illegal sort clause, must be of the form "
  31. + "[['field1', '(ascending|descending)'], "
  32. + "['field2', '(ascending|descending)']]");
  33. }
  34. };
  35. var formattedOrderClause = exports.formattedOrderClause = function(sortValue) {
  36. var orderBy = {};
  37. if(sortValue == null) return null;
  38. if (Array.isArray(sortValue)) {
  39. if(sortValue.length === 0) {
  40. return null;
  41. }
  42. for(var i = 0; i < sortValue.length; i++) {
  43. if(sortValue[i].constructor == String) {
  44. orderBy[sortValue[i]] = 1;
  45. } else {
  46. orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]);
  47. }
  48. }
  49. } else if(sortValue != null && typeof sortValue == 'object') {
  50. orderBy = sortValue;
  51. } else if (typeof sortValue == 'string') {
  52. orderBy[sortValue] = 1;
  53. } else {
  54. throw new Error("Illegal sort clause, must be of the form " +
  55. "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]");
  56. }
  57. return orderBy;
  58. };
  59. var checkCollectionName = function checkCollectionName (collectionName) {
  60. if('string' !== typeof collectionName) {
  61. throw Error("collection name must be a String");
  62. }
  63. if(!collectionName || collectionName.indexOf('..') != -1) {
  64. throw Error("collection names cannot be empty");
  65. }
  66. if(collectionName.indexOf('$') != -1 &&
  67. collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null) {
  68. throw Error("collection names must not contain '$'");
  69. }
  70. if(collectionName.match(/^\.|\.$/) != null) {
  71. throw Error("collection names must not start or end with '.'");
  72. }
  73. // Validate that we are not passing 0x00 in the colletion name
  74. if(!!~collectionName.indexOf("\x00")) {
  75. throw new Error("collection names cannot contain a null character");
  76. }
  77. };
  78. var handleCallback = function(callback, err, value1, value2) {
  79. try {
  80. if(callback == null) return;
  81. if(value2) return callback(err, value1, value2);
  82. return callback(err, value1);
  83. } catch(err) {
  84. process.nextTick(function() { throw err; });
  85. return false;
  86. }
  87. return true;
  88. }
  89. /**
  90. * Wrap a Mongo error document in an Error instance
  91. * @ignore
  92. * @api private
  93. */
  94. var toError = function(error) {
  95. if (error instanceof Error) return error;
  96. var msg = error.err || error.errmsg || error.errMessage || error;
  97. var e = MongoError.create({message: msg, driver:true});
  98. // Get all object keys
  99. var keys = typeof error == 'object'
  100. ? Object.keys(error)
  101. : [];
  102. for(var i = 0; i < keys.length; i++) {
  103. e[keys[i]] = error[keys[i]];
  104. }
  105. return e;
  106. }
  107. /**
  108. * @ignore
  109. */
  110. var normalizeHintField = function normalizeHintField(hint) {
  111. var finalHint = null;
  112. if(typeof hint == 'string') {
  113. finalHint = hint;
  114. } else if(Array.isArray(hint)) {
  115. finalHint = {};
  116. hint.forEach(function(param) {
  117. finalHint[param] = 1;
  118. });
  119. } else if(hint != null && typeof hint == 'object') {
  120. finalHint = {};
  121. for (var name in hint) {
  122. finalHint[name] = hint[name];
  123. }
  124. }
  125. return finalHint;
  126. };
  127. /**
  128. * Create index name based on field spec
  129. *
  130. * @ignore
  131. * @api private
  132. */
  133. var parseIndexOptions = function(fieldOrSpec) {
  134. var fieldHash = {};
  135. var indexes = [];
  136. var keys;
  137. // Get all the fields accordingly
  138. if('string' == typeof fieldOrSpec) {
  139. // 'type'
  140. indexes.push(fieldOrSpec + '_' + 1);
  141. fieldHash[fieldOrSpec] = 1;
  142. } else if(Array.isArray(fieldOrSpec)) {
  143. fieldOrSpec.forEach(function(f) {
  144. if('string' == typeof f) {
  145. // [{location:'2d'}, 'type']
  146. indexes.push(f + '_' + 1);
  147. fieldHash[f] = 1;
  148. } else if(Array.isArray(f)) {
  149. // [['location', '2d'],['type', 1]]
  150. indexes.push(f[0] + '_' + (f[1] || 1));
  151. fieldHash[f[0]] = f[1] || 1;
  152. } else if(isObject(f)) {
  153. // [{location:'2d'}, {type:1}]
  154. keys = Object.keys(f);
  155. keys.forEach(function(k) {
  156. indexes.push(k + '_' + f[k]);
  157. fieldHash[k] = f[k];
  158. });
  159. } else {
  160. // undefined (ignore)
  161. }
  162. });
  163. } else if(isObject(fieldOrSpec)) {
  164. // {location:'2d', type:1}
  165. keys = Object.keys(fieldOrSpec);
  166. keys.forEach(function(key) {
  167. indexes.push(key + '_' + fieldOrSpec[key]);
  168. fieldHash[key] = fieldOrSpec[key];
  169. });
  170. }
  171. return {
  172. name: indexes.join("_"), keys: keys, fieldHash: fieldHash
  173. }
  174. }
  175. var isObject = exports.isObject = function (arg) {
  176. return '[object Object]' == toString.call(arg)
  177. }
  178. var debugOptions = function(debugFields, options) {
  179. var finaloptions = {};
  180. debugFields.forEach(function(n) {
  181. finaloptions[n] = options[n];
  182. });
  183. return finaloptions;
  184. }
  185. var decorateCommand = function(command, options, exclude) {
  186. for(var name in options) {
  187. if(exclude[name] == null) command[name] = options[name];
  188. }
  189. return command;
  190. }
  191. exports.shallowClone = shallowClone;
  192. exports.getSingleProperty = getSingleProperty;
  193. exports.checkCollectionName = checkCollectionName;
  194. exports.toError = toError;
  195. exports.formattedOrderClause = formattedOrderClause;
  196. exports.parseIndexOptions = parseIndexOptions;
  197. exports.normalizeHintField = normalizeHintField;
  198. exports.handleCallback = handleCallback;
  199. exports.decorateCommand = decorateCommand;
  200. exports.isObject = isObject;
  201. exports.debugOptions = debugOptions;