[REQUIRES_FULL_CACHE_FLUSH_WHEN_RELEASED] Refactor FlatEntity to be UniversalFlatEntity superset (#17452)
# Introduction
In this PR we're refactoring the `FlatEntity` type to become a superset
of the `UniversalFlatEntity`.
Right now we're storing all the extra properties in `__universal`
property, at some point it might just be sibling to other entity and we
might rely on the `propertiesToCompare` constants and TypeScript
allowing passing a superset type into a smaller subset type
## FromTo utils
The entity to flat entity method now computes the universal information,
standardized a typing and pattern to do
## Example
Also strictly type
```ts
"bbb019ea-6205-498c-aea5-67bc53bce8a9": {
"workspaceId": "20202020-1c25-4d02-bf25-6aeccf7ea419",
"universalIdentifier": "20202020-d111-4d11-8d11-da5ab0a11002",
"applicationId": "d01b010d-b984-465b-b40b-370e954e5188",
"id": "bbb019ea-6205-498c-aea5-67bc53bce8a9",
"pageLayoutTabId": "791a512f-169f-4209-b731-aa86716668c6",
"title": "Deals by Company",
"type": "GRAPH",
"objectMetadataId": "9e14efea-df5b-4c0e-aba9-cfe455f32397",
"gridPosition": { "row": 0, "column": 6, "rowSpan": 6, "columnSpan": 6 },
"configuration": {
"color": "orange",
"orderBy": "FIELD_ASC",
"timezone": "UTC",
"displayLegend": true,
"displayDataLabel": false,
"showCenterMetric": true,
"configurationType": "PIE_CHART",
"firstDayOfTheWeek": 0,
"aggregateOperation": "COUNT",
"groupBySubFieldName": "name",
"groupByFieldMetadataId": "6673ff18-63d2-47a1-8f85-2b9b09ca27a5",
"aggregateFieldMetadataId": "8d64ee41-5dd4-4de6-945a-7c0c18399715"
},
"createdAt": "2026-01-28T14:08:52.140Z",
"updatedAt": "2026-01-28T14:08:52.140Z",
"deletedAt": null,
"__universal": {
"universalIdentifier": "20202020-d111-4d11-8d11-da5ab0a11002",
"applicationUniversalIdentifier": "20202020-64aa-4b6f-b003-9c74b97cee20",
"pageLayoutTabUniversalIdentifier": "20202020-d011-4d11-8d11-da5ab0a01001",
"objectMetadataUniversalIdentifier": "20202020-9549-49dd-b2b2-883999db8938",
"gridPosition": {
"row": 0,
"column": 6,
"rowSpan": 6,
"columnSpan": 6
},
"configuration": {
"color": "orange",
"orderBy": "FIELD_ASC",
"timezone": "UTC",
"displayLegend": true,
"displayDataLabel": false,
"showCenterMetric": true,
"configurationType": "PIE_CHART",
"firstDayOfTheWeek": 0,
"aggregateOperation": "COUNT",
"groupBySubFieldName": "name",
"aggregateFieldMetadataUniversalIdentifier": "20202020-d01a-4131-8a31-f123456789ab",
"groupByFieldMetadataUniversalIdentifier": "20202020-cbac-457e-b565-adece5fc815f"
}
}
},
```
This commit is contained in:
+78
-30
@@ -1,36 +1,84 @@
|
||||
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
|
||||
import { type RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
|
||||
import { type EntityManyToOneIdByUniversalIdentifierMaps } from 'src/engine/workspace-cache/types/entity-many-to-one-id-by-universal-identifier-maps.type';
|
||||
import { type EntityWithRegroupedOneToManyRelations } from 'src/engine/workspace-cache/types/entity-with-regrouped-one-to-many-relations.type';
|
||||
import { type RegroupedEntity } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
|
||||
|
||||
type FromRoleEntityToFlatRoleArgs = {
|
||||
entity: Omit<
|
||||
EntityWithRegroupedOneToManyRelations<MetadataEntity<'role'>>,
|
||||
'objectPermissions' | 'permissionFlags' | 'fieldPermissions'
|
||||
> & {
|
||||
objectPermissions: RegroupedEntity[];
|
||||
permissionFlags: RegroupedEntity[];
|
||||
fieldPermissions: RegroupedEntity[];
|
||||
};
|
||||
} & EntityManyToOneIdByUniversalIdentifierMaps<'role'>;
|
||||
|
||||
export const fromRoleEntityToFlatRole = ({
|
||||
entity: roleEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
}: FromRoleEntityToFlatRoleArgs): FlatRole => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(roleEntity.applicationId);
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${roleEntity.applicationId} not found for role ${roleEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
export const fromRoleEntityToFlatRole = (role: RoleEntity): FlatRole => {
|
||||
return {
|
||||
id: role.id,
|
||||
standardId: role.standardId,
|
||||
label: role.label,
|
||||
description: role.description,
|
||||
icon: role.icon,
|
||||
isEditable: role.isEditable,
|
||||
canUpdateAllSettings: role.canUpdateAllSettings,
|
||||
canAccessAllTools: role.canAccessAllTools,
|
||||
canReadAllObjectRecords: role.canReadAllObjectRecords,
|
||||
canUpdateAllObjectRecords: role.canUpdateAllObjectRecords,
|
||||
canSoftDeleteAllObjectRecords: role.canSoftDeleteAllObjectRecords,
|
||||
canDestroyAllObjectRecords: role.canDestroyAllObjectRecords,
|
||||
canBeAssignedToUsers: role.canBeAssignedToUsers,
|
||||
canBeAssignedToAgents: role.canBeAssignedToAgents,
|
||||
canBeAssignedToApiKeys: role.canBeAssignedToApiKeys,
|
||||
workspaceId: role.workspaceId,
|
||||
createdAt: role.createdAt.toISOString(),
|
||||
updatedAt: role.updatedAt.toISOString(),
|
||||
universalIdentifier: role.universalIdentifier,
|
||||
applicationId: role.applicationId,
|
||||
roleTargetIds: role.roleTargets.map((rt) => rt.id),
|
||||
objectPermissionIds: role.objectPermissions.map((op) => op.id),
|
||||
permissionFlagIds: role.permissionFlags.map((pf) => pf.id),
|
||||
fieldPermissionIds: role.fieldPermissions.map((fp) => fp.id),
|
||||
rowLevelPermissionPredicateIds: role.rowLevelPermissionPredicates.map(
|
||||
(rp) => rp.id,
|
||||
id: roleEntity.id,
|
||||
standardId: roleEntity.standardId,
|
||||
label: roleEntity.label,
|
||||
description: roleEntity.description,
|
||||
icon: roleEntity.icon,
|
||||
isEditable: roleEntity.isEditable,
|
||||
canUpdateAllSettings: roleEntity.canUpdateAllSettings,
|
||||
canAccessAllTools: roleEntity.canAccessAllTools,
|
||||
canReadAllObjectRecords: roleEntity.canReadAllObjectRecords,
|
||||
canUpdateAllObjectRecords: roleEntity.canUpdateAllObjectRecords,
|
||||
canSoftDeleteAllObjectRecords: roleEntity.canSoftDeleteAllObjectRecords,
|
||||
canDestroyAllObjectRecords: roleEntity.canDestroyAllObjectRecords,
|
||||
canBeAssignedToUsers: roleEntity.canBeAssignedToUsers,
|
||||
canBeAssignedToAgents: roleEntity.canBeAssignedToAgents,
|
||||
canBeAssignedToApiKeys: roleEntity.canBeAssignedToApiKeys,
|
||||
workspaceId: roleEntity.workspaceId,
|
||||
createdAt: roleEntity.createdAt.toISOString(),
|
||||
updatedAt: roleEntity.updatedAt.toISOString(),
|
||||
universalIdentifier: roleEntity.universalIdentifier,
|
||||
applicationId: roleEntity.applicationId,
|
||||
roleTargetIds: roleEntity.roleTargets.map(({ id }) => id),
|
||||
objectPermissionIds: roleEntity.objectPermissions.map(({ id }) => id),
|
||||
permissionFlagIds: roleEntity.permissionFlags.map(({ id }) => id),
|
||||
fieldPermissionIds: roleEntity.fieldPermissions.map(({ id }) => id),
|
||||
rowLevelPermissionPredicateIds: roleEntity.rowLevelPermissionPredicates.map(
|
||||
({ id }) => id,
|
||||
),
|
||||
rowLevelPermissionPredicateGroupIds:
|
||||
role.rowLevelPermissionPredicateGroups.map((rp) => rp.id),
|
||||
roleEntity.rowLevelPermissionPredicateGroups.map(({ id }) => id),
|
||||
__universal: {
|
||||
universalIdentifier: roleEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleTargetUniversalIdentifiers: roleEntity.roleTargets.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
rowLevelPermissionPredicateUniversalIdentifiers:
|
||||
roleEntity.rowLevelPermissionPredicates.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifiers:
|
||||
roleEntity.rowLevelPermissionPredicateGroups.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user