feat: new relation sync-metadata, twenty-orm, create/update (#10217)

Fix
https://github.com/twentyhq/core-team-issues/issues/330#issue-2827026606
and
https://github.com/twentyhq/core-team-issues/issues/327#issue-2827001814

What this PR does when `isNewRelationEnabled` is set to `true`:
- [x] Drop the creation of the  foreign key as a `FieldMetadata`
- [x] Stop creating `RelationMetadata`
- [x] Properly fill `FieldMetadata` of type `RELATION` during the sync
command
- [x] Use new relation settings in TwentyORM
- [x] Properly create `FieldMetadata` relations when we create a new
object
- [x] Handle `database:reset` with new relations

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
Jérémy M
2025-04-22 19:01:39 +02:00
committed by GitHub
parent de1489aabb
commit cc29c25176
160 changed files with 3247 additions and 711 deletions
@@ -1,5 +1,7 @@
import { Injectable } from '@nestjs/common';
import { FieldMetadataType } from 'twenty-shared/types';
import { capitalize } from 'twenty-shared/utils';
import {
EntityManager,
EntityTarget,
@@ -10,12 +12,13 @@ import {
} from 'typeorm';
import { DeepPartial } from 'typeorm/common/DeepPartial';
import { v4 as uuidV4 } from 'uuid';
import { capitalize } from 'twenty-shared/utils';
import { FieldMetadataType } from 'twenty-shared/types';
import { PartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
import { PartialIndexMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-index-metadata.interface';
import { UpdaterOptions } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/updater-options.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { FieldMetadataComplexOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -25,63 +28,77 @@ import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { CompositeFieldMetadataType } from 'src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory';
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
import { FieldMetadataUpdate } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field.factory';
import { ObjectMetadataUpdate } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-object.factory';
import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage';
@Injectable()
export class WorkspaceMetadataUpdaterService {
constructor(private readonly featureFlagService: FeatureFlagService) {}
async updateObjectMetadata(
manager: EntityManager,
storage: WorkspaceSyncStorage,
options?: UpdaterOptions,
): Promise<{
createdObjectMetadataCollection: ObjectMetadataEntity[];
updatedObjectMetadataCollection: ObjectMetadataUpdate[];
}> {
const objectMetadataRepository =
manager.getRepository(ObjectMetadataEntity);
let createdObjectMetadataCollection: ObjectMetadataEntity[] = [];
let updatedObjectMetadataCollection: ObjectMetadataUpdate[] = [];
/**
* Create object metadata
*/
const createdPartialObjectMetadataCollection =
await objectMetadataRepository.save(
storage.objectMetadataCreateCollection.map((objectMetadata) => ({
...objectMetadata,
isActive: true,
})) as DeepPartial<ObjectMetadataEntity>[],
if (!options || options.actions.includes('create')) {
const createdPartialObjectMetadataCollection =
await objectMetadataRepository.save(
storage.objectMetadataCreateCollection.map((objectMetadata) => ({
...objectMetadata,
isActive: true,
})) as DeepPartial<ObjectMetadataEntity>[],
);
const identifiers = createdPartialObjectMetadataCollection.map(
(object) => object.id,
);
const identifiers = createdPartialObjectMetadataCollection.map(
(object) => object.id,
);
const createdObjectMetadataCollection = await manager.find(
ObjectMetadataEntity,
{
where: { id: In(identifiers) },
relations: ['dataSource', 'fields'],
},
);
createdObjectMetadataCollection = await manager.find(
ObjectMetadataEntity,
{
where: { id: In(identifiers) },
relations: ['dataSource', 'fields'],
},
);
}
/**
* Update object metadata
*/
const updatedObjectMetadataCollection = await this.updateEntities(
manager,
ObjectMetadataEntity,
storage.objectMetadataUpdateCollection,
[
'fields',
'dataSourceId',
'workspaceId',
'labelIdentifierFieldMetadataId',
'imageIdentifierFieldMetadataId',
],
);
if (!options || options.actions.includes('update')) {
updatedObjectMetadataCollection = await this.updateEntities(
manager,
ObjectMetadataEntity,
storage.objectMetadataUpdateCollection,
[
'fields',
'dataSourceId',
'workspaceId',
'labelIdentifierFieldMetadataId',
'imageIdentifierFieldMetadataId',
],
);
}
/**
* Delete object metadata
*/
if (storage.objectMetadataDeleteCollection.length > 0) {
if (
storage.objectMetadataDeleteCollection.length > 0 &&
(!options || options.actions.includes('delete'))
) {
await objectMetadataRepository.delete(
storage.objectMetadataDeleteCollection.map((object) => object.id),
);
@@ -121,6 +138,7 @@ export class WorkspaceMetadataUpdaterService {
async updateFieldMetadata(
manager: EntityManager,
storage: WorkspaceSyncStorage,
options?: UpdaterOptions,
): Promise<{
createdFieldMetadataCollection: FieldMetadataEntity[];
updatedFieldMetadataCollection: FieldMetadataUpdate[];
@@ -130,26 +148,32 @@ export class WorkspaceMetadataUpdaterService {
IndexFieldMetadataEntity,
);
const indexMetadataRepository = manager.getRepository(IndexMetadataEntity);
let createdFieldMetadataCollection: FieldMetadataEntity[] = [];
let updatedFieldMetadataCollection: FieldMetadataUpdate[] = [];
/**
* Update field metadata
*/
const updatedFieldMetadataCollection =
await this.updateEntities<FieldMetadataEntity>(
manager,
FieldMetadataEntity,
storage.fieldMetadataUpdateCollection,
['objectMetadataId', 'workspaceId'],
);
if (!options || options.actions.includes('update')) {
updatedFieldMetadataCollection =
await this.updateEntities<FieldMetadataEntity>(
manager,
FieldMetadataEntity,
storage.fieldMetadataUpdateCollection,
['objectMetadataId', 'workspaceId'],
);
}
/**
* Create field metadata
*/
const createdFieldMetadataCollection = await fieldMetadataRepository.save(
storage.fieldMetadataCreateCollection.map((field) =>
this.prepareFieldMetadataForCreation(field),
) as DeepPartial<FieldMetadataEntity>[],
);
if (!options || options.actions.includes('create')) {
createdFieldMetadataCollection = await fieldMetadataRepository.save(
storage.fieldMetadataCreateCollection.map((field) =>
this.prepareFieldMetadataForCreation(field),
) as DeepPartial<FieldMetadataEntity>[],
);
}
/**
* Delete field metadata
@@ -160,7 +184,10 @@ export class WorkspaceMetadataUpdaterService {
(field) => field.type !== FieldMetadataType.RELATION,
);
if (fieldMetadataDeleteCollectionWithoutRelationType.length > 0) {
if (
fieldMetadataDeleteCollectionWithoutRelationType.length > 0 &&
(!options || options.actions.includes('delete'))
) {
await this.deleteIndexFieldMetadata(
fieldMetadataDeleteCollectionWithoutRelationType,
indexFieldMetadataRepository,
@@ -181,6 +208,68 @@ export class WorkspaceMetadataUpdaterService {
};
}
async updateFieldRelationMetadata(
manager: EntityManager,
storage: WorkspaceSyncStorage,
options?: UpdaterOptions,
): Promise<{
createdFieldRelationMetadataCollection: FieldMetadataUpdate<FieldMetadataType.RELATION>[];
updatedFieldRelationMetadataCollection: FieldMetadataUpdate<FieldMetadataType.RELATION>[];
deletedFieldRelationMetadataCollection: FieldMetadataUpdate<FieldMetadataType.RELATION>[];
}> {
let createdFieldRelationMetadataCollection: FieldMetadataUpdate<FieldMetadataType.RELATION>[] =
[];
let updatedFieldRelationMetadataCollection: FieldMetadataUpdate<FieldMetadataType.RELATION>[] =
[];
let deletedFieldRelationMetadataCollection: FieldMetadataUpdate<FieldMetadataType.RELATION>[] =
[];
/**
* Create field relation metadata
*/
if (!options || options.actions.includes('create')) {
createdFieldRelationMetadataCollection = await this.updateEntities<
FieldMetadataEntity<FieldMetadataType.RELATION>
>(
manager,
FieldMetadataEntity,
storage.fieldRelationMetadataCreateCollection,
['objectMetadataId', 'workspaceId'],
);
}
/**
* Update field relation metadata
*/
if (!options || options.actions.includes('update')) {
updatedFieldRelationMetadataCollection = await this.updateEntities<
FieldMetadataEntity<FieldMetadataType.RELATION>
>(
manager,
FieldMetadataEntity,
storage.fieldRelationMetadataUpdateCollection,
['objectMetadataId', 'workspaceId'],
);
}
if (!options || options.actions.includes('delete')) {
deletedFieldRelationMetadataCollection = await this.updateEntities<
FieldMetadataEntity<FieldMetadataType.RELATION>
>(
manager,
FieldMetadataEntity,
storage.fieldRelationMetadataDeleteCollection,
['objectMetadataId', 'workspaceId'],
);
}
return {
createdFieldRelationMetadataCollection,
updatedFieldRelationMetadataCollection,
deletedFieldRelationMetadataCollection,
};
}
async deleteIndexFieldMetadata(
fieldMetadataDeleteCollectionWithoutRelationType: Partial<FieldMetadataEntity>[],
indexFieldMetadataRepository: Repository<IndexFieldMetadataEntity>,
@@ -276,6 +365,15 @@ export class WorkspaceMetadataUpdaterService {
createdIndexMetadataCollection: IndexMetadataEntity[];
}> {
const indexMetadataRepository = manager.getRepository(IndexMetadataEntity);
const workspaceId = originalObjectMetadataCollection?.[0]?.workspaceId;
let isNewRelationEnabled = false;
if (workspaceId) {
isNewRelationEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsNewRelationEnabled,
workspaceId,
);
}
const convertIndexMetadataForSaving = (
indexMetadata: PartialIndexMetadata,
@@ -288,6 +386,15 @@ export class WorkspaceMetadataUpdaterService {
const fieldMetadata = originalObjectMetadataCollection
.find((object) => object.id === indexMetadata.objectMetadataId)
?.fields.find((field) => {
if (
isNewRelationEnabled &&
isFieldMetadataEntityOfType(field, FieldMetadataType.RELATION)
) {
if (field.settings?.joinColumnName === column) {
return true;
}
}
if (field.name === column) {
return true;
}
@@ -0,0 +1,267 @@
import { Injectable, Logger } from '@nestjs/common';
import { FieldMetadataType } from 'twenty-shared/types';
import { EntityManager } from 'typeorm';
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
import {
ComparatorAction,
FieldRelationComparatorResult,
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.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 { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceMigrationFieldRelationFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field-relation.factory';
import {
FieldMetadataUpdate,
WorkspaceMigrationFieldFactory,
} from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field.factory';
import { WorkspaceFieldRelationComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field-relation.comparator';
import { StandardFieldRelationFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field-relation.factory';
import { WorkspaceMetadataUpdaterService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service';
import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects';
import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage';
import { mapObjectMetadataByUniqueIdentifier } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/sync-metadata.util';
@Injectable()
export class WorkspaceSyncFieldMetadataRelationService {
private readonly logger = new Logger(
WorkspaceSyncFieldMetadataRelationService.name,
);
constructor(
private readonly standardFieldRelationFactory: StandardFieldRelationFactory,
private readonly workspaceFieldRelationComparator: WorkspaceFieldRelationComparator,
private readonly workspaceMetadataUpdaterService: WorkspaceMetadataUpdaterService,
private readonly workspaceMigrationFieldFactory: WorkspaceMigrationFieldFactory,
private readonly workspaceMigrationFieldRelationFactory: WorkspaceMigrationFieldRelationFactory,
) {}
async synchronize(
context: WorkspaceSyncContext,
manager: EntityManager,
storage: WorkspaceSyncStorage,
): Promise<Partial<WorkspaceMigrationEntity>[]> {
let originalObjectMetadataCollection =
await this.getOriginalObjectMetadataCollection(context, manager);
const customObjectMetadataCollection =
originalObjectMetadataCollection.filter(
(objectMetadata) => objectMetadata.isCustom,
);
// Create map of object metadata & field metadata by unique identifier
const originalObjectMetadataMapByName = mapObjectMetadataByUniqueIdentifier(
originalObjectMetadataCollection,
// Relation are based on the singular name
(objectMetadata) => objectMetadata.nameSingular,
);
await this.synchronizeStandardObjectRelationFields(
context,
originalObjectMetadataCollection,
originalObjectMetadataMapByName,
storage,
);
await this.synchronizeCustomObjectRelationFields(
context,
customObjectMetadataCollection,
originalObjectMetadataMapByName,
storage,
);
this.logger.log('Updating workspace metadata');
// Save field metadata to DB
const metadataFieldUpdaterResult =
await this.workspaceMetadataUpdaterService.updateFieldRelationMetadata(
manager,
storage,
);
this.logger.log('Generating migrations');
const updateFieldWorkspaceMigrations =
await this.workspaceMigrationFieldFactory.create(
originalObjectMetadataCollection,
[
// Both of them are update as field where created in WorkspaceSyncFieldMetadataService
...metadataFieldUpdaterResult.createdFieldRelationMetadataCollection,
...metadataFieldUpdaterResult.updatedFieldRelationMetadataCollection,
...metadataFieldUpdaterResult.deletedFieldRelationMetadataCollection,
] as FieldMetadataUpdate[],
WorkspaceMigrationBuilderAction.UPDATE,
);
// Resync updated object metadata
originalObjectMetadataCollection =
await this.getOriginalObjectMetadataCollection(context, manager);
const deletedFieldRelationMetadataCollection =
metadataFieldUpdaterResult.deletedFieldRelationMetadataCollection.map(
(field) => field.altered,
);
const deleteFieldRelationWorkspaceMigrations =
await this.workspaceMigrationFieldRelationFactory.create(
originalObjectMetadataCollection,
deletedFieldRelationMetadataCollection,
WorkspaceMigrationBuilderAction.DELETE,
);
const createdFieldRelationMetadataCollection =
metadataFieldUpdaterResult.createdFieldRelationMetadataCollection.map(
(field) => field.altered,
);
const createFieldRelationWorkspaceMigrations =
await this.workspaceMigrationFieldRelationFactory.create(
originalObjectMetadataCollection,
createdFieldRelationMetadataCollection,
WorkspaceMigrationBuilderAction.CREATE,
);
const updateFieldRelationWorkspaceMigrations =
await this.workspaceMigrationFieldRelationFactory.create(
originalObjectMetadataCollection,
metadataFieldUpdaterResult.updatedFieldRelationMetadataCollection,
WorkspaceMigrationBuilderAction.UPDATE,
);
// TODO: Should we handle deletion of relation here?
this.logger.log('Saving migrations');
return [
...updateFieldWorkspaceMigrations,
...deleteFieldRelationWorkspaceMigrations,
...createFieldRelationWorkspaceMigrations,
...updateFieldRelationWorkspaceMigrations,
];
}
private async synchronizeStandardObjectRelationFields(
context: WorkspaceSyncContext,
originalObjectMetadataCollection: ObjectMetadataEntity[],
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) {
const originalObjectMetadata =
originalObjectMetadataMap[standardObjectId];
const originalFieldRelationMetadataCollection =
(originalObjectMetadata?.fields.filter(
(field) => field.type === FieldMetadataType.RELATION,
) ?? []) as FieldMetadataEntity<FieldMetadataType.RELATION>[];
if (originalFieldRelationMetadataCollection.length === 0) {
continue;
}
const fieldComparatorResults =
this.workspaceFieldRelationComparator.compare(
originalFieldRelationMetadataCollection,
standardFieldMetadataCollection,
);
this.storeComparatorResults(fieldComparatorResults, storage);
}
}
private async synchronizeCustomObjectRelationFields(
context: WorkspaceSyncContext,
customObjectMetadataCollection: ObjectMetadataEntity[],
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 fieldComparatorResults =
this.workspaceFieldRelationComparator.compare(
customObjectMetadata.fields as FieldMetadataEntity<FieldMetadataType.RELATION>[],
customFieldMetadataRelationCollection,
);
this.storeComparatorResults(fieldComparatorResults, storage);
}
}
private async getOriginalObjectMetadataCollection(
context: WorkspaceSyncContext,
manager: EntityManager,
): Promise<ObjectMetadataEntity[]> {
const objectMetadataRepository =
manager.getRepository(ObjectMetadataEntity);
const originalObjectMetadataCollection =
await objectMetadataRepository.find({
where: {
workspaceId: context.workspaceId,
fields: {
type: FieldMetadataType.RELATION,
},
},
relations: ['dataSource', 'fields'],
});
return originalObjectMetadataCollection;
}
private storeComparatorResults(
fieldComparatorResults: FieldRelationComparatorResult[],
storage: WorkspaceSyncStorage,
): void {
for (const fieldComparatorResult of fieldComparatorResults) {
switch (fieldComparatorResult.action) {
case ComparatorAction.CREATE: {
storage.addCreateFieldRelationMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.UPDATE: {
storage.addUpdateFieldRelationMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.DELETE: {
storage.addDeleteFieldRelationMetadata(fieldComparatorResult.object);
break;
}
}
}
}
}
@@ -2,7 +2,6 @@ import { Injectable, Logger } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
import {
ComparatorAction,
@@ -37,7 +36,6 @@ export class WorkspaceSyncFieldMetadataService {
context: WorkspaceSyncContext,
manager: EntityManager,
storage: WorkspaceSyncStorage,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Promise<Partial<WorkspaceMigrationEntity>[]> {
const objectMetadataRepository =
manager.getRepository(ObjectMetadataEntity);
@@ -61,14 +59,12 @@ export class WorkspaceSyncFieldMetadataService {
originalObjectMetadataCollection,
customObjectMetadataCollection,
storage,
workspaceFeatureFlagsMap,
);
await this.synchronizeCustomObjectFields(
context,
customObjectMetadataCollection,
storage,
workspaceFeatureFlagsMap,
);
this.logger.log('Updating workspace metadata');
@@ -121,14 +117,12 @@ export class WorkspaceSyncFieldMetadataService {
originalObjectMetadataCollection: ObjectMetadataEntity[],
customObjectMetadataCollection: ObjectMetadataEntity[],
storage: WorkspaceSyncStorage,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Promise<void> {
// Create standard field metadata map
const standardObjectStandardFieldMetadataMap =
this.standardFieldFactory.create(
standardObjectMetadataDefinitions,
context,
workspaceFeatureFlagsMap,
);
// Create map of original and standard object metadata by standard ids
@@ -145,6 +139,7 @@ export class WorkspaceSyncFieldMetadataService {
originalObjectMetadataMap[standardObjectId];
const computedStandardFieldMetadataCollection = computeStandardFields(
context,
standardFieldMetadataCollection,
originalObjectMetadata,
// We need to provide this for generated relations with custom objects
@@ -161,24 +156,46 @@ export class WorkspaceSyncFieldMetadataService {
}
}
synchronizeCustomObject(
context: WorkspaceSyncContext,
customObjectMetadata: ObjectMetadataEntity,
): FieldComparatorResult[] {
// Create standard field metadata collection
const customObjectStandardFieldMetadataCollection =
this.standardFieldFactory.create(CustomWorkspaceEntity, context);
const standardFieldMetadataCollection = computeStandardFields(
context,
customObjectStandardFieldMetadataCollection,
customObjectMetadata,
);
/**
* COMPARE FIELD METADATA
*/
const fieldComparatorResults = this.workspaceFieldComparator.compare(
customObjectMetadata.id,
customObjectMetadata.fields,
standardFieldMetadataCollection,
);
return fieldComparatorResults;
}
private async synchronizeCustomObjectFields(
context: WorkspaceSyncContext,
customObjectMetadataCollection: ObjectMetadataEntity[],
storage: WorkspaceSyncStorage,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Promise<void> {
// Create standard field metadata collection
const customObjectStandardFieldMetadataCollection =
this.standardFieldFactory.create(
CustomWorkspaceEntity,
context,
workspaceFeatureFlagsMap,
);
this.standardFieldFactory.create(CustomWorkspaceEntity, context);
// Loop over all custom objects from the DB and compare their fields with standard fields
for (const customObjectMetadata of customObjectMetadataCollection) {
// Also, maybe it's better to refactor a bit and move generation part into a separate module ?
const standardFieldMetadataCollection = computeStandardFields(
context,
customObjectStandardFieldMetadataCollection,
customObjectMetadata,
);
@@ -2,7 +2,6 @@ import { Injectable, Logger } from '@nestjs/common';
import { Any, EntityManager } from 'typeorm';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
import { ComparatorAction } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface';
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
@@ -33,7 +32,6 @@ export class WorkspaceSyncIndexMetadataService {
context: WorkspaceSyncContext,
manager: EntityManager,
storage: WorkspaceSyncStorage,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Promise<Partial<WorkspaceMigrationEntity>[]> {
this.logger.log('Syncing index metadata');
@@ -89,7 +87,6 @@ export class WorkspaceSyncIndexMetadataService {
context,
originalStandardObjectMetadataMap,
originalCustomObjectMetadataMap,
workspaceFeatureFlagsMap,
);
const indexComparatorResults = this.workspaceIndexComparator.compare(
@@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common';
import { EntityManager, Repository } from 'typeorm';
import { FieldMetadataType } from 'twenty-shared/types';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.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';
@@ -21,7 +20,6 @@ export class WorkspaceSyncObjectMetadataIdentifiersService {
context: WorkspaceSyncContext,
manager: EntityManager,
_storage: WorkspaceSyncStorage,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Promise<void> {
const objectMetadataRepository =
manager.getRepository(ObjectMetadataEntity);
@@ -32,10 +30,8 @@ export class WorkspaceSyncObjectMetadataIdentifiersService {
objectMetadataRepository,
);
const standardObjectMetadataMap = this.createStandardObjectMetadataMap(
context,
workspaceFeatureFlagsMap,
);
const standardObjectMetadataMap =
this.createStandardObjectMetadataMap(context);
await this.processObjectMetadataCollection(
originalObjectMetadataCollection,
@@ -56,12 +52,10 @@ export class WorkspaceSyncObjectMetadataIdentifiersService {
private createStandardObjectMetadataMap(
context: WorkspaceSyncContext,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Record<string, any> {
const standardObjectMetadataCollection = this.standardObjectFactory.create(
standardObjectMetadataDefinitions,
context,
workspaceFeatureFlagsMap,
);
return mapObjectMetadataByUniqueIdentifier(
@@ -2,7 +2,6 @@ import { Injectable, Logger } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
import { ComparatorAction } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface';
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
@@ -33,7 +32,6 @@ export class WorkspaceSyncObjectMetadataService {
context: WorkspaceSyncContext,
manager: EntityManager,
storage: WorkspaceSyncStorage,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Promise<Partial<WorkspaceMigrationEntity>[]> {
const objectMetadataRepository =
manager.getRepository(ObjectMetadataEntity);
@@ -83,7 +81,6 @@ export class WorkspaceSyncObjectMetadataService {
const standardObjectMetadataCollection = this.standardObjectFactory.create(
standardObjectMetadataDefinitions,
context,
workspaceFeatureFlagsMap,
);
// Create map of original and standard object metadata by standard ids
@@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
import { ComparatorAction } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface';
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
@@ -32,7 +31,6 @@ export class WorkspaceSyncRelationMetadataService {
context: WorkspaceSyncContext,
manager: EntityManager,
storage: WorkspaceSyncStorage,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Promise<Partial<WorkspaceMigrationEntity>[]> {
const objectMetadataRepository =
manager.getRepository(ObjectMetadataEntity);
@@ -76,7 +74,6 @@ export class WorkspaceSyncRelationMetadataService {
standardObjectMetadataDefinitions,
context,
originalObjectMetadataMap,
workspaceFeatureFlagsMap,
);
const customRelationMetadataCollection =
@@ -87,7 +84,6 @@ export class WorkspaceSyncRelationMetadataService {
})),
context,
originalObjectMetadataMap,
workspaceFeatureFlagsMap,
);
const relationComparatorResults = this.workspaceRelationComparator.compare(