UNPKG

object-deep-compare

Version:

A type-safe collection of comparison methods for objects and arrays in TypeScript/JavaScript

156 lines (155 loc) 7.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeSafeCompareValuesWithDetailedDifferences = exports.TypeSafeCompareObjects = exports.MapObjectProperties = exports.TypeSafeCompareArrays = void 0; const compare_arrays_1 = require("../comparison/compare-arrays"); const object_comparison_1 = require("../comparison/object-comparison"); const detailed_comparison_1 = require("../comparison/detailed-comparison"); const schema_validation_1 = require("../core/schema-validation"); const utils_1 = require("../core/utils"); /** * Type-safe comparison of arrays that includes type information * * @param firstArray - First array to compare * @param secondArray - Second array to compare * @param options - Optional comparison options (strict, circularReferences) * @returns Object with isEqual flag and type information */ const TypeSafeCompareArrays = (firstArray, secondArray, options = {}) => { // Perform schema validation if specified if (options.schemaValidation) { // Convert arrays to objects for schema validation if schemas are provided if (options.schemaValidation.firstObjectSchema || options.schemaValidation.secondObjectSchema) { const firstObject = { items: firstArray }; const secondObject = { items: secondArray }; // Wrap the array schemas inside an object with 'items' property const wrappedFirstSchema = options.schemaValidation.firstObjectSchema ? { items: [options.schemaValidation.firstObjectSchema] } : undefined; const wrappedSecondSchema = options.schemaValidation.secondObjectSchema ? { items: [options.schemaValidation.secondObjectSchema] } : undefined; const wrappedSchemaValidation = { firstObjectSchema: wrappedFirstSchema, secondObjectSchema: wrappedSecondSchema, throwOnValidationFailure: options.schemaValidation.throwOnValidationFailure }; // Run the schema validation (0, schema_validation_1.ValidateObjectsAgainstSchemas)(firstObject, secondObject, wrappedSchemaValidation); } } const isEqual = (0, compare_arrays_1.CompareArrays)(firstArray, secondArray, options); return { isEqual, firstType: (0, utils_1.getTypeName)(firstArray), secondType: (0, utils_1.getTypeName)(secondArray) }; }; exports.TypeSafeCompareArrays = TypeSafeCompareArrays; /** * Maps properties between objects with different structures * * @param sourceObject - Source object * @param propertyMapping - Mapping from source properties to target properties * @returns A new object with mapped properties */ const MapObjectProperties = (sourceObject, propertyMapping) => { const result = {}; Object.entries(propertyMapping).forEach(([sourceKey, targetKey]) => { if (sourceKey in sourceObject && targetKey) { // @ts-ignore - We know these keys exist based on the check result[targetKey] = sourceObject[sourceKey]; } }); return result; }; exports.MapObjectProperties = MapObjectProperties; /** * Type-safe version of object comparison that supports objects with different structures * * @param firstObject - First object to compare * @param secondObject - Second object to compare * @param options - Type-safe comparison options * @returns Object with isEqual flag and type information */ const TypeSafeCompareObjects = (firstObject, secondObject, options = {}) => { // Handle null and undefined cases if (!firstObject || !secondObject) { return { isEqual: firstObject === secondObject, firstType: (firstObject === null ? 'null' : firstObject === undefined ? 'undefined' : 'object'), secondType: (secondObject === null ? 'null' : secondObject === undefined ? 'undefined' : 'object') }; } // Create a new object for comparison if property mapping is provided if (options.propertyMapping && Object.keys(options.propertyMapping).length > 0) { // Create a clean object with only mapped properties const mappedFirstObject = {}; // Apply property mapping for (const [sourceKey, targetKey] of Object.entries(options.propertyMapping)) { if (sourceKey in firstObject && targetKey) { // Map the source property to the target property name // @ts-ignore - We know these keys exist based on the check mappedFirstObject[targetKey] = firstObject[sourceKey]; } } // Use existing CompareValuesWithConflicts function for comparison const conflicts = (0, object_comparison_1.CompareValuesWithConflicts)(mappedFirstObject, secondObject, '', { strict: options.strict, circularReferences: options.circularReferences, pathFilter: options.pathFilter }); return { isEqual: conflicts.length === 0, firstType: 'object', secondType: 'object' }; } else { // Without property mapping, do a regular comparison const conflicts = (0, object_comparison_1.CompareValuesWithConflicts)(firstObject, secondObject, '', { strict: options.strict, circularReferences: options.circularReferences, pathFilter: options.pathFilter }); return { isEqual: conflicts.length === 0, firstType: 'object', secondType: 'object' }; } }; exports.TypeSafeCompareObjects = TypeSafeCompareObjects; /** * Type-safe version of detailed comparison that supports objects with different structures * and provides type information * * @param firstObject - First object to compare * @param secondObject - Second object to compare * @param options - Type-safe comparison options * @returns Array of typed detailed differences with type information */ const TypeSafeCompareValuesWithDetailedDifferences = (firstObject, secondObject, options = {}) => { if (!firstObject || !secondObject) { return []; } // Perform schema validation if specified if (options.schemaValidation) { (0, schema_validation_1.ValidateObjectsAgainstSchemas)(firstObject, secondObject, options.schemaValidation); } // Get standard detailed differences const differences = (0, detailed_comparison_1.CompareValuesWithDetailedDifferences)(firstObject, secondObject, '', options); // If we don't need type info, just return the standard differences if (!options.includeTypeInfo) { return differences; } // Add type information to each difference return differences.map((diff) => { const typedDiff = { ...diff, oldValueType: diff.oldValue !== undefined ? (0, utils_1.getTypeName)(diff.oldValue) : undefined, newValueType: diff.newValue !== undefined ? (0, utils_1.getTypeName)(diff.newValue) : undefined }; return typedDiff; }); }; exports.TypeSafeCompareValuesWithDetailedDifferences = TypeSafeCompareValuesWithDetailedDifferences;