utils.js 5.8 KB

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