UNPKG

camote-utils

Version:

A comprehensive TypeScript utility library featuring advanced string and number formatting, data structures, and algorithms

183 lines (182 loc) 7.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.deepExclude = exports.deepMerge = exports.deepCompareObjects = exports.deepCompare = exports.deepSortAlphabetical = exports.deepClone = void 0; const deepClone = (obj) => { if (obj === null || typeof obj !== 'object') { return obj; } if (obj instanceof Date) { return new Date(obj.getTime()); } if (Array.isArray(obj)) { const arrCopy = []; obj.forEach((item, index) => { arrCopy[index] = (0, exports.deepClone)(item); }); return arrCopy; } const objCopy = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { objCopy[key] = (0, exports.deepClone)(obj[key]); } } return objCopy; }; exports.deepClone = deepClone; const deepSortAlphabetical = (input, inReverse = false) => { if (Array.isArray(input)) { return input .map((item) => (0, exports.deepSortAlphabetical)(item)) .sort((a, b) => { const aType = typeof a; const bType = typeof b; // Prioritize objects over numbers if (aType === 'object' && bType !== 'object') return inReverse ? 1 : -1; if (bType === 'object' && aType !== 'object') return inReverse ? -1 : 1; // If both are of the same type, proceed with comparison if (aType === bType) { if (aType === 'string') { return inReverse ? b.localeCompare(a) : a.localeCompare(b); } else if (aType === 'object') { // Sort objects by their keys const aKeys = Object.keys(a).sort(); const bKeys = Object.keys(b).sort(); return inReverse ? bKeys[0].localeCompare(aKeys[0]) : aKeys[0].localeCompare(bKeys[0]); } else { // For numbers and other types, convert to string for comparison return inReverse ? String(b).localeCompare(String(a)) : String(a).localeCompare(String(b)); } } // Handle cases where types differ return inReverse ? bType.localeCompare(aType) : aType.localeCompare(bType); }); } else if (input && typeof input === 'object') { return Object.keys(input) .sort((a, b) => (inReverse ? b.localeCompare(a) : a.localeCompare(b))) .reduce((acc, key) => { acc[key] = (0, exports.deepSortAlphabetical)(input[key], inReverse); return acc; }, {}); } else { return input; } }; exports.deepSortAlphabetical = deepSortAlphabetical; const deepCompare = (objectA, objectB, returnChanges = false) => { const originalObj = (0, exports.deepSortAlphabetical)(objectA); const toCompareObj = (0, exports.deepSortAlphabetical)(objectB); // Handle null/undefined cases if (originalObj === toCompareObj) return returnChanges ? {} : true; if (!originalObj || !toCompareObj) { if (typeof originalObj === 'string' && toCompareObj === null) return returnChanges ? originalObj : false; if (typeof toCompareObj === 'string' && originalObj === null) return returnChanges ? toCompareObj : false; return returnChanges ? toCompareObj : false; } // For primitive types, do direct comparison if (typeof originalObj === 'number' && typeof toCompareObj === 'number') { return returnChanges ? (originalObj === toCompareObj ? {} : toCompareObj) : originalObj === toCompareObj; } // Get object types const originalType = typeof originalObj; const compareType = typeof toCompareObj; // If types don't match, objects are different if (originalType !== compareType) return returnChanges ? toCompareObj : false; // Handle array comparison if (Array.isArray(originalObj) && Array.isArray(toCompareObj)) { if (!returnChanges && originalObj.length !== toCompareObj.length) return false; const differences = []; for (let i = 0; i < toCompareObj.length; i++) { if (i >= originalObj.length) { differences.push(toCompareObj[i]); continue; } const compResult = (0, exports.deepCompare)(originalObj[i], toCompareObj[i], returnChanges); if (returnChanges) { if (compResult && (typeof compResult === 'object' ? Object.keys(compResult).length > 0 : true)) { differences.push(toCompareObj[i]); } } else if (!compResult) { return false; } } return returnChanges ? differences : true; } // Handle object comparison if (originalType === 'object') { const changes = {}; const originalKeys = Object.keys(originalObj); const compareKeys = Object.keys(toCompareObj); for (const key of compareKeys) { if (!originalKeys.includes(key)) { if (returnChanges) { changes[key] = toCompareObj[key]; } else { return false; } } else { const compResult = (0, exports.deepCompare)(originalObj[key], toCompareObj[key], returnChanges); if (returnChanges) { if (compResult !== true && (typeof compResult !== 'object' || Object.keys(compResult).length > 0)) { changes[key] = compResult; } } else if (!compResult) { return false; } } } return returnChanges ? changes : Object.keys(changes).length === 0; } // For primitive types, do direct comparison const areEqual = originalObj === toCompareObj; return returnChanges ? (areEqual ? {} : toCompareObj) : areEqual; }; exports.deepCompare = deepCompare; exports.deepCompareObjects = exports.deepCompare; const deepMerge = (obj1, obj2, excluded = []) => { const merged = { ...obj1 }; // Iterate over the keys of obj2 Object.keys(obj2).forEach(key => { if (!excluded.includes(key)) { if (typeof obj2[key] === 'object' && obj2[key] !== null) { // If the property is an array, merge and remove duplicates if (Array.isArray(obj2[key])) { merged[key] = [...new Set([...(obj1[key] || []), ...(obj2[key] || [])])]; } else { merged[key] = (0, exports.deepMerge)(obj1[key] || {}, obj2[key], excluded); } } else { merged[key] = obj2[key]; } } }); return merged; }; exports.deepMerge = deepMerge; const deepExclude = (sourceArray, valuesToExclude, keySelector = (value) => JSON.stringify(value)) => { const valuesToExcludeKeys = new Set(valuesToExclude.map((value) => keySelector(value))); return sourceArray.filter((value) => { const key = keySelector(value); return !valuesToExcludeKeys.has(key); }); }; exports.deepExclude = deepExclude;