Add applicationId to syncableEntity and fix syncApp deletion (#15170)
## Context - All flatEntity should extend SyncableEntity - SyncableEntity should now have applicationId and application relation - Fix syncApp deletion, should now properly use migration v2 to delete syncable entities
This commit is contained in:
+1
@@ -4,4 +4,5 @@ import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/f
|
||||
export const EMPTY_FLAT_ENTITY_MAPS = {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
} as const satisfies FlatEntityMaps<FlatEntity>;
|
||||
|
||||
+1
@@ -3,4 +3,5 @@ import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/f
|
||||
export type FlatEntityMaps<T extends FlatEntity> = {
|
||||
byId: Partial<Record<string, T>>;
|
||||
idByUniversalIdentifier: Partial<Record<string, string>>;
|
||||
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>;
|
||||
};
|
||||
|
||||
+20
-2
@@ -1,4 +1,22 @@
|
||||
export interface FlatEntity {
|
||||
import { type SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
|
||||
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
import { type NonNullableProperties } from 'src/types/non-nullable-properties.type';
|
||||
|
||||
export type SyncableEntityRelationProperties =
|
||||
ExtractRecordTypeOrmRelationProperties<SyncableEntity, ApplicationEntity>;
|
||||
|
||||
export interface FlatEntity
|
||||
extends NonNullableProperties<
|
||||
Omit<SyncableEntity, SyncableEntityRelationProperties | 'applicationId'>
|
||||
> {
|
||||
id: string;
|
||||
universalIdentifier: string;
|
||||
applicationId: string | null;
|
||||
}
|
||||
|
||||
export type FlatEntityFrom<
|
||||
TEntity extends SyncableEntity,
|
||||
TEntityRelationProperties extends keyof TEntity,
|
||||
> = FlatEntity &
|
||||
Omit<TEntity, TEntityRelationProperties | SyncableEntityRelationProperties>;
|
||||
|
||||
+16
-1
@@ -1,4 +1,4 @@
|
||||
import { isDefined } from 'class-validator';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
@@ -32,5 +32,20 @@ export const addFlatEntityToFlatEntityMapsOrThrow = <T extends FlatEntity>({
|
||||
...flatEntityMaps.idByUniversalIdentifier,
|
||||
[flatEntity.universalIdentifier]: flatEntity.id,
|
||||
},
|
||||
universalIdentifiersByApplicationId: {
|
||||
...flatEntityMaps.universalIdentifiersByApplicationId,
|
||||
...(isDefined(flatEntity.applicationId)
|
||||
? {
|
||||
[flatEntity.applicationId]: Array.from(
|
||||
new Set([
|
||||
...(flatEntityMaps.universalIdentifiersByApplicationId?.[
|
||||
flatEntity.applicationId
|
||||
] ?? []),
|
||||
flatEntity.universalIdentifier,
|
||||
]),
|
||||
),
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
+27
@@ -1,3 +1,4 @@
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
@@ -31,10 +32,36 @@ export const deleteFlatEntityFromFlatEntityMapsOrThrow = <
|
||||
flatEntityMaps.idByUniversalIdentifier,
|
||||
).filter(([_universalIdentifier, id]) => id !== entityToDeleteId);
|
||||
|
||||
const updatedUniversalIdentifiersByApplicationIdEntries = Object.entries(
|
||||
flatEntityMaps.universalIdentifiersByApplicationId,
|
||||
)
|
||||
.map(([applicationId, universalIdentifiers]) => {
|
||||
const stillPresentUniversalIdentifiers = universalIdentifiers?.filter(
|
||||
(universalIdentifier) =>
|
||||
updatedIdByUniversalIdentifierEntries.some(
|
||||
([existingUniversalIdentifier]) =>
|
||||
existingUniversalIdentifier === universalIdentifier,
|
||||
),
|
||||
);
|
||||
|
||||
if (
|
||||
isDefined(stillPresentUniversalIdentifiers) ||
|
||||
isEmpty(stillPresentUniversalIdentifiers)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return [applicationId, stillPresentUniversalIdentifiers];
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
return {
|
||||
byId: removePropertiesFromRecord(flatEntityMaps.byId, [entityToDeleteId]),
|
||||
idByUniversalIdentifier: Object.fromEntries(
|
||||
updatedIdByUniversalIdentifierEntries,
|
||||
),
|
||||
universalIdentifiersByApplicationId: Object.fromEntries(
|
||||
updatedUniversalIdentifiersByApplicationIdEntries,
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
|
||||
export const getFlatEntitiesByApplicationId = <T extends FlatEntity>(
|
||||
maps: FlatEntityMaps<T>,
|
||||
applicationId: string,
|
||||
): T[] => {
|
||||
const universalIdentifiers =
|
||||
maps.universalIdentifiersByApplicationId[applicationId];
|
||||
|
||||
if (!isDefined(universalIdentifiers)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return universalIdentifiers
|
||||
.map((universalId) => {
|
||||
const id = maps.idByUniversalIdentifier[universalId];
|
||||
|
||||
if (!isDefined(id)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const entity = maps.byId[id];
|
||||
|
||||
if (!isDefined(entity)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (entity.applicationId !== applicationId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return entity;
|
||||
})
|
||||
.filter(isDefined);
|
||||
};
|
||||
Reference in New Issue
Block a user