Refactor new relation sync (#11711)
In this PR: - this should fix the sync metadata for new relation system This goes with the recent PR: https://github.com/twentyhq/twenty/pull/11725 What we want: - ONE_TO_MANY relations should have no joinColumn and no onDelete - MANY_TO_ONE should have both
This commit is contained in:
@ -129,8 +129,14 @@ export class MigrateRelationsToFieldMetadataCommand extends ActiveOrSuspendedWor
|
||||
...fieldMetadata,
|
||||
settings: {
|
||||
relationType,
|
||||
onDelete: relationMetadata.onDeleteAction,
|
||||
joinColumnName: joinColumnFieldMetadata?.name,
|
||||
onDelete:
|
||||
relationType === RelationType.MANY_TO_ONE
|
||||
? relationMetadata.onDeleteAction
|
||||
: undefined,
|
||||
joinColumnName:
|
||||
relationType === RelationType.MANY_TO_ONE
|
||||
? joinColumnFieldMetadata?.name
|
||||
: undefined,
|
||||
},
|
||||
relationTargetFieldMetadataId,
|
||||
relationTargetObjectMetadataId,
|
||||
|
||||
@ -72,6 +72,9 @@ export class AccessTokenService {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{
|
||||
shouldFailIfMetadataNotFound: false,
|
||||
},
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOne({
|
||||
|
||||
@ -355,7 +355,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
});
|
||||
|
||||
if (fieldMetadata.type === FieldMetadataType.RELATION) {
|
||||
const isManyToManyRelation =
|
||||
const isManyToOneRelation =
|
||||
(fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>)
|
||||
.settings?.relationType === RelationType.MANY_TO_ONE;
|
||||
|
||||
@ -385,7 +385,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.DROP,
|
||||
columnName: isManyToManyRelation
|
||||
columnName: isManyToOneRelation
|
||||
? `${(fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>).settings?.joinColumnName}`
|
||||
: `${(targetFieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>).settings?.joinColumnName}`,
|
||||
} satisfies WorkspaceMigrationColumnDrop,
|
||||
|
||||
@ -100,7 +100,6 @@ export class ObjectMetadataFieldRelationService {
|
||||
...sourceFieldMetadata,
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
|
||||
@ -55,6 +55,12 @@ export class RelationColumnActionFactory extends ColumnActionAbstractFactory<Fie
|
||||
return [];
|
||||
}
|
||||
|
||||
if (
|
||||
currentFieldMetadata.settings.relationType === RelationType.ONE_TO_MANY
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const currentJoinColumnName = currentFieldMetadata.settings.joinColumnName;
|
||||
const alteredJoinColumnName = alteredFieldMetadata.settings.joinColumnName;
|
||||
|
||||
|
||||
@ -1,110 +1,232 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'class-validator';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface';
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util';
|
||||
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
|
||||
import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util';
|
||||
import { assert } from 'src/utils/assert';
|
||||
|
||||
interface CustomRelationFactory {
|
||||
object: ObjectMetadataEntity;
|
||||
metadata: typeof BaseWorkspaceEntity;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class StandardFieldRelationFactory {
|
||||
createFieldRelationForCustomObject(
|
||||
customObjectFactories: CustomRelationFactory[],
|
||||
context: WorkspaceSyncContext,
|
||||
computeRelationFieldsForCustomObject(
|
||||
customObjectMetadata: ObjectMetadataEntity,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): FieldMetadataEntity<FieldMetadataType.RELATION>[] {
|
||||
return customObjectFactories.flatMap((customObjectFactory) =>
|
||||
this.updateFieldRelationMetadata(
|
||||
customObjectFactory,
|
||||
context,
|
||||
originalObjectMetadataMap,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
createFieldRelationForStandardObject(
|
||||
standardObjectMetadataDefinitions: (typeof BaseWorkspaceEntity)[],
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): Map<string, FieldMetadataEntity<FieldMetadataType.RELATION>[]> {
|
||||
return standardObjectMetadataDefinitions.reduce(
|
||||
(acc, standardObjectMetadata) => {
|
||||
const workspaceEntityMetadataArgs = metadataArgsStorage.filterEntities(
|
||||
standardObjectMetadata,
|
||||
);
|
||||
|
||||
if (!workspaceEntityMetadataArgs) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (
|
||||
isGatedAndNotEnabled(
|
||||
workspaceEntityMetadataArgs.gate,
|
||||
context.featureFlags,
|
||||
)
|
||||
) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc.set(
|
||||
workspaceEntityMetadataArgs.standardId,
|
||||
this.updateFieldRelationMetadata(
|
||||
standardObjectMetadata,
|
||||
context,
|
||||
originalObjectMetadataMap,
|
||||
),
|
||||
);
|
||||
|
||||
return acc;
|
||||
},
|
||||
new Map<string, FieldMetadataEntity<FieldMetadataType.RELATION>[]>(),
|
||||
);
|
||||
}
|
||||
|
||||
private updateFieldRelationMetadata(
|
||||
workspaceEntityOrCustomRelationFactory:
|
||||
| typeof BaseWorkspaceEntity
|
||||
| CustomRelationFactory,
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): FieldMetadataEntity<FieldMetadataType.RELATION>[] {
|
||||
const target =
|
||||
'metadata' in workspaceEntityOrCustomRelationFactory
|
||||
? workspaceEntityOrCustomRelationFactory.metadata
|
||||
: workspaceEntityOrCustomRelationFactory;
|
||||
const workspaceEntity =
|
||||
'metadata' in workspaceEntityOrCustomRelationFactory
|
||||
? metadataArgsStorage.filterExtendedEntities(target)
|
||||
: metadataArgsStorage.filterEntities(target);
|
||||
const workspaceRelationMetadataArgsCollection =
|
||||
metadataArgsStorage.filterRelations(target);
|
||||
metadataArgsStorage.filterRelations(CustomWorkspaceEntity);
|
||||
|
||||
if (!workspaceEntity) {
|
||||
const joinColumnsMetadataArgsCollection =
|
||||
metadataArgsStorage.filterJoinColumns(CustomWorkspaceEntity);
|
||||
|
||||
const objectNameSingular = customObjectMetadata.nameSingular;
|
||||
|
||||
const sourceObjectMetadata = originalObjectMetadataMap[objectNameSingular];
|
||||
|
||||
if (!isDefined(sourceObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Object metadata decorator not found, can't parse ${target.name}`,
|
||||
`Source object ${objectNameSingular} not found in database while parsing ${objectNameSingular} relations`,
|
||||
);
|
||||
}
|
||||
|
||||
return workspaceRelationMetadataArgsCollection.map(
|
||||
(workspaceRelationMetadataArgs) => {
|
||||
const inverseSideTarget =
|
||||
workspaceRelationMetadataArgs.inverseSideTarget();
|
||||
const targetObjectNameSingular = convertClassNameToObjectMetadataName(
|
||||
inverseSideTarget.name,
|
||||
);
|
||||
const targetObjectMetadata =
|
||||
originalObjectMetadataMap[targetObjectNameSingular];
|
||||
|
||||
if (!isDefined(targetObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Target object ${targetObjectNameSingular} not found in database while parsing ${objectNameSingular} relations`,
|
||||
);
|
||||
}
|
||||
|
||||
const sourceFieldMetadataName = workspaceRelationMetadataArgs.name;
|
||||
|
||||
const targetFieldMetadataName =
|
||||
workspaceRelationMetadataArgs.inverseSideFieldKey ??
|
||||
objectNameSingular;
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata.fields.find(
|
||||
(field) => field.name === targetFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
if (!isDefined(targetFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Target field ${targetFieldMetadataName} not found in object ${targetObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
const joinColumnName =
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? getJoinColumn(
|
||||
joinColumnsMetadataArgsCollection,
|
||||
workspaceRelationMetadataArgs as WorkspaceRelationMetadataArgs,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const sourceFieldMetadata = sourceObjectMetadata.fields.find(
|
||||
(field) => field.name === sourceFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
if (!isDefined(sourceFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Source field ${sourceFieldMetadataName} not found in object ${sourceFieldMetadata.name} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...sourceFieldMetadata,
|
||||
type: FieldMetadataType.RELATION,
|
||||
settings: {
|
||||
relationType: workspaceRelationMetadataArgs.type,
|
||||
onDelete:
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? workspaceRelationMetadataArgs.onDelete
|
||||
: undefined,
|
||||
joinColumnName,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
isNullable: workspaceRelationMetadataArgs.isNullable,
|
||||
} satisfies FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
computeRelationFieldsForStandardObject(
|
||||
standardObjectMetadataWorkspaceEntity: typeof BaseWorkspaceEntity,
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): FieldMetadataEntity<FieldMetadataType.RELATION>[] {
|
||||
const workspaceEntityMetadataArgs = metadataArgsStorage.filterEntities(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
if (!workspaceEntityMetadataArgs) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (
|
||||
!workspaceRelationMetadataArgsCollection ||
|
||||
isGatedAndNotEnabled(workspaceEntity?.gate, context.featureFlags)
|
||||
isGatedAndNotEnabled(
|
||||
workspaceEntityMetadataArgs.gate,
|
||||
context.featureFlags,
|
||||
)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return workspaceRelationMetadataArgsCollection
|
||||
const sourceObjectNameSingular = workspaceEntityMetadataArgs.nameSingular;
|
||||
|
||||
const workspaceStaticRelationMetadataArgsCollection =
|
||||
metadataArgsStorage.filterRelations(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
const workspaceDynamicRelationMetadataArgsCollection =
|
||||
metadataArgsStorage.filterDynamicRelations(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
const joinColumnsMetadataArgsCollection =
|
||||
metadataArgsStorage.filterJoinColumns(
|
||||
standardObjectMetadataWorkspaceEntity,
|
||||
);
|
||||
|
||||
if (
|
||||
!isDefined(workspaceStaticRelationMetadataArgsCollection) &&
|
||||
!isDefined(workspaceDynamicRelationMetadataArgsCollection)
|
||||
) {
|
||||
throw new Error(
|
||||
`No relations found for object ${sourceObjectNameSingular}`,
|
||||
);
|
||||
}
|
||||
|
||||
const sourceObjectMetadata =
|
||||
originalObjectMetadataMap[sourceObjectNameSingular];
|
||||
|
||||
if (!isDefined(sourceObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Source object ${sourceObjectNameSingular} not found in database while parsing relations`,
|
||||
);
|
||||
}
|
||||
|
||||
const relationsFromDynamicRelations =
|
||||
workspaceDynamicRelationMetadataArgsCollection
|
||||
.filter(
|
||||
(workspaceDynamicRelationMetadataArgs) =>
|
||||
!isGatedAndNotEnabled(
|
||||
workspaceDynamicRelationMetadataArgs.gate,
|
||||
context.featureFlags,
|
||||
),
|
||||
)
|
||||
.flatMap((workspaceDynamicRelationMetadataArgs) => {
|
||||
const customObjectMetadataItems = Object.values(
|
||||
originalObjectMetadataMap,
|
||||
).filter((objectMetadata) => objectMetadata.isCustom);
|
||||
|
||||
// TODO: this is hacky and needs to be simplified
|
||||
return customObjectMetadataItems.flatMap((targetObjectMetadata) => {
|
||||
const relationMetadataArgs =
|
||||
workspaceDynamicRelationMetadataArgs.argsFactory(
|
||||
targetObjectMetadata,
|
||||
);
|
||||
|
||||
const sourceFieldMetadata = sourceObjectMetadata?.fields.find(
|
||||
(field) => field.name === relationMetadataArgs.name,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata?.fields.find(
|
||||
(field) =>
|
||||
field.name ===
|
||||
workspaceDynamicRelationMetadataArgs.inverseSideFieldKey,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
if (!isDefined(sourceFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Source field ${relationMetadataArgs.name} not found in object ${sourceObjectNameSingular} for relation ${relationMetadataArgs.name} of type ${relationMetadataArgs}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDefined(targetFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Target field ${workspaceDynamicRelationMetadataArgs.inverseSideFieldKey} not found in object ${targetObjectMetadata.nameSingular} for relation ${relationMetadataArgs.name} of type ${workspaceDynamicRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...sourceFieldMetadata,
|
||||
type: FieldMetadataType.RELATION,
|
||||
settings: {
|
||||
relationType: workspaceDynamicRelationMetadataArgs.type,
|
||||
onDelete:
|
||||
workspaceDynamicRelationMetadataArgs.type ===
|
||||
RelationType.MANY_TO_ONE
|
||||
? workspaceDynamicRelationMetadataArgs.onDelete
|
||||
: undefined,
|
||||
joinColumnName: relationMetadataArgs.joinColumn,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
isNullable: workspaceDynamicRelationMetadataArgs.isNullable,
|
||||
} satisfies FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
});
|
||||
});
|
||||
|
||||
const staticRelations = workspaceStaticRelationMetadataArgsCollection
|
||||
.filter(
|
||||
(workspaceRelationMetadataArgs) =>
|
||||
!isGatedAndNotEnabled(
|
||||
@ -113,13 +235,6 @@ export class StandardFieldRelationFactory {
|
||||
),
|
||||
)
|
||||
.map((workspaceRelationMetadataArgs) => {
|
||||
// Compute reflect relation metadata
|
||||
const sourceObjectNameSingular =
|
||||
'object' in workspaceEntityOrCustomRelationFactory
|
||||
? workspaceEntityOrCustomRelationFactory.object.nameSingular
|
||||
: convertClassNameToObjectMetadataName(
|
||||
workspaceRelationMetadataArgs.target.name,
|
||||
);
|
||||
const inverseSideTarget =
|
||||
workspaceRelationMetadataArgs.inverseSideTarget();
|
||||
const targetObjectNameSingular = convertClassNameToObjectMetadataName(
|
||||
@ -127,60 +242,62 @@ export class StandardFieldRelationFactory {
|
||||
);
|
||||
const sourceFieldMetadataName = workspaceRelationMetadataArgs.name;
|
||||
const targetFieldMetadataName =
|
||||
(workspaceRelationMetadataArgs.inverseSideFieldKey as
|
||||
| string
|
||||
| undefined) ?? sourceObjectNameSingular;
|
||||
const sourceObjectMetadata =
|
||||
originalObjectMetadataMap[sourceObjectNameSingular];
|
||||
const joinColumnsMetadataArgsCollection =
|
||||
metadataArgsStorage.filterJoinColumns(target);
|
||||
const joinColumnName = getJoinColumn(
|
||||
joinColumnsMetadataArgsCollection,
|
||||
workspaceRelationMetadataArgs,
|
||||
);
|
||||
workspaceRelationMetadataArgs.inverseSideFieldKey ??
|
||||
sourceObjectNameSingular;
|
||||
|
||||
assert(
|
||||
sourceObjectMetadata,
|
||||
`Source object ${sourceObjectNameSingular} not found in databse for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
|
||||
const targetObjectMetadata =
|
||||
originalObjectMetadataMap[targetObjectNameSingular];
|
||||
|
||||
assert(
|
||||
targetObjectMetadata,
|
||||
`Target object ${targetObjectNameSingular} not found in databse for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
const joinColumnName =
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? getJoinColumn(
|
||||
joinColumnsMetadataArgsCollection,
|
||||
workspaceRelationMetadataArgs as WorkspaceRelationMetadataArgs,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const sourceFieldMetadata = sourceObjectMetadata?.fields.find(
|
||||
(field) => field.name === sourceFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
assert(
|
||||
sourceFieldMetadata,
|
||||
`Source field ${sourceFieldMetadataName} not found in object ${sourceObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
if (!isDefined(sourceFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Source field ${sourceFieldMetadataName} not found in object ${sourceObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata?.fields.find(
|
||||
const targetObjectMetadata =
|
||||
originalObjectMetadataMap[targetObjectNameSingular];
|
||||
|
||||
if (!isDefined(targetObjectMetadata)) {
|
||||
throw new Error(
|
||||
`Target object ${targetObjectNameSingular} not found in database for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
const targetFieldMetadata = targetObjectMetadata.fields.find(
|
||||
(field) => field.name === targetFieldMetadataName,
|
||||
) as FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
|
||||
assert(
|
||||
targetFieldMetadata,
|
||||
`Target field ${targetFieldMetadataName} not found in object ${targetObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
if (!isDefined(targetFieldMetadata)) {
|
||||
throw new Error(
|
||||
`Target field ${targetFieldMetadataName} not found in object ${targetObjectNameSingular} for relation ${workspaceRelationMetadataArgs.name} of type ${workspaceRelationMetadataArgs.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...sourceFieldMetadata,
|
||||
type: FieldMetadataType.RELATION,
|
||||
settings: {
|
||||
relationType: workspaceRelationMetadataArgs.type,
|
||||
onDelete: workspaceRelationMetadataArgs.onDelete,
|
||||
onDelete:
|
||||
workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE
|
||||
? workspaceRelationMetadataArgs.onDelete
|
||||
: undefined,
|
||||
joinColumnName,
|
||||
},
|
||||
relationTargetObjectMetadataId: targetObjectMetadata.id,
|
||||
relationTargetFieldMetadataId: targetFieldMetadata.id,
|
||||
} satisfies FieldMetadataEntity<FieldMetadataType.RELATION>;
|
||||
});
|
||||
|
||||
return [...staticRelations, ...relationsFromDynamicRelations];
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-syn
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { WorkspaceMigrationFieldRelationFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field-relation.factory';
|
||||
import {
|
||||
FieldMetadataUpdate,
|
||||
@ -150,26 +150,30 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
originalObjectMetadataMapByName: Record<string, ObjectMetadataEntity>,
|
||||
storage: WorkspaceSyncStorage,
|
||||
): Promise<void> {
|
||||
// Create standard field metadata map
|
||||
const standardFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.createFieldRelationForStandardObject(
|
||||
standardObjectMetadataDefinitions,
|
||||
context,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
// Create map of original and standard object metadata by standard ids
|
||||
const originalObjectMetadataMap = mapObjectMetadataByUniqueIdentifier(
|
||||
originalObjectMetadataCollection,
|
||||
);
|
||||
|
||||
// Loop over all standard objects and compare them with the objects in DB
|
||||
for (const [
|
||||
standardObjectId,
|
||||
standardFieldMetadataCollection,
|
||||
] of standardFieldMetadataRelationCollection) {
|
||||
for (const standardObjectMetadataDefinition of standardObjectMetadataDefinitions) {
|
||||
const workspaceEntityMetadataArgs = metadataArgsStorage.filterEntities(
|
||||
standardObjectMetadataDefinition,
|
||||
);
|
||||
|
||||
if (!workspaceEntityMetadataArgs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const standardFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.computeRelationFieldsForStandardObject(
|
||||
standardObjectMetadataDefinition,
|
||||
context,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
const originalObjectMetadata =
|
||||
originalObjectMetadataMap[standardObjectId];
|
||||
originalObjectMetadataMap[workspaceEntityMetadataArgs.standardId];
|
||||
|
||||
const originalFieldRelationMetadataCollection =
|
||||
(originalObjectMetadata?.fields.filter(
|
||||
@ -183,7 +187,7 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
const fieldComparatorResults =
|
||||
this.workspaceFieldRelationComparator.compare(
|
||||
originalFieldRelationMetadataCollection,
|
||||
standardFieldMetadataCollection,
|
||||
standardFieldMetadataRelationCollection,
|
||||
);
|
||||
|
||||
this.storeComparatorResults(fieldComparatorResults, storage);
|
||||
@ -196,25 +200,22 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
originalObjectMetadataMapByName: Record<string, ObjectMetadataEntity>,
|
||||
storage: WorkspaceSyncStorage,
|
||||
): Promise<void> {
|
||||
// Create standard field metadata collection
|
||||
const customFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.createFieldRelationForCustomObject(
|
||||
customObjectMetadataCollection.map((objectMetadata) => ({
|
||||
object: objectMetadata,
|
||||
metadata: CustomWorkspaceEntity,
|
||||
})),
|
||||
context,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
// Loop over all custom objects from the DB and compare their fields with standard fields
|
||||
for (const customObjectMetadata of customObjectMetadataCollection) {
|
||||
/**
|
||||
* COMPARE FIELD METADATA
|
||||
*/
|
||||
const originalFieldRelationMetadataCollection =
|
||||
(customObjectMetadata.fields.filter(
|
||||
(field) => field.type === FieldMetadataType.RELATION,
|
||||
) ?? []) as FieldMetadataEntity<FieldMetadataType.RELATION>[];
|
||||
|
||||
const customFieldMetadataRelationCollection =
|
||||
this.standardFieldRelationFactory.computeRelationFieldsForCustomObject(
|
||||
customObjectMetadata,
|
||||
originalObjectMetadataMapByName,
|
||||
);
|
||||
|
||||
const fieldComparatorResults =
|
||||
this.workspaceFieldRelationComparator.compare(
|
||||
customObjectMetadata.fields as FieldMetadataEntity<FieldMetadataType.RELATION>[],
|
||||
originalFieldRelationMetadataCollection,
|
||||
customFieldMetadataRelationCollection,
|
||||
);
|
||||
|
||||
@ -233,9 +234,6 @@ export class WorkspaceSyncFieldMetadataRelationService {
|
||||
await objectMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId: context.workspaceId,
|
||||
fields: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
},
|
||||
},
|
||||
relations: ['dataSource', 'fields'],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user