@rzl-zone/utils-js
Version:
A modern, lightweight set of JavaScript utility functions with TypeScript support for everyday development, crafted to enhance code readability and maintainability.
371 lines (342 loc) • 13.5 kB
JavaScript
/*!
* ====================================================
* Rzl Utils-JS.
* ----------------------------------------------------
* Version: 3.11.0.
* Author: Rizalvin Dwiky.
* Repository: https://github.com/rzl-zone/utils-js.
* ====================================================
*/
import { isURL } from './chunk-ONZFBJVW.js';
import { isTypedArray } from './chunk-TJHGRQ4P.js';
import { parseCurrencyString } from './chunk-2XSZ2ANI.js';
import { isEmptyString } from './chunk-ULQPCIA2.js';
import { assertIsString } from './chunk-3T6VSWYX.js';
import { isEqual, isRegExp, baseDeepEqual } from './chunk-GXKQ3LHF.js';
import { isEmptyArray } from './chunk-GOFINGT6.js';
import { safeStableStringify, isDate, isMap } from './chunk-AXDYWO67.js';
import { isArray, getPreciseType, assertIsBoolean, isNonEmptyString, assertIsPlainObject, isObjectOrArray, isFunction, isString, isNumber, isSymbol, isSet, isPlainObject, isNil, isBoolean, isBuffer, isNaN, isUndefined, isObject, isNull } from './chunk-MSUW5VHZ.js';
var areArraysEqual = (array1, array2, ignoreOrder = false) => {
if (!(isArray(array1) && isArray(array2))) {
throw new TypeError(
`Parameters \`array1\` and \`array2\` property of the \`options\` (second parameter) must be of type \`array\`, but received: ['array1': \`${getPreciseType(
array1
)}\`, 'array2': \`${getPreciseType(array2)}\`].`
);
}
assertIsBoolean(ignoreOrder, {
message: ({ currentType, validType }) => `Third parameter \`ignoreOrder\` must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
if (!isEqual(array1.length, array2.length)) return false;
const deepIgnoreOrder = (arr) => {
if (!isArray(arr)) return arr;
const sorted = arr.map((item) => {
if (isArray(item)) {
return deepIgnoreOrder(item);
}
return item;
});
return sorted.sort((a, b) => {
const sa = safeStableStringify(a);
const sb = safeStableStringify(b);
return sa < sb ? -1 : sa > sb ? 1 : 0;
});
};
const normalizedArr1 = ignoreOrder ? deepIgnoreOrder(array1) : array1;
const normalizedArr2 = ignoreOrder ? deepIgnoreOrder(array2) : array2;
if (!isEqual(normalizedArr1.length, normalizedArr2.length)) return false;
return normalizedArr1.every(
(item, index) => safeStableStringify(item) === safeStableStringify(normalizedArr2[index])
);
};
var areObjectsEqual = (object1, object2) => {
return isEqual(object1, object2);
};
var areURLsEqualPath = (urlA, urlB) => {
if (!isURL(urlA) || !isURL(urlB)) {
throw new TypeError(
`Parameters \`urlA\` and \`urlB\` (first and second parameter) must be instance of URL.`
);
}
return urlA.protocol + "//" + urlA.host + urlA.pathname === urlB.protocol + "//" + urlB.host + urlB.pathname;
};
var areURLsIdentical = (urlA, urlB) => {
if (!isURL(urlA) || !isURL(urlB)) {
throw new TypeError(
`Parameters \`urlA\` and \`urlB\` (first and second parameter) must be instance of URL.`
);
}
return urlA.protocol + "//" + urlA.host + urlA.pathname + urlA.search === urlB.protocol + "//" + urlB.host + urlB.pathname + urlB.search;
};
var textContainsAll = (text, searchWords, options = {}) => {
if (!isNonEmptyString(text) || !isArray(searchWords)) {
return false;
}
assertIsPlainObject(options, {
message: ({ currentType, validType }) => `Third parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const { exactMatch = false, flags = "i" } = options;
assertIsBoolean(exactMatch, {
message: ({ currentType, validType }) => `Parameter \`exactMatch\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
assertIsString(flags, {
message: ({ currentType, validType }) => `Parameter \`flags\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const validSearchWords = searchWords.filter((word) => isNonEmptyString(word)).map(escapeRegex);
if (validSearchWords.length === 0) return false;
return validSearchWords.every((word) => {
const pattern = exactMatch ? `(?<!\\S)${word}(?!\\S)` : word;
return new RegExp(pattern, flags.includes("u") ? flags : flags + "u").test(text);
});
};
var textContainsAny = (text, searchWords, options = {}) => {
if (!isNonEmptyString(text) || !isArray(searchWords)) {
return false;
}
assertIsPlainObject(options, {
message: ({ currentType, validType }) => `Third parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const { exactMatch = false, flags = "i" } = options;
assertIsBoolean(exactMatch, {
message: ({ currentType, validType }) => `Parameter \`exactMatch\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
assertIsString(flags, {
message: ({ currentType, validType }) => `Parameter \`flags\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.`
});
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const validSearchWords = searchWords.filter((word) => isNonEmptyString(word)).map(escapeRegex);
if (validSearchWords.length === 0) return false;
const pattern = exactMatch ? `(?<!\\S)(${validSearchWords.join("|")})(?!\\S)` : `(${validSearchWords.join("|")})`;
return new RegExp(pattern, flags.includes("u") ? flags : flags + "u").test(text);
};
function isPropertyKey(value) {
const type = typeof value;
return type === "string" || type === "number" || type === "symbol";
}
var doesKeyExist = (object, key) => {
if (!isObjectOrArray(object)) return false;
if (!isPropertyKey(key)) {
throw new TypeError(
`Second Parameter (\`key\`) must be of type \`string\`, \`number\` or \`symbol\`, but received: \`${getPreciseType(
key
)}\`.`
);
}
if (Object.prototype.hasOwnProperty.call(object, key)) return true;
if (isArray(object)) {
return object.some((item) => doesKeyExist(item, key));
}
return Object.values(object).some(
(value) => isObjectOrArray(value) && doesKeyExist(value, key)
);
};
var arrayHasAnyMatch = (sourceArray, targetArray) => {
if (!isArray(sourceArray) || !isArray(targetArray) || isEmptyArray(sourceArray) || isEmptyArray(targetArray)) {
return false;
}
const sourceSet = new Set(sourceArray);
return targetArray.some((item) => sourceSet.has(item));
};
var isArguments = (value) => {
return Object.prototype.toString.call(value) === "[object Arguments]";
};
function isLength(value) {
return typeof value === "number" && value > -1 && Number.isInteger(value) && value <= Number.MAX_SAFE_INTEGER;
}
function isArrayLike(value) {
return !isFunction(value) && isObjectOrArray(value) && isLength(value?.length);
}
function isArrayLikeObject(value) {
return isObjectOrArray(value) && isLength(value.length);
}
var isCurrencyLike = (input) => {
if (!(isString(input) || isNumber(input))) return false;
const parsed = parseCurrencyString(input.toString());
if (parsed !== 0) return true;
return input.toString().trim() === "0";
};
var isDeepEqual = (a, b) => {
if (typeof a === "number" && typeof b === "number" && Number.isNaN(a) && Number.isNaN(b)) {
return true;
}
if (a === b) return true;
if (typeof a !== typeof b) return false;
if (isDate(a) && isDate(b)) {
return a.getTime() === b.getTime();
}
if (isRegExp(a) && isRegExp(b)) {
return a.toString() === b.toString();
}
if (isSymbol(a) && isSymbol(b)) {
return a.toString() === b.toString();
}
if (isSet(a) && isSet(b)) {
if (a.size !== b.size) return false;
const bValues = Array.from(b);
const matched = /* @__PURE__ */ new Set();
for (const aVal of a) {
let found = false;
for (let i = 0; i < bValues.length; i++) {
if (matched.has(i)) continue;
if (isDeepEqual(aVal, bValues[i])) {
matched.add(i);
found = true;
break;
}
}
if (!found) return false;
}
return true;
}
if (isMap(a) && isMap(b)) {
if (a.size !== b.size) return false;
const bEntries = Array.from(b);
const matched = /* @__PURE__ */ new Set();
for (const [aKey, aVal] of a) {
let found = false;
for (let i = 0; i < bEntries.length; i++) {
if (matched.has(i)) continue;
const [bKey, bVal] = bEntries[i];
if (isDeepEqual(aKey, bKey) && isDeepEqual(aVal, bVal)) {
matched.add(i);
found = true;
break;
}
}
if (!found) return false;
}
return true;
}
if (isArray(a) && isArray(b)) {
if (a.length !== b.length) return false;
return a.every((item, i) => isDeepEqual(item, b[i]));
}
if (isObjectOrArray(a) && isObjectOrArray(b) && a && b) {
if (isArray(a) !== isArray(b)) return false;
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
if (aKeys.length !== bKeys.length) return false;
return aKeys.every((key) => isDeepEqual(a[key], b[key]));
}
return false;
};
function isElement(value) {
return !!value && typeof value === "object" && value?.nodeType === 1 && !isPlainObject(value);
}
function isEmpty(value) {
if (isNil(value)) return true;
if (isBoolean(value) || isNumber(value, { includeNaN: true }) || isSymbol(value))
return true;
if (isFunction(value)) {
return Object.keys(value).length === 0;
}
if (isString(value) || isArray(value) || isArguments(value) || isTypedArray(value)) {
return value.length === 0;
}
if (isMap(value) || isSet(value)) {
return value.size === 0;
}
if (isBuffer(value)) {
return value.length === 0;
}
if (isPlainObject(value)) {
return Object.keys(value).length === 0;
}
return false;
}
var isEmptyDeep = (value) => {
if (isString(value)) return isEmptyString(value);
if (isNumber(value)) return isNaN(value);
if (isArray(value)) {
return isEmptyArray(value) || value.every(isEmptyDeep);
}
if (isObjectOrArray(value)) {
const keys = Object.keys(value);
const symbols = Object.getOwnPropertySymbols(value);
if (keys.length === 0 && symbols.length === 0) return true;
return [...keys, ...symbols].every((key) => isEmptyDeep(value[key]));
}
if (!value) return true;
return false;
};
function isEqualWith(value, other, customizer) {
return baseDeepEqual(value, other, customizer, /* @__PURE__ */ new WeakMap());
}
function isMatchWith(value, other, customizer) {
return baseIsMatch(value, other, customizer);
}
function isSameValue(x, y) {
return x === y || x === 0 && y === 0 || Number.isNaN(x) && Number.isNaN(y);
}
function baseIsMatch(object, source, customizer) {
if (object === source) return true;
if (!isObjectOrArray(source)) {
return isSameValue(object, source);
}
if (!isObjectOrArray(object)) {
return false;
}
const keys = Reflect.ownKeys(source).filter(
(k) => !(isArray(source) && k === "length")
);
for (const key of keys) {
if (!(key in object)) return false;
const objValue = object[key];
const srcValue = source[key];
const result = customizer?.(objValue, srcValue, key, object, source);
if (!isUndefined(result)) {
if (!result) return false;
continue;
}
if (isObjectOrArray(objValue) && isObjectOrArray(srcValue)) {
if (!isMatchWith(objValue, srcValue, customizer)) return false;
} else {
if (!isSameValue(objValue, srcValue)) return false;
}
}
return true;
}
function isMatch(object, source) {
return baseIsMatch(object, source);
}
var funcToString = Function.prototype.toString;
var reIsNative = /\{\s*\[native code\]\s*\}/;
function isNative(value) {
if (!isFunction(value)) return false;
try {
const source = funcToString.call(value);
return reIsNative.test(source);
} catch {
return false;
}
}
function isObjectLoose(value) {
return !isNil(value) && (isObjectOrArray(value) || isFunction(value));
}
function isSafeInteger(value) {
return typeof value === "number" && Number.isSafeInteger(value);
}
var isValidURL = (url) => {
if (!isNonEmptyString(url)) return false;
let decodedUrl;
try {
decodedUrl = decodeURIComponent(url);
} catch {
return false;
}
if (!decodedUrl.startsWith("http://") && !decodedUrl.startsWith("https://")) {
return false;
}
const urlPattern = new RegExp(
/^https?:\/\/(?:localhost(?::\d+)?(?:[\/?#][^\s]*)?|(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}(?::\d+)?(?:[\/?#][^\s]*)?)$/
//! DEPRECATED
// /^https?:\/\/(?:localhost(?::\d+)?(?:[/?#][^\s]*)?|(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6})(?:[/?#][^\s]*)?$/
// /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/
);
return urlPattern.test(decodedUrl);
};
function isWeakMap(value) {
return isObject(value) && !isNull(value) && value instanceof WeakMap;
}
export { areArraysEqual, areObjectsEqual, areURLsEqualPath, areURLsIdentical, arrayHasAnyMatch, doesKeyExist, isArguments, isArrayLike, isArrayLikeObject, isCurrencyLike, isDeepEqual, isElement, isEmpty, isEmptyDeep, isEqualWith, isLength, isMatch, isMatchWith, isNative, isObjectLoose, isPropertyKey, isSafeInteger, isValidURL, isWeakMap, textContainsAll, textContainsAny };