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.

553 lines (537 loc) 22.2 kB
/*! * ==================================================== * Rzl Utils-JS. * ---------------------------------------------------- * Version: 3.11.0. * Author: Rizalvin Dwiky. * Repository: https://github.com/rzl-zone/utils-js. * ==================================================== */ import { isNonEmptyValue, isTypedArray } from './chunk-TJHGRQ4P.js'; import { filterNilArray } from './chunk-22V4WP3H.js'; import { isEmptyString } from './chunk-ULQPCIA2.js'; import { assertIsString } from './chunk-3T6VSWYX.js'; import { isRegExp, isEqual } from './chunk-GXKQ3LHF.js'; import { isEmptyObject, isEmptyArray } from './chunk-GOFINGT6.js'; import { assertIsArray } from './chunk-RZOGBYIS.js'; import { safeStableStringify, isDate, isMap } from './chunk-AXDYWO67.js'; import { isBigInt } from './chunk-QNKGP5DY.js'; import { assertIsPlainObject, hasOwnProp, assertIsBoolean, isArray, isNull, getPreciseType, isNaN, isString, isNumber, isBoolean, isNil, isNumberObject, isBooleanObject, isStringObject, isSymbol, isFunction, isObjectOrArray, isError, isSet, isObject, isNonEmptyString, isPlainObject, isUndefined, isInfinityNumber, isBuffer } from './chunk-MSUW5VHZ.js'; function toNumberArrayUnRecursive(array, options = {}) { assertIsPlainObject(options, { message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const riv = hasOwnProp(options, "removeInvalidValueNumber") ? options.removeInvalidValueNumber : true; assertIsBoolean(riv, { message: ({ currentType, validType }) => `Parameter \`removeInvalidValueNumber\` property of the \`options\` (second parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); if (isArray(array)) { const result = Array.from(array, (x) => { if (isBigInt(x)) return Number(x); const str = String(x).trim(); const match = str.match(/-?\d+(\.\d+)?/); return match ? Number(match[0]) : isNull(x) ? null : void 0; }); return riv ? filterNilArray(result) : result; } return void 0; } function toStringDeepForce(value, forceToString) { if (!(forceToString === false || forceToString === "stringOrNumber" || forceToString === "primitives" || forceToString === "all")) { throw new TypeError( `Second parameter \`forceToString\` must be of type \`false\` or \`string\` with value one of "stringOrNumber" | "primitives" | "all", but received: \`${getPreciseType( forceToString )}\`, with value: \`${safeStableStringify(forceToString, { keepUndefined: true })}\`.` ); } if (isNaN(value)) { return forceToString === "primitives" || forceToString === "all" ? "NaN" : NaN; } if (isString(value) || isNumber(value)) { return forceToString === "stringOrNumber" || forceToString === "primitives" || forceToString === "all" ? String(value) : value; } if (isBoolean(value) || isBigInt(value) || isNil(value)) { return forceToString === "primitives" || forceToString === "all" ? String(value) : value; } if (isNumberObject(value) || isBooleanObject(value) || isStringObject(value)) { return forceToString === "all" ? value.valueOf().toString() : value; } if (isSymbol(value)) { return forceToString === "all" ? value.toString() : value; } if (isFunction(value)) { return forceToString === "all" ? value.toString() : value; } if (isArray(value)) { return value.map((v) => toStringDeepForce(v, forceToString)); } if (isObjectOrArray(value)) { if (isDate(value)) { return forceToString === "all" ? value.toISOString() : value; } if (isRegExp(value)) { return forceToString === "all" ? value.toString() : value; } if (isError(value) || value instanceof Promise) { return forceToString === "all" ? value.toString() : value; } if (isSet(value)) { return forceToString === "all" ? [...value].map((v) => toStringDeepForce(v, forceToString)) : value; } if (isMap(value)) { return forceToString === "all" ? [...value.entries()].map(([k, v]) => [ toStringDeepForce(k, forceToString), toStringDeepForce(v, forceToString) ]) : value; } const result = {}; if (isObject(value)) { for (const key of Object.keys(value)) { result[key] = toStringDeepForce(value[key], forceToString); } } return result; } return value; } var dedupeArray = (inputArray, options = {}) => { assertIsArray(inputArray, { message: ({ currentType, validType }) => `First parameter (\`inputArray\`) must be of type \`${validType}\` (array literal or instance), but received: \`${currentType}\`.` }); assertIsPlainObject(options, { message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const flatten = hasOwnProp(options, "flatten") ? options.flatten : false; const forceToString = hasOwnProp(options, "forceToString") ? options.forceToString : false; if (!(forceToString === false || forceToString === "stringOrNumber" || forceToString === "primitives" || forceToString === "all")) { throw new TypeError( `Parameter \`forceToString\` property of the \`options\` (second parameter) must be of type \`false\` or \`string\` with value one of "stringOrNumber" | "primitives" | "all", but received: \`${getPreciseType( forceToString )}\`, with value: \`${safeStableStringify(forceToString, { keepUndefined: true })}\`.` ); } assertIsBoolean(flatten, { message: ({ currentType, validType }) => `Parameter \`flatten\` property of the \`options\` (second parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const process = (arr) => { const seen = []; return arr.reduce((acc, item) => { const value = isArray(item) ? process(item) : toStringDeepForce(item, forceToString); if (!seen.some((s) => isEqual(s, value))) { seen.push(value); acc.push(value); } return acc; }, []); }; const deepFlatten = (value) => { if (isArray(value)) { return value.flatMap(deepFlatten); } if (isSet(value)) { return [...value].flatMap(deepFlatten); } if (isMap(value)) { return [...value.values()].flatMap(deepFlatten); } return [value]; }; return flatten ? process(deepFlatten(inputArray)) : process(inputArray); }; var toBooleanContent = (value) => { if (isNil(value)) return false; if (isString(value)) return isNonEmptyString(value); if (isBoolean(value)) return value; if (isNumber(value, { includeNaN: true })) return value !== 0; if (isArray(value) || isObject(value)) return isNonEmptyValue(value); return Boolean(value); }; var toBooleanContentDeep = (value) => { if (isNil(value)) return false; if (isString(value)) return isNonEmptyString(value); if (isBoolean(value)) return value; if (isNumber(value, { includeNaN: true })) return value !== 0; if (isArray(value)) return value.some(toBooleanContentDeep); if (isObject(value)) return Object.values(value).some(toBooleanContentDeep); return false; }; var toBooleanExplicit = (value, options = {}) => { if (isNil(value)) return false; if (!isPlainObject(options)) options = {}; const ci = hasOwnProp(options, "caseInsensitive") ? options.caseInsensitive : false; const ts = hasOwnProp(options, "trimString") ? options.trimString : true; const incInd = hasOwnProp(options, "includeIndeterminate") ? options.includeIndeterminate : false; if (!isBoolean(ci) || !isBoolean(ts) || !isBoolean(incInd)) { throw new TypeError( `Parameters \`caseInsensitive\`, \`trimString\` and \`includeIndeterminate\` property of the \`options\` (second parameter) expected to be a \`boolean\` type, but received: ['caseInsensitive': \`${getPreciseType( ci )}\`, 'trimString': \`${getPreciseType( ts )}\`, 'includeIndeterminate': \`${getPreciseType(incInd)}\`].` ); } if (isString(value)) { let normalized = value; if (ts) normalized = normalized.trim(); if (ci) normalized = normalized.toLowerCase(); const validTrueStrings = ["true", "on", "yes", "1"]; if (incInd) validTrueStrings.push("indeterminate"); return validTrueStrings.includes(normalized); } if (isNumber(value)) return value === 1; if (isBoolean(value)) return value; return false; }; var toBooleanLoose = (value) => { if (isNil(value)) return false; if (isString(value)) return !isEmptyString(value); if (isBoolean(value)) return value; if (isNumber(value, { includeNaN: true })) return value !== 0; if (isArray(value)) return value.length > 0; return Boolean(value); }; var convertType = (value) => { const predefinedValues = { undefined: void 0, null: null, nan: NaN, true: true, false: false, yes: true, no: false }; if (isString(value)) { const normalized = value.trim().toLowerCase(); if (Object.prototype.hasOwnProperty.call(predefinedValues, normalized)) { return predefinedValues[normalized]; } const numericString = normalized.replace(/,/g, ""); const numberString = Number(numericString); if (!isNaN(numberString) && isNonEmptyString(numericString)) { return numberString; } return value.trim(); } return value; }; var deepCloneSafe = (obj) => { try { if (isFunction(structuredClone)) { return structuredClone(obj); } } catch { } return JSON.parse(JSON.stringify(obj)); }; var deleteNestedKey = (obj, path) => { if (!isObjectOrArray(obj)) return obj; const [currentKey, ...rest] = path; if (isArray(obj)) { for (const item of obj) { if (isObjectOrArray(item)) deleteNestedKey(item, path); } } else if (isEmptyArray(rest)) { if (isPlainObject(obj)) delete obj[currentKey]; } else if (isPlainObject(obj) && isObjectOrArray(obj[currentKey])) { deleteNestedKey(obj[currentKey], rest); } return obj; }; var deleteExactPathOnce = (obj, path) => { if (!isPlainObject(obj)) return obj; const [currentKey, ...rest] = path; if (rest.length === 0) { if (isPlainObject(obj)) delete obj[currentKey]; } else if (isPlainObject(obj[currentKey])) { deleteExactPathOnce(obj[currentKey], rest); } return obj; }; function removeObjectPaths(object, keysToDelete, deepClone = true) { if (isEmptyObject(object, { checkSymbols: true })) return {}; assertIsArray(keysToDelete, { message: ({ currentType, validType }) => `Second parameter (\`keysToDelete\`) must be of type \`${validType}\` with value of { key: string, deep?: boolean } plain-object, but received: \`${currentType}\`, with value: \`${safeStableStringify( keysToDelete, { keepUndefined: true } )}\`.` }); if (!keysToDelete.every((k) => isPlainObject(k) && "key" in k)) { throw new TypeError( `Each element in Second Parameter (\`keysToDelete\`) must be of type \`plain-object\` with at least a "key" property (optionally "deep"), but received: \`${safeStableStringify( keysToDelete, { keepUndefined: true } )}\`.` ); } let result = deepClone ? deepCloneSafe(object) : object; for (const { key, deep } of keysToDelete) { assertIsString(key, { message: ({ currentType, validType }) => `Parameter \`key\` at Second Parameter (\`keysToDelete\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); if (!isUndefined(deep) && !isBoolean(deep)) { throw new TypeError( `Parameter \`deep\` at Second Parameter (\`keysToDelete\`) \u2794 (key: "${key}", deep: ${deep}) must be of type \`boolean\` or \`undefined\`, but received: \`${getPreciseType( deep )}\`.` ); } const path = key.split("."); result = deep ? deleteNestedKey(result, path) : deleteExactPathOnce(result, path); } return result; } function toNumberDeep(input, options = {}) { assertIsPlainObject(options, { message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const removeEmptyObjects = hasOwnProp(options, "removeEmptyObjects") ? options.removeEmptyObjects : false; const removeEmptyArrays = hasOwnProp(options, "removeEmptyArrays") ? options.removeEmptyArrays : false; function _internal(input2, options2) { if (isNil(input2) || isRegExp(input2)) return void 0; const { removeEmptyArrays: removeEmptyArrays2, removeEmptyObjects: removeEmptyObjects2, isRoot } = options2; if (!isBoolean(removeEmptyObjects2) || !isBoolean(removeEmptyArrays2)) { throw new TypeError( `Parameters \`removeEmptyObjects\` and \`removeEmptyArrays\` property of the \`options\` (second parameter) must be of type \`boolean\`, but received: ['removeEmptyObjects': \`${getPreciseType( removeEmptyObjects2 )}\`, 'removeEmptyArrays': \`${getPreciseType(removeEmptyArrays2)}\`].` ); } if (isNumber(input2) || isBoolean(input2) || isNonEmptyString(input2)) { const num = Number(input2); return isInfinityNumber(num) || isNaN(num) ? void 0 : num; } if (isNumberObject(input2) || isStringObject(input2) || isBooleanObject(input2)) { const valOf = Number(input2.valueOf()); return isInfinityNumber(valOf) || isNaN(valOf) ? void 0 : valOf; } if (isDate(input2, { skipInvalidDate: true })) { try { return !isNaN(input2.getTime()) ? input2.getTime() : 0; } catch { return 0; } } if (isBuffer(input2)) { const arr = Array.from(input2).map( (n) => _internal(n, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).filter((item) => !isUndefined(item)); if (removeEmptyArrays2 && isEmptyArray(arr)) return void 0; return arr; } if (isTypedArray(input2)) { if (input2 instanceof BigInt64Array || input2 instanceof BigUint64Array) { const newArray = Array.from(input2).map( (item) => _internal(item, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).filter((item) => !isUndefined(item)); if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } else { const newArray = Array.from(input2).map( (item) => _internal(item, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).filter((item) => !isUndefined(item)); if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } } if (isSet(input2)) { const newArray = Array.from(input2).map( (item) => _internal(item, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).filter((item) => !isUndefined(item)); if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } if (isMap(input2)) { let newArray = Array.from(input2.entries()).map(([k, v]) => { const key = _internal(k, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }); const value = _internal(v, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }); return !isUndefined(key) && !isUndefined(value) ? [key, value] : void 0; }).filter((item) => !isUndefined(item)); if (removeEmptyArrays2) { newArray = newArray.filter((v) => !isEmptyArray(v)); } if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } if (isArray(input2)) { const newArray = input2.map( (item) => _internal(item, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).filter((item) => !isUndefined(item)); if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } if (isObject(input2)) { const newObject = {}; for (const [key, value] of Object.entries(input2)) { const convertedValue = _internal(value, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }); if (!isUndefined(convertedValue)) { newObject[key] = convertedValue; } } if (removeEmptyObjects2 && isEmptyObject(newObject)) { return isRoot ? {} : void 0; } return newObject; } return void 0; } return _internal(input, { removeEmptyObjects, removeEmptyArrays, isRoot: true }); } function toStringDeep(input, options = {}) { assertIsPlainObject(options, { message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const removeEmptyObjects = hasOwnProp(options, "removeEmptyObjects") ? options.removeEmptyObjects : false; const removeEmptyArrays = hasOwnProp(options, "removeEmptyArrays") ? options.removeEmptyArrays : false; function _internal(input2, options2) { if (isNil(input2) || isInfinityNumber(input2)) return void 0; const { removeEmptyArrays: removeEmptyArrays2, removeEmptyObjects: removeEmptyObjects2, isRoot } = options2; if (!isBoolean(removeEmptyObjects2) || !isBoolean(removeEmptyArrays2)) { throw new TypeError( `Parameters \`removeEmptyObjects\` and \`removeEmptyArrays\` property of the \`options\` (second parameter) must be of type \`boolean\`, but received: ['removeEmptyObjects': \`${getPreciseType( removeEmptyObjects2 )}\`, 'removeEmptyArrays': \`${getPreciseType(removeEmptyArrays2)}\`].` ); } if (isNumber(input2) || isString(input2) || isBoolean(input2)) return String(input2); if (isNumberObject(input2)) { const valOf = input2.valueOf(); return isInfinityNumber(valOf) || isNaN(valOf) ? void 0 : valOf.toString(); } if (isStringObject(input2)) return input2.valueOf(); if (isBooleanObject(input2)) return input2.valueOf().toString(); if (isDate(input2, { skipInvalidDate: true })) { try { return input2.toISOString(); } catch { return input2.toString(); } } if (isRegExp(input2)) return input2.toString(); if (isBuffer(input2)) { return Array.from(input2).map((v) => String(v)).filter((v) => !isUndefined(v)); } if (isTypedArray(input2)) { if (input2 instanceof BigInt64Array || input2 instanceof BigUint64Array) { const newArray = Array.from(input2).map( (item) => _internal(item, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).map((v) => String(v)).filter((item) => !isUndefined(item)); if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } else { const newArray = Array.from(input2).map( (item) => _internal(item, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).map((v) => String(v)).filter((item) => !isUndefined(item)); if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } } if (isSet(input2)) { const arr = Array.from(input2).map( (v) => _internal(v, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).filter((v) => !isUndefined(v)); if (removeEmptyArrays2 && isEmptyArray(arr)) return void 0; return arr; } if (isMap(input2)) { const arr = Array.from(input2.entries()).map(([k, v]) => [ _internal(k, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }), _internal(v, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ]).filter(([k, v]) => !isUndefined(k) && !isUndefined(v)); if (removeEmptyArrays2 && isEmptyArray(arr)) return void 0; return arr; } if (isArray(input2)) { let newArray = input2.map( (item) => _internal(item, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }) ).filter((item) => !isUndefined(item)); if (removeEmptyArrays2) { newArray = newArray.filter((v) => !(isArray(v) && v.length === 0)); } if (removeEmptyArrays2 && isEmptyArray(newArray)) return void 0; return newArray; } if (isObject(input2)) { const newObject = {}; for (const [key, value] of Object.entries(input2)) { const convertedValue = _internal(value, { removeEmptyObjects: removeEmptyObjects2, removeEmptyArrays: removeEmptyArrays2, isRoot: false }); if (!isUndefined(convertedValue)) { newObject[key] = convertedValue; } else if (isArray(value) && !removeEmptyArrays2) { newObject[key] = []; } } if (removeEmptyObjects2 && Object.keys(newObject).length === 0) { return isRoot ? {} : void 0; } return newObject; } return void 0; } return _internal(input, { removeEmptyObjects, removeEmptyArrays, isRoot: true }); } export { convertType, dedupeArray, removeObjectPaths, toBooleanContent, toBooleanContentDeep, toBooleanExplicit, toBooleanLoose, toNumberArrayUnRecursive, toNumberDeep, toStringDeep, toStringDeepForce };