PageRenderTime 117ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js

https://bitbucket.org/itsTamas/crawler
JavaScript | 580 lines | 359 code | 192 blank | 29 comment | 72 complexity | b2103ff6b87bbb867913fdd348a15e27 MD5 | raw file
  1. // Load modules
  2. var Fs = require('fs');
  3. var Escape = require('./escape');
  4. // Declare internals
  5. var internals = {};
  6. // Clone object or array
  7. exports.clone = function (obj, seen) {
  8. if (typeof obj !== 'object' ||
  9. obj === null) {
  10. return obj;
  11. }
  12. seen = seen || { orig: [], copy: [] };
  13. var lookup = seen.orig.indexOf(obj);
  14. if (lookup !== -1) {
  15. return seen.copy[lookup];
  16. }
  17. var newObj = (obj instanceof Array) ? [] : {};
  18. seen.orig.push(obj);
  19. seen.copy.push(newObj);
  20. for (var i in obj) {
  21. if (obj.hasOwnProperty(i)) {
  22. if (obj[i] instanceof Buffer) {
  23. newObj[i] = new Buffer(obj[i]);
  24. }
  25. else if (obj[i] instanceof Date) {
  26. newObj[i] = new Date(obj[i].getTime());
  27. }
  28. else if (obj[i] instanceof RegExp) {
  29. var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
  30. newObj[i] = new RegExp(obj[i].source, flags);
  31. }
  32. else {
  33. newObj[i] = exports.clone(obj[i], seen);
  34. }
  35. }
  36. }
  37. return newObj;
  38. };
  39. // Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
  40. exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
  41. exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
  42. exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
  43. if (!source) {
  44. return target;
  45. }
  46. if (source instanceof Array) {
  47. exports.assert(target instanceof Array, 'Cannot merge array onto an object');
  48. if (isMergeArrays === false) { // isMergeArrays defaults to true
  49. target.length = 0; // Must not change target assignment
  50. }
  51. source.forEach(function (item) {
  52. target.push(item);
  53. });
  54. return target;
  55. }
  56. Object.keys(source).forEach(function (key) {
  57. var value = source[key];
  58. if (value &&
  59. typeof value === 'object') {
  60. if (!target[key] ||
  61. typeof target[key] !== 'object') {
  62. target[key] = exports.clone(value);
  63. }
  64. else {
  65. exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
  66. }
  67. }
  68. else {
  69. if (value !== null && value !== undefined) { // Explicit to preserve empty strings
  70. target[key] = value;
  71. }
  72. else if (isNullOverride !== false) { // Defaults to true
  73. target[key] = value;
  74. }
  75. }
  76. });
  77. return target;
  78. };
  79. // Apply options to a copy of the defaults
  80. exports.applyToDefaults = function (defaults, options) {
  81. exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
  82. exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
  83. if (!options) { // If no options, return null
  84. return null;
  85. }
  86. var copy = exports.clone(defaults);
  87. if (options === true) { // If options is set to true, use defaults
  88. return copy;
  89. }
  90. return exports.merge(copy, options, false, false);
  91. };
  92. // Remove duplicate items from array
  93. exports.unique = function (array, key) {
  94. var index = {};
  95. var result = [];
  96. for (var i = 0, il = array.length; i < il; ++i) {
  97. var id = (key ? array[i][key] : array[i]);
  98. if (index[id] !== true) {
  99. result.push(array[i]);
  100. index[id] = true;
  101. }
  102. }
  103. return result;
  104. };
  105. // Convert array into object
  106. exports.mapToObject = function (array, key) {
  107. if (!array) {
  108. return null;
  109. }
  110. var obj = {};
  111. for (var i = 0, il = array.length; i < il; ++i) {
  112. if (key) {
  113. if (array[i][key]) {
  114. obj[array[i][key]] = true;
  115. }
  116. }
  117. else {
  118. obj[array[i]] = true;
  119. }
  120. }
  121. return obj;
  122. };
  123. // Find the common unique items in two arrays
  124. exports.intersect = function (array1, array2) {
  125. if (!array1 || !array2) {
  126. return [];
  127. }
  128. var common = [];
  129. var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
  130. var found = {};
  131. for (var i = 0, il = array2.length; i < il; ++i) {
  132. if (hash[array2[i]] && !found[array2[i]]) {
  133. common.push(array2[i]);
  134. found[array2[i]] = true;
  135. }
  136. }
  137. return common;
  138. };
  139. // Find which keys are present
  140. exports.matchKeys = function (obj, keys) {
  141. var matched = [];
  142. for (var i = 0, il = keys.length; i < il; ++i) {
  143. if (obj.hasOwnProperty(keys[i])) {
  144. matched.push(keys[i]);
  145. }
  146. }
  147. return matched;
  148. };
  149. // Flatten array
  150. exports.flatten = function (array, target) {
  151. var result = target || [];
  152. for (var i = 0, il = array.length; i < il; ++i) {
  153. if (Array.isArray(array[i])) {
  154. exports.flatten(array[i], result);
  155. }
  156. else {
  157. result.push(array[i]);
  158. }
  159. }
  160. return result;
  161. };
  162. // Remove keys
  163. exports.removeKeys = function (object, keys) {
  164. for (var i = 0, il = keys.length; i < il; i++) {
  165. delete object[keys[i]];
  166. }
  167. };
  168. // Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
  169. exports.reach = function (obj, chain) {
  170. var path = chain.split('.');
  171. var ref = obj;
  172. path.forEach(function (level) {
  173. if (ref) {
  174. ref = ref[level];
  175. }
  176. });
  177. return ref;
  178. };
  179. // Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
  180. exports.inheritAsync = function (self, obj, keys) {
  181. keys = keys || null;
  182. for (var i in obj) {
  183. if (obj.hasOwnProperty(i)) {
  184. if (keys instanceof Array &&
  185. keys.indexOf(i) < 0) {
  186. continue;
  187. }
  188. self.prototype[i] = (function (fn) {
  189. return function (next) {
  190. var result = null;
  191. try {
  192. result = fn();
  193. }
  194. catch (err) {
  195. return next(err);
  196. }
  197. return next(null, result);
  198. };
  199. })(obj[i]);
  200. }
  201. }
  202. };
  203. exports.formatStack = function (stack) {
  204. var trace = [];
  205. stack.forEach(function (item) {
  206. trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
  207. });
  208. return trace;
  209. };
  210. exports.formatTrace = function (trace) {
  211. var display = [];
  212. trace.forEach(function (row) {
  213. display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
  214. });
  215. return display;
  216. };
  217. exports.callStack = function (slice) {
  218. // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
  219. var v8 = Error.prepareStackTrace;
  220. Error.prepareStackTrace = function (err, stack) {
  221. return stack;
  222. };
  223. var capture = {};
  224. Error.captureStackTrace(capture, arguments.callee);
  225. var stack = capture.stack;
  226. Error.prepareStackTrace = v8;
  227. var trace = exports.formatStack(stack);
  228. if (slice) {
  229. return trace.slice(slice);
  230. }
  231. return trace;
  232. };
  233. exports.displayStack = function (slice) {
  234. var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
  235. return exports.formatTrace(trace);
  236. };
  237. exports.abortThrow = false;
  238. exports.abort = function (message, hideStack) {
  239. if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
  240. throw new Error(message || 'Unknown error');
  241. }
  242. var stack = '';
  243. if (!hideStack) {
  244. stack = exports.displayStack(1).join('\n\t');
  245. }
  246. console.log('ABORT: ' + message + '\n\t' + stack);
  247. process.exit(1);
  248. };
  249. exports.assert = function (condition /*, msg1, msg2, msg3 */) {
  250. if (condition) {
  251. return;
  252. }
  253. var msgs = Array.prototype.slice.call(arguments, 1);
  254. msgs = msgs.map(function (msg) {
  255. return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : JSON.stringify(msg);
  256. });
  257. throw new Error(msgs.join(' ') || 'Unknown error');
  258. };
  259. exports.loadDirModules = function (path, excludeFiles, target) { // target(filename, name, capName)
  260. var exclude = {};
  261. for (var i = 0, il = excludeFiles.length; i < il; ++i) {
  262. exclude[excludeFiles[i] + '.js'] = true;
  263. }
  264. Fs.readdirSync(path).forEach(function (filename) {
  265. if (/\.js$/.test(filename) &&
  266. !exclude[filename]) {
  267. var name = filename.substr(0, filename.lastIndexOf('.'));
  268. var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();
  269. if (typeof target !== 'function') {
  270. target[capName] = require(path + '/' + name);
  271. }
  272. else {
  273. target(path + '/' + name, name, capName);
  274. }
  275. }
  276. });
  277. };
  278. exports.rename = function (obj, from, to) {
  279. obj[to] = obj[from];
  280. delete obj[from];
  281. };
  282. exports.Timer = function () {
  283. this.reset();
  284. };
  285. exports.Timer.prototype.reset = function () {
  286. this.ts = Date.now();
  287. };
  288. exports.Timer.prototype.elapsed = function () {
  289. return Date.now() - this.ts;
  290. };
  291. // Load and parse package.json process root or given directory
  292. exports.loadPackage = function (dir) {
  293. var result = {};
  294. var filepath = (dir || process.env.PWD) + '/package.json';
  295. if (Fs.existsSync(filepath)) {
  296. try {
  297. result = JSON.parse(Fs.readFileSync(filepath));
  298. }
  299. catch (e) { }
  300. }
  301. return result;
  302. };
  303. // Escape string for Regex construction
  304. exports.escapeRegex = function (string) {
  305. // Escape ^$.*+-?=!:|\/()[]{},
  306. return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
  307. };
  308. // Return an error as first argument of a callback
  309. exports.toss = function (condition /*, [message], next */) {
  310. var message = (arguments.length === 3 ? arguments[1] : '');
  311. var next = (arguments.length === 3 ? arguments[2] : arguments[1]);
  312. var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));
  313. if (condition instanceof Error ||
  314. !condition) {
  315. return next(err);
  316. }
  317. };
  318. // Base64url (RFC 4648) encode
  319. exports.base64urlEncode = function (value) {
  320. return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
  321. };
  322. // Base64url (RFC 4648) decode
  323. exports.base64urlDecode = function (encoded) {
  324. if (encoded &&
  325. !encoded.match(/^[\w\-]*$/)) {
  326. return new Error('Invalid character');
  327. }
  328. try {
  329. return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
  330. }
  331. catch (err) {
  332. return err;
  333. }
  334. };
  335. // Escape attribute value for use in HTTP header
  336. exports.escapeHeaderAttribute = function (attribute) {
  337. // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
  338. exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');
  339. return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"'); // Escape quotes and slash
  340. };
  341. exports.escapeHtml = function (string) {
  342. return Escape.escapeHtml(string);
  343. };
  344. exports.escapeJavaScript = function (string) {
  345. return Escape.escapeJavaScript(string);
  346. };
  347. /*
  348. var event = {
  349. timestamp: now.getTime(),
  350. tags: ['tag'],
  351. data: { some: 'data' }
  352. };
  353. */
  354. exports.consoleFunc = console.log;
  355. exports.printEvent = function (event) {
  356. var pad = function (value) {
  357. return (value < 10 ? '0' : '') + value;
  358. };
  359. var now = new Date(event.timestamp);
  360. var timestring = (now.getYear() - 100).toString() +
  361. pad(now.getMonth() + 1) +
  362. pad(now.getDate()) +
  363. '/' +
  364. pad(now.getHours()) +
  365. pad(now.getMinutes()) +
  366. pad(now.getSeconds()) +
  367. '.' +
  368. now.getMilliseconds();
  369. var data = event.data;
  370. if (typeof event.data !== 'string') {
  371. try {
  372. data = JSON.stringify(event.data);
  373. }
  374. catch (e) {
  375. data = 'JSON Error: ' + e.message;
  376. }
  377. }
  378. var output = timestring + ', ' + event.tags[0] + ', ' + data;
  379. exports.consoleFunc(output);
  380. };
  381. exports.nextTick = function (callback) {
  382. return function () {
  383. var args = arguments;
  384. process.nextTick(function () {
  385. callback.apply(null, args);
  386. });
  387. };
  388. };