diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/sanitize-raw-update-field-input.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/sanitize-raw-update-field-input.ts index eeccaa0698..fdcff31544 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/sanitize-raw-update-field-input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/sanitize-raw-update-field-input.ts @@ -16,6 +16,7 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; import { nullifyEmptyCompositeDefaultValue } from 'src/engine/metadata-modules/flat-field-metadata/utils/nullify-empty-composite-default-value.util'; import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util'; +import { computeMetadataOverridesBlob } from 'src/engine/metadata-modules/utils/compute-metadata-overrides-blob.util'; type SanitizeRawUpdateFieldInputArgs = { rawUpdateFieldInput: UpdateFieldInput; @@ -81,51 +82,16 @@ export const sanitizeRawUpdateFieldInput = ({ ); } - const standardOverrides = FIELD_METADATA_STANDARD_OVERRIDES_PROPERTIES.reduce( - (standardOverrides, property) => { - const propertyValue = updatedEditableFieldProperties[property]; - - const isPropertyUpdated = - updatedEditableFieldProperties[property] !== undefined; - - if (!isPropertyUpdated) { - return standardOverrides; - } - delete updatedEditableFieldProperties[property]; - - if (propertyValue === existingFlatFieldMetadata[property]) { - if ( - isDefined(standardOverrides) && - Object.prototype.hasOwnProperty.call(standardOverrides, property) - ) { - const { [property]: _, ...restOverrides } = standardOverrides; - - return restOverrides; - } - - return standardOverrides; - } - - return { - ...standardOverrides, - [property]: propertyValue, - }; - }, - existingFlatFieldMetadata.standardOverrides, - ); - - if ( - isDefined(standardOverrides) && - Object.keys(standardOverrides).length === 0 - ) { - return { - standardOverrides: null, - updatedEditableFieldProperties, - }; - } + const { overrides: standardOverrides, remainingProperties } = + computeMetadataOverridesBlob({ + overridableProperties: FIELD_METADATA_STANDARD_OVERRIDES_PROPERTIES, + updatedProperties: updatedEditableFieldProperties, + existingEntity: existingFlatFieldMetadata, + existingOverrides: existingFlatFieldMetadata.standardOverrides, + }); return { standardOverrides, - updatedEditableFieldProperties, + updatedEditableFieldProperties: remainingProperties, }; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/sanitize-raw-update-object-input.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/sanitize-raw-update-object-input.ts index b468c7ff5e..daf81f7332 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/sanitize-raw-update-object-input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/sanitize-raw-update-object-input.ts @@ -1,7 +1,4 @@ -import { - extractAndSanitizeObjectStringFields, - isDefined, -} from 'twenty-shared/utils'; +import { extractAndSanitizeObjectStringFields } from 'twenty-shared/utils'; import { FLAT_OBJECT_METADATA_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-object-metadata/constants/flat-object-metadata-editable-properties.constant'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; @@ -13,6 +10,7 @@ import { } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; import { type ObjectMetadataStandardOverridesProperties } from 'src/engine/metadata-modules/object-metadata/types/object-metadata-standard-overrides-properties.types'; import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util'; +import { computeMetadataOverridesBlob } from 'src/engine/metadata-modules/utils/compute-metadata-overrides-blob.util'; type SanitizeRawUpdateObjectInputArgs = { rawUpdateObjectInput: UpdateOneObjectInput; @@ -59,52 +57,16 @@ export const sanitizeRawUpdateObjectInput = ({ ); } - const standardOverrides = - OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES.reduce( - (standardOverrides, property) => { - const propertyValue = updatedEditableObjectProperties[property]; - - const isPropertyUpdated = - updatedEditableObjectProperties[property] !== undefined; - - if (!isPropertyUpdated) { - return standardOverrides; - } - delete updatedEditableObjectProperties[property]; - - if (propertyValue === existingFlatObjectMetadata[property]) { - if ( - isDefined(standardOverrides) && - Object.prototype.hasOwnProperty.call(standardOverrides, property) - ) { - const { [property]: _, ...restOverrides } = standardOverrides; - - return restOverrides; - } - - return standardOverrides; - } - - return { - ...standardOverrides, - [property]: propertyValue, - }; - }, - existingFlatObjectMetadata.standardOverrides, - ); - - if ( - isDefined(standardOverrides) && - Object.keys(standardOverrides).length === 0 - ) { - return { - standardOverrides: null, - updatedEditableObjectProperties, - }; - } + const { overrides: standardOverrides, remainingProperties } = + computeMetadataOverridesBlob({ + overridableProperties: OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES, + updatedProperties: updatedEditableObjectProperties, + existingEntity: existingFlatObjectMetadata, + existingOverrides: existingFlatObjectMetadata.standardOverrides, + }); return { standardOverrides, - updatedEditableObjectProperties, + updatedEditableObjectProperties: remainingProperties, }; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/utils/compute-metadata-overrides-blob.util.ts b/packages/twenty-server/src/engine/metadata-modules/utils/compute-metadata-overrides-blob.util.ts new file mode 100644 index 0000000000..996f190b9d --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/utils/compute-metadata-overrides-blob.util.ts @@ -0,0 +1,74 @@ +import { fastDeepEqual, isDefined } from 'twenty-shared/utils'; + +type ComputeMetadataOverridesBlobArgs< + TProperties extends object, + TOverrides, +> = { + overridableProperties: readonly string[]; + updatedProperties: TProperties; + existingEntity: object; + existingOverrides: TOverrides | null; +}; + +export const computeMetadataOverridesBlob = < + TProperties extends object, + TOverrides = Record, +>({ + overridableProperties, + updatedProperties, + existingEntity, + existingOverrides, +}: ComputeMetadataOverridesBlobArgs): { + overrides: TOverrides | null; + remainingProperties: TProperties; +} => { + const remainingRecord: Record = { + ...(updatedProperties as unknown as Record), + }; + const existingRecord = existingEntity as Record; + + const overrides = overridableProperties.reduce | null>( + (acc, property) => { + if (remainingRecord[property] === undefined) { + return acc; + } + + const propertyValue = remainingRecord[property]; + + delete remainingRecord[property]; + + if (fastDeepEqual(propertyValue, existingRecord[property])) { + if ( + isDefined(acc) && + Object.prototype.hasOwnProperty.call(acc, property) + ) { + const { [property]: _removedProperty, ...restOverrides } = acc; + + return restOverrides; + } + + return acc; + } + + return { + ...acc, + [property]: propertyValue, + }; + }, + existingOverrides as unknown as Record | null, + ); + + const remainingProperties = remainingRecord as unknown as TProperties; + + if (isDefined(overrides) && Object.keys(overrides).length === 0) { + return { overrides: null, remainingProperties }; + } + + return { + overrides: overrides as unknown as TOverrides | null, + remainingProperties, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/utils/sanitize-overridable-entity-input.util.ts b/packages/twenty-server/src/engine/metadata-modules/utils/sanitize-overridable-entity-input.util.ts index 94bb2d3c3f..687bff9680 100644 --- a/packages/twenty-server/src/engine/metadata-modules/utils/sanitize-overridable-entity-input.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/utils/sanitize-overridable-entity-input.util.ts @@ -1,8 +1,7 @@ -import isEqual from 'lodash.isequal'; import { type AllMetadataName } from 'twenty-shared/metadata'; -import { isDefined } from 'twenty-shared/utils'; import { ALL_OVERRIDABLE_PROPERTIES_BY_METADATA_NAME } from 'src/engine/metadata-modules/flat-entity/constant/all-overridable-properties-by-metadata-name.constant'; +import { computeMetadataOverridesBlob } from 'src/engine/metadata-modules/utils/compute-metadata-overrides-blob.util'; type FlatEntityWithOverrides = { [key: string]: unknown; @@ -26,63 +25,21 @@ export const sanitizeOverridableEntityInput = < overrides: Record | null; updatedEditableProperties: TProperties; } => { - const existingOverrides = existingFlatEntity.overrides; - if (!shouldOverride) { return { - overrides: existingOverrides, + overrides: existingFlatEntity.overrides, updatedEditableProperties, }; } - const sanitizedEditableProperties = { - ...updatedEditableProperties, - } as TProperties; + const { overrides, remainingProperties } = computeMetadataOverridesBlob({ + overridableProperties: ALL_OVERRIDABLE_PROPERTIES_BY_METADATA_NAME[ + metadataName + ] as string[], + updatedProperties: updatedEditableProperties, + existingEntity: existingFlatEntity, + existingOverrides: existingFlatEntity.overrides, + }); - const overridableProperties = ALL_OVERRIDABLE_PROPERTIES_BY_METADATA_NAME[ - metadataName - ] as string[]; - - const overrides = overridableProperties.reduce | null>((acc, property) => { - const isPropertyUpdated = - sanitizedEditableProperties[property] !== undefined; - - if (!isPropertyUpdated) { - return acc; - } - - const propertyValue = sanitizedEditableProperties[property]; - - delete sanitizedEditableProperties[property]; - - if (isEqual(propertyValue, existingFlatEntity[property])) { - if ( - isDefined(acc) && - Object.prototype.hasOwnProperty.call(acc, property) - ) { - const { [property]: _, ...restOverrides } = acc; - - return restOverrides; - } - - return acc; - } - - return { - ...acc, - [property]: propertyValue, - }; - }, existingOverrides); - - if (isDefined(overrides) && Object.keys(overrides).length === 0) { - return { - overrides: null, - updatedEditableProperties: sanitizedEditableProperties, - }; - } - - return { overrides, updatedEditableProperties: sanitizedEditableProperties }; + return { overrides, updatedEditableProperties: remainingProperties }; };