= {
+ [K in keyof OneToManyRelations]: OneToManyRelations[K] extends {
+ universalFlatEntityForeignKeyAggregator: infer Agg extends string;
}
- ? Agg extends string
- ? Agg
- : never
+ ? Agg
: never;
-}[keyof ManyToOneRelations];
+}[keyof OneToManyRelations];
export type ExtractUniversalForeignKeyAggregatorForMetadataName<
T extends AllMetadataName,
-> = {
- [M in AllMetadataName]: ExtractForeignKeyAggregatorFromManyToOneRelations<
- (typeof ALL_UNIVERSAL_METADATA_RELATIONS)[M]['manyToOne'],
- T
- >;
-}[AllMetadataName];
+> = ExtractUniversalForeignKeyAggregators<
+ (typeof ALL_ONE_TO_MANY_METADATA_RELATIONS)[T]
+>;
type UniversalFlatEntityForeignKeyAggregatorProperties = {
[P in AllMetadataName]: ExtractUniversalForeignKeyAggregatorForMetadataName[];
@@ -36,25 +27,20 @@ type UniversalFlatEntityForeignKeyAggregatorProperties = {
const computeForeignKeyAggregatorProperties = (
metadataName: T,
): ExtractUniversalForeignKeyAggregatorForMetadataName[] => {
+ const oneToManyRelations = ALL_ONE_TO_MANY_METADATA_RELATIONS[metadataName];
+
const aggregatorProperties: ExtractUniversalForeignKeyAggregatorForMetadataName[] =
[];
- for (const relationsEntry of Object.values(
- ALL_UNIVERSAL_METADATA_RELATIONS,
- )) {
- for (const relation of Object.values(relationsEntry.manyToOne)) {
- if (!isDefined(relation)) {
- continue;
- }
+ for (const relation of Object.values(oneToManyRelations)) {
+ if (!isDefined(relation)) {
+ continue;
+ }
- if (
- relation.metadataName === metadataName &&
- isDefined(relation.universalFlatEntityForeignKeyAggregator)
- ) {
- aggregatorProperties.push(
- relation.universalFlatEntityForeignKeyAggregator as ExtractUniversalForeignKeyAggregatorForMetadataName,
- );
- }
+ if (isDefined(relation.universalFlatEntityForeignKeyAggregator)) {
+ aggregatorProperties.push(
+ relation.universalFlatEntityForeignKeyAggregator as ExtractUniversalForeignKeyAggregatorForMetadataName,
+ );
}
}
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant.ts
deleted file mode 100644
index ae6581c9fe7..00000000000
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant.ts
+++ /dev/null
@@ -1,543 +0,0 @@
-import { type AllMetadataName } from 'twenty-shared/metadata';
-
-import { type ALL_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
-
-export type ToUniversalForeignKey =
- T extends `${infer Prefix}Id` ? `${Prefix}UniversalIdentifier` : never;
-
-type ToUniversalAggregator = T extends `${infer Prefix}Ids`
- ? `${Prefix}UniversalIdentifiers`
- : never;
-
-export type ToUniversalMetadataManyToOneRelationConfiguration = T extends {
- metadataName: infer M extends AllMetadataName;
- foreignKey: infer FK extends string;
- flatEntityForeignKeyAggregator: infer Agg;
- isNullable: infer N extends boolean;
-}
- ? {
- metadataName: M;
- foreignKey: FK;
- universalForeignKey: ToUniversalForeignKey;
- universalFlatEntityForeignKeyAggregator: Agg extends string
- ? ToUniversalAggregator
- : null;
- isNullable: N;
- }
- : null;
-
-type ToUniversalManyToOneRelations = {
- [K in keyof T]: ToUniversalMetadataManyToOneRelationConfiguration;
-};
-
-type ToUniversalOneToManyRelations = T;
-
-export type UniversalMetadataRelationsProperties = {
- [M in AllMetadataName]: {
- manyToOne: ToUniversalManyToOneRelations<
- (typeof ALL_METADATA_RELATIONS)[M]['manyToOne']
- >;
- oneToMany: ToUniversalOneToManyRelations<
- (typeof ALL_METADATA_RELATIONS)[M]['oneToMany']
- >;
- };
-};
-
-export const ALL_UNIVERSAL_METADATA_RELATIONS = {
- agent: {
- manyToOne: {
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- skill: {
- manyToOne: {
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- commandMenuItem: {
- manyToOne: {
- workspace: null,
- application: null,
- availabilityObjectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'availabilityObjectMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'availabilityObjectMetadataUniversalIdentifier',
- isNullable: true,
- },
- frontComponent: {
- metadataName: 'frontComponent',
- foreignKey: 'frontComponentId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'frontComponentUniversalIdentifier',
- isNullable: true,
- },
- },
- oneToMany: {},
- },
- navigationMenuItem: {
- manyToOne: {
- workspace: null,
- userWorkspace: null,
- application: null,
- targetObjectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'targetObjectMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'targetObjectMetadataUniversalIdentifier',
- isNullable: true,
- },
- folder: {
- metadataName: 'navigationMenuItem',
- foreignKey: 'folderId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'folderUniversalIdentifier',
- isNullable: true,
- },
- view: {
- metadataName: 'view',
- foreignKey: 'viewId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'viewUniversalIdentifier',
- isNullable: true,
- },
- },
- oneToMany: {},
- },
- fieldMetadata: {
- manyToOne: {
- object: {
- metadataName: 'objectMetadata',
- foreignKey: 'objectMetadataId',
- universalFlatEntityForeignKeyAggregator: 'fieldUniversalIdentifiers',
- universalForeignKey: 'objectMetadataUniversalIdentifier',
- isNullable: false,
- },
- workspace: null,
- application: null,
- relationTargetFieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'relationTargetFieldMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'relationTargetFieldMetadataUniversalIdentifier',
- isNullable: true,
- },
- relationTargetObjectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'relationTargetObjectMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'relationTargetObjectMetadataUniversalIdentifier',
- isNullable: true,
- },
- },
- oneToMany: {
- fieldPermissions: null,
- indexFieldMetadatas: null,
- viewFields: { metadataName: 'viewField' },
- viewFilters: { metadataName: 'viewFilter' },
- kanbanAggregateOperationViews: { metadataName: 'view' },
- calendarViews: { metadataName: 'view' },
- mainGroupByFieldMetadataViews: { metadataName: 'view' },
- },
- },
- objectMetadata: {
- manyToOne: {
- dataSource: null,
- workspace: null,
- application: null,
- },
- oneToMany: {
- fields: { metadataName: 'fieldMetadata' },
- indexMetadatas: { metadataName: 'index' },
- targetRelationFields: { metadataName: 'fieldMetadata' },
- objectPermissions: null,
- fieldPermissions: null,
- views: { metadataName: 'view' },
- },
- },
- view: {
- manyToOne: {
- objectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'objectMetadataId',
- universalFlatEntityForeignKeyAggregator: 'viewUniversalIdentifiers',
- universalForeignKey: 'objectMetadataUniversalIdentifier',
- isNullable: false,
- },
- workspace: null,
- createdBy: null,
- application: null,
- calendarFieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'calendarFieldMetadataId',
- universalFlatEntityForeignKeyAggregator:
- 'calendarViewUniversalIdentifiers',
- universalForeignKey: 'calendarFieldMetadataUniversalIdentifier',
- isNullable: true,
- },
- kanbanAggregateOperationFieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'kanbanAggregateOperationFieldMetadataId',
- universalFlatEntityForeignKeyAggregator:
- 'kanbanAggregateOperationViewUniversalIdentifiers',
- universalForeignKey:
- 'kanbanAggregateOperationFieldMetadataUniversalIdentifier',
- isNullable: true,
- },
- mainGroupByFieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'mainGroupByFieldMetadataId',
- universalFlatEntityForeignKeyAggregator:
- 'mainGroupByFieldMetadataViewUniversalIdentifiers',
- universalForeignKey: 'mainGroupByFieldMetadataUniversalIdentifier',
- isNullable: true,
- },
- },
- oneToMany: {
- viewFields: { metadataName: 'viewField' },
- viewFilters: { metadataName: 'viewFilter' },
- viewFilterGroups: { metadataName: 'viewFilterGroup' },
- viewGroups: { metadataName: 'viewGroup' },
- viewFieldGroups: { metadataName: 'viewFieldGroup' },
- // TODO migrate viewSort to v2
- viewSorts: null,
- },
- },
- viewField: {
- manyToOne: {
- fieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'fieldMetadataId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFieldUniversalIdentifiers',
- universalForeignKey: 'fieldMetadataUniversalIdentifier',
- isNullable: false,
- },
- view: {
- metadataName: 'view',
- foreignKey: 'viewId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFieldUniversalIdentifiers',
- universalForeignKey: 'viewUniversalIdentifier',
- isNullable: false,
- },
- viewFieldGroup: {
- metadataName: 'viewFieldGroup',
- foreignKey: 'viewFieldGroupId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFieldUniversalIdentifiers',
- universalForeignKey: 'viewFieldGroupUniversalIdentifier',
- isNullable: true,
- },
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- viewFieldGroup: {
- manyToOne: {
- view: {
- metadataName: 'view',
- foreignKey: 'viewId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFieldGroupUniversalIdentifiers',
- universalForeignKey: 'viewUniversalIdentifier',
- isNullable: false,
- },
- workspace: null,
- application: null,
- },
- oneToMany: {
- viewFields: { metadataName: 'viewField' },
- },
- },
- viewFilter: {
- manyToOne: {
- fieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'fieldMetadataId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFilterUniversalIdentifiers',
- universalForeignKey: 'fieldMetadataUniversalIdentifier',
- isNullable: false,
- },
- view: {
- metadataName: 'view',
- foreignKey: 'viewId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFilterUniversalIdentifiers',
- universalForeignKey: 'viewUniversalIdentifier',
- isNullable: false,
- },
- viewFilterGroup: {
- metadataName: 'viewFilterGroup',
- foreignKey: 'viewFilterGroupId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFilterUniversalIdentifiers',
- universalForeignKey: 'viewFilterGroupUniversalIdentifier',
- isNullable: true,
- },
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- viewGroup: {
- manyToOne: {
- view: {
- metadataName: 'view',
- foreignKey: 'viewId',
- universalFlatEntityForeignKeyAggregator:
- 'viewGroupUniversalIdentifiers',
- universalForeignKey: 'viewUniversalIdentifier',
- isNullable: false,
- },
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- index: {
- manyToOne: {
- objectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'objectMetadataId',
- universalFlatEntityForeignKeyAggregator:
- 'indexMetadataUniversalIdentifiers',
- universalForeignKey: 'objectMetadataUniversalIdentifier',
- isNullable: false,
- },
- workspace: null,
- application: null,
- },
- oneToMany: {
- indexFieldMetadatas: null,
- },
- },
- logicFunction: {
- manyToOne: {
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- role: {
- manyToOne: {
- workspace: null,
- application: null,
- },
- oneToMany: {
- roleTargets: { metadataName: 'roleTarget' },
- objectPermissions: null,
- permissionFlags: null,
- fieldPermissions: null,
- rowLevelPermissionPredicates: {
- metadataName: 'rowLevelPermissionPredicate',
- },
- rowLevelPermissionPredicateGroups: {
- metadataName: 'rowLevelPermissionPredicateGroup',
- },
- },
- },
- roleTarget: {
- manyToOne: {
- role: {
- metadataName: 'role',
- foreignKey: 'roleId',
- universalFlatEntityForeignKeyAggregator:
- 'roleTargetUniversalIdentifiers',
- universalForeignKey: 'roleUniversalIdentifier',
- isNullable: false,
- },
- apiKey: null,
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- pageLayout: {
- manyToOne: {
- workspace: null,
- objectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'objectMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'objectMetadataUniversalIdentifier',
- isNullable: true,
- },
- application: null,
- defaultTabToFocusOnMobileAndSidePanel: {
- metadataName: 'pageLayoutTab',
- foreignKey: 'defaultTabToFocusOnMobileAndSidePanelId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey:
- 'defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier',
- isNullable: true,
- },
- },
- oneToMany: {
- tabs: { metadataName: 'pageLayoutTab' },
- },
- },
- pageLayoutTab: {
- manyToOne: {
- workspace: null,
- pageLayout: {
- metadataName: 'pageLayout',
- foreignKey: 'pageLayoutId',
- universalFlatEntityForeignKeyAggregator: 'tabUniversalIdentifiers',
- universalForeignKey: 'pageLayoutUniversalIdentifier',
- isNullable: false,
- },
- application: null,
- },
- oneToMany: {
- widgets: { metadataName: 'pageLayoutWidget' },
- },
- },
- pageLayoutWidget: {
- manyToOne: {
- workspace: null,
- pageLayoutTab: {
- metadataName: 'pageLayoutTab',
- foreignKey: 'pageLayoutTabId',
- universalFlatEntityForeignKeyAggregator: 'widgetUniversalIdentifiers',
- universalForeignKey: 'pageLayoutTabUniversalIdentifier',
- isNullable: false,
- },
- objectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'objectMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'objectMetadataUniversalIdentifier',
- isNullable: true,
- },
- application: null,
- },
- oneToMany: {},
- },
- rowLevelPermissionPredicate: {
- manyToOne: {
- workspace: null,
- role: {
- metadataName: 'role',
- foreignKey: 'roleId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'roleUniversalIdentifier',
- isNullable: false,
- },
- fieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'fieldMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'fieldMetadataUniversalIdentifier',
- isNullable: false,
- },
- workspaceMemberFieldMetadata: {
- metadataName: 'fieldMetadata',
- foreignKey: 'workspaceMemberFieldMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'workspaceMemberFieldMetadataUniversalIdentifier',
- isNullable: true,
- },
- objectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'objectMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'objectMetadataUniversalIdentifier',
- isNullable: false,
- },
- rowLevelPermissionPredicateGroup: {
- metadataName: 'rowLevelPermissionPredicateGroup',
- foreignKey: 'rowLevelPermissionPredicateGroupId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey:
- 'rowLevelPermissionPredicateGroupUniversalIdentifier',
- isNullable: true,
- },
- application: null,
- },
- oneToMany: {},
- },
- rowLevelPermissionPredicateGroup: {
- manyToOne: {
- objectMetadata: {
- metadataName: 'objectMetadata',
- foreignKey: 'objectMetadataId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'objectMetadataUniversalIdentifier',
- isNullable: false,
- },
- role: {
- metadataName: 'role',
- foreignKey: 'roleId',
- universalFlatEntityForeignKeyAggregator: null,
- universalForeignKey: 'roleUniversalIdentifier',
- isNullable: false,
- },
- parentRowLevelPermissionPredicateGroup: {
- metadataName: 'rowLevelPermissionPredicateGroup',
- foreignKey: 'parentRowLevelPermissionPredicateGroupId',
- universalFlatEntityForeignKeyAggregator:
- 'childRowLevelPermissionPredicateGroupUniversalIdentifiers',
- universalForeignKey:
- 'parentRowLevelPermissionPredicateGroupUniversalIdentifier',
- isNullable: true,
- },
- workspace: null,
- application: null,
- },
- oneToMany: {
- childRowLevelPermissionPredicateGroups: {
- metadataName: 'rowLevelPermissionPredicateGroup',
- },
- rowLevelPermissionPredicates: {
- metadataName: 'rowLevelPermissionPredicate',
- },
- },
- },
- viewFilterGroup: {
- manyToOne: {
- application: null,
- parentViewFilterGroup: {
- metadataName: 'viewFilterGroup',
- foreignKey: 'parentViewFilterGroupId',
- universalFlatEntityForeignKeyAggregator:
- 'childViewFilterGroupUniversalIdentifiers',
- universalForeignKey: 'parentViewFilterGroupUniversalIdentifier',
- isNullable: true,
- },
- view: {
- metadataName: 'view',
- foreignKey: 'viewId',
- universalFlatEntityForeignKeyAggregator:
- 'viewFilterGroupUniversalIdentifiers',
- universalForeignKey: 'viewUniversalIdentifier',
- isNullable: false,
- },
- workspace: null,
- },
- oneToMany: {
- childViewFilterGroups: { metadataName: 'viewFilterGroup' },
- viewFilters: { metadataName: 'viewFilter' },
- },
- },
- frontComponent: {
- manyToOne: {
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
- webhook: {
- manyToOne: {
- workspace: null,
- application: null,
- },
- oneToMany: {},
- },
-} as const satisfies UniversalMetadataRelationsProperties;
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/to-universal-foreign-key.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/to-universal-foreign-key.type.ts
new file mode 100644
index 00000000000..a0a46c56157
--- /dev/null
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/to-universal-foreign-key.type.ts
@@ -0,0 +1,2 @@
+export type ToUniversalForeignKey =
+ T extends `${infer Prefix}Id` ? `${Prefix}UniversalIdentifier` : never;
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type.ts
index d193d2fab35..3a85c717de8 100644
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type.ts
@@ -1,7 +1,8 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { type FormatRecordSerializedRelationProperties } from 'twenty-shared/types';
-import { type ALL_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
+import { type ALL_MANY_TO_ONE_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-relations.constant';
+import { type ALL_ONE_TO_MANY_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-one-to-many-metadata-relations.constant';
import { type AddSuffixToEntityManyToOneProperties } from 'src/engine/metadata-modules/flat-entity/types/add-suffix-to-entity-many-to-one-properties.type';
import { type AddSuffixToEntityOneToManyProperties } from 'src/engine/metadata-modules/flat-entity/types/add-suffix-to-entity-one-to-many-properties.type';
import { type CastRecordTypeOrmDatePropertiesToString } from 'src/engine/metadata-modules/flat-entity/types/cast-record-typeorm-date-properties-to-string.type';
@@ -46,8 +47,8 @@ export type UniversalFlatEntityFrom<
| 'applicationId'
| 'workspaceId'
| 'id'
- | keyof (typeof ALL_METADATA_RELATIONS)[TMetadataName]['manyToOne']
- | keyof (typeof ALL_METADATA_RELATIONS)[TMetadataName]['oneToMany']
+ | keyof (typeof ALL_MANY_TO_ONE_METADATA_RELATIONS)[TMetadataName]
+ | keyof (typeof ALL_ONE_TO_MANY_METADATA_RELATIONS)[TMetadataName]
| Extract, keyof TEntity>
| keyof CastRecordTypeOrmDatePropertiesToString
| AllJsonbPropertiesWithSerializedPropertiesForMetadataName
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type.ts
index 7c417ae5b1c..8e6ffe1444e 100644
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type.ts
@@ -4,7 +4,6 @@ import { type UniversalFlatEntityFrom } from 'src/engine/workspace-manager/works
export type UniversalFlatObjectMetadata = UniversalFlatEntityFrom<
Omit<
ObjectMetadataEntity,
- | 'targetRelationFields'
| 'dataSourceId'
| 'labelIdentifierFieldMetadataId'
| 'imageIdentifierFieldMetadataId'
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts
index 711ed248d31..0e822604b95 100644
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts
@@ -1,16 +1,17 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { isDefined } from 'twenty-shared/utils';
+import { ALL_MANY_TO_ONE_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-relations.constant';
+import { ALL_ONE_TO_MANY_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-one-to-many-metadata-relations.constant';
import {
FlatEntityMapsException,
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
-import { type MetadataUniversalFlatEntityAndRelatedUniversalFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-flat-entity-maps-keys.type';
+import { type MetadataUniversalFlatEntityAndRelatedUniversalFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
import { type MetadataUniversalFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-universal-flat-entity.type';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
-import { ALL_UNIVERSAL_METADATA_RELATIONS } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant';
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
import { addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-maps-through-mutation-or-throw.util';
import { replaceUniversalFlatEntityInUniversalFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/replace-universal-flat-entity-in-universal-flat-entity-maps-through-mutation-or-throw.util';
@@ -37,29 +38,46 @@ export const addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThro
universalFlatEntityAndRelatedMapsToMutate[flatEntityMapsKey],
});
- const universalManyToOneRelations = Object.values(
- ALL_UNIVERSAL_METADATA_RELATIONS[metadataName].manyToOne,
- ) as Array<{
- metadataName: AllMetadataName;
- universalFlatEntityForeignKeyAggregator: string | null;
- universalForeignKey: string;
- } | null>;
+ const manyToOneRelations = ALL_MANY_TO_ONE_METADATA_RELATIONS[metadataName];
- for (const universalRelation of universalManyToOneRelations) {
- if (!isDefined(universalRelation)) {
+ for (const relationPropertyName of Object.keys(manyToOneRelations)) {
+ const relation = manyToOneRelations[
+ relationPropertyName as keyof typeof manyToOneRelations
+ ] as {
+ metadataName: AllMetadataName;
+ inverseOneToManyProperty: string | null;
+ universalForeignKey: string;
+ } | null;
+
+ if (!isDefined(relation)) {
continue;
}
const {
metadataName: relatedMetadataName,
- universalFlatEntityForeignKeyAggregator,
+ inverseOneToManyProperty,
universalForeignKey,
- } = universalRelation;
+ } = relation;
- if (!isDefined(universalFlatEntityForeignKeyAggregator)) {
+ if (!isDefined(inverseOneToManyProperty)) {
continue;
}
+ const oneToManyRelations =
+ ALL_ONE_TO_MANY_METADATA_RELATIONS[relatedMetadataName];
+
+ const inverseRelation = oneToManyRelations[
+ inverseOneToManyProperty as keyof typeof oneToManyRelations
+ ] as {
+ universalFlatEntityForeignKeyAggregator: string;
+ } | null;
+
+ if (!isDefined(inverseRelation)) {
+ continue;
+ }
+
+ const { universalFlatEntityForeignKeyAggregator } = inverseRelation;
+
const relatedFlatEntityMapsKey =
getMetadataFlatEntityMapsKey(relatedMetadataName);
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/delete-universal-flat-entity-from-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/delete-universal-flat-entity-from-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts
index bce96cc57bf..6cdec3004a2 100644
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/delete-universal-flat-entity-from-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/delete-universal-flat-entity-from-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util.ts
@@ -1,6 +1,8 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { isDefined } from 'twenty-shared/utils';
+import { ALL_MANY_TO_ONE_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-relations.constant';
+import { ALL_ONE_TO_MANY_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-one-to-many-metadata-relations.constant';
import {
FlatEntityMapsException,
FlatEntityMapsExceptionCode,
@@ -10,7 +12,6 @@ import { type MetadataUniversalFlatEntityAndRelatedUniversalFlatEntityMaps } fro
import { type MetadataUniversalFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-universal-flat-entity.type';
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
-import { ALL_UNIVERSAL_METADATA_RELATIONS } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant';
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
import { deleteUniversalFlatEntityFromUniversalFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/delete-universal-flat-entity-from-universal-flat-entity-maps-through-mutation-or-throw.util';
import { replaceUniversalFlatEntityInUniversalFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/replace-universal-flat-entity-in-universal-flat-entity-maps-through-mutation-or-throw.util';
@@ -41,29 +42,46 @@ export const deleteUniversalFlatEntityFromUniversalFlatEntityAndRelatedEntityMap
>,
});
- const universalManyToOneRelations = Object.values(
- ALL_UNIVERSAL_METADATA_RELATIONS[metadataName].manyToOne,
- ) as Array<{
- metadataName: AllMetadataName;
- universalFlatEntityForeignKeyAggregator: string | null;
- universalForeignKey: string;
- } | null>;
+ const manyToOneRelations = ALL_MANY_TO_ONE_METADATA_RELATIONS[metadataName];
- for (const universalRelation of universalManyToOneRelations) {
- if (!isDefined(universalRelation)) {
+ for (const relationPropertyName of Object.keys(manyToOneRelations)) {
+ const relation = manyToOneRelations[
+ relationPropertyName as keyof typeof manyToOneRelations
+ ] as {
+ metadataName: AllMetadataName;
+ inverseOneToManyProperty: string | null;
+ universalForeignKey: string;
+ } | null;
+
+ if (!isDefined(relation)) {
continue;
}
const {
metadataName: relatedMetadataName,
- universalFlatEntityForeignKeyAggregator,
+ inverseOneToManyProperty,
universalForeignKey,
- } = universalRelation;
+ } = relation;
- if (!isDefined(universalFlatEntityForeignKeyAggregator)) {
+ if (!isDefined(inverseOneToManyProperty)) {
continue;
}
+ const oneToManyRelations =
+ ALL_ONE_TO_MANY_METADATA_RELATIONS[relatedMetadataName];
+
+ const inverseRelation = oneToManyRelations[
+ inverseOneToManyProperty as keyof typeof oneToManyRelations
+ ] as {
+ universalFlatEntityForeignKeyAggregator: string;
+ } | null;
+
+ if (!isDefined(inverseRelation)) {
+ continue;
+ }
+
+ const { universalFlatEntityForeignKeyAggregator } = inverseRelation;
+
const relatedFlatEntityMapsKey =
getMetadataFlatEntityMapsKey(relatedMetadataName);
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util.ts
index 607b53a0111..17c809330a0 100644
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util.ts
@@ -2,44 +2,38 @@ import { t } from '@lingui/core/macro';
import { type AllMetadataName } from 'twenty-shared/metadata';
import { isDefined } from 'twenty-shared/utils';
-import { type MetadataManyToOneRelationConfiguration } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
+import { ALL_MANY_TO_ONE_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-relations.constant';
import {
FlatEntityMapsException,
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
-import { type ExtractEntityManyToOneEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-many-to-one-entity-relation-properties.type';
-import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
import { type MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
-import {
- ALL_UNIVERSAL_METADATA_RELATIONS,
- type ToUniversalMetadataManyToOneRelationConfiguration,
-} from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant';
-type UniversalManyToOneConfig =
- (typeof ALL_UNIVERSAL_METADATA_RELATIONS)[T]['manyToOne'];
+type ManyToOneRelationsConfig =
+ (typeof ALL_MANY_TO_ONE_METADATA_RELATIONS)[T];
type ExtractUniversalForeignKeys = {
[K in keyof T]: T[K] extends { universalForeignKey: infer UFK } ? UFK : never;
}[keyof T];
type MetadataUniversalManyToOneJoinColumn =
- ExtractUniversalForeignKeys>;
+ ExtractUniversalForeignKeys>;
type TargetMetadataNamesForUniversalForeignKeys<
T extends AllMetadataName,
TProvidedKeys extends string,
> = {
- [K in keyof UniversalManyToOneConfig]: UniversalManyToOneConfig[K] extends {
+ [K in keyof ManyToOneRelationsConfig]: ManyToOneRelationsConfig[K] extends {
universalForeignKey: infer _UFK extends TProvidedKeys;
metadataName: infer MN extends AllMetadataName;
}
? MN
: never;
-}[keyof UniversalManyToOneConfig];
+}[keyof ManyToOneRelationsConfig];
type RequiredFlatEntityMapsForUniversalForeignKeys<
T extends AllMetadataName,
@@ -58,14 +52,14 @@ type ResolvedForeignKeyIds<
string
>,
> = {
- [K in keyof UniversalManyToOneConfig as UniversalManyToOneConfig[K] extends {
+ [K in keyof ManyToOneRelationsConfig as ManyToOneRelationsConfig[K] extends {
universalForeignKey: infer UFK extends string;
foreignKey: infer FK extends string;
}
? UFK extends TProvidedKeys
? FK
: never
- : never]: UniversalManyToOneConfig[K] extends { isNullable: true }
+ : never]: ManyToOneRelationsConfig[K] extends { isNullable: true }
? string | null
: string;
};
@@ -88,18 +82,20 @@ export const resolveUniversalRelationIdentifiersToIds = <
TProvidedKeys
>;
}): ResolvedForeignKeyIds => {
- const relations = ALL_UNIVERSAL_METADATA_RELATIONS[metadataName].manyToOne;
+ const relationEntries = ALL_MANY_TO_ONE_METADATA_RELATIONS[metadataName];
const result: Record = {};
- for (const relation of Object.values(
- relations,
- ) as ToUniversalMetadataManyToOneRelationConfiguration<
- MetadataManyToOneRelationConfiguration<
- T,
- ExtractEntityManyToOneEntityRelationProperties>
- >
- >[]) {
- if (!isDefined(relation)) {
+ for (const relationPropertyName of Object.keys(relationEntries)) {
+ const relationEntry = relationEntries[
+ relationPropertyName as keyof typeof relationEntries
+ ] as {
+ foreignKey: string;
+ metadataName: AllMetadataName;
+ isNullable: boolean;
+ universalForeignKey: string;
+ } | null;
+
+ if (!isDefined(relationEntry)) {
continue;
}
@@ -108,7 +104,7 @@ export const resolveUniversalRelationIdentifiersToIds = <
universalForeignKey,
metadataName: targetMetadataName,
isNullable,
- } = relation;
+ } = relationEntry;
if (
!Object.prototype.hasOwnProperty.call(
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-update-relation-identifiers-to-ids.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-update-relation-identifiers-to-ids.util.ts
index 084f061cc28..28599ee6e1f 100644
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-update-relation-identifiers-to-ids.util.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-update-relation-identifiers-to-ids.util.ts
@@ -1,22 +1,16 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { isDefined } from 'twenty-shared/utils';
-import { type MetadataManyToOneRelationConfiguration } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
+import { ALL_MANY_TO_ONE_METADATA_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-many-to-one-metadata-relations.constant';
import {
FlatEntityMapsException,
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
-import { type ExtractEntityManyToOneEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-many-to-one-entity-relation-properties.type';
import { type FlatEntityUpdate } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-update.type';
-import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
-import {
- ALL_UNIVERSAL_METADATA_RELATIONS,
- type ToUniversalMetadataManyToOneRelationConfiguration,
-} from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/constants/all-universal-metadata-relations.constant';
import { type UniversalFlatEntityUpdate } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-update.type';
export const resolveUniversalUpdateRelationIdentifiersToIds = <
@@ -30,17 +24,18 @@ export const resolveUniversalUpdateRelationIdentifiersToIds = <
universalUpdate: UniversalFlatEntityUpdate;
allFlatEntityMaps: AllFlatEntityMaps;
}): FlatEntityUpdate => {
- const relations = ALL_UNIVERSAL_METADATA_RELATIONS[metadataName].manyToOne;
+ const relationEntries = ALL_MANY_TO_ONE_METADATA_RELATIONS[metadataName];
const result: Record = { ...universalUpdate };
- for (const relation of Object.values(
- relations,
- ) as ToUniversalMetadataManyToOneRelationConfiguration<
- MetadataManyToOneRelationConfiguration<
- T,
- ExtractEntityManyToOneEntityRelationProperties>
- >
- >[]) {
+ for (const relationPropertyName of Object.keys(relationEntries)) {
+ const relation = relationEntries[
+ relationPropertyName as keyof typeof relationEntries
+ ] as {
+ foreignKey: string;
+ universalForeignKey: string;
+ metadataName: AllMetadataName;
+ } | null;
+
if (!isDefined(relation)) {
continue;
}
diff --git a/packages/twenty-server/src/utils/__test__/get-object-metadata-entity.mock.ts b/packages/twenty-server/src/utils/__test__/get-object-metadata-entity.mock.ts
index 0efc2140301..79bbc4ddfb4 100644
--- a/packages/twenty-server/src/utils/__test__/get-object-metadata-entity.mock.ts
+++ b/packages/twenty-server/src/utils/__test__/get-object-metadata-entity.mock.ts
@@ -46,7 +46,6 @@ export const getMockObjectMetadataEntity = (
universalIdentifier: faker.string.uuid(),
applicationId: faker.string.uuid(),
application: {} as ApplicationEntity,
- targetRelationFields: [],
standardOverrides: null,
targetTableName: faker.string.uuid(),
views: [],
diff --git a/packages/twenty-server/test/integration/metadata/suites/application/__snapshots__/successful-sync-application-workspace-migration.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/application/__snapshots__/successful-sync-application-workspace-migration.integration-spec.ts.snap
index 7a88499af87..bb72264e09f 100644
--- a/packages/twenty-server/test/integration/metadata/suites/application/__snapshots__/successful-sync-application-workspace-migration.integration-spec.ts.snap
+++ b/packages/twenty-server/test/integration/metadata/suites/application/__snapshots__/successful-sync-application-workspace-migration.integration-spec.ts.snap
@@ -79,8 +79,6 @@ exports[`syncApplication should return workspace migration actions on initial sy
"icon": null,
"isEditable": true,
"label": "Test Role",
- "rowLevelPermissionPredicateGroupUniversalIdentifiers": [],
- "rowLevelPermissionPredicateUniversalIdentifiers": [],
"universalIdentifier": Any,
"updatedAt": Any,
},
@@ -123,8 +121,6 @@ exports[`syncApplication should return workspace migration actions on initial sy
"icon": null,
"isEditable": true,
"label": "Viewer Role",
- "rowLevelPermissionPredicateGroupUniversalIdentifiers": [],
- "rowLevelPermissionPredicateUniversalIdentifiers": [],
"universalIdentifier": Any,
"updatedAt": Any,
},