UNPKG

node-vitals

Version:

Do more with less. A simple, high-performing, functional JavaScript library.

2,061 lines (1,768 loc) 189 kB
/** * ----------------------------------------------------------------------------- * VITALS JS - NODE VERSION - BASE METHODS * ----------------------------------------------------------------------------- * @file A JavaScript library of utility methods designed for elegance, * performance, and reliability. * @version 4.1.3 * @see [vitals]{@link https://github.com/imaginate/vitals} * * @author Adam Smith <adam@imaginate.life> (https://github.com/imaginate) * @copyright 2017 Adam A Smith <adam@imaginate.life> (https://github.com/imaginate) * * Annotations: * @see [JSDoc3](http://usejsdoc.org) * @see [Closure Compiler JSDoc Syntax](https://developers.google.com/closure/compiler/docs/js-for-compiler) */ 'use strict'; // ***************************************************************************** // PRIVATE HELPERS // ***************************************************************************** //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: escape //////////////////////////////////////////////////////////////////////////////// var escape = (function escapePrivateScope() { /** * @private * @type {!RegExp} * @const */ var CHARS = /[\\^$.*+?|(){}[\]]/g; /** * @param {string} source * @return {string} */ function escape(source) { return source.replace(CHARS, '\\$&'); } //////////////////////////////////////////////////// // PRIVATE SCOPE END: escape return escape; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: inArr //////////////////////////////////////////////////////////////////////////////// /** * @param {!Object} source * @param {*} val * @return {boolean} */ function inArr(source, val) { /** @type {number} */ var len; /** @type {number} */ var i; len = source.length; i = -1; while (++i < len) { if (source[i] === val) return true; } return false; } //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: inObj //////////////////////////////////////////////////////////////////////////////// var inObj = (function inObjPrivateScope() { /** * @private * @param {*} key * @return {boolean} */ var hasOwn = Object.prototype.hasOwnProperty; /** * @param {(!Object|function)} source * @param {*} val * @return {boolean} */ function inObj(source, val) { /** @type {string} */ var key; for (key in source) { if ( hasOwn.call(source, key) && source[key] === val ) return true; } return false; } //////////////////////////////////////////////////// // PRIVATE SCOPE END: inObj return inObj; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: inStr //////////////////////////////////////////////////////////////////////////////// var inStr = (function inStrPrivateScope() { /** * @private * @param {string} source * @param {string} str * @return {boolean} */ var baseInStr = !!String.prototype.includes ? function baseInStr(source, str) { return source.includes(str); } : function baseInStr(source, str) { return source.indexOf(str) !== -1; }; /** * A shortcut for `String.prototype.includes`. * @param {string} source * @param {*} str * @return {boolean} */ function inStr(source, str) { str = String(str); if (!source) return !str; if (!str) return true; return baseInStr(source, str); } //////////////////////////////////////////////////// // PRIVATE SCOPE END: inStr return inStr; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: _is //////////////////////////////////////////////////////////////////////////////// var _is = (function _isPrivateScope() { /** @type {!Object} */ var is = {}; ////////////////////////////////////////////////////////// // PRIMITIVES ////////////////////////////////////////////////////////// /** * @param {*} val * @return {boolean} */ is.nil = function isNull(val) { return val === null; }; /** * @param {*} val * @return {boolean} */ is.undefined = function isUndefined(val) { return val === undefined; }; /** * @param {*} val * @return {boolean} */ is.bool = function isBoolean(val) { return typeof val === 'boolean'; }; /** * @param {*} val * @return {boolean} */ is.str = function isString(val) { return typeof val === 'string'; }; /** * Empty strings return false in this method. * @param {*} val * @return {boolean} */ is._str = function isNonEmptyString(val) { return !!val && typeof val === 'string'; }; /** * @param {*} val * @return {boolean} */ is.num = function isNumber(val) { return typeof val === 'number' && val === val; }; /** * Zeros return false in this method. * @param {*} val * @return {boolean} */ is._num = function isNonZeroNumber(val) { return !!val && typeof val === 'number' && val === val; }; /** * @param {*} val * @return {boolean} */ is.nan = function isNan(val) { return val !== val; }; ////////////////////////////////////////////////////////// // JS OBJECTS ////////////////////////////////////////////////////////// /** * @private * @return {string} */ var toStr = Object.prototype.toString; /** * @param {*} val * @return {boolean} */ is.obj = function isObject(val) { return !!val && typeof val === 'object'; }; /** * Functions return true in this method. * @param {*} val * @return {boolean} */ is._obj = function isObjectOrFunction(val) { val = !!val && typeof val; return val && (val === 'object' || val === 'function'); }; /** * @param {*} val * @return {boolean} */ is.func = function isFunction(val) { return !!val && typeof val === 'function'; }; /** * @param {*} val * @return {boolean} */ is.arr = function isArray(val) { return !!val && typeof val === 'object' && toStr.call(val) === '[object Array]'; }; /** * Arguments return true in this method. * @param {*} val * @return {boolean} */ is._arr = function isArrayOrArguments(val) { if ( !is.obj(val) ) return false; val = toStr.call(val); return val === '[object Array]' || val === '[object Arguments]'; }; /** * @param {*} val * @return {boolean} */ is.regex = function isRegExp(val) { return !!val && typeof val === 'object' && toStr.call(val) === '[object RegExp]'; }; /** * @param {*} val * @return {boolean} */ is.date = function isDate(val) { return !!val && typeof val === 'object' && toStr.call(val) === '[object Date]'; }; /** * @param {*} val * @return {boolean} */ is.err = function isError(val) { return !!val && typeof val === 'object' && toStr.call(val) === '[object Error]'; }; /** * @param {*} val * @return {boolean} */ is.args = function isArguments(val) { return !!val && typeof val === 'object' && toStr.call(val) === '[object Arguments]'; }; ////////////////////////////////////////////////////////// // DOM OBJECTS ////////////////////////////////////////////////////////// /** * @param {*} val * @return {boolean} */ is.doc = function isDOMDocument(val) { return !!val && typeof val === 'object' && val.nodeType === 9; }; /** * @param {*} val * @return {boolean} */ is.elem = function isDOMElement(val) { return !!val && typeof val === 'object' && val.nodeType === 1; }; ////////////////////////////////////////////////////////// // MISCELLANEOUS ////////////////////////////////////////////////////////// /** * @private * @param {*} key * @return {boolean} */ var hasOwn = Object.prototype.hasOwnProperty; /** * Checks if a value is considered empty. * @param {...*} val * @return {boolean} Returns `false` if value is one of the following: * ` 0, "", {}, [], null, undefined, false, NaN, function(){} ` * Note that for functions this method checks whether it has any defined * params: ` function empty(){}; function notEmpty(param){}; ` */ is.empty = function isEmpty(val) { /** @type {string} */ var key; // handle empty primitives - 0, "", null, undefined, false, NaN if (!val) return true; // handle functions if (typeof val === 'function') return !val.length; // handle non-empty primitives if (typeof val !== 'object') return false; // handle arrays if (toStr.call(val) === '[object Array]') return !val.length; // handle all other objects for (key in val) { if ( hasOwn.call(val, key) ) return false; } return true; }; /** * @private * @type {!RegExp} * @const */ var EOL = /^(?:cr|lf|crlf)$/i; /** * @param {string} val * @return {boolean} */ is.eol = function isEol(val) { return EOL.test(val); }; ////////////////////////////////////////////////////////// // OBJECT STATES ////////////////////////////////////////////////////////// /** * `Object.isFrozen` or a proper polyfill. * @param {(!Object|function)} obj * @return {boolean} */ is.frozen = (function() { if (!Object.isFrozen) return function isFrozen(obj) { return false; }; try { Object.isFrozen( function(){} ); return Object.isFrozen; } catch (err) { return function isFrozen(obj) { return typeof obj === 'object' && Object.isFrozen(obj); }; } })(); ////////////////////////////////////////////////////////// // NUMBER STATES ////////////////////////////////////////////////////////// /** * @param {number} val * @return {boolean} */ is.whole = function isWholeNumber(val) { return !(val % 1); }; /** * @param {number} val * @return {boolean} */ is.odd = function isOddNumber(val) { return !!(val % 2); }; /** * @param {number} val * @return {boolean} */ is.even = function isEvenNumber(val) { return !(val % 2); }; ////////////////////////////////////////////////////////// // OR UNDEFINED ////////////////////////////////////////////////////////// /** @type {!Object} */ is.un = {}; /** * @param {*} val * @return {boolean} */ is.un.bool = function isUndefinedOrBoolean(val) { return val === undefined || typeof val === 'boolean'; }; /** * @param {*} val * @return {boolean} */ is.un.str = function isUndefinedOrString(val) { return val === undefined || typeof val === 'string'; }; /** * @param {*} val * @return {boolean} */ is.un.num = function isUndefinedOrNumber(val) { return val === undefined || (typeof val === 'number' && val === val); }; /** * @param {*} val * @return {boolean} */ is.un.obj = function isUndefinedOrObject(val) { return val === undefined || (!!val && typeof val === 'object'); }; /** * @param {*} val * @return {boolean} */ is.un.func = function isUndefinedOrFunction(val) { return val === undefined || (!!val && typeof val === 'function'); }; /** * @param {*} val * @return {boolean} */ is.un.arr = function isUndefinedOrArray(val) { return val === undefined || ( !!val && typeof val === 'object' && toStr.call(val) === '[object Array]' ); }; /** * @param {*} val * @return {boolean} */ is.un.regex = function isUndefinedOrRegExp(val) { return val === undefined || ( !!val && typeof val === 'object' && toStr.call(val) === '[object RegExp]' ); }; ////////////////////////////////////////////////////////// // OR NULL ////////////////////////////////////////////////////////// /** * @param {*} val * @return {boolean} */ is.nil.bool = function isNullOrBoolean(val) { return val === null || typeof val === 'boolean'; }; /** * @param {*} val * @return {boolean} */ is.nil.str = function isNullOrString(val) { return val === null || typeof val === 'string'; }; /** * @param {*} val * @return {boolean} */ is.nil.num = function isNullOrNumber(val) { return val === null || (typeof val === 'number' && val === val); }; /** * @param {*} val * @return {boolean} */ is.nil.obj = function isNullOrObject(val) { return val === null || (!!val && typeof val === 'object'); }; /** * @param {*} val * @return {boolean} */ is.nil.func = function isNullOrFunction(val) { return val === null || (!!val && typeof val === 'function'); }; /** * @param {*} val * @return {boolean} */ is.nil.arr = function isNullOrArray(val) { return val === null || ( !!val && typeof val === 'object' && toStr.call(val) === '[object Array]' ); }; /** * @param {*} val * @return {boolean} */ is.nil.regex = function isNullOrRegExp(val) { return val === null || ( !!val && typeof val === 'object' && toStr.call(val) === '[object RegExp]' ); }; ////////////////////////////////////////////////////////// // OR NULL OR UNDEFINED ////////////////////////////////////////////////////////// /** @type {!Object} */ is.nil.un = {}; /** * @param {*} val * @return {boolean} */ is.nil.un.bool = function isNullOrUndefinedOrBoolean(val) { return val === null || val === undefined || typeof val === 'boolean'; }; /** * @param {*} val * @return {boolean} */ is.nil.un.str = function isNullOrUndefinedOrString(val) { return val === null || val === undefined || typeof val === 'string'; }; /** * @param {*} val * @return {boolean} */ is.nil.un.num = function isNullOrUndefinedOrNumber(val) { return val === null || val === undefined || ( typeof val === 'number' && val === val ); }; /** * @param {*} val * @return {boolean} */ is.nil.un.obj = function isNullOrUndefinedOrObject(val) { return val === null || val === undefined || ( !!val && typeof val === 'object' ); }; /** * @param {*} val * @return {boolean} */ is.nil.un.func = function isNullOrUndefinedOrFunction(val) { return val === null || val === undefined || ( !!val && typeof val === 'undefined' ); }; /** * @param {*} val * @return {boolean} */ is.nil.un.arr = function isNullOrUndefinedOrArray(val) { return val === null || val === undefined || ( !!val && typeof val === 'object' && toStr.call(val) === '[object Array]' ); }; /** * @param {*} val * @return {boolean} */ is.nil.un.regex = function isNullOrUndefinedOrRegExp(val) { return val === null || val === undefined || ( !!val && typeof val === 'object' && toStr.call(val) === '[object RegExp]' ); }; //////////////////////////////////////////////////// // PRIVATE SCOPE END: _is return is; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: match //////////////////////////////////////////////////////////////////////////////// var match = (function matchPrivateScope() { /** * A shortcut for `String.prototype.includes` and `RegExp.prototype.test`. * @param {string} source * @param {*} pattern * @return {boolean} */ function match(source, pattern) { return isRegex(pattern) ? pattern.test(source) : inStr(source, pattern); } /** * @private * @return {string} */ var toStr = Object.prototype.toString; /** * @private * @param {*} val * @return {boolean} */ function isRegex(val) { return !!val && typeof val === 'object' && toStr.call(val) === '[object RegExp]'; } /** * @private * @param {string} source * @param {string} str * @return {boolean} */ var baseInStr = !!String.prototype.includes ? function baseInStr(source, str) { return source.includes(str); } : function baseInStr(source, str) { return source.indexOf(str) !== -1; }; /** * @private * @param {string} source * @param {*} str * @return {boolean} */ function inStr(source, str) { str = String(str); if (!source) return !str; if (!str) return true; return baseInStr(source, str); } //////////////////////////////////////////////////// // PRIVATE SCOPE END: match return match; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: merge //////////////////////////////////////////////////////////////////////////////// var merge = (function mergePrivateScope() { /** * @private * @param {*} key * @return {boolean} */ var hasOwn = Object.prototype.hasOwnProperty; /** * @param {(!Object|function)} dest * @param {(!Object|function)} source * @return {(!Object|function)} */ function merge(dest, source) { /** @type {string} */ var key; for (key in source) { if ( hasOwn.call(source, key) ) dest[key] = source[key]; } return dest; } //////////////////////////////////////////////////// // PRIVATE SCOPE END: merge return merge; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: newErrorMaker //////////////////////////////////////////////////////////////////////////////// /** * @param {string} main - A vitals method. * @return {function} */ function newErrorMaker(main) { main = 'vitals.' + main; /** * @param {string} msg * @param {string=} method * @return {!Error} */ var maker = function error(msg, method) { /** @type {!Error} */ var err; method = method ? main : main + '.' + method; err = new Error(msg + ' for ' + method + ' call.'); err.__vitals = true; err.vitals = true; return err; }; /** * @param {string} param * @param {string=} method * @return {!TypeError} */ maker.type = function typeError(param, method) { /** @type {!TypeError} */ var err; param += ' param'; method = method ? main : main + '.' + method; err = new TypeError('Invalid ' + param + ' in ' + method + ' call.'); err.__vitals = true; err.vitals = true; return err; }; /** * @param {string} param * @param {string=} valid * @param {string=} method * @return {!RangeError} */ maker.range = function rangeError(param, valid, method) { /** @type {!RangeError} */ var err; /** @type {string} */ var msg; param += ' param'; method = method ? main : main + '.' + method; msg = 'The '+ param +' was out-of-range for a '+ method +' call.'; msg += valid ? ' The valid options are: ' + valid : ''; err = new RangeError(msg); err.__vitals = true; err.vitals = true; return err; }; return maker; } //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: own //////////////////////////////////////////////////////////////////////////////// var own = (function ownPrivateScope() { /** * @private * @param {*} key * @return {boolean} */ var hasOwn = Object.prototype.hasOwnProperty; /** * @param {(Object|?function)} source * @param {*} key * @return {boolean} */ function own(source, key) { return !!source && hasOwn.call(source, key); } //////////////////////////////////////////////////// // PRIVATE SCOPE END: own return own; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: ownEnum //////////////////////////////////////////////////////////////////////////////// var ownEnum = (function ownEnumPrivateScope() { /** * @private * @param {*} key * @return {boolean} */ var hasEnum = Object.prototype.propertyIsEnumerable; /** * @param {(Object|?function)} source * @param {*} key * @return {boolean} */ function ownEnum(source, key) { return !!source && hasEnum.call(source, key); } //////////////////////////////////////////////////// // PRIVATE SCOPE END: ownEnum return ownEnum; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: sliceArr //////////////////////////////////////////////////////////////////////////////// /** * @param {(!Object|function)} source * @param {number=} start - [default= 0] * @param {number=} end - [default= source.length] * @return {!Array} */ function sliceArr(source, start, end) { /** @type {!Array} */ var arr; /** @type {number} */ var len; /** @type {number} */ var ii; /** @type {number} */ var i; len = source.length; start = start ? start < 0 ? len + start : start : 0; start = start < 0 ? 0 : start; end = end === undefined || end > len ? len : end < 0 ? len + end : end; if (start >= end) return []; arr = new Array(end - start); ii = start - 1; i = 0; while (++ii < end) { arr[i++] = source[ii]; } return arr; } //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: sliceStr //////////////////////////////////////////////////////////////////////////////// /** * @param {string} str * @param {number=} start - [default= 0] * @param {number=} end - [default= str.length] * @return {string} */ function sliceStr(str, start, end) { /** @type {number} */ var len; len = str.length; start = start ? start < 0 ? len + start : start : 0; start = start < 0 ? 0 : start; end = end === undefined || end > len ? len : end < 0 ? len + end : end; return start >= end ? '' : str.substring(start, end); } //////////////////////////////////////////////////////////////////////////////// // VITALS HELPER: splitKeys //////////////////////////////////////////////////////////////////////////////// var splitKeys = (function splitKeysPrivateScope() { /** * @private * @param {string} keys * @param {string} str * @return {boolean} */ var inStr = !!String.prototype.includes ? function inStr(keys, str) { return keys.includes(str); } : function inStr(keys, str) { return keys.indexOf(str) !== -1; }; /** * @param {string} keys - The keys are split using one of the values in the * following list as the separator (values listed in order of rank): * - `", "` * - `","` * - `"|"` * - `" "` * @return {!Array<string>} */ function splitKeys(keys) { /** @type {string} */ var separator; if (!keys) return [ '' ]; separator = inStr(keys, ', ') ? ', ' : inStr(keys, ',') ? ',' : inStr(keys, '|') ? '|' : ' '; return keys.split(separator); } //////////////////////////////////////////////////// // PRIVATE SCOPE END: splitKeys return splitKeys; })(); // ***************************************************************************** // SECTION: BASE METHODS // ***************************************************************************** //////////////////////////////////////////////////////////////////////////////// // VITALS METHOD: is //////////////////////////////////////////////////////////////////////////////// var is = (function isPrivateScope() { ////////////////////////////////////////////////////////// // PUBLIC METHODS // - is // - is.null (is.nil) // - is.undefined // - is.boolean (is.bool) // - is.string (is.str) // - is._string (is._str) // - is.number (is.num) // - is._number (is._num) // - is.nan // - is.object (is.obj) // - is._object (is._obj) // - is.func (is.function|is.fn) // - is.array (is.arr) // - is._array (is._arr) // - is.regexp (is.regex|is.re) // - is.date // - is.error (is.err) // - is.args // - is.document (is.doc) // - is.element (is.elem) // - is.empty // - is.frozen // - is.whole // - is.odd // - is.even ////////////////////////////////////////////////////////// /** * Checks if a value(s) is one of the provided types. See the [type docs](https://github.com/imaginate/vitals/wiki/vitals.is-types) * for all available options. Note that all object types are nullable by * default (i.e. `null` will return `true`). * * @public * @param {string} types - The valid data types. See the [type docs](https://github.com/imaginate/vitals/wiki/vitals.is-types) * for all options. * @param {...*} val - The value to evaluate. If multiple values are * provided all must pass the type check to return true. * @return {boolean} The evaluation result. */ function is(types, val) { /** @type {string} */ var nullable; /** @type {Array<function>} */ var checks; if (arguments.length < 2) throw _error('No type or val'); if ( !_is._str(types) ) throw _error.type('types'); if ( _hasSpecial('*', types) ) return true; checks = _getChecks(types); if (!checks) throw _error.range('types', DOCS); nullable = _getNullable(types); return arguments.length > 2 ? _checkVals(checks, arguments, nullable) : _checkVal(checks, val, nullable); } /** * Checks if a value(s) is `null`. * * @public * @param {...*} val * @return {boolean} */ is['null'] = function isNull(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'null'); case 1: return _is.nil(val); default: return _are(arguments, _is.nil); } }; // define shorthand is.nil = is['null']; /** * Checks if a value(s) is `undefined`. * * @public * @param {...*} val * @return {boolean} */ is.undefined = function isUndefined(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'undefined'); case 1: return _is.undefined(val); default: return _are(arguments, _is.undefined); } }; /** * Checks if a value(s) is a boolean. * * @public * @param {...*} val * @return {boolean} */ is['boolean'] = function isBoolean(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'boolean'); case 1: return _is.bool(val); default: return _are(arguments, _is.bool); } }; // define shorthand is.bool = is['boolean']; /** * Checks if a value(s) is a string. * * @public * @param {...*} val * @return {boolean} */ is.string = function isString(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'string'); case 1: return _is.str(val); default: return _are(arguments, _is.str); } }; // define shorthand is.str = is.string; /** * Checks if a value(s) is a non-empty string. * * @public * @param {...*} val * @return {boolean} */ is._string = function isNonEmptyString(val) { switch (arguments.length) { case 0: throw _error('Missing a val', '_string'); case 1: return _is._str(val); default: return _are(arguments, _is._str); } }; // define shorthand is._str = is._string; /** * Checks if a value(s) is a number. * * @public * @param {...*} val * @return {boolean} */ is.number = function isNumber(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'number'); case 1: return _is.num(val); default: return _are(arguments, _is.num); } }; // define shorthand is.num = is.number; /** * Checks if a value(s) is a number and not `0`. * * @public * @param {...*} val * @return {boolean} */ is._number = function isNonZeroNumber(val) { switch (arguments.length) { case 0: throw _error('Missing a val', '_number'); case 1: return _is._num(val); default: return _are(arguments, _is._num); } }; // define shorthand is._num = is._number; /** * Checks if a value(s) is `NaN`. * * @public * @param {...*} val * @return {boolean} */ is.nan = function isNan(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'nan'); case 1: return _is.nan(val); default: return _are(arguments, _is.nan); } }; /** * Checks if a value(s) is an object. * * @public * @param {...*} val * @return {boolean} */ is.object = function isObject(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'object'); case 1: return _is.obj(val); default: return _are(arguments, _is.obj); } }; // define shorthand is.obj = is.object; /** * Checks if a value(s) is an object or function. * * @public * @param {...*} val * @return {boolean} */ is._object = function isObjectOrFunction(val) { switch (arguments.length) { case 0: throw _error('Missing a val', '_object'); case 1: return _is._obj(val); default: return _are(arguments, _is._obj); } }; // define shorthand is._obj = is._object; /** * Checks if a value(s) is a function. Note that `vitals.is.function` is not * valid in ES3 and some ES5 browser environments. Use `vitals.is.func` for * browser safety. * * @public * @param {...*} val * @return {boolean} */ is.func = function isFunction(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'function'); case 1: return _is.func(val); default: return _are(arguments, _is.func); } }; // define shorthand is.fn = is.func; try { is['function'] = is.func; } catch (error) {} /** * Checks if a value(s) is an `Array` instance. * * @public * @param {...*} val * @return {boolean} */ is.array = function isArray(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'array'); case 1: return _is.arr(val); default: return _are(arguments, _is.arr); } }; // define shorthand is.arr = is.array; /** * Checks if a value(s) is an `Array` or `Arguments` instance. * * @public * @param {...*} val * @return {boolean} */ is._array = function isArrayOrArguments(val) { switch (arguments.length) { case 0: throw _error('Missing a val', '_array'); case 1: return _is._arr(val); default: return _are(arguments, _is._arr); } }; // define shorthand is._arr = is._array; /** * Checks if a value(s) is a `RegExp` instance. * * @public * @param {...*} val * @return {boolean} */ is.regexp = function isRegExp(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'regexp'); case 1: return _is.regex(val); default: return _are(arguments, _is.regex); } }; // define shorthand is.regex = is.regexp; is.re = is.regexp; /** * Checks if a value(s) is a `Date` instance. * * @public * @param {...*} val * @return {boolean} */ is.date = function isDate(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'date'); case 1: return _is.date(val); default: return _are(arguments, _is.date); } }; /** * Checks if a value(s) is an `Error` instance. * * @public * @param {...*} val * @return {boolean} */ is.error = function isError(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'error'); case 1: return _is.err(val); default: return _are(arguments, _is.err); } }; // define shorthand is.err = is.error; /** * Checks if a value(s) is an `Arguments` instance. * * @public * @param {...*} val * @return {boolean} */ is.args = function isArguments(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'args'); case 1: return _is.args(val); default: return _are(arguments, _is.args); } }; /** * Checks if a value(s) is a DOM `Document` instance. * * @public * @param {...*} val * @return {boolean} */ is.document = function isDocument(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'document'); case 1: return _is.doc(val); default: return _are(arguments, _is.doc); } }; // define shorthand is.doc = is.document; /** * Checks if a value(s) is a DOM `Element` instance. * * @public * @param {...*} val * @return {boolean} */ is.element = function isElement(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'element'); case 1: return _is.elem(val); default: return _are(arguments, _is.elem); } }; // define shorthand is.elem = is.element; /** * Checks if a value(s) is considered empty. * * @public * @param {...*} val * @return {boolean} Returns `false` if value is one of the following: * ``` * 0, "", {}, [], null, undefined, false, NaN, function(){...} * ``` * Note that for functions this method checks whether it has any defined * params: * ``` * function empty(){} * function notEmpty(param){} * ``` */ is.empty = function isEmpty(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'empty'); case 1: return _is.empty(val); default: return _are(arguments, _is.empty); } }; /** * Checks if a value(s) is [frozen](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen). * * @public * @param {...(Object|?function)} val * @return {boolean} */ is.frozen = function isFrozen(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'frozen'); case 1: return _isFrozen(val); default: return _are(arguments, _isFrozen); } }; /** * Checks if a number(s) is whole (i.e. has no decimal). Zero and non-decimal * negative numbers will return `true`. * * @public * @param {...number} val * @return {boolean} */ is.whole = function isWholeNumber(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'whole'); case 1: return _isWhole(val); default: return _are(arguments, _isWhole); } }; /** * Checks if a number(s) is odd. * * @public * @param {...number} val - Each val must be a whole number. * @return {boolean} */ is.odd = function isOddNumber(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'odd'); case 1: return _isOdd(val); default: return _are(arguments, _isOdd); } }; /** * Checks if a number(s) is even. * * @public * @param {...number} val - Each val must be a whole number. * @return {boolean} */ is.even = function isEvenNumber(val) { switch (arguments.length) { case 0: throw _error('Missing a val', 'even'); case 1: return _isEven(val); default: return _are(arguments, _isEven); } }; ////////////////////////////////////////////////////////// // PRIVATE METHODS - ARE ////////////////////////////////////////////////////////// /** * @private * @param {!Arguments} vals * @param {function} check * @return {boolean} */ function _are(vals, check) { /** @type {number} */ var i; i = vals.length; while (i--) { if ( !check(vals[i]) ) return false; } return true; } ////////////////////////////////////////////////////////// // PRIVATE METHODS - IS ////////////////////////////////////////////////////////// /** * @private * @param {(Object|?function)} val * @return {boolean} */ function _isFrozen(val) { if ( _is.nil(val) ) return false; if ( !_is._obj(val) ) throw _error.type('val', 'frozen'); return _is.frozen(val); } /** * @private * @param {number} val * @return {boolean} */ function _isWhole(val) { if ( !_is.num(val) ) throw _error.type('val', 'whole'); return _is.whole(val); } /** * @private * @param {number} val * @return {boolean} */ function _isOdd(val) { if ( !_is.num(val) ) throw _error.type('val', 'odd'); if ( !_is.whole(val) ) throw _error.range('val', 'whole numbers', 'odd'); return _is.odd(val); } /** * @private * @param {number} val * @return {boolean} */ function _isEven(val) { if ( !_is.num(val) ) throw _error.type('val', 'even'); if ( !_is.whole(val) ) throw _error.range('val', 'whole numbers', 'even'); return _is.even(val); } ////////////////////////////////////////////////////////// // PRIVATE METHODS - CHECKS ////////////////////////////////////////////////////////// /** * @private * @param {!Array<function>} checks * @param {*} val * @param {boolean=} nullable * @return {boolean} */ function _checkVal(checks, val, nullable) { /** @type {number} */ var i; i = checks.length; while (i--) { if ( checks[i](val, nullable) ) return true; } return false; } /** * @private * @param {!Array<function>} checks * @param {!Arguments} vals * @param {boolean=} nullable * @return {boolean} */ function _checkVals(checks, vals, nullable) { /** @type {number} */ var i; i = vals.length; while (--i) { if ( !_checkVal(checks, vals[i], nullable) ) return false; } return true; } ////////////////////////////////////////////////////////// // PRIVATE METHODS - TYPES ////////////////////////////////////////////////////////// /** * @typedef {!Object<string, function(*, boolean=): boolean>} DataTypes */ /** * @private * @type {DataTypes} */ var TYPES = (function() { /** * @type {DataTypes} */ var _types = {}; /** * Adds types to the _types hash map with a check method that evaluates * nullable properties and invokes their type section's method. * @private * @param {string} section - The category for the types. * @param {!Object<string, function(*): boolean>} types - Each type's * "key => value" pair should be expressed as "typeName => checkMethod". * @param {boolean=} nullable - The type's default nullable value. Defaults * to true if not set. * @return {DataTypes} */ function addTypes(section, types, nullable) { /** @type {string} */ var type; for (type in types) { if( own(types, type) ) addType(section, type, types[type], nullable); } return _types; } /** * Adds type to the _types hash map with a check method that evaluates * nullable properties and invokes its type section's method. * @private * @param {string} section - The type's category. * @param {string} type - The type's name. * @param {function(*): boolean} check - The type's check method. * @param {boolean=} nullable - The type's default nullable value. Defaults * to true if not set. * @return {DataTypes} */ function addType(section, type, check, nullable) { check = own(addType, section) ? addType[section](check) : check; nullable = nullable !== false; _types['_' + type] = function(val, _nullable) { _nullable = _is.bool(_nullable) ? _nullable : nullable; return _is.nil(val) ? _nullable : check(val); }; return _types; } /** * Adds the type shortcuts to the _types hash map. * @private * @param {!Object<string, string>} shortcuts * @return {DataTypes} */ function addShortcuts(shortcuts) { /** @type {string} */ var shortcut; /** @type {string} */ var type; for (shortcut in shortcuts) { if( own(shortcuts, shortcut) ) { type = '_' + shortcuts[shortcut]; shortcut = '_' + shortcut; _types[shortcut] = _types[type]; } } return _types; } /** * @private * @param {function(*): boolean} eachCheck - The check method for each of * the array's values. * @return {function(*): boolean} The array type's check method. */ addType.arrays = function(eachCheck) { /** @type {function(*): boolean} */ return function check(arr) { /** @type {number} */ var i; if ( !_is.arr(arr) ) return false; i = arr.length; while (i--) { if ( !eachCheck(arr[i]) ) return false; } return true; }; }; /** * @private * @param {function(*): boolean} eachCheck - The check method for each of * the hash map's properties. * @return {function(*): boolean} The hash map type's check method. */ addType.maps = function(eachCheck) { /** @type {function(*): boolean} */ return function check(obj) { /** @type {string} */ var prop; if ( !_is.obj(obj) ) return false; for (prop in obj) { if( own(obj, prop) && !eachCheck(obj[prop]) ) return false; } return true; }; }; _types = addTypes('primitives', { 'undefined': _is.undefined, 'boolean': _is.bool, 'string': _is.str, 'number': _is.num, 'nan': _is.nan }, false); _types = addType('primitives', 'null', _is.nil); _types = addTypes('js_objects', { 'object': _is.obj, 'regexp': _is.regex, 'array': _is.arr, 'date': _is.date, 'error': _is.err }); _types = addType('js_objects', 'arguments', _is.args); _types = addType('js_objects', 'function', _is.func, false); _types = addTypes('dom_objects', { 'element': _is.elem, 'document': _is.doc }); _types = addType('others', 'empty', _is.empty); _types = addTypes('arrays', { 'nulls': _is.nil, 'booleans': _is.bool, 'strings': _is.str, 'numbers': _is.num, 'nans': _is.nan, 'objects': _is.obj, 'functions': _is.func, 'regexps': _is.regex, 'arrays': _is.arr, 'dates': _is.date, 'errors': _is.err, 'elements': _is.elem, 'documents': _is.doc }); _types = addTypes('maps', { 'nullmap': _is.nil, 'booleanmap': _is.bool, 'stringmap': _is.str, 'numbermap': _is.num, 'nanmap': _is.nan, 'objectmap': _is.obj, 'functionmap': _is.func, 'regexpmap': _is.regex, 'arraymap': _is.arr, 'datemap': _is.date, 'errormap': _is.err, 'elementmap': _is.elem, 'documentmap': _is.doc }); _types = addShortcuts({ // primitives nil: 'null', bool: 'boolean', str: 'string', num: 'number', // js objects obj: 'object', func: 'function', fn: 'function', regex: 'regexp', re: 'regexp', arr: 'array', err: 'error', args: 'arguments', // dom objects elem: 'element', doc: 'document', // arrays nils: 'nulls', strs: 'strings', nums: 'numbers', bools: 'booleans', objs: 'objects', funcs: 'functions', fns: 'functions', regexs: 'regexps', res: 'regexps', arrs: 'arrays', errs: 'errors', elems: 'elements', docs: 'documents', // maps nilmap: 'nullmap', strmap: 'stringmap', nummap: 'numbermap', boolmap: 'booleanmap', objmap: 'objectmap', funcmap: 'functionmap', fnmap: 'functionmap', regexmap: 'regexpmap', remap: 'regexpmap', arrmap: 'arraymap', errmap: 'errormap', elemmap: 'elementmap', docmap: 'documentmap' }); return _types; })(); ////////////////////////////////////////////////////////// // PRIVATE METHODS - PARSING ////////////////////////////////////////////////////////// /** * @private * @type {!RegExp} */ var ALL_SPECIALS = /[^a-z\|]/g; /** * @private * @type {!Object<string, function(string): boolean>} */ var SPECIALS = (function(pipe, exPoint, quesMark, equals, asterisk) { return { '|': function(str) { return pipe.test(str); }, '!': function(str) { return exPoint.test(str); }, '?': function(str) { return quesMark.test(str); }, '=': function(str) { return equals.test(str); }, '*': function(str) { return asterisk.test(str); } }; })(/\|/, /\!/, /\?/, /\=/, /\*|any/); /** * @private * @param {string} special * @param {string} types * @return {boolean} */ function _hasSpecial(special, types) { return SPECIALS[special](types); } /** * @private * @param {string} types * @return {Array<function>} */ function _getChecks(types) { /** @type {Array<function>} */ var checks; /** @type {string} */ var type; /** @type {number} */ var i; if ( _hasSpecial('=', types) ) types += '|undefined'; types = types.toLowerCase(); types = types.replace(ALL_SPECIALS, ''); checks = types.split('|'); i = checks.length; while (i--) { type = '_' + checks[i]; if ( !own(TYPES, type) ) return null; checks[i] = TYPES[type]; } return checks.length ? checks : null; } /** * Method checks whether "!" or "?" exists in the types. * @private * @param {string} types * @return {(undefined|boolean)} If undefined no override exists. */ function _getNullable(types) { /** @type {boolean} */ var override; /** @type {boolean} */ var ensure; /** @type {boolean} */ var negate; ensure = _hasSpecial('?', types); negate = _hasSpecial('!', types); override = ensure && negate ? false : ensure || negate; return override ? !negate && ensure : undefined; } ////////////////////////////////////////////////////////// // PRIVATE METHODS - GENERAL ////////////////////////////////////////////////////////// /** * @private * @type {!ErrorAid} */ var _error = newErrorMaker('is'); /** * @private * @type {string} */ var DOCS = 'https://github.com/imaginate/vitals/wiki/vitals.is-types'; ////////////////////////////////////////////////////////// // END OF PRIVATE SCOPE FOR IS return is; })(); //////////////////////////////////////////////////////////////////////////////// // VITALS METHOD: copy //////////////////////////////////////////////////////////////////////////////// var copy = (function copyPrivateScope() { ////////////////////////////////////////////////////////// // PUBLIC METHODS // - copy // - copy.object (copy.obj) // - copy.array (copy.arr|copy.args) // - copy.regexp (copy.re|copy.regex) // - copy.func (copy.fn|copy.function*) // // * Note that copy.function will fail in all ES3 browser // environments and even some ES5. Use copy.func for // compatibility with older browser environments. ////////////////////////////////////////////////////////// /** * Get a [copy](https://en.wikipedia.org/wiki/Cloning_(programming)) of any * value. Note that for array values [vitals.slice](https://github.com/imaginate/vitals/wiki/vitals.slice) * only copies the indexed properties while [vitals.copy](https://github.com/imaginate/vitals/wiki/vitals.copy) * copies all of the properties. * * @public * @param {*} val * @param {boolean=} deep * @return {*} */ function copy(val, deep) { if (!arguments.length) throw _error('Missing a val'); if ( !_is.un.bool(deep) ) throw _error.type('deep'); return !_is._obj(val) ? val : _is.func(val) ? _copyFunc(val, deep) : _is._arr(val) ? _copyArr(val, deep) : _is.regex(val) ? _copyRegex(val) : _copyObj(val, deep); } /** * [Clones](https://en.wikipedia.org/wiki/Cloning_(programming)) an object. * * @public * @param {!Object} obj * @param {boolean=} deep * @return {!Object} */ copy.object = function copyObject(obj, deep) { if ( !_is.obj(obj) ) throw _error.type('obj', 'object'); if ( !_is.un.bool(deep) ) throw _error.type('deep', 'object'); return _copyObj(obj, deep); }; // define shorthand copy.obj = copy.object; /** * [Clones](https://en.wikipedia.org/wiki/Cloning_(programming)) an array. * Note that [vitals.slice.array](https://github.com/imaginate/vitals/wiki/vitals.slice#slicearray) * only copies the indexed properties while [vitals.copy.array](https://github.com/imaginate/vitals/wiki/vitals.copy#copyarray) * copies all of the properties. * * @public * @param {!Object} obj * @param {boolean=} deep * @return {!Array} */ copy.array = function copyArray(obj, deep) { if ( !_is.obj(obj) ) throw _error.type('obj', 'array'); if ( !_is.num(obj.length) ) throw _error.type('obj.length', 'array'); if ( !_is.un.bool(deep) ) throw _error.type('deep', 'array'); return _copyArr(obj, deep); }; // define shorthand copy.arr = copy.array; copy.args = copy.array; /** * [Clones](https://en.wikipedia.org/wiki/Cloning_(programming)) a `RegExp`. * * @public * @param {!RegExp} regex * @param {boolean=} forceGlobal * @return {!RegExp} */ copy.regexp = function copyRegexp(regex, forceGlobal) { if ( !_is.regex(regex) ) throw _error.type('regex', 'regexp'); if ( !_is.un.bool(forceGlobal) ) throw _error.type('forceGlobal', 'regexp'); return _copyRegex(regex, forceGlobal); }; // define shorthand copy.re = copy.regexp; copy.regex = copy.regexp; /**