diff options
| author | Arman Shah <[email protected]> | 2018-02-19 23:50:04 -0800 |
|---|---|---|
| committer | Arman Shah <[email protected]> | 2018-02-19 23:50:04 -0800 |
| commit | ae34dcfd3823a609ba7182f2d6eda593be876f7d (patch) | |
| tree | b9d7f2884c4999349418cbdc4f9ab46d113e0afd /node_modules/hoek/lib/index.js | |
| parent | Initial commit (diff) | |
| download | launcher-ae34dcfd3823a609ba7182f2d6eda593be876f7d.tar.xz launcher-ae34dcfd3823a609ba7182f2d6eda593be876f7d.zip | |
add base files
Diffstat (limited to 'node_modules/hoek/lib/index.js')
| -rwxr-xr-x | node_modules/hoek/lib/index.js | 978 |
1 files changed, 978 insertions, 0 deletions
diff --git a/node_modules/hoek/lib/index.js b/node_modules/hoek/lib/index.js new file mode 100755 index 0000000..75bbeb7 --- /dev/null +++ b/node_modules/hoek/lib/index.js @@ -0,0 +1,978 @@ +'use strict'; + +// Load modules + +const Crypto = require('crypto'); +const Path = require('path'); +const Util = require('util'); +const Escape = require('./escape'); + + +// Declare internals + +const internals = {}; + + +// Clone object or array + +exports.clone = function (obj, seen) { + + if (typeof obj !== 'object' || + obj === null) { + + return obj; + } + + seen = seen || new Map(); + + const lookup = seen.get(obj); + if (lookup) { + return lookup; + } + + let newObj; + let cloneDeep = false; + + if (!Array.isArray(obj)) { + if (Buffer.isBuffer(obj)) { + newObj = new Buffer(obj); + } + else if (obj instanceof Date) { + newObj = new Date(obj.getTime()); + } + else if (obj instanceof RegExp) { + newObj = new RegExp(obj); + } + else { + const proto = Object.getPrototypeOf(obj); + if (proto && + proto.isImmutable) { + + newObj = obj; + } + else { + newObj = Object.create(proto); + cloneDeep = true; + } + } + } + else { + newObj = []; + cloneDeep = true; + } + + seen.set(obj, newObj); + + if (cloneDeep) { + const keys = Object.getOwnPropertyNames(obj); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const descriptor = Object.getOwnPropertyDescriptor(obj, key); + if (descriptor && + (descriptor.get || + descriptor.set)) { + + Object.defineProperty(newObj, key, descriptor); + } + else { + newObj[key] = exports.clone(obj[key], seen); + } + } + } + + return newObj; +}; + + +// Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied + +/*eslint-disable */ +exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) { +/*eslint-enable */ + + exports.assert(target && typeof target === 'object', 'Invalid target value: must be an object'); + exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object'); + + if (!source) { + return target; + } + + if (Array.isArray(source)) { + exports.assert(Array.isArray(target), 'Cannot merge array onto an object'); + if (isMergeArrays === false) { // isMergeArrays defaults to true + target.length = 0; // Must not change target assignment + } + + for (let i = 0; i < source.length; ++i) { + target.push(exports.clone(source[i])); + } + + return target; + } + + const keys = Object.keys(source); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (key === '__proto__') { + continue; + } + + const value = source[key]; + if (value && + typeof value === 'object') { + + if (!target[key] || + typeof target[key] !== 'object' || + (Array.isArray(target[key]) !== Array.isArray(value)) || + value instanceof Date || + Buffer.isBuffer(value) || + value instanceof RegExp) { + + target[key] = exports.clone(value); + } + else { + exports.merge(target[key], value, isNullOverride, isMergeArrays); + } + } + else { + if (value !== null && + value !== undefined) { // Explicit to preserve empty strings + + target[key] = value; + } + else if (isNullOverride !== false) { // Defaults to true + target[key] = value; + } + } + } + + return target; +}; + + +// Apply options to a copy of the defaults + +exports.applyToDefaults = function (defaults, options, isNullOverride) { + + exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object'); + exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object'); + + if (!options) { // If no options, return null + return null; + } + + const copy = exports.clone(defaults); + + if (options === true) { // If options is set to true, use defaults + return copy; + } + + return exports.merge(copy, options, isNullOverride === true, false); +}; + + +// Clone an object except for the listed keys which are shallow copied + +exports.cloneWithShallow = function (source, keys) { + + if (!source || + typeof source !== 'object') { + + return source; + } + + const storage = internals.store(source, keys); // Move shallow copy items to storage + const copy = exports.clone(source); // Deep copy the rest + internals.restore(copy, source, storage); // Shallow copy the stored items and restore + return copy; +}; + + +internals.store = function (source, keys) { + + const storage = {}; + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const value = exports.reach(source, key); + if (value !== undefined) { + storage[key] = value; + internals.reachSet(source, key, undefined); + } + } + + return storage; +}; + + +internals.restore = function (copy, source, storage) { + + const keys = Object.keys(storage); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + internals.reachSet(copy, key, storage[key]); + internals.reachSet(source, key, storage[key]); + } +}; + + +internals.reachSet = function (obj, key, value) { + + const path = key.split('.'); + let ref = obj; + for (let i = 0; i < path.length; ++i) { + const segment = path[i]; + if (i + 1 === path.length) { + ref[segment] = value; + } + + ref = ref[segment]; + } +}; + + +// Apply options to defaults except for the listed keys which are shallow copied from option without merging + +exports.applyToDefaultsWithShallow = function (defaults, options, keys) { + + exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object'); + exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object'); + exports.assert(keys && Array.isArray(keys), 'Invalid keys'); + + if (!options) { // If no options, return null + return null; + } + + const copy = exports.cloneWithShallow(defaults, keys); + + if (options === true) { // If options is set to true, use defaults + return copy; + } + + const storage = internals.store(options, keys); // Move shallow copy items to storage + exports.merge(copy, options, false, false); // Deep copy the rest + internals.restore(copy, options, storage); // Shallow copy the stored items and restore + return copy; +}; + + +// Deep object or array comparison + +exports.deepEqual = function (obj, ref, options, seen) { + + options = options || { prototype: true }; + + const type = typeof obj; + + if (type !== typeof ref) { + return false; + } + + if (type !== 'object' || + obj === null || + ref === null) { + + if (obj === ref) { // Copied from Deep-eql, copyright(c) 2013 Jake Luer, [email protected], MIT Licensed, https://github.com/chaijs/deep-eql + return obj !== 0 || 1 / obj === 1 / ref; // -0 / +0 + } + + return obj !== obj && ref !== ref; // NaN + } + + seen = seen || []; + if (seen.indexOf(obj) !== -1) { + return true; // If previous comparison failed, it would have stopped execution + } + + seen.push(obj); + + if (Array.isArray(obj)) { + if (!Array.isArray(ref)) { + return false; + } + + if (!options.part && obj.length !== ref.length) { + return false; + } + + for (let i = 0; i < obj.length; ++i) { + if (options.part) { + let found = false; + for (let j = 0; j < ref.length; ++j) { + if (exports.deepEqual(obj[i], ref[j], options)) { + found = true; + break; + } + } + + return found; + } + + if (!exports.deepEqual(obj[i], ref[i], options)) { + return false; + } + } + + return true; + } + + if (Buffer.isBuffer(obj)) { + if (!Buffer.isBuffer(ref)) { + return false; + } + + if (obj.length !== ref.length) { + return false; + } + + for (let i = 0; i < obj.length; ++i) { + if (obj[i] !== ref[i]) { + return false; + } + } + + return true; + } + + if (obj instanceof Date) { + return (ref instanceof Date && obj.getTime() === ref.getTime()); + } + + if (obj instanceof RegExp) { + return (ref instanceof RegExp && obj.toString() === ref.toString()); + } + + if (options.prototype) { + if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) { + return false; + } + } + + const keys = Object.getOwnPropertyNames(obj); + + if (!options.part && keys.length !== Object.getOwnPropertyNames(ref).length) { + return false; + } + + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const descriptor = Object.getOwnPropertyDescriptor(obj, key); + if (descriptor.get) { + if (!exports.deepEqual(descriptor, Object.getOwnPropertyDescriptor(ref, key), options, seen)) { + return false; + } + } + else if (!exports.deepEqual(obj[key], ref[key], options, seen)) { + return false; + } + } + + return true; +}; + + +// Remove duplicate items from array + +exports.unique = (array, key) => { + + let result; + if (key) { + result = []; + const index = new Set(); + array.forEach((item) => { + + const identifier = item[key]; + if (!index.has(identifier)) { + index.add(identifier); + result.push(item); + } + }); + } + else { + result = Array.from(new Set(array)); + } + + return result; +}; + + +// Convert array into object + +exports.mapToObject = function (array, key) { + + if (!array) { + return null; + } + + const obj = {}; + for (let i = 0; i < array.length; ++i) { + if (key) { + if (array[i][key]) { + obj[array[i][key]] = true; + } + } + else { + obj[array[i]] = true; + } + } + + return obj; +}; + + +// Find the common unique items in two arrays + +exports.intersect = function (array1, array2, justFirst) { + + if (!array1 || !array2) { + return []; + } + + const common = []; + const hash = (Array.isArray(array1) ? exports.mapToObject(array1) : array1); + const found = {}; + for (let i = 0; i < array2.length; ++i) { + if (hash[array2[i]] && !found[array2[i]]) { + if (justFirst) { + return array2[i]; + } + + common.push(array2[i]); + found[array2[i]] = true; + } + } + + return (justFirst ? null : common); +}; + + +// Test if the reference contains the values + +exports.contain = function (ref, values, options) { + + /* + string -> string(s) + array -> item(s) + object -> key(s) + object -> object (key:value) + */ + + let valuePairs = null; + if (typeof ref === 'object' && + typeof values === 'object' && + !Array.isArray(ref) && + !Array.isArray(values)) { + + valuePairs = values; + values = Object.keys(values); + } + else { + values = [].concat(values); + } + + options = options || {}; // deep, once, only, part + + exports.assert(arguments.length >= 2, 'Insufficient arguments'); + exports.assert(typeof ref === 'string' || typeof ref === 'object', 'Reference must be string or an object'); + exports.assert(values.length, 'Values array cannot be empty'); + + let compare; + let compareFlags; + if (options.deep) { + compare = exports.deepEqual; + + const hasOnly = options.hasOwnProperty('only'); + const hasPart = options.hasOwnProperty('part'); + + compareFlags = { + prototype: hasOnly ? options.only : hasPart ? !options.part : false, + part: hasOnly ? !options.only : hasPart ? options.part : true + }; + } + else { + compare = (a, b) => a === b; + } + + let misses = false; + const matches = new Array(values.length); + for (let i = 0; i < matches.length; ++i) { + matches[i] = 0; + } + + if (typeof ref === 'string') { + let pattern = '('; + for (let i = 0; i < values.length; ++i) { + const value = values[i]; + exports.assert(typeof value === 'string', 'Cannot compare string reference to non-string value'); + pattern += (i ? '|' : '') + exports.escapeRegex(value); + } + + const regex = new RegExp(pattern + ')', 'g'); + const leftovers = ref.replace(regex, ($0, $1) => { + + const index = values.indexOf($1); + ++matches[index]; + return ''; // Remove from string + }); + + misses = !!leftovers; + } + else if (Array.isArray(ref)) { + for (let i = 0; i < ref.length; ++i) { + let matched = false; + for (let j = 0; j < values.length && matched === false; ++j) { + matched = compare(values[j], ref[i], compareFlags) && j; + } + + if (matched !== false) { + ++matches[matched]; + } + else { + misses = true; + } + } + } + else { + const keys = Object.getOwnPropertyNames(ref); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const pos = values.indexOf(key); + if (pos !== -1) { + if (valuePairs && + !compare(valuePairs[key], ref[key], compareFlags)) { + + return false; + } + + ++matches[pos]; + } + else { + misses = true; + } + } + } + + let result = false; + for (let i = 0; i < matches.length; ++i) { + result = result || !!matches[i]; + if ((options.once && matches[i] > 1) || + (!options.part && !matches[i])) { + + return false; + } + } + + if (options.only && + misses) { + + return false; + } + + return result; +}; + + +// Flatten array + +exports.flatten = function (array, target) { + + const result = target || []; + + for (let i = 0; i < array.length; ++i) { + if (Array.isArray(array[i])) { + exports.flatten(array[i], result); + } + else { + result.push(array[i]); + } + } + + return result; +}; + + +// Convert an object key chain string ('a.b.c') to reference (object[a][b][c]) + +exports.reach = function (obj, chain, options) { + + if (chain === false || + chain === null || + typeof chain === 'undefined') { + + return obj; + } + + options = options || {}; + if (typeof options === 'string') { + options = { separator: options }; + } + + const path = chain.split(options.separator || '.'); + let ref = obj; + for (let i = 0; i < path.length; ++i) { + let key = path[i]; + if (key[0] === '-' && Array.isArray(ref)) { + key = key.slice(1, key.length); + key = ref.length - key; + } + + if (!ref || + !((typeof ref === 'object' || typeof ref === 'function') && key in ref) || + (typeof ref !== 'object' && options.functions === false)) { // Only object and function can have properties + + exports.assert(!options.strict || i + 1 === path.length, 'Missing segment', key, 'in reach path ', chain); + exports.assert(typeof ref === 'object' || options.functions === true || typeof ref !== 'function', 'Invalid segment', key, 'in reach path ', chain); + ref = options.default; + break; + } + + ref = ref[key]; + } + + return ref; +}; + + +exports.reachTemplate = function (obj, template, options) { + + return template.replace(/{([^}]+)}/g, ($0, chain) => { + + const value = exports.reach(obj, chain, options); + return (value === undefined || value === null ? '' : value); + }); +}; + + +exports.formatStack = function (stack) { + + const trace = []; + for (let i = 0; i < stack.length; ++i) { + const item = stack[i]; + trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]); + } + + return trace; +}; + + +exports.formatTrace = function (trace) { + + const display = []; + + for (let i = 0; i < trace.length; ++i) { + const row = trace[i]; + display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')'); + } + + return display; +}; + + +exports.callStack = function (slice) { + + // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi + + const v8 = Error.prepareStackTrace; + Error.prepareStackTrace = function (_, stack) { + + return stack; + }; + + const capture = {}; + Error.captureStackTrace(capture, this); // arguments.callee is not supported in strict mode so we use this and slice the trace of this off the result + const stack = capture.stack; + + Error.prepareStackTrace = v8; + + const trace = exports.formatStack(stack); + + return trace.slice(1 + slice); +}; + + +exports.displayStack = function (slice) { + + const trace = exports.callStack(slice === undefined ? 1 : slice + 1); + + return exports.formatTrace(trace); +}; + + +exports.abortThrow = false; + + +exports.abort = function (message, hideStack) { + + if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) { + throw new Error(message || 'Unknown error'); + } + + let stack = ''; + if (!hideStack) { + stack = exports.displayStack(1).join('\n\t'); + } + console.log('ABORT: ' + message + '\n\t' + stack); + process.exit(1); +}; + + +exports.assert = function (condition /*, msg1, msg2, msg3 */) { + + if (condition) { + return; + } + + if (arguments.length === 2 && arguments[1] instanceof Error) { + throw arguments[1]; + } + + let msgs = []; + for (let i = 1; i < arguments.length; ++i) { + if (arguments[i] !== '') { + msgs.push(arguments[i]); // Avoids Array.slice arguments leak, allowing for V8 optimizations + } + } + + msgs = msgs.map((msg) => { + + return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : exports.stringify(msg); + }); + + throw new Error(msgs.join(' ') || 'Unknown error'); +}; + + +exports.Timer = function () { + + this.ts = 0; + this.reset(); +}; + + +exports.Timer.prototype.reset = function () { + + this.ts = Date.now(); +}; + + +exports.Timer.prototype.elapsed = function () { + + return Date.now() - this.ts; +}; + + +exports.Bench = function () { + + this.ts = 0; + this.reset(); +}; + + +exports.Bench.prototype.reset = function () { + + this.ts = exports.Bench.now(); +}; + + +exports.Bench.prototype.elapsed = function () { + + return exports.Bench.now() - this.ts; +}; + + +exports.Bench.now = function () { + + const ts = process.hrtime(); + return (ts[0] * 1e3) + (ts[1] / 1e6); +}; + + +// Escape string for Regex construction + +exports.escapeRegex = function (string) { + + // Escape ^$.*+-?=!:|\/()[]{}, + return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&'); +}; + + +// Base64url (RFC 4648) encode + +exports.base64urlEncode = function (value, encoding) { + + exports.assert(typeof value === 'string' || Buffer.isBuffer(value), 'value must be string or buffer'); + const buf = (Buffer.isBuffer(value) ? value : new Buffer(value, encoding || 'binary')); + return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, ''); +}; + + +// Base64url (RFC 4648) decode + +exports.base64urlDecode = function (value, encoding) { + + if (typeof value !== 'string') { + + return new Error('Value not a string'); + } + + if (!/^[\w\-]*$/.test(value)) { + + return new Error('Invalid character'); + } + + const buf = new Buffer(value, 'base64'); + return (encoding === 'buffer' ? buf : buf.toString(encoding || 'binary')); +}; + + +// Escape attribute value for use in HTTP header + +exports.escapeHeaderAttribute = function (attribute) { + + // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, " + + exports.assert(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/.test(attribute), 'Bad attribute value (' + attribute + ')'); + + return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"'); // Escape quotes and slash +}; + + +exports.escapeHtml = function (string) { + + return Escape.escapeHtml(string); +}; + + +exports.escapeJavaScript = function (string) { + + return Escape.escapeJavaScript(string); +}; + +exports.escapeJson = function (string) { + + return Escape.escapeJson(string); +}; + +exports.nextTick = function (callback) { + + return function () { + + const args = arguments; + process.nextTick(() => { + + callback.apply(null, args); + }); + }; +}; + + +exports.once = function (method) { + + if (method._hoekOnce) { + return method; + } + + let once = false; + const wrapped = function () { + + if (!once) { + once = true; + method.apply(null, arguments); + } + }; + + wrapped._hoekOnce = true; + + return wrapped; +}; + + +exports.isInteger = Number.isSafeInteger; + + +exports.ignore = function () { }; + + +exports.inherits = Util.inherits; + + +exports.format = Util.format; + + +exports.transform = function (source, transform, options) { + + exports.assert(source === null || source === undefined || typeof source === 'object' || Array.isArray(source), 'Invalid source object: must be null, undefined, an object, or an array'); + const separator = (typeof options === 'object' && options !== null) ? (options.separator || '.') : '.'; + + if (Array.isArray(source)) { + const results = []; + for (let i = 0; i < source.length; ++i) { + results.push(exports.transform(source[i], transform, options)); + } + return results; + } + + const result = {}; + const keys = Object.keys(transform); + + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const path = key.split(separator); + const sourcePath = transform[key]; + + exports.assert(typeof sourcePath === 'string', 'All mappings must be "." delineated strings'); + + let segment; + let res = result; + + while (path.length > 1) { + segment = path.shift(); + if (!res[segment]) { + res[segment] = {}; + } + res = res[segment]; + } + segment = path.shift(); + res[segment] = exports.reach(source, sourcePath, options); + } + + return result; +}; + + +exports.uniqueFilename = function (path, extension) { + + if (extension) { + extension = extension[0] !== '.' ? '.' + extension : extension; + } + else { + extension = ''; + } + + path = Path.resolve(path); + const name = [Date.now(), process.pid, Crypto.randomBytes(8).toString('hex')].join('-') + extension; + return Path.join(path, name); +}; + + +exports.stringify = function () { + + try { + return JSON.stringify.apply(null, arguments); + } + catch (err) { + return '[Cannot display object: ' + err.message + ']'; + } +}; + + +exports.shallow = function (source) { + + const target = {}; + const keys = Object.keys(source); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + target[key] = source[key]; + } + + return target; +}; |