@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
JavaScript
//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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