diff --git a/src/backend/src/common/utils/object-comparison.util.ts b/src/backend/src/common/utils/object-comparison.util.ts new file mode 100644 index 000000000..1bd270543 --- /dev/null +++ b/src/backend/src/common/utils/object-comparison.util.ts @@ -0,0 +1,61 @@ +const convertToISODate = (object: any) => { + if (object instanceof Date) { + return object.toISOString(); + } + + return object; +}; + +export const deepEqual = ( + object1: any, + object2: any, + skipKeys: Array = [], +) => { + if ( + typeof object1 !== 'object' || + typeof object2 !== 'object' || + object1 === null || + object1 === undefined || + object2 === null || + object2 === undefined + ) { + if (object1 instanceof Date || object2 instanceof Date) { + object1 = convertToISODate(object1); + object2 = convertToISODate(object2); + } + + return object1 === object2; + } + + const keys1 = Object.keys(object1); + const keys2 = Object.keys(object2); + + if (keys1.length !== keys2.length) { + return false; + } + + for (const key of keys1) { + if (skipKeys.includes(key)) continue; + + // recursive check for nested values [objects] + if ( + typeof object1[key] === typeof object2[key] && + typeof object1[key] === 'object' && + object1[key] !== null && + object1[key] !== undefined && + object2[key] !== null && + object2[key] !== undefined + ) { + if (deepEqual(object1[key], object2[key])) continue; + + return false; + } + + // check for primitive values + if (object1[key] !== object2[key]) { + return false; + } + } + + return true; +}; diff --git a/src/backend/src/modules/pia-intake/helper/handle-pia-updates.ts b/src/backend/src/modules/pia-intake/helper/handle-pia-updates.ts index 2897f3160..9b96e3b4a 100644 --- a/src/backend/src/modules/pia-intake/helper/handle-pia-updates.ts +++ b/src/backend/src/modules/pia-intake/helper/handle-pia-updates.ts @@ -1,7 +1,7 @@ import { ForbiddenException } from '@nestjs/common'; import { PiaTypesEnum } from 'src/common/enums/pia-types.enum'; import { UserTypesEnum } from 'src/common/enums/users.enum'; -import { isDeepStrictEqual } from 'util'; +import { deepEqual } from 'src/common/utils/object-comparison.util'; import { UpdatePiaIntakeDto } from '../dto/update-pia-intake.dto'; import { PiaIntakeEntity } from '../entities/pia-intake.entity'; import { piaStatusMetadata } from '../metadata/pia-status.metadata'; @@ -29,7 +29,7 @@ export const handlePiaUpdates = ( if (Object.keys(updates).length === 0) return; const hasUpdates = !Object.keys(updates || {}).every((key) => - isDeepStrictEqual(updates[key], storedValue?.[key]), + deepEqual(updates[key], storedValue?.[key]), ); // when no updates diff --git a/src/frontend/src/utils/object-comparison.util.ts b/src/frontend/src/utils/object-comparison.util.ts index a316a21f2..1bd270543 100644 --- a/src/frontend/src/utils/object-comparison.util.ts +++ b/src/frontend/src/utils/object-comparison.util.ts @@ -1,8 +1,32 @@ +const convertToISODate = (object: any) => { + if (object instanceof Date) { + return object.toISOString(); + } + + return object; +}; + export const deepEqual = ( - object1: Record, - object2: Record, + object1: any, + object2: any, skipKeys: Array = [], ) => { + if ( + typeof object1 !== 'object' || + typeof object2 !== 'object' || + object1 === null || + object1 === undefined || + object2 === null || + object2 === undefined + ) { + if (object1 instanceof Date || object2 instanceof Date) { + object1 = convertToISODate(object1); + object2 = convertToISODate(object2); + } + + return object1 === object2; + } + const keys1 = Object.keys(object1); const keys2 = Object.keys(object2);