UNPKG

@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
/*! * ==================================================== * 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 };