Refactor workspace migration update action (#17701)
# 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);
};
```
This commit is contained in:
+7
-15
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a created entity 1`] = `
|
||||
{
|
||||
@@ -152,13 +152,9 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect an upd
|
||||
"byUniversalIdentifier": {
|
||||
"universal-identifier-1": {
|
||||
"id": "field-id-1",
|
||||
"updates": [
|
||||
{
|
||||
"from": false,
|
||||
"property": "isActive",
|
||||
"to": true,
|
||||
},
|
||||
],
|
||||
"update": {
|
||||
"isActive": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -281,13 +277,9 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
|
||||
"byUniversalIdentifier": {
|
||||
"universal-identifier-1": {
|
||||
"id": "field-id-1",
|
||||
"updates": [
|
||||
{
|
||||
"from": true,
|
||||
"property": "isActive",
|
||||
"to": false,
|
||||
},
|
||||
],
|
||||
"update": {
|
||||
"isActive": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+9
-21
@@ -21,37 +21,25 @@ describe('aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldA
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalIdentifier: 'search-vector-field-1',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
from: 'Search Vector',
|
||||
to: 'Updated Search Vector',
|
||||
},
|
||||
],
|
||||
update: {
|
||||
label: 'Updated Search Vector',
|
||||
},
|
||||
} satisfies UniversalUpdateFieldAction,
|
||||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalIdentifier: 'regular-field-1',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
from: 'First Name',
|
||||
to: 'Updated First Name',
|
||||
},
|
||||
],
|
||||
update: {
|
||||
label: 'Updated First Name',
|
||||
},
|
||||
} satisfies UniversalUpdateFieldAction,
|
||||
{
|
||||
type: 'update',
|
||||
metadataName: 'fieldMetadata',
|
||||
universalIdentifier: 'regular-field-2',
|
||||
updates: [
|
||||
{
|
||||
property: 'label',
|
||||
from: 'Last Name',
|
||||
to: 'Updated Last Name',
|
||||
},
|
||||
],
|
||||
update: {
|
||||
label: 'Updated Last Name',
|
||||
},
|
||||
} satisfies UniversalUpdateFieldAction,
|
||||
],
|
||||
delete: [],
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type';
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type FlatEntityPropertyUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-property-update.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { isPropertyUpdate } from 'src/engine/workspace-manager/workspace-migration/utils/is-property-update.util';
|
||||
|
||||
export const findFlatEntityPropertyUpdate = <
|
||||
T extends AllMetadataName,
|
||||
P extends Extract<
|
||||
FlatEntityPropertiesToCompare<T>,
|
||||
keyof MetadataFlatEntity<T>
|
||||
>,
|
||||
>({
|
||||
property,
|
||||
flatEntityUpdates,
|
||||
}: {
|
||||
flatEntityUpdates: FlatEntityPropertiesUpdates<T>;
|
||||
property: P;
|
||||
}) =>
|
||||
flatEntityUpdates.find((update): update is FlatEntityPropertyUpdate<T, P> =>
|
||||
isPropertyUpdate(update, property),
|
||||
);
|
||||
+5
-5
@@ -6,7 +6,7 @@ import { ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { type FlatEntityPropertiesToCompare } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-compare.type';
|
||||
import { type FlatEntityPropertiesToStringify } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-to-stringify.type';
|
||||
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type FlatEntityUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
|
||||
import { compareTwoFlatEntity } from 'src/engine/metadata-modules/flat-entity/utils/compare-two-flat-entity.util';
|
||||
@@ -21,7 +21,7 @@ export type DeletedCreatedUpdatedMatrix<T extends AllMetadataName> = {
|
||||
byUniversalIdentifier: Record<
|
||||
string,
|
||||
{
|
||||
updates: FlatEntityPropertiesUpdates<T>;
|
||||
update: FlatEntityUpdate<T>;
|
||||
// TMP remove when maps is universal based
|
||||
id: string;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = <
|
||||
if (!isDefined(toFlatEntity)) {
|
||||
continue;
|
||||
}
|
||||
const updates = compareTwoFlatEntity({
|
||||
const update = compareTwoFlatEntity({
|
||||
fromFlatEntity,
|
||||
toFlatEntity,
|
||||
propertiesToCompare: propertiesToCompare as unknown as Extract<
|
||||
@@ -101,7 +101,7 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = <
|
||||
>[],
|
||||
});
|
||||
|
||||
if (updates.length === 0) {
|
||||
if (!isDefined(update)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export const flatEntityDeletedCreatedUpdatedMatrixDispatcher = <
|
||||
fromFlatEntity.universalIdentifier
|
||||
] = {
|
||||
id: toFlatEntity.id,
|
||||
updates,
|
||||
update,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration/types/property-update.type';
|
||||
|
||||
export const isPropertyUpdate = <T, P extends keyof T>(
|
||||
update: PropertyUpdate<T, keyof T>,
|
||||
property: P,
|
||||
): update is PropertyUpdate<T, P> => {
|
||||
return update.property === property;
|
||||
};
|
||||
Reference in New Issue
Block a user