Refactor flat entity maps to be universal oriented (#17665)
# Introduction
In preparation of the workspace agnostic builder, we're migrating
`FlatEntityMaps` to be universal identifier oriented and based
As in the builder context there're won't be any ids at all
Please also note that the FlatEntity is a UniversalFlatEntity superset
From
```ts
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
export type FlatEntityMaps<T extends SyncableFlatEntity> = {
byId: Partial<Record<string, T>>;
idByUniversalIdentifier: Partial<Record<string, string>>;
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>;
};
```
To
```ts
export type FlatEntityMaps<
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
> = {
byUniversalIdentifier: Partial<Record<string, T>>;
universalIdentifierById: Partial<Record<string, string>>;
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>; // this might make more sense to be migrated to universalIdentifiersByApplicationUniversalIdentifier but it's the main topic of this PR
};
```
## Low level maps tools
Had to refactor find | create | delete | replace | find-many | get-sub
tools ( through mutations and or throw equivalent )
This commit is contained in:
+13
-7
@@ -4,6 +4,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
@@ -72,21 +73,26 @@ describe('addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow',
|
||||
});
|
||||
|
||||
expect(
|
||||
flatEntityAndRelatedMapsToMutate.flatViewMaps.byId[mockView.id],
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockView.id,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatViewMaps,
|
||||
}),
|
||||
).toMatchObject(mockView);
|
||||
|
||||
expect(
|
||||
flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps.byId[
|
||||
objectMetadataId
|
||||
],
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatObjectMetadata>>({
|
||||
viewIds: [mockView.id],
|
||||
});
|
||||
|
||||
expect(
|
||||
flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps.byId[
|
||||
mockFieldMetadata.id
|
||||
],
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockFieldMetadata.id,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatFieldMetadata>>({
|
||||
calendarViewIds: [mockView.id],
|
||||
});
|
||||
|
||||
+13
-7
@@ -4,6 +4,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
@@ -82,21 +83,26 @@ describe('deleteFlatEntityFromFlatEntityAndRelatedEntityMapsThroughMutationOrThr
|
||||
});
|
||||
|
||||
expect(
|
||||
flatEntityAndRelatedMapsToMutate.flatViewMaps.byId[viewId],
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: viewId,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatViewMaps,
|
||||
}),
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps.byId[
|
||||
objectMetadataId
|
||||
],
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatObjectMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatObjectMetadata>>({
|
||||
viewIds: ['something-else'],
|
||||
});
|
||||
|
||||
expect(
|
||||
flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps.byId[
|
||||
mockFieldMetadata.id
|
||||
],
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: mockFieldMetadata.id,
|
||||
flatEntityMaps: flatEntityAndRelatedMapsToMutate.flatFieldMetadataMaps,
|
||||
}),
|
||||
).toMatchObject<Partial<FlatFieldMetadata>>({
|
||||
calendarViewIds: [],
|
||||
});
|
||||
|
||||
+11
-7
@@ -18,7 +18,11 @@ export const addFlatEntityToFlatEntityMapsOrThrow = <
|
||||
flatEntity,
|
||||
flatEntityMaps,
|
||||
}: AddFlatEntityToFlatEntityMapsOrThrowArgs<T>): FlatEntityMaps<T> => {
|
||||
if (isDefined(flatEntityMaps.byId[flatEntity.id])) {
|
||||
if (
|
||||
isDefined(
|
||||
flatEntityMaps.byUniversalIdentifier[flatEntity.universalIdentifier],
|
||||
)
|
||||
) {
|
||||
throw new FlatEntityMapsException(
|
||||
'addFlatEntityToFlatEntityMapsOrThrow: flat entity to add already exists',
|
||||
FlatEntityMapsExceptionCode.ENTITY_ALREADY_EXISTS,
|
||||
@@ -26,13 +30,13 @@ export const addFlatEntityToFlatEntityMapsOrThrow = <
|
||||
}
|
||||
|
||||
return {
|
||||
byId: {
|
||||
...flatEntityMaps.byId,
|
||||
[flatEntity.id]: flatEntity,
|
||||
byUniversalIdentifier: {
|
||||
...flatEntityMaps.byUniversalIdentifier,
|
||||
[flatEntity.universalIdentifier]: flatEntity,
|
||||
},
|
||||
idByUniversalIdentifier: {
|
||||
...flatEntityMaps.idByUniversalIdentifier,
|
||||
[flatEntity.universalIdentifier]: flatEntity.id,
|
||||
universalIdentifierById: {
|
||||
...flatEntityMaps.universalIdentifierById,
|
||||
[flatEntity.id]: flatEntity.universalIdentifier,
|
||||
},
|
||||
universalIdentifiersByApplicationId: {
|
||||
...flatEntityMaps.universalIdentifiersByApplicationId,
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { type FlatEntityToCreateDeleteUpdate } from 'src/engine/metadata-modules
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityByIdsMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-by-ids-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
|
||||
export type ComputeFlatEntityMapsFromToArgs<T extends AllMetadataName> = {
|
||||
@@ -21,7 +21,7 @@ export const computeFlatEntityMapsFromTo = <T extends AllMetadataName>({
|
||||
} => {
|
||||
const fromFlatEntityMaps =
|
||||
flatEntityToDelete.length > 0
|
||||
? getSubFlatEntityMapsOrThrow({
|
||||
? getSubFlatEntityByIdsMapsOrThrow({
|
||||
flatEntityIds: [...flatEntityToDelete, ...flatEntityToUpdate].map(
|
||||
({ id }) => id,
|
||||
),
|
||||
|
||||
+14
-11
@@ -21,16 +21,19 @@ export const deleteFlatEntityFromFlatEntityMapsOrThrow = <
|
||||
flatEntityMaps,
|
||||
entityToDeleteId,
|
||||
}: DeleteFlatEntityFromFlatEntityMapsOrThrowArgs<T>): FlatEntityMaps<T> => {
|
||||
if (!isDefined(flatEntityMaps.byId[entityToDeleteId])) {
|
||||
const universalIdentifierToDelete =
|
||||
flatEntityMaps.universalIdentifierById[entityToDeleteId];
|
||||
|
||||
if (!isDefined(universalIdentifierToDelete)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'deleteFlatEntityFromFlatEntityMapsOrThrow: entity to delete not found',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedIdByUniversalIdentifierEntries = Object.entries(
|
||||
flatEntityMaps.idByUniversalIdentifier,
|
||||
).filter(([_universalIdentifier, id]) => id !== entityToDeleteId);
|
||||
const updatedUniversalIdentifierByIdEntries = Object.entries(
|
||||
flatEntityMaps.universalIdentifierById,
|
||||
).filter(([id]) => id !== entityToDeleteId);
|
||||
|
||||
const updatedUniversalIdentifiersByApplicationIdEntries = Object.entries(
|
||||
flatEntityMaps.universalIdentifiersByApplicationId,
|
||||
@@ -38,10 +41,7 @@ export const deleteFlatEntityFromFlatEntityMapsOrThrow = <
|
||||
.map(([applicationId, universalIdentifiers]) => {
|
||||
const stillPresentUniversalIdentifiers = universalIdentifiers?.filter(
|
||||
(universalIdentifier) =>
|
||||
updatedIdByUniversalIdentifierEntries.some(
|
||||
([existingUniversalIdentifier]) =>
|
||||
existingUniversalIdentifier === universalIdentifier,
|
||||
),
|
||||
universalIdentifier !== universalIdentifierToDelete,
|
||||
);
|
||||
|
||||
if (
|
||||
@@ -56,9 +56,12 @@ export const deleteFlatEntityFromFlatEntityMapsOrThrow = <
|
||||
.filter(isDefined);
|
||||
|
||||
return {
|
||||
byId: removePropertiesFromRecord(flatEntityMaps.byId, [entityToDeleteId]),
|
||||
idByUniversalIdentifier: Object.fromEntries(
|
||||
updatedIdByUniversalIdentifierEntries,
|
||||
byUniversalIdentifier: removePropertiesFromRecord(
|
||||
flatEntityMaps.byUniversalIdentifier,
|
||||
[universalIdentifierToDelete],
|
||||
),
|
||||
universalIdentifierById: Object.fromEntries(
|
||||
updatedUniversalIdentifierByIdEntries,
|
||||
),
|
||||
universalIdentifiersByApplicationId: Object.fromEntries(
|
||||
updatedUniversalIdentifiersByApplicationIdEntries,
|
||||
|
||||
+1
-7
@@ -19,13 +19,7 @@ export const findFlatEntitiesByApplicationId = <T extends SyncableFlatEntity>({
|
||||
|
||||
return universalIdentifiers
|
||||
.map((universalId) => {
|
||||
const id = flatEntityMaps.idByUniversalIdentifier[universalId];
|
||||
|
||||
if (!isDefined(id)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const entity = flatEntityMaps.byId[id];
|
||||
const entity = flatEntityMaps.byUniversalIdentifier[universalId];
|
||||
|
||||
if (!isDefined(entity)) {
|
||||
return undefined;
|
||||
|
||||
+11
-1
@@ -20,7 +20,17 @@ export const findFlatEntityByIdInFlatEntityMapsOrThrow = <
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
}: FindFlatEntityByIdInFlatEntityMapsOrThrowArgs<T>): T => {
|
||||
const flatEntity = flatEntityMaps.byId[flatEntityId];
|
||||
const universalIdentifier =
|
||||
flatEntityMaps.universalIdentifierById[flatEntityId];
|
||||
|
||||
if (!isDefined(universalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
t`Could not find flat entity in maps`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const flatEntity = flatEntityMaps.byUniversalIdentifier[universalIdentifier];
|
||||
|
||||
if (!isDefined(flatEntity)) {
|
||||
throw new FlatEntityMapsException(
|
||||
|
||||
+2
-18
@@ -1,5 +1,3 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
|
||||
@@ -11,20 +9,6 @@ export const findFlatEntityByUniversalIdentifier = <
|
||||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): (T & { id: string }) | undefined => {
|
||||
const flatEntityId =
|
||||
flatEntityMaps.idByUniversalIdentifier[universalIdentifier];
|
||||
|
||||
if (!isDefined(flatEntityId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = flatEntityMaps.byId[flatEntityId];
|
||||
|
||||
return isDefined(result)
|
||||
? {
|
||||
...result,
|
||||
id: flatEntityId,
|
||||
}
|
||||
: undefined;
|
||||
}): T | undefined => {
|
||||
return flatEntityMaps.byUniversalIdentifier[universalIdentifier];
|
||||
};
|
||||
|
||||
+5
-3
@@ -2,7 +2,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { getSubFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityByIdsMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-by-ids-maps-or-throw.util';
|
||||
|
||||
export type FindManyFlatEntityByIdInFlatEntityMapsOrThrowArgs<
|
||||
T extends SyncableFlatEntity,
|
||||
@@ -16,10 +16,12 @@ export const findManyFlatEntityByIdInFlatEntityMapsOrThrow = <
|
||||
flatEntityMaps,
|
||||
flatEntityIds,
|
||||
}: FindManyFlatEntityByIdInFlatEntityMapsOrThrowArgs<T>): T[] => {
|
||||
const subFlatEntityMaps = getSubFlatEntityMapsOrThrow<T>({
|
||||
const subFlatEntityMaps = getSubFlatEntityByIdsMapsOrThrow<T>({
|
||||
flatEntityIds,
|
||||
flatEntityMaps,
|
||||
});
|
||||
|
||||
return Object.values(subFlatEntityMaps.byId).filter(isDefined);
|
||||
return Object.values(subFlatEntityMaps.byUniversalIdentifier).filter(
|
||||
isDefined,
|
||||
);
|
||||
};
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
|
||||
export type FindManyFlatEntityByIdInFlatEntityMapsArgs<
|
||||
T extends SyncableFlatEntity,
|
||||
> = {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
flatEntityIds: string[];
|
||||
};
|
||||
|
||||
export const findManyFlatEntityByIdInFlatEntityMaps = <
|
||||
T extends SyncableFlatEntity,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
flatEntityIds,
|
||||
}: FindManyFlatEntityByIdInFlatEntityMapsArgs<T>): T[] => {
|
||||
return flatEntityIds
|
||||
.map((flatEntityId) =>
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId,
|
||||
flatEntityMaps,
|
||||
}),
|
||||
)
|
||||
.filter(isDefined);
|
||||
};
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/typ
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
|
||||
export const getSubFlatEntityMapsOrThrow = <T extends SyncableFlatEntity>({
|
||||
export const getSubFlatEntityByIdsMapsOrThrow = <T extends SyncableFlatEntity>({
|
||||
flatEntityIds,
|
||||
flatEntityMaps,
|
||||
}: {
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntitiesByApplicationId } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entities-by-application-id.util';
|
||||
import { getSubFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-maps-or-throw.util';
|
||||
import { getSubFlatEntityByIdsMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/get-sub-flat-entity-by-ids-maps-or-throw.util';
|
||||
|
||||
export const getSubFlatEntityMapsByApplicationIdOrThrow = <
|
||||
T extends SyncableFlatEntity,
|
||||
@@ -17,7 +17,7 @@ export const getSubFlatEntityMapsByApplicationIdOrThrow = <
|
||||
flatEntityMaps,
|
||||
});
|
||||
|
||||
return getSubFlatEntityMapsOrThrow({
|
||||
return getSubFlatEntityByIdsMapsOrThrow({
|
||||
flatEntityIds: allApplicationFlatEntity.map((flatEntity) => flatEntity.id),
|
||||
flatEntityMaps,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user