UNPKG

nhb-toolbox

Version:

A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.

213 lines (212 loc) 7.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseJSON = exports.isDeepEqual = void 0; exports.convertArrayToString = convertArrayToString; exports.debounceAction = debounceAction; exports.throttleAction = throttleAction; exports.getInstanceMethodNames = getInstanceMethodNames; exports.getStaticMethodNames = getStaticMethodNames; exports.countInstanceMethods = countInstanceMethods; exports.countStaticMethods = countStaticMethods; exports.getInstanceGetterNames = getInstanceGetterNames; exports.getStaticGetterNames = getStaticGetterNames; exports.getClassDetails = getClassDetails; exports.stableStringify = stableStringify; exports.stripJsonEdgeGarbage = stripJsonEdgeGarbage; exports.deepParsePrimitives = deepParsePrimitives; exports.definePrototypeMethod = definePrototypeMethod; const helpers_1 = require("../array/helpers"); const sort_1 = require("../array/sort"); const guards_1 = require("../date/guards"); const non_primitives_1 = require("../guards/non-primitives"); const primitives_1 = require("../guards/primitives"); const specials_1 = require("../guards/specials"); const isDeepEqual = (a, b) => { if (a === b) return true; if (typeof a !== typeof b) return false; if (a === null || b === null) return a === b; if ((0, non_primitives_1.isArray)(a) && (0, non_primitives_1.isArray)(b)) { if (a?.length !== b?.length) return false; return a?.every((element, index) => (0, exports.isDeepEqual)(element, b?.[index])); } if ((0, non_primitives_1.isObject)(a) && (0, non_primitives_1.isObject)(b)) { const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys?.length !== bKeys?.length) return false; return aKeys?.every((key) => (0, exports.isDeepEqual)(a?.[key], b?.[key])); } return false; }; exports.isDeepEqual = isDeepEqual; function convertArrayToString(array, options) { if (!(0, non_primitives_1.isValidArray)(array)) return ''; const { separator = ', ' } = options ?? {}; if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isPrimitive)) { return array?.join(separator); } else if ((0, non_primitives_1.isArrayOfType)(array, non_primitives_1.isNotEmptyObject)) { if (options && 'target' in options) { return array?.map((el) => (0, helpers_1._resolveNestedKey)(el, options?.target))?.join(separator); } else { return ''; } } return ''; } function debounceAction(callback, delay = 300) { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => { callback(...args); }, delay); }; } function throttleAction(callback, delay = 150) { let lastCall = 0; return (...args) => { const now = Date.now(); if (now - lastCall >= delay) { lastCall = now; callback(...args); } }; } function getInstanceMethodNames(cls) { const prototype = cls.prototype; const methods = Object.getOwnPropertyNames(prototype).filter((method) => { if (method === 'constructor') { return false; } const descriptor = Object.getOwnPropertyDescriptor(prototype, method); return (0, non_primitives_1.isMethodDescriptor)(descriptor); }); return (0, sort_1.sortAnArray)(methods); } function getStaticMethodNames(cls) { const methods = Object.getOwnPropertyNames(cls).filter((method) => { return method !== 'prototype' && method !== 'name' && method !== 'length'; }); return (0, sort_1.sortAnArray)(methods); } function countInstanceMethods(cls) { return getInstanceMethodNames(cls)?.length; } function countStaticMethods(cls) { return getStaticMethodNames(cls)?.length; } function getInstanceGetterNames(cls) { const descriptors = Object.getOwnPropertyDescriptors(cls.prototype); const result = Object.entries(descriptors) .filter(([key, desc]) => typeof desc.get === 'function' && key !== 'constructor') .map(([key]) => key); return (0, sort_1.sortAnArray)(result); } function getStaticGetterNames(cls) { const descriptors = Object.getOwnPropertyDescriptors(cls); const result = Object.entries(descriptors) .filter(([key, desc]) => typeof desc.get === 'function' && key !== 'prototype') .map(([key]) => key); return (0, sort_1.sortAnArray)(result); } function getClassDetails(cls) { const instanceNames = getInstanceMethodNames(cls); const staticNames = getStaticMethodNames(cls); const instanceGetters = getInstanceGetterNames(cls); const staticGetters = getStaticGetterNames(cls); return { instanceMethods: instanceNames, staticMethods: staticNames, instanceGetters, staticGetters, instanceCount: instanceNames?.length, staticCount: staticNames?.length, totalGetters: instanceGetters?.length + staticGetters?.length, totalMethods: instanceNames?.length + staticNames?.length, }; } function stableStringify(obj) { const _replacer = (_, v) => (v === undefined ? null : v); if ((0, non_primitives_1.isNotEmptyObject)(obj)) { const keys = Object.keys(obj).sort(); return ('{' + keys .map((k) => JSON.stringify(k, _replacer) + ':' + ((0, guards_1.isDateLike)(obj[k]) ? JSON.stringify(obj[k]) : stableStringify(obj[k]))) .join(',') + '}'); } if ((0, non_primitives_1.isValidArray)(obj)) { return '[' + obj.map((v) => stableStringify(v)).join(',') + ']'; } return JSON.stringify(obj, _replacer); } function stripJsonEdgeGarbage(str) { if (!(0, primitives_1.isNonEmptyString)(str)) return ''; const lastIdx = Math.max(str.lastIndexOf('}'), str.lastIndexOf(']')); const _idxOf = (sym) => (str.indexOf(sym) !== -1 ? str.indexOf(sym) : Infinity); const firstIdx = Math.min(_idxOf('{'), _idxOf('[')); if (lastIdx === -1 || firstIdx === Infinity) return str; return str.slice(firstIdx, lastIdx + 1); } const parseJSON = (value, parsePrimitives = true) => { try { const parsed = JSON.parse(value); return (parsePrimitives ? deepParsePrimitives(parsed) : parsed); } catch { return {}; } }; exports.parseJSON = parseJSON; function deepParsePrimitives(input) { if (Array.isArray(input)) { return input?.map(deepParsePrimitives); } if ((0, non_primitives_1.isObject)(input)) { const result = {}; for (const [key, value] of Object.entries(input)) { result[key] = deepParsePrimitives(value); } return result; } if ((0, primitives_1.isString)(input)) { if (/^(true|false)$/i.test(input)) { return (input?.toLowerCase() === 'true'); } if ((0, specials_1.isNumericString)(input)) { return Number(input); } if (input === 'null') { return null; } if (input === 'undefined') { return undefined; } return input; } return input; } function definePrototypeMethod(proto, name, impl, options) { const alreadyExists = Object.hasOwn(proto, name); if (alreadyExists && !options?.overwrite) return; Object.defineProperty(proto, name, { value: function (...args) { return impl.apply(this, args); }, enumerable: options?.enumerable ?? false, configurable: options?.configurable ?? false, writable: options?.writable ?? true, }); }