feat: refactor workspace sync fields (#6069)

This PR was first here to fix the issue related to ticket #5004, after
some testing it seems that changing the name of a relation is actually
properly working, if we rename `ONE-TO-MANY` side, the only things that
is going to be updated is the FieldMetadata as the `joinColumn` is
stored on the opposite object.
For `MANY-TO-ONE` relations, the `joinColumn` migration is properly
generated. We need to take care that if we rename a side of a relation,
sometimes the opposite side doesn't have `inverseSideFieldKey`
implemented and used by default the name of the opposite object, so this
is going to throw an error as the field can't be found in the object.

---------

Co-authored-by: Marie <51697796+ijreilly@users.noreply.github.com>
This commit is contained in:
Jérémy M 2024-07-02 17:21:13 +02:00 committed by GitHub
parent a163ccced6
commit 5b26452649
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 229 additions and 149 deletions

View File

@ -43,21 +43,21 @@
"[typescript]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.eslint": "explicit",
"source.addMissingImports": "always"
}
},
"[javascript]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.eslint": "explicit",
"source.addMissingImports": "always"
}
},
"[typescriptreact]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.eslint": "explicit",
"source.addMissingImports": "always"
}
},

View File

@ -122,7 +122,7 @@ export class TimelineCalendarEventService {
return {
totalNumberOfCalendarEvents: total,
timelineCalendarEvents,
timelineCalendarEvents: timelineCalendarEvents,
};
}

View File

@ -8,9 +8,9 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects';
import { StandardObjectFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory';
import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util';
import { StandardFieldFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { computeStandardFields } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util';
interface RunCommandOptions {
workspaceId?: string;
@ -123,11 +123,8 @@ export class AddStandardIdCommand extends CommandRunner {
continue;
}
const computedStandardObjectMetadata = computeStandardObject(
standardObjectMetadata ?? {
...originalObjectMetadata,
fields: standardFieldMetadataCollection,
},
const computedStandardFieldMetadataCollection = computeStandardFields(
standardFieldMetadataCollection,
originalObjectMetadata,
customObjectMetadataCollection,
);
@ -135,13 +132,13 @@ export class AddStandardIdCommand extends CommandRunner {
if (!originalObjectMetadata.isCustom) {
updateObjectMetadataCollection.push({
id: originalObjectMetadata.id,
standardId: computedStandardObjectMetadata.standardId,
standardId: originalObjectMetadata.standardId,
});
}
for (const fieldMetadata of originalObjectMetadata.fields) {
const standardFieldMetadata =
computedStandardObjectMetadata.fields.find(
computedStandardFieldMetadataCollection.find(
(field) => field.name === fieldMetadata.name && !field.isCustom,
);

View File

@ -36,7 +36,7 @@ describe('WorkspaceFieldComparator', () => {
],
} as any;
const result = comparator.compare(original, standard);
const result = comparator.compare('', original.fields, standard.fields);
expect(result).toEqual([
{
@ -65,7 +65,7 @@ describe('WorkspaceFieldComparator', () => {
],
} as any;
const result = comparator.compare(original, standard);
const result = comparator.compare('', original.fields, standard.fields);
expect(result).toEqual([
{
@ -88,7 +88,7 @@ describe('WorkspaceFieldComparator', () => {
} as any;
const standard = { fields: [] } as any;
const result = comparator.compare(original, standard);
const result = comparator.compare('', original.fields, standard.fields);
expect(result).toEqual([
{
@ -108,7 +108,7 @@ describe('WorkspaceFieldComparator', () => {
fields: [createMockFieldMetadata({ standardId: '1' })],
} as any;
const result = comparator.compare(original, standard);
const result = comparator.compare('', original.fields, standard.fields);
expect(result).toHaveLength(0);
});

View File

@ -7,9 +7,7 @@ import {
FieldComparatorResult,
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface';
import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
import { ComputedPartialWorkspaceEntity } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
import {
FieldMetadataEntity,
@ -35,8 +33,9 @@ export class WorkspaceFieldComparator {
constructor() {}
public compare(
originalObjectMetadata: ObjectMetadataEntity,
standardObjectMetadata: ComputedPartialWorkspaceEntity,
originalObjectMetadataId: string,
originalFieldMetadataCollection: FieldMetadataEntity[],
standardFieldMetadataCollection: ComputedPartialFieldMetadata[],
): FieldComparatorResult[] {
const result: FieldComparatorResult[] = [];
const fieldPropertiesToUpdateMap: Record<
@ -46,7 +45,7 @@ export class WorkspaceFieldComparator {
// Double security to only compare non-custom fields
const filteredOriginalFieldCollection =
originalObjectMetadata.fields.filter((field) => !field.isCustom);
originalFieldMetadataCollection.filter((field) => !field.isCustom);
const originalFieldMetadataMap = transformMetadataForComparison(
filteredOriginalFieldCollection,
{
@ -73,7 +72,7 @@ export class WorkspaceFieldComparator {
},
);
const standardFieldMetadataMap = transformMetadataForComparison(
standardObjectMetadata.fields,
standardFieldMetadataCollection,
{
shouldIgnoreProperty: (property, originalMetadata) => {
if (commonFieldPropertiesToIgnore.includes(property)) {
@ -117,9 +116,9 @@ export class WorkspaceFieldComparator {
};
// Object shouldn't have thousands of fields, so we can use find here
const standardFieldMetadata =
standardObjectMetadata.fields.find(findField);
standardFieldMetadataCollection.find(findField);
const originalFieldMetadata =
originalObjectMetadata.fields.find(findField);
originalFieldMetadataCollection.find(findField);
switch (difference.type) {
case 'CREATE': {
@ -133,7 +132,7 @@ export class WorkspaceFieldComparator {
action: ComparatorAction.CREATE,
object: {
...standardFieldMetadata,
objectMetadataId: originalObjectMetadata.id,
objectMetadataId: originalObjectMetadataId,
},
});
break;

View File

@ -27,8 +27,8 @@ export class WorkspaceObjectComparator {
constructor() {}
public compare(
originalObjectMetadata: ObjectMetadataEntity | undefined,
standardObjectMetadata: ComputedPartialWorkspaceEntity,
originalObjectMetadata: Omit<ObjectMetadataEntity, 'fields'> | undefined,
standardObjectMetadata: Omit<ComputedPartialWorkspaceEntity, 'fields'>,
): ObjectComparatorResult {
// If the object doesn't exist in the original metadata, we need to create it
if (!originalObjectMetadata) {

View File

@ -24,10 +24,53 @@ export class StandardFieldFactory {
target: typeof BaseWorkspaceEntity,
context: WorkspaceSyncContext,
workspaceFeatureFlagsMap: FeatureFlagMap,
): Array<PartialFieldMetadata | PartialComputedFieldMetadata> {
): (PartialFieldMetadata | PartialComputedFieldMetadata)[];
create(
targets: (typeof BaseWorkspaceEntity)[],
context: WorkspaceSyncContext,
workspaceFeatureFlagsMap: FeatureFlagMap, // Map of standardId to field metadata
): Map<string, (PartialFieldMetadata | PartialComputedFieldMetadata)[]>;
create(
targetOrTargets:
| typeof BaseWorkspaceEntity
| (typeof BaseWorkspaceEntity)[],
context: WorkspaceSyncContext,
workspaceFeatureFlagsMap: FeatureFlagMap,
):
| (PartialFieldMetadata | PartialComputedFieldMetadata)[]
| Map<string, (PartialFieldMetadata | PartialComputedFieldMetadata)[]> {
if (Array.isArray(targetOrTargets)) {
return targetOrTargets.reduce((acc, target) => {
const workspaceEntityMetadataArgs =
metadataArgsStorage.filterEntities(target);
if (!workspaceEntityMetadataArgs) {
return acc;
}
if (
isGatedAndNotEnabled(
workspaceEntityMetadataArgs.gate,
workspaceFeatureFlagsMap,
)
) {
return acc;
}
acc.set(
workspaceEntityMetadataArgs.standardId,
this.create(target, context, workspaceFeatureFlagsMap),
);
return acc;
}, new Map<string, (PartialFieldMetadata | PartialComputedFieldMetadata)[]>());
}
const workspaceEntityMetadataArgs =
metadataArgsStorage.filterEntities(target);
const metadataCollections = this.collectMetadata(target);
metadataArgsStorage.filterEntities(targetOrTargets);
const metadataCollections = this.collectMetadata(targetOrTargets);
return [
...this.processMetadata(

View File

@ -8,17 +8,13 @@ import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-syn
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
import { StandardFieldFactory } from './standard-field.factory';
@Injectable()
export class StandardObjectFactory {
constructor(private readonly standardFieldFactory: StandardFieldFactory) {}
create(
standardObjectMetadataDefinitions: (typeof BaseWorkspaceEntity)[],
context: WorkspaceSyncContext,
workspaceFeatureFlagsMap: FeatureFlagMap,
): PartialWorkspaceEntity[] {
): Omit<PartialWorkspaceEntity, 'fields'>[] {
return standardObjectMetadataDefinitions
.map((metadata) =>
this.createObjectMetadata(metadata, context, workspaceFeatureFlagsMap),
@ -30,7 +26,7 @@ export class StandardObjectFactory {
target: typeof BaseWorkspaceEntity,
context: WorkspaceSyncContext,
workspaceFeatureFlagsMap: FeatureFlagMap,
): PartialWorkspaceEntity | undefined {
): Omit<PartialWorkspaceEntity, 'fields'> | undefined {
const workspaceEntityMetadataArgs =
metadataArgsStorage.filterEntities(target);
@ -49,12 +45,6 @@ export class StandardObjectFactory {
return undefined;
}
const fields = this.standardFieldFactory.create(
target,
context,
workspaceFeatureFlagsMap,
);
return {
...workspaceEntityMetadataArgs,
// TODO: Remove targetTableName when we remove the old metadata
@ -64,7 +54,6 @@ export class StandardObjectFactory {
isCustom: false,
isRemote: false,
isSystem: workspaceEntityMetadataArgs.isSystem ?? false,
fields,
};
}
}

View File

@ -33,9 +33,9 @@ export interface ComparatorDeleteResult<T> {
export type ObjectComparatorResult =
| ComparatorSkipResult
| ComparatorCreateResult<ComputedPartialWorkspaceEntity>
| ComparatorCreateResult<Omit<ComputedPartialWorkspaceEntity, 'fields'>>
| ComparatorUpdateResult<
Partial<ComputedPartialWorkspaceEntity> & { id: string }
Partial<Omit<ComputedPartialWorkspaceEntity, 'fields'>> & { id: string }
>;
export type FieldComparatorResult =

View File

@ -47,9 +47,6 @@ export class WorkspaceMetadataUpdaterService {
storage.objectMetadataCreateCollection.map((objectMetadata) => ({
...objectMetadata,
isActive: true,
fields: objectMetadata.fields.map((field) =>
this.prepareFieldMetadataForCreation(field),
),
})) as DeepPartial<ObjectMetadataEntity>[],
);
const identifiers = createdPartialObjectMetadataCollection.map(

View File

@ -15,7 +15,9 @@ import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-syn
import { WorkspaceMigrationFieldFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field.factory';
import { StandardFieldFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util';
import { computeStandardFields } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util';
import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects';
import { mapObjectMetadataByUniqueIdentifier } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/sync-metadata.util';
@Injectable()
export class WorkspaceSyncFieldMetadataService {
@ -47,56 +49,25 @@ export class WorkspaceSyncFieldMetadataService {
},
relations: ['dataSource', 'fields'],
});
// Filter out non-custom objects
const customObjectMetadataCollection =
originalObjectMetadataCollection.filter(
(objectMetadata) => objectMetadata.isCustom,
);
// Create standard field metadata collection
const standardFieldMetadataCollection = this.standardFieldFactory.create(
CustomWorkspaceEntity,
await this.synchronizeStandardObjectFields(
context,
originalObjectMetadataCollection,
customObjectMetadataCollection,
storage,
workspaceFeatureFlagsMap,
);
// 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 standardObjectMetadata = computeStandardObject(
{
...customObjectMetadata,
fields: standardFieldMetadataCollection,
},
customObjectMetadata,
);
/**
* COMPARE FIELD METADATA
*/
const fieldComparatorResults = this.workspaceFieldComparator.compare(
customObjectMetadata,
standardObjectMetadata,
);
for (const fieldComparatorResult of fieldComparatorResults) {
switch (fieldComparatorResult.action) {
case ComparatorAction.CREATE: {
storage.addCreateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.UPDATE: {
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.DELETE: {
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
break;
}
}
}
}
await this.synchronizeCustomObjectFields(
context,
customObjectMetadataCollection,
storage,
workspaceFeatureFlagsMap,
);
this.logger.log('Updating workspace metadata');
@ -137,4 +108,120 @@ export class WorkspaceSyncFieldMetadataService {
...deleteFieldWorkspaceMigrations,
];
}
/**
* This can be optimized to avoid import of standardObjectFactory here.
* We should refactor the logic of the factory, so this one only create the objects and not the fields.
* Then standardFieldFactory should be used to create the fields of standard objects.
*/
private async synchronizeStandardObjectFields(
context: WorkspaceSyncContext,
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
const originalObjectMetadataMap = mapObjectMetadataByUniqueIdentifier(
originalObjectMetadataCollection,
);
this.logger.log('Comparing standard objects and fields metadata');
// Loop over all standard objects and compare them with the objects in DB
for (const [
standardObjectId,
standardFieldMetadataCollection,
] of standardObjectStandardFieldMetadataMap) {
const originalObjectMetadata =
originalObjectMetadataMap[standardObjectId];
const computedStandardFieldMetadataCollection = computeStandardFields(
standardFieldMetadataCollection,
originalObjectMetadata,
// We need to provide this for generated relations with custom objects
customObjectMetadataCollection,
);
const fieldComparatorResults = this.workspaceFieldComparator.compare(
originalObjectMetadata.id,
originalObjectMetadata.fields,
computedStandardFieldMetadataCollection,
);
for (const fieldComparatorResult of fieldComparatorResults) {
switch (fieldComparatorResult.action) {
case ComparatorAction.CREATE: {
storage.addCreateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.UPDATE: {
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.DELETE: {
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
break;
}
}
}
}
}
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,
);
// 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(
customObjectStandardFieldMetadataCollection,
customObjectMetadata,
);
/**
* COMPARE FIELD METADATA
*/
const fieldComparatorResults = this.workspaceFieldComparator.compare(
customObjectMetadata.id,
customObjectMetadata.fields,
standardFieldMetadataCollection,
);
for (const fieldComparatorResult of fieldComparatorResults) {
switch (fieldComparatorResult.action) {
case ComparatorAction.CREATE: {
storage.addCreateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.UPDATE: {
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.DELETE: {
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
break;
}
}
}
}
}
}

View File

@ -12,11 +12,9 @@ import { mapObjectMetadataByUniqueIdentifier } from 'src/engine/workspace-manage
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
import { StandardObjectFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory';
import { WorkspaceObjectComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-object.comparator';
import { WorkspaceFieldComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator';
import { WorkspaceMetadataUpdaterService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service';
import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage';
import { WorkspaceMigrationObjectFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-object.factory';
import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util';
import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects';
@Injectable()
@ -26,7 +24,6 @@ export class WorkspaceSyncObjectMetadataService {
constructor(
private readonly standardObjectFactory: StandardObjectFactory,
private readonly workspaceObjectComparator: WorkspaceObjectComparator,
private readonly workspaceFieldComparator: WorkspaceFieldComparator,
private readonly workspaceMetadataUpdaterService: WorkspaceMetadataUpdaterService,
private readonly workspaceMigrationObjectFactory: WorkspaceMigrationObjectFactory,
) {}
@ -49,10 +46,6 @@ export class WorkspaceSyncObjectMetadataService {
},
relations: ['dataSource', 'fields'],
});
const customObjectMetadataCollection =
originalObjectMetadataCollection.filter(
(objectMetadata) => objectMetadata.isCustom,
);
// Create standard object metadata collection
const standardObjectMetadataCollection = this.standardObjectFactory.create(
@ -87,11 +80,8 @@ export class WorkspaceSyncObjectMetadataService {
for (const standardObjectId in standardObjectMetadataMap) {
const originalObjectMetadata =
originalObjectMetadataMap[standardObjectId];
const standardObjectMetadata = computeStandardObject(
standardObjectMetadataMap[standardObjectId],
originalObjectMetadata,
customObjectMetadataCollection,
);
const standardObjectMetadata =
standardObjectMetadataMap[standardObjectId];
/**
* COMPARE OBJECT METADATA
@ -109,35 +99,6 @@ export class WorkspaceSyncObjectMetadataService {
if (objectComparatorResult.action === ComparatorAction.UPDATE) {
storage.addUpdateObjectMetadata(objectComparatorResult.object);
}
/**
* COMPARE FIELD METADATA
* NOTE: This should be moved to WorkspaceSyncFieldMetadataService for more clarity since
* this code only adds field metadata to the storage but it's actually used in the other service.
* NOTE2: WorkspaceSyncFieldMetadataService has been added for custom fields sync, it should be refactored to handle
* both custom and non-custom fields.
*/
const fieldComparatorResults = this.workspaceFieldComparator.compare(
originalObjectMetadata,
standardObjectMetadata,
);
for (const fieldComparatorResult of fieldComparatorResults) {
switch (fieldComparatorResult.action) {
case ComparatorAction.CREATE: {
storage.addCreateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.UPDATE: {
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
break;
}
case ComparatorAction.DELETE: {
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
break;
}
}
}
}
this.logger.log('Updating workspace metadata');

View File

@ -28,6 +28,7 @@ import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/stan
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
// TODO: Maybe we should automate this with the DiscoverService of Nest.JS
export const standardObjectMetadataDefinitions = [
ActivityTargetWorkspaceEntity,
ActivityWorkspaceEntity,

View File

@ -8,9 +8,13 @@ import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/
export class WorkspaceSyncStorage {
// Object metadata
private readonly _objectMetadataCreateCollection: ComputedPartialWorkspaceEntity[] =
[];
private readonly _objectMetadataUpdateCollection: (Partial<ComputedPartialWorkspaceEntity> & {
private readonly _objectMetadataCreateCollection: Omit<
ComputedPartialWorkspaceEntity,
'fields'
>[] = [];
private readonly _objectMetadataUpdateCollection: (Partial<
Omit<ComputedPartialWorkspaceEntity, 'fields'>
> & {
id: string;
})[] = [];
private readonly _objectMetadataDeleteCollection: ObjectMetadataEntity[] = [];
@ -88,7 +92,9 @@ export class WorkspaceSyncStorage {
return this._indexMetadataDeleteCollection;
}
addCreateObjectMetadata(object: ComputedPartialWorkspaceEntity) {
addCreateObjectMetadata(
object: Omit<ComputedPartialWorkspaceEntity, 'fields'>,
) {
this._objectMetadataCreateCollection.push(object);
}

View File

@ -1,8 +1,8 @@
import {
ComputedPartialWorkspaceEntity,
PartialWorkspaceEntity,
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface';
import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
ComputedPartialFieldMetadata,
PartialComputedFieldMetadata,
PartialFieldMetadata,
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@ -11,16 +11,18 @@ import {
createRelationDeterministicUuid,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
export const computeStandardObject = (
standardObjectMetadata: Omit<PartialWorkspaceEntity, 'standardId'> & {
standardId: string | null;
},
export const computeStandardFields = (
standardFieldMetadataCollection: (
| PartialFieldMetadata
| PartialComputedFieldMetadata
)[],
originalObjectMetadata: ObjectMetadataEntity,
customObjectMetadataCollection: ObjectMetadataEntity[] = [],
): ComputedPartialWorkspaceEntity => {
): ComputedPartialFieldMetadata[] => {
const fields: ComputedPartialFieldMetadata[] = [];
for (const partialFieldMetadata of standardObjectMetadata.fields) {
for (const partialFieldMetadata of standardFieldMetadataCollection) {
// Relation from standard object to custom object
if ('argsFactory' in partialFieldMetadata) {
// Compute standard fields of custom object
for (const customObjectMetadata of customObjectMetadataCollection) {
@ -63,6 +65,7 @@ export const computeStandardObject = (
});
}
} else {
// Relation from standard object to standard object
const labelText =
typeof partialFieldMetadata.label === 'function'
? partialFieldMetadata.label(originalObjectMetadata)
@ -80,8 +83,5 @@ export const computeStandardObject = (
}
}
return {
...standardObjectMetadata,
fields,
};
return fields;
};