48c8fa6809
# Introduction
Removing:
- `from` property from actions definition, as it's a legitimate source
of truth. The stored comparison might have been compromised since action
generation. If from is needed it should be computed from the optimistic
cache at runner lvl
- Removed the `FlatEntityPropertyUpdates` Array complexity in favor of
From
```ts
export type PropertyUpdate<T, P extends keyof T> = {
property: P;
} & FromTo<T[P]>;
```
To
```ts
export type FlatEntityUpdate<T extends AllMetadataName> = Partial<
Pick<
MetadataFlatEntity<T>,
Extract<FlatEntityPropertiesToCompare<T>, keyof MetadataFlatEntity<T>>
>
>;
```
## New interactions
From
```ts
const positionUpdate = findFlatEntityPropertyUpdate({
flatEntityUpdates,
property: 'position',
});
if (
isDefined(positionUpdate) &&
(!Number.isInteger(positionUpdate.to) || positionUpdate.to < 0)
) {
const toFlatNavigationMenuItem = {
...fromFlatNavigationMenuItem,
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
updates: flatEntityUpdates,
}),
};
```
To
```ts
const positionUpdate = flatEntityUpdate.position;
if (
isDefined(positionUpdate) &&
(!Number.isInteger(positionUpdate) || positionUpdate < 0)
) {
const toFlatNavigationMenuItem = {
...fromFlatNavigationMenuItem,
...flatEntityUpdate,
};
```
## `SanitizeFlatEntityUpdate`
Enforcing the `flatEntityUpdate` to only contains comparable properties
per flat entity by striping out all unexpected keys
In the future we will also move the whole validation at runner lvl at
some point
```ts
export const sanitizeFlatEntityUpdate = <T extends AllMetadataName>({
flatEntityUpdate,
metadataName,
}: {
flatEntityUpdate: FlatEntityUpdate<T>;
metadataName: T;
}): FlatEntityUpdate<T> => {
const { propertiesToCompare } =
ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName];
const initialAccumulator: FlatEntityUpdate<T> = {};
return propertiesToCompare.reduce((accumulator, property) => {
const updatedValue =
flatEntityUpdate[property as MetadataFlatEntityComparableProperties<T>];
if (updatedValue === undefined) {
return accumulator;
}
return {
...accumulator,
[property]: updatedValue,
};
}, initialAccumulator);
};
```
95 lines
3.6 KiB
TypeScript
95 lines
3.6 KiB
TypeScript
import { type EnumFieldMetadataType, type FromTo } from 'twenty-shared/types';
|
|
|
|
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
|
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
|
import {
|
|
type FlatViewFiltersToDeleteAndUpdate,
|
|
recomputeViewFiltersOnFlatFieldMetadataOptionsUpdate,
|
|
} from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-view-filters-on-flat-field-metadata-options-update.util';
|
|
import { recomputeViewGroupsOnEnumFlatFieldMetadataIsNullableUpdate } from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-view-groups-on-enum-flat-field-metadata-is-nullable-update.util';
|
|
import {
|
|
type FlatViewGroupsToDeleteUpdateAndCreate,
|
|
recomputeViewGroupsOnFlatFieldMetadataOptionsUpdate,
|
|
} from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-view-groups-on-flat-field-metadata-options-update.util';
|
|
|
|
type HandleEnumFlatFieldMetadataOptionsUpdateSideEffectsArgs = FromTo<
|
|
FlatFieldMetadata<EnumFieldMetadataType>,
|
|
'flatFieldMetadata'
|
|
> &
|
|
Pick<
|
|
AllFlatEntityMaps,
|
|
'flatViewFilterMaps' | 'flatViewGroupMaps' | 'flatViewMaps'
|
|
>;
|
|
|
|
type EnumFieldMetadataSideEffectResult = FlatViewGroupsToDeleteUpdateAndCreate &
|
|
FlatViewFiltersToDeleteAndUpdate;
|
|
|
|
const EMPTY_ENUM_FIELD_METADATA_SIDE_EFFECT_RESULT: EnumFieldMetadataSideEffectResult =
|
|
{
|
|
flatViewFiltersToDelete: [],
|
|
flatViewFiltersToUpdate: [],
|
|
flatViewGroupsToCreate: [],
|
|
flatViewGroupsToDelete: [],
|
|
flatViewGroupsToUpdate: [],
|
|
};
|
|
|
|
export const handleEnumFlatFieldMetadataUpdateSideEffects = ({
|
|
fromFlatFieldMetadata,
|
|
toFlatFieldMetadata,
|
|
flatViewFilterMaps,
|
|
flatViewGroupMaps,
|
|
flatViewMaps,
|
|
}: HandleEnumFlatFieldMetadataOptionsUpdateSideEffectsArgs): EnumFieldMetadataSideEffectResult => {
|
|
const sideEffectResult = structuredClone(
|
|
EMPTY_ENUM_FIELD_METADATA_SIDE_EFFECT_RESULT,
|
|
);
|
|
|
|
if (
|
|
JSON.stringify(fromFlatFieldMetadata.options) !==
|
|
JSON.stringify(toFlatFieldMetadata.options)
|
|
) {
|
|
const optionsPropertyUpdate =
|
|
toFlatFieldMetadata.options as FlatFieldMetadata<EnumFieldMetadataType>['options'];
|
|
|
|
const { flatViewFiltersToDelete, flatViewFiltersToUpdate } =
|
|
recomputeViewFiltersOnFlatFieldMetadataOptionsUpdate({
|
|
flatViewFilterMaps,
|
|
fromFlatFieldMetadata,
|
|
toOptions: optionsPropertyUpdate,
|
|
});
|
|
|
|
sideEffectResult.flatViewFiltersToDelete.push(...flatViewFiltersToDelete);
|
|
sideEffectResult.flatViewFiltersToUpdate.push(...flatViewFiltersToUpdate);
|
|
|
|
const {
|
|
flatViewGroupsToCreate,
|
|
flatViewGroupsToDelete,
|
|
flatViewGroupsToUpdate,
|
|
} = recomputeViewGroupsOnFlatFieldMetadataOptionsUpdate({
|
|
flatViewMaps,
|
|
flatViewGroupMaps,
|
|
fromFlatFieldMetadata,
|
|
toOptions: optionsPropertyUpdate,
|
|
});
|
|
|
|
sideEffectResult.flatViewGroupsToCreate.push(...flatViewGroupsToCreate);
|
|
sideEffectResult.flatViewGroupsToDelete.push(...flatViewGroupsToDelete);
|
|
sideEffectResult.flatViewGroupsToUpdate.push(...flatViewGroupsToUpdate);
|
|
}
|
|
|
|
if (fromFlatFieldMetadata.isNullable !== toFlatFieldMetadata.isNullable) {
|
|
const { flatViewGroupsToCreate, flatViewGroupsToDelete } =
|
|
recomputeViewGroupsOnEnumFlatFieldMetadataIsNullableUpdate({
|
|
flatViewMaps,
|
|
flatViewGroupMaps,
|
|
fromFlatFieldMetadata,
|
|
toFlatFieldMetadata,
|
|
});
|
|
|
|
sideEffectResult.flatViewGroupsToCreate.push(...flatViewGroupsToCreate);
|
|
sideEffectResult.flatViewGroupsToDelete.push(...flatViewGroupsToDelete);
|
|
}
|
|
|
|
return sideEffectResult;
|
|
};
|