UNPKG

@cute-dw/core

Version:

This TypeScript library is the main part of a more powerfull package designed for the fast WEB software development. The cornerstone of the library is the **DataStore** class, which might be useful when you need a full control of the data, but do not need

814 lines 88.1 kB
//import { ClassCastException } from "./exception/ClassCastException"; import { NullPointerException } from "./exception/NullPointerException"; import { Strings } from "./Strings"; const ARRAY_TAG = '[object Array]'; const BOOL_TAG = '[object Boolean]'; const DATE_TAG = '[object Date]'; const FUNC_TAG = '[object Function]'; const NULL_TAG = '[object Null]'; const NUMBER_TAG = '[object Number]'; const OBJECT_TAG = '[object Object]'; const REGEXP_TAG = '[object RegExp]'; const STRING_TAG = '[object String]'; const MAP_TAG = '[object Map]'; const SET_TAG = '[object Set]'; const UNDEFINED_TAG = '[object Undefined]'; const RE_CLASS_NAME = /^\[object\s(.*)\]$/; const FN_TOSTRING = Object.prototype.toString; /** * This class consists of the static utility methods for operating on objects, or checking certain conditions before operation */ export class Objects { /** * Returns a string presentation of any JavaScript object * @static * @param value JavaScript object/value of any type * @returns String in the following format: [object \<type\>] */ static toString(value) { return FN_TOSTRING.call(value); } /** * Returns a first not _nullable_ value from the specified `values` * @param values An array or list of values to check * @returns A first not _nullable_ value in the `values` array if any, or _null_ if else. */ static coalesce(...values) { if (values && values.length) { for (let i = 0; i < values.length; i++) { if (!(values[i] == null)) { return values[i]; } } } return null; } /** * * @param v1 * @param v2 * @returns */ static ifNull(v1, v2) { if (v1 === null) return v2; return v1; } static ifUndefined(v1, v2) { return (v1 === undefined) ? v2 : v1; } static ifEmpty(v1, v2) { if (Objects.isEmpty(v1)) { return v2; } return v1; } static ifNotArray(v1, v2) { if (Objects.isArray(v1)) { return v1; } return v2; } static nullIf(v1, v2) { if (v1 === v2) return null; return v1; } static isArray(value) { return Objects.toString(value) == ARRAY_TAG; } static isBoolean(value) { return Objects.toString(value) == BOOL_TAG; } static isCloneable(value) { return "clone" in value && (typeof value.clone === 'function'); } static isDate(value) { return Objects.toString(value) == DATE_TAG || (value instanceof Date); } static isIterable(value) { return Symbol.iterator in value; } static isMap(value) { return value instanceof Map; } static isNull(value) { return (value === null); } static isNumber(value) { return typeof value === 'number' && isFinite(value); } static isSet(value) { return value instanceof Set; } static isString(value) { return Objects.toString(value) === STRING_TAG; } static isUndefined(value) { return (value === undefined); } /** * Check if specified value is empty (falsy) * @static * @param {any} value Any value to check * @returns {boolean} true/false */ static isEmpty(value) { if (value) { const type = Objects.toString(value); switch (type) { case STRING_TAG: return Strings.isEmpty(value); case OBJECT_TAG: return Object.keys(value).length == 0; case ARRAY_TAG: return value.length == 0; case MAP_TAG: return value.size == 0; case SET_TAG: return value.size == 0; } return false; } return true; } /** * Return whether the provided value is a function. * * @static * @param {*} value The value to test. * @returns {boolean} Whether the provided value is a function. * @since 1.0.0 * @example * const a = function () { console.log('foo bar'); }; * const b = { foo: "bar" }; * console.log(Objects.isFunction(a)); // true * console.log(Objects.isFunction(b)); // false */ static isFunction(value) { return Objects.toString(value) == FUNC_TAG; } static isNumberObject(value) { return (Objects.toString(value) === NUMBER_TAG); } /** * Return whether the provided value is an object. * * @static * @param {*} value The value to test. * @returns {boolean} Whether the provided value is an object. * @since 1.0.0 * * @example * const a = { foo: "bar" }; * const b = 'foo bar'; * console.log(Objects.isObject(a)); // true * console.log(Objects.isObject(b)); // false */ static isObject(value) { return (value instanceof Object) && !Array.isArray(value); } static isPlainObject(value) { return !!value && typeof value === 'object' && value.constructor === Object; } static isPrimitive(arg) { return (arg !== Object(arg)); } /** * Objects casting with runtime checkings * @param obj Object to cast * @param AnyClass Target class value or type * @returns Object of type `AnyClass` if succeeds, or _undefined_ if the `obj` is not the `AnyClass`' instance * @example * // %inferred-type: any * const parsed = JSON.parse( someJsonObjectString ); * const p: Person = Objects.cast(parsed, Person); */ static cast(obj, AnyClass) { if (!(obj instanceof AnyClass)) { return undefined; } return obj; } /** * Creates an instance of the JavaScript's class value * @static * @param AnyClass Class value * @param args Constructor arguments * @returns The instance of the class * @example * class Person { * constructor(public name: string) {} * } * // %inferred-type: Person * const jane = Objects.createInstance(Person, 'Jane'); */ static createInstance(AnyClass, ...args) { return new AnyClass(args); } /** * Returns constructor object of the specified value/object. If the `value` is _null_ or _undefined_, method returns constructor of an empty object * @param value An object for which the class object to return * @returns Returns constructor object * @static * @see {@link getClassName} */ static getClass(value) { return value.constructor; } /** * Returns class name of the specified value/object * @param value A value for which the class name to return * @returns The name of the JavaScript class to which the `value` belongs * @static * @see {@link getClass} */ static getClassName(value) { return Objects.toString(value).match(RE_CLASS_NAME)[1]; } /** * Tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object * @param value The object to test * @param ctor Constructor or a name of the class to test against * @returns Boolean value * @static */ static isInstanceOf(value, ctor) { if (Objects.isObject(value)) { if (typeof ctor === "string") { ctor = ctor.trim(); if (ctor == "") return false; if (value instanceof Function && (value.name === ctor || value.constructor.name === ctor)) return true; let pr = Object.getPrototypeOf(value); while (pr) { if (pr.name === ctor) { return true; } pr = Object.getPrototypeOf(pr); } } else { return (value instanceof ctor || (value instanceof Function && (value.name === ctor.name || value.constructor.name === ctor.name))); } } return false; } /** * Checks that the specified object reference is not null and throws a customized `NullPointerException` if it is * @param obj The object reference to check for nullity * @param message Detail message to be used in the event that a `NullPointerException` is thrown * @returns `obj` if not null or undefined * @throws NullPointerException if `obj` is null * @static */ static requireNonNull(obj, message) { if (obj == null) { throw new NullPointerException(typeof message == "function" ? message() : message); } return obj; } static _isPrototypePolluted(key) { return ['__proto__', 'prototype', 'constructor'].includes(key); } /** * Returns objects's property value using property's path in hierarchical structure of the object * * @static * @param object Source object * @param path Path to property point ('.') delimited * @param defValue Optional default value * @returns Value of property or undefined if it was not found in object's structure * * @example * let obj = {a:1, b:{c:2, d:3, f:[10,20,30,[{s:100}]]}}; * console.log(Objects.getValue(obj, "b.c.d")); // undefined * console.log(Objects.getValue(obj, "b.f.3.0.s")); // 100 */ static getValue(object, path, defValue) { if (!(Objects.isObject(object) && Objects.isString(path))) { return object; } const parts = path.split('.'); const partsLen = parts.length; let res = object; let key; let i = -1; while (++i < partsLen) { key = parts[i].trim(); if (key in res) { res = res[key]; if (i < (partsLen - 1) && !Objects.isObject(res)) { res = undefined; break; } } else { res = undefined; break; } } return res ?? defValue; } /** * Checks existance a path to the property in the specified object * @static * @param object Object to check * @param path Path to the object's property dot (".") delimited * @returns _true_ if the path is a valid path to the some property in the `object`, _false_ otherwise */ static hasValue(object, path) { if (!(Objects.isObject(object) && Objects.isString(path))) { return false; } const parts = path.split('.'); const partsLen = parts.length; let valid = true; let obj = object; let key; let i = -1; while (++i < partsLen && valid) { key = parts[i].trim(); valid = (key in obj); if (valid) { obj = obj[key]; if (i < (partsLen - 1) && !Objects.isObject(obj)) { valid = false; } } } return valid; } /** * Sets value of object property using its path in the object's structure * @static * @param object Target object * @param path String path delimited by dot (".") * @param newValue New value for the property if it will be found in the object's structure * @param force Optional. Enforce to create the full `path` in the `object` structure if it doesn't exist. Default is _false_. * @returns 1 if it succeeds and -1 if an error occurs */ static setValue(object, path, newValue, force = false) { if (!(Objects.isObject(object) && Objects.isString(path))) { return -1; } const parts = path.split('.'); const partsLen = parts.length; let valid = true; let obj = object; let key; let i = -1; while (++i < partsLen && valid) { key = parts[i].trim(); valid = (key in obj); if (valid) { obj = obj[key]; if (i == (partsLen - 1)) { if (!Objects.isObject(obj)) { obj[key] = newValue; return 1; } } else { valid = Objects.isObject(obj); } } else if (force) { if (i == (partsLen - 1)) { obj[key] = newValue; } else { obj[key] = {}; } return 1; } } return -1; } /** * Return whether `prop` is matched by any string or regular expression in * `blacklist`. * * @static * @param {string} prop The name of a property to check. * @param {array} blacklist Array of strings and regular expressions. * @returns {boolean} Whether `prop` was matched. * @since 1.0.0 * @example * const blacklist = [/^\$hashKey/g, /^_/g, 'id']; * console.log(Objects.isBlacklisted("$hashKey", blacklist)); // true * console.log(Objects.isBlacklisted("id", blacklist)); // true * console.log(Objects.isBlacklisted("_myProp", blacklist)); // true * console.log(Objects.isBlacklisted("my_id", blacklist)); // false */ static isBlacklisted(prop, blacklist) { if (!blacklist || !blacklist.length) { return false; } let matches; for (var i = 0; i < blacklist.length; i++) { if ((String(blacklist[i]) === REGEXP_TAG && blacklist[i].test(prop)) || blacklist[i] === prop) { matches = prop; return !!matches; } } return !!matches; } /** * Iterate over an object's own enumerable properties. * * @static * @param {object} object The object whose properties are to be enumerated. * @param {Function} fn Iteration function. * @param {object} [thisArg] Content to which to bind `fn`. * @since 1.0.0 * @example * const a = { b: 1, c: 4 }; * let sum = 0; * Objects.forOwn(a, function (value, key) { * sum += value; * }); * console.log(sum); // 5 */ static forOwn(object, fn, thisArg) { const keys = Object.keys(object); const len = keys.length; let i = -1; while (++i < len) { if (fn.call(thisArg, object[keys[i]], keys[i], object) === false) { break; } } } /** * Shallow copy own enumerable properties from `src` to `dest` that are on * `src` but are missing from `dest. * * @static * @param {object} dest The destination object. * @param {object} source The source object. * @returns {object} The destination object. * @since 1.0.0 * * @example * const a = { foo: 'bar', beep: 'boop' }; * const b = { beep: 'bip' }; * Objects.fillIn(b, a); * console.log(b); // {"foo":"bar","beep":"bip"} */ static fillIn(dest, ...source) { if (source && Objects.isIterable(source)) { for (const src of source) { Objects.forOwn(src, (value, key) => { if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { dest[key] = value; } }); } } return dest; } /** * Recursively shallow fill in own enumerable properties from `source` to `dest`. * * @static * @param {object} dest The destination object. * @param {object} source The source object. * @returns {object} The destination object. * @see {@link fillIn} * @see {@link deepMixIn} * @since 1.0.0 * * @example * const a = { foo: { bar: 'baz' }, beep: 'boop' }; * const b = { beep: 'bip' } * Objects.deepFillIn(b, a); * console.log(b); // {"foo":{"bar":"baz"},"beep":"bip"} */ static deepFillIn(dest, source) { Objects.forOwn(source, (value, key) => { const existing = dest[key]; if (Objects.isPlainObject(value) && Objects.isPlainObject(existing)) { Objects.deepFillIn(existing, value); } else if (!Object.hasOwnProperty.call(dest, key) || dest[key] === undefined) { dest[key] = value; } }); return dest; } /** * Recursively shallow copy enumerable properties from `source` to `dest`. * * @static * @param {object} dest The destination object. * @param {object} source The source object. * @since 1.0.0 * * @example * const a = { foo: { bar: 'baz' }, beep: 'boop' }; * const b = { beep: 'bip' }; * Objects.deepMixIn(b, a); * console.log(b); // {"foo":{"bar":"baz"},"beep":"boop"} */ static deepMixIn(dest, source) { if (Objects.isObject(source)) { for (const key in source) { if (Objects._isPrototypePolluted(key)) continue; const value = source[key]; const existing = dest[key]; if (Objects.isPlainObject(value) && Objects.isPlainObject(existing)) { Objects.deepMixIn(existing, value); } else { dest[key] = value; } } } return dest; } /** * Return whether the two values are the same value * * @static * @param {*} a The first value to compare * @param {*} b The second value to compare * @returns {boolean} A boolean indicating whether or not the two arguments are the same value * @see {@link deepEqual} * @since 1.0.0 * * @example * console.log( Objects.equals(1, 1) ); // true * console.log( Objects.equals(1,'1') ); // false * console.log( Objects.equals(93, 66) ); // false */ static equals(a, b) { return Object.is(a, b); } /** * Check whether the two provided objects are deeply equal. * * @static * @param {object} a First object in the comparison. * @param {object} b Second object in the comparison. * @returns {boolean} Whether the two provided objects are deeply equal. * @see {@link equal} * @since 1.0.0 * * @example * const objA = { * name: 'John', * id: 27, * nested: { * item: 'item 1', * colors: ['red', 'green', 'blue'] * } * }; * * const objB = { * name: 'John', * id: 27, * nested: { * item: 'item 1', * colors: ['red', 'green', 'blue'] * } * }; * * console.log(Objects.deepEqual(a,b)); // true * objB.nested.colors.add('yellow'); // make a change to a nested object's array * console.log(Objects.deepEqual(a,b)); // false */ static deepEqual(a, b) { if (a === b) { return true; } let _equal = true; if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) { return false; } for (let i = a.length - 1; i >= 0; i--) { if (!Objects.deepEqual(a[i], b[i])) { // Exit loop early return false; } } } else if (Objects.isObject(a) && Objects.isObject(b)) { Objects.forOwn(a, (value, key) => { _equal = Objects.deepEqual(value, b[key]); return _equal; /* if (!(_equal = Objects.deepEqual(value, b[key]))) { // Exit loop early return false; } */ }); if (_equal) { Objects.forOwn(b, (value, key) => { _equal = Objects.deepEqual(value, a[key]); return _equal; /* if (!(_equal = Objects.deepEqual(value, a[key]))) { // Exit loop early return false; } */ }); } } else { return false; } return _equal; } /** * Return a diff of the base object to the comparison object. * * @static * @param {object} newObject Comparison object. * @param {object} oldObject Base object. * @param {object} [opts] Configuration options. * @returns {Object} The diff from the base object to the comparison object. * @see {@link areDifferent} * @since 1.0.0 * * @example * const oldObject = { foo: 'bar', a: 1234 }; * const newObject = { beep: 'boop', a: 5678 }; * const diff = Objects.diffObjects.(oldObject, newObject); * console.log(diff.added); // {"beep":"boop"} * console.log(diff.changed); // {"a":5678} * console.log(diff.removed); // {"foo":undefined} */ static diffObjects(newObject, oldObject, opts) { opts || (opts = {}); const equalsFn = opts.equalsFn ?? Objects.deepEqual; const blacklist = opts.ignore || []; const diff = { added: {}, changed: {}, removed: {} }; const newKeys = Object.keys(newObject).filter(function (key) { return !Objects.isBlacklisted(key, blacklist); }); const oldKeys = Object.keys(oldObject).filter(function (key) { return !Objects.isBlacklisted(key, blacklist); }); // Check for properties that were added or changed newKeys.forEach((key) => { const oldValue = oldObject[key]; const newValue = newObject[key]; if (equalsFn(oldValue, newValue)) { return; } if (oldValue === undefined) { diff.added[key] = newValue; } else { diff.changed[key] = newValue; } }); // Check for properties that were removed oldKeys.forEach((key) => { const oldValue = oldObject[key]; const newValue = newObject[key]; if (newValue === undefined && oldValue !== undefined) { diff.removed[key] = undefined; } }); return diff; } /** * Return whether the two objects are deeply different. * * @static * @param {object} newObject Base object. * @param {object} oldObject Comparison object. * @param {object} [opts] Configuration options. * @returns {boolean} Whether the two objects are deeply different. * @see {@link diffObjects} * @since 1.0.0 * * @example * Objects.areDifferent({}, {}); // false * Objects.areDifferent({ a: 1 }, { a: 1 }); // false * Objects.areDifferent({ foo: 'bar' }, {}); // true */ static areDifferent(newObject, oldObject, opts) { opts || (opts = {}); const diff = Objects.diffObjects(newObject, oldObject, opts); const diffCount = Object.keys(diff.added).length + Object.keys(diff.removed).length + Object.keys(diff.changed).length; return diffCount > 0; } /** * Deep cloning of the specified object. If the `source` object implements * `Cloneable` interface its `clone` method is executed. * * @static * @param {object} source Source object to clone * @returns {object} Cloned object. * @since 1.0.0 */ static deepClone(source) { return DeepClone.run(source); } } /** * This class incapsulates static methods to deep clone properties of the some object. * The main public static method is `run` which must be called to deep clone the specified object. */ class DeepClone { static cloneOtherType(target) { switch (DeepClone.toRawType(target)) { case "Boolean": case "Number": case "String": case "Error": case "Date": const constrFun = target.constructor; return new constrFun(target); case "RegExp": return DeepClone.cloneReg(target); case "Symbol": return DeepClone.cloneSymbol(target); case "Function": return target; default: if (Objects.isCloneable(target)) { return target.clone(); } return null; } } static toRawType(value) { const str = Objects.toString(value); return str.slice(8, -1); } static cloneSymbol(target) { return Object(Symbol.prototype.valueOf.call(target)); } static cloneReg(target) { const reFlags = /\w*$/; const result = new target.constructor(target.source, reFlags.exec(target)); result.lastIndex = target.lastIndex; return result; } static forEach(array, iteratee) { let index = -1; const length = array.length; while (++index < length) { iteratee(array[index], index); } return array; } // core function static run(target, map = new WeakMap()) { // clone primitive types if (typeof target != "object" || target == null) { return target; } const type = DeepClone.toRawType(target); let cloneTarget = null; if (map.get(target)) { return map.get(target); } map.set(target, cloneTarget); if (type != "Set" && type != "Map" && type != "Array" && type != "Object") { return DeepClone.cloneOtherType(target); } else if (Objects.isCloneable(target)) { return target.clone(); } // clone Set if (type == "Set") { cloneTarget = new Set(); target.forEach((value) => { cloneTarget.add(DeepClone.run(value, map)); }); return cloneTarget; } // clone Map if (type == "Map") { cloneTarget = new Map(); target.forEach((value, key) => { cloneTarget.set(key, DeepClone.run(value, map)); }); return cloneTarget; } // clone Array if (type == "Array") { cloneTarget = new Array(); DeepClone.forEach(target, (value, index) => { cloneTarget[index] = DeepClone.run(value, map); }); } // clone normal Object if (type == "Object") { cloneTarget = new Object(); DeepClone.forEach(Object.keys(target), (key, index) => { cloneTarget[key] = DeepClone.run(target[key], map); }); } return cloneTarget; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT2JqZWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2N1dGUtY29yZS9zcmMvbGliL3V0aWwvT2JqZWN0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxzRUFBc0U7QUFDdEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFJeEUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUVwQyxNQUFNLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQztBQUNuQyxNQUFNLFFBQVEsR0FBRyxrQkFBa0IsQ0FBQztBQUNwQyxNQUFNLFFBQVEsR0FBRyxlQUFlLENBQUM7QUFDakMsTUFBTSxRQUFRLEdBQUcsbUJBQW1CLENBQUM7QUFDckMsTUFBTSxRQUFRLEdBQUcsZUFBZSxDQUFDO0FBQ2pDLE1BQU0sVUFBVSxHQUFHLGlCQUFpQixDQUFDO0FBQ3JDLE1BQU0sVUFBVSxHQUFHLGlCQUFpQixDQUFDO0FBQ3JDLE1BQU0sVUFBVSxHQUFHLGlCQUFpQixDQUFDO0FBQ3JDLE1BQU0sVUFBVSxHQUFHLGlCQUFpQixDQUFDO0FBQ3JDLE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQztBQUMvQixNQUFNLE9BQU8sR0FBRyxjQUFjLENBQUM7QUFDL0IsTUFBTSxhQUFhLEdBQUcsb0JBQW9CLENBQUM7QUFFM0MsTUFBTSxhQUFhLEdBQUcsb0JBQW9CLENBQUM7QUFFM0MsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7QUFDOUM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sT0FBTztJQUVsQjs7Ozs7T0FLRztJQUNILE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBVTtRQUN4QixPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUNEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsTUFBYTtRQUM5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