diff --git a/packages/twenty-server/src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util.ts b/packages/twenty-server/src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util.ts new file mode 100644 index 0000000000..5680447a7d --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util.ts @@ -0,0 +1,25 @@ +import { isDefined } from 'twenty-shared/utils'; + +import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { type FlatEntity } from 'src/engine/core-modules/common/types/flat-entity.type'; +import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util'; + +export type FindManyFlatEntityByIdInFlatEntityMapsOrThrowArgs< + T extends FlatEntity, +> = { + flatEntityMaps: FlatEntityMaps; + flatEntityIds: string[]; +}; +export const findManyFlatEntityByIdInFlatEntityMapsOrThrow = < + T extends FlatEntity, +>({ + flatEntityMaps, + flatEntityIds, +}: FindManyFlatEntityByIdInFlatEntityMapsOrThrowArgs): T[] => { + const subFlatEntityMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds, + flatEntityMaps, + }); + + return Object.values(subFlatEntityMaps.byId).filter(isDefined); +}; diff --git a/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-field-map-cache.service.ts b/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-field-map-cache.service.ts index 82116ead4d..a662168257 100644 --- a/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-field-map-cache.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-field-map-cache.service.ts @@ -6,6 +6,8 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { FlatViewFieldMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-field-maps.type'; import { fromViewFieldEntityToFlatViewField } from 'src/engine/core-modules/view/flat-view/utils/from-view-field-entity-to-flat-view-field.util'; @@ -36,20 +38,13 @@ export class WorkspaceFlatViewFieldMapCacheService extends WorkspaceFlatMapCache withDeleted: true, }); - const flatViewFieldMaps: FlatViewFieldMaps = { - byId: {}, - idByUniversalIdentifier: {}, - }; - - for (const viewFieldEntity of existingViewFields) { + return existingViewFields.reduce((flatViewFieldMaps, viewFieldEntity) => { const flatViewField = fromViewFieldEntityToFlatViewField(viewFieldEntity); - flatViewFieldMaps.byId[flatViewField.id] = flatViewField; - flatViewFieldMaps.idByUniversalIdentifier[ - flatViewField.universalIdentifier - ] = flatViewField.id; - } - - return flatViewFieldMaps; + return addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatViewField, + flatEntityMaps: flatViewFieldMaps, + }); + }, EMPTY_FLAT_ENTITY_MAPS); } } diff --git a/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-map-cache.service.ts b/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-map-cache.service.ts index f347168c8a..9983fc7864 100644 --- a/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-map-cache.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/flat-view/services/workspace-flat-view-map-cache.service.ts @@ -6,9 +6,11 @@ import { Repository } from 'typeorm'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { type FlatViewMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-maps.type'; -import { generateFlatViewMaps } from 'src/engine/core-modules/view/flat-view/utils/generate-flat-view-maps.util'; +import { fromViewEntityToFlatView } from 'src/engine/core-modules/view/flat-view/utils/from-view-entity-to-flat-view.util'; import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; @@ -33,9 +35,22 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceFlatMapCacheServi where: { workspaceId, }, + select: { + viewFields: { + id: true, + }, + }, + relations: ['viewFields'], withDeleted: true, }); - return generateFlatViewMaps(views); + return views.reduce((flatViewMaps, viewEntity) => { + const flatView = fromViewEntityToFlatView(viewEntity); + + return addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatView, + flatEntityMaps: flatViewMaps, + }); + }, EMPTY_FLAT_ENTITY_MAPS); } } diff --git a/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-create-view-field-input-to-flat-view-field-to-create.util.ts b/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-create-view-field-input-to-flat-view-field-to-create.util.ts index c65a5fbec5..e6a0f3f4cc 100644 --- a/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-create-view-field-input-to-flat-view-field-to-create.util.ts +++ b/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-create-view-field-input-to-flat-view-field-to-create.util.ts @@ -1,8 +1,9 @@ -import { v4 } from 'uuid'; import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils'; +import { v4 } from 'uuid'; import { type CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input'; import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; +import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({ createViewFieldInput: rawCreateViewFieldInput, @@ -30,7 +31,7 @@ export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({ deletedAt: null, universalIdentifier: viewFieldId, isVisible: createViewFieldInput.isVisible ?? true, - size: createViewFieldInput.size ?? 0, + size: createViewFieldInput.size ?? DEFAULT_VIEW_FIELD_SIZE, position: createViewFieldInput.position ?? 0, aggregateOperation: createViewFieldInput.aggregateOperation ?? null, }; diff --git a/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-view-entity-to-flat-view.util.ts b/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-view-entity-to-flat-view.util.ts index 24b72131d8..9a2b2192ff 100644 --- a/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-view-entity-to-flat-view.util.ts +++ b/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/from-view-entity-to-flat-view.util.ts @@ -15,6 +15,6 @@ export const fromViewEntityToFlatView = (viewEntity: ViewEntity): FlatView => { universalIdentifier: viewEntityWithoutRelations.universalIdentifier ?? viewEntityWithoutRelations.id, - viewFieldIds: viewEntity.viewFields?.map((viewField) => viewField.id) ?? [], + viewFieldIds: viewEntity.viewFields.map((viewField) => viewField.id) ?? [], }; }; diff --git a/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/generate-flat-view-maps.util.ts b/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/generate-flat-view-maps.util.ts deleted file mode 100644 index 32dd80ed4d..0000000000 --- a/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/generate-flat-view-maps.util.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; -import { type FlatViewMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-maps.type'; -import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type'; - -export const generateFlatViewMaps = ( - viewCollection: ViewEntity[], -): FlatViewMaps => { - const flatViewMaps: FlatViewMaps = { - byId: {}, - idByUniversalIdentifier: {}, - }; - - for (const view of viewCollection) { - const processedFlatView: FlatView = { - ...view, - viewFieldIds: view.viewFields?.map((viewField) => viewField.id) ?? [], - universalIdentifier: view.universalIdentifier ?? view.id, // TODO: should not fallback to id, to remove once we have universalIdentifier required - }; - - flatViewMaps.byId[view.id] = processedFlatView; - flatViewMaps.idByUniversalIdentifier[ - processedFlatView.universalIdentifier - ] = view.id; - } - - return flatViewMaps; -}; diff --git a/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/is-view-field-in-lowest-position.util.ts b/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/is-view-field-in-lowest-position.util.ts new file mode 100644 index 0000000000..e10146c544 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/view/flat-view/utils/is-view-field-in-lowest-position.util.ts @@ -0,0 +1,17 @@ +import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; + +export const isViewFieldInLowestPosition = ({ + flatViewField, + otherFlatViewFields, +}: { + otherFlatViewFields: FlatViewField[]; + flatViewField: FlatViewField; +}) => { + if (otherFlatViewFields.length === 0) { + return true; + } + const positions = otherFlatViewFields.map(({ position }) => position); + const lowestPosition = Math.min(...positions); + + return flatViewField.position < lowestPosition; +}; diff --git a/packages/twenty-server/src/engine/core-modules/view/services/view-field-v2.service.ts b/packages/twenty-server/src/engine/core-modules/view/services/view-field-v2.service.ts index be63db7701..fd7327b850 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/view-field-v2.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/view-field-v2.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { isDefined } from 'twenty-shared/utils'; +import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; @@ -38,6 +39,7 @@ export class ViewFieldV2Service { flatViewFieldMaps: existingFlatViewFieldMaps, flatViewMaps, flatFieldMetadataMaps, + flatObjectMetadataMaps, } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( { workspaceId, @@ -45,6 +47,7 @@ export class ViewFieldV2Service { 'flatViewFieldMaps', 'flatViewMaps', 'flatFieldMetadataMaps', + 'flatObjectMetadataMaps', ], }, ); @@ -72,6 +75,7 @@ export class ViewFieldV2Service { dependencyAllFlatEntityMaps: { flatFieldMetadataMaps, flatViewMaps, + flatObjectMetadataMaps, }, buildOptions: { isSystemBuild: false, @@ -109,13 +113,20 @@ export class ViewFieldV2Service { workspaceId: string; updateViewFieldInput: UpdateViewFieldInput; }): Promise { - const { flatViewFieldMaps: existingFlatViewFieldMaps } = - await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( - { - workspaceId, - flatMapsKeys: ['flatViewFieldMaps'], - }, - ); + const { + flatViewFieldMaps: existingFlatViewFieldMaps, + flatObjectMetadataMaps, + flatViewMaps, + } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: [ + 'flatViewFieldMaps', + 'flatObjectMetadataMaps', + 'flatViewMaps', + ], + }, + ); const optimisticallyUpdatedFlatView = fromUpdateViewFieldInputToFlatViewFieldToUpdateOrThrow({ @@ -123,13 +134,9 @@ export class ViewFieldV2Service { updateViewFieldInput, }); - const fromFlatViewFieldMaps = getSubFlatEntityMapsOrThrow({ - flatEntityIds: [optimisticallyUpdatedFlatView.id], - flatEntityMaps: existingFlatViewFieldMaps, - }); - const toFlatViewFieldMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + const toFlatViewFieldMaps = addFlatEntityToFlatEntityMapsOrThrow({ flatEntity: optimisticallyUpdatedFlatView, - flatEntityMaps: fromFlatViewFieldMaps, + flatEntityMaps: EMPTY_FLAT_ENTITY_MAPS, }); const validateAndBuildResult = @@ -137,10 +144,14 @@ export class ViewFieldV2Service { { fromToAllFlatEntityMaps: { flatViewFieldMaps: { - from: fromFlatViewFieldMaps, + from: existingFlatViewFieldMaps, to: toFlatViewFieldMaps, }, }, + dependencyAllFlatEntityMaps: { + flatObjectMetadataMaps, + flatViewMaps, + }, buildOptions: { isSystemBuild: false, inferDeletionFromMissingEntities: false, @@ -177,13 +188,20 @@ export class ViewFieldV2Service { deleteViewFieldInput: DeleteViewFieldInput; workspaceId: string; }): Promise { - const { flatViewFieldMaps: existingFlatViewFieldMaps } = - await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( - { - workspaceId, - flatMapsKeys: ['flatViewFieldMaps'], - }, - ); + const { + flatViewFieldMaps: existingFlatViewFieldMaps, + flatObjectMetadataMaps, + flatViewMaps, + } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: [ + 'flatViewFieldMaps', + 'flatObjectMetadataMaps', + 'flatViewMaps', + ], + }, + ); const optimisticallyUpdatedFlatViewWithDeletedAt = fromDeleteViewFieldInputToFlatViewFieldOrThrow({ @@ -205,6 +223,10 @@ export class ViewFieldV2Service { to: toFlatViewFieldMaps, }, }, + dependencyAllFlatEntityMaps: { + flatObjectMetadataMaps, + flatViewMaps, + }, buildOptions: { isSystemBuild: false, inferDeletionFromMissingEntities: false, diff --git a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts index 1d81a40b3c..e205f43db4 100644 --- a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts +++ b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts @@ -9,6 +9,7 @@ import { type IndexMetadataInterface } from 'src/engine/metadata-modules/index-m import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { I18nService } from 'src/engine/core-modules/i18n/i18n.service'; import { type IDataloaders } from 'src/engine/dataloaders/dataloader.interface'; import { filterMorphRelationDuplicateFields } from 'src/engine/dataloaders/utils/filter-morph-relation-duplicate-fields.util'; @@ -18,7 +19,6 @@ import { RelationDTO } from 'src/engine/metadata-modules/field-metadata/dtos/rel import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { resolveFieldMetadataStandardOverride } from 'src/engine/metadata-modules/field-metadata/utils/resolve-field-metadata-standard-override.util'; import { findAllOthersMorphRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { fromFlatFieldMetadataToFieldMetadataDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-flat-field-metadata-to-field-metadata-dto.util'; import { fromMorphOrRelationFlatFieldMetadataToRelationDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-morph-or-relation-flat-field-metadata-to-relation-dto.util'; import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; @@ -361,10 +361,10 @@ export class DataloaderService { flatEntityId: objectMetadataId, flatEntityMaps: flatObjectMetadataMaps, }); - const { objectFlatFieldMetadatas } = - findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps: flatFieldMetadataMaps, - flatObjectMetadata, + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: flatObjectMetadata.fieldMetadataIds, }); const overriddenFieldMetadataEntities = diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts index edcb4ccc2e..713d40499d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.entity.ts @@ -19,6 +19,7 @@ import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-met import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface'; import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { type FieldStandardOverridesDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-standard-overrides.dto'; import { AssignIfIsGivenFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/assign-if-is-given-field-metadata-type.type'; import { AssignTypeIfIsMorphOrRelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/assign-type-if-is-morph-or-relation-field-metadata-type.type'; @@ -133,8 +134,7 @@ export class FieldMetadataEntity< @OneToOne( () => FieldMetadataEntity, - (fieldMetadata: FieldMetadataEntity) => - fieldMetadata.relationTargetFieldMetadataId, + (fieldMetadata) => fieldMetadata.relationTargetFieldMetadataId, { nullable: true }, ) @JoinColumn({ name: 'relationTargetFieldMetadataId' }) @@ -151,8 +151,7 @@ export class FieldMetadataEntity< @ManyToOne( () => ObjectMetadataEntity, - (objectMetadata: ObjectMetadataEntity) => - objectMetadata.targetRelationFields, + (objectMetadata) => objectMetadata.targetRelationFields, { onDelete: 'CASCADE', nullable: true }, ) @JoinColumn({ name: 'relationTargetObjectMetadataId' }) @@ -170,8 +169,7 @@ export class FieldMetadataEntity< @OneToMany( () => IndexFieldMetadataEntity, - (indexFieldMetadata: IndexFieldMetadataEntity) => - indexFieldMetadata.indexMetadata, + (indexFieldMetadata) => indexFieldMetadata.indexMetadata, { cascade: true, }, @@ -186,7 +184,10 @@ export class FieldMetadataEntity< @OneToMany( () => FieldPermissionEntity, - (fieldPermission: FieldPermissionEntity) => fieldPermission.fieldMetadata, + (fieldPermission) => fieldPermission.fieldMetadata, ) fieldPermissions: Relation; + + @OneToMany(() => ViewFieldEntity, (viewField) => viewField.fieldMetadata) + viewFields: Relation; } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock.ts index 84be773435..56f6df7d6a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock.ts @@ -19,6 +19,7 @@ export const getFlatFieldMetadataMock = ( const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date; return { + viewFieldIds: [], createdAt, updatedAt: createdAt, defaultValue: null, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-morph-or-relation-target-flat-field-metadata-mock.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-morph-or-relation-target-flat-field-metadata-mock.ts index 1764291fc8..927372cbf1 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-morph-or-relation-target-flat-field-metadata-mock.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/get-morph-or-relation-target-flat-field-metadata-mock.ts @@ -32,6 +32,7 @@ export const getRelationTargetFlatFieldMetadataMock = ({ const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date; return { + viewFieldIds: [], createdAt, updatedAt: createdAt, description: 'default flat field metadata description', diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/__snapshots__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts.snap b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/__snapshots__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts.snap index d35b2d2f6c..d7ec766caa 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/__snapshots__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts.snap +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/__snapshots__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts.snap @@ -113,6 +113,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su "type": "MORPH_RELATION", "universalIdentifier": Any, "updatedAt": Any, + "viewFieldIds": [], "workspaceId": Any, }, { @@ -145,6 +146,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su "type": "RELATION", "universalIdentifier": Any, "updatedAt": Any, + "viewFieldIds": [], "workspaceId": Any, }, { @@ -175,6 +177,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su "type": "MORPH_RELATION", "universalIdentifier": Any, "updatedAt": Any, + "viewFieldIds": [], "workspaceId": Any, }, { @@ -207,6 +210,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su "type": "RELATION", "universalIdentifier": Any, "updatedAt": Any, + "viewFieldIds": [], "workspaceId": Any, }, ], diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts index 5ebb980ce9..ee7102fbe5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service.ts @@ -8,6 +8,7 @@ import { CacheStorageService } from 'src/engine/core-modules/cache-storage/servi import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { fromFieldMetadataEntityToFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-field-metadata-entity-to-flat-field-metadata.util'; @@ -37,28 +38,26 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceFlatMapC where: { workspaceId, }, + select: { + viewFields: { + id: true, + }, + }, withDeleted: true, - relations: [], + relations: ['viewFields'], }); - const flatFieldMetadataMaps = fieldMetadatas.reduce< - FlatEntityMaps - >((flatEntityMaps, field) => { - const flatFieldMetadata = - fromFieldMetadataEntityToFlatFieldMetadata(field); + return fieldMetadatas.reduce( + (flatFieldMetadataMaps, fieldMetadataEntity) => { + const flatFieldMetadata = + fromFieldMetadataEntityToFlatFieldMetadata(fieldMetadataEntity); - return { - byId: { - ...flatEntityMaps.byId, - [flatFieldMetadata.id]: flatFieldMetadata, - }, - idByUniversalIdentifier: { - ...flatEntityMaps.idByUniversalIdentifier, - [flatFieldMetadata.universalIdentifier]: flatFieldMetadata.id, - }, - }; - }, EMPTY_FLAT_ENTITY_MAPS); - - return flatFieldMetadataMaps; + return addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatFieldMetadata, + flatEntityMaps: flatFieldMetadataMaps, + }); + }, + EMPTY_FLAT_ENTITY_MAPS, + ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type.ts index 0705628d41..862f4c6d66 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type.ts @@ -8,6 +8,7 @@ export const fieldMetadataRelationProperties = [ 'fieldPermissions', 'indexFieldMetadatas', 'object', + 'viewFields', ] as const satisfies (keyof FieldMetadataEntity)[]; export type FieldMetadataEntityRelationProperties = @@ -16,5 +17,5 @@ export type FieldMetadataEntityRelationProperties = export type FlatFieldMetadata = Omit, FieldMetadataEntityRelationProperties> & { universalIdentifier: string; - // Could add indexField metadatas and so on ? + viewFieldIds: string[]; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util.ts index 5ec15b8462..7b946a07ff 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util.ts @@ -6,8 +6,8 @@ import { FlatEntityMapsExceptionCode, } from 'src/engine/core-modules/common/exceptions/flat-entity-maps.exception'; import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; @@ -30,10 +30,11 @@ export const findAllOthersMorphRelationFlatFieldMetadatasOrThrow = ({ ); } - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: flatObjectMetadata.fieldMetadataIds, + }); return objectFlatFieldMetadatas.filter( ( diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util.ts deleted file mode 100644 index c2a3f05cb8..0000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { isDefined } from 'twenty-shared/utils'; - -import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; -import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util'; -import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; - -type FindObjectFieldsInFlatFieldMetadataMapsArgs = { - flatFieldMetadataMaps: FlatEntityMaps; - flatObjectMetadata: FlatObjectMetadata; -}; -export const findObjectFlatFieldMetadatasOrThrow = ({ - flatFieldMetadataMaps, - flatObjectMetadata, -}: FindObjectFieldsInFlatFieldMetadataMapsArgs): { - objectFlatFieldMetadatas: FlatFieldMetadata[]; -} => { - const objectFlatFieldMetadataMaps = getSubFlatEntityMapsOrThrow({ - flatEntityIds: flatObjectMetadata.fieldMetadataIds, - flatEntityMaps: flatFieldMetadataMaps, - }); - - const objectFlatFieldMetadatas = Object.values( - objectFlatFieldMetadataMaps.byId, - ).filter(isDefined); - - return { - objectFlatFieldMetadatas, - }; -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts index 04d7416bb7..3d125b2b90 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts @@ -6,6 +6,7 @@ import { import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { type DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input'; import { FieldMetadataException, @@ -13,7 +14,6 @@ import { } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { computeFlatFieldMetadataRelatedFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compute-flat-field-metadata-related-flat-field-metadata.util'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { generateFlatIndexMetadataWithNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/generate-flat-index.util'; @@ -140,10 +140,11 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({ flatEntityMaps: existingFlatObjectMetadataMaps, flatEntityId: flatIndex.objectMetadataId, }); - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps: existingFlatFieldMetadataMaps, - flatObjectMetadata, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: existingFlatFieldMetadataMaps, + flatEntityIds: flatObjectMetadata.fieldMetadataIds, + }); const newIndex = generateFlatIndexMetadataWithNameOrThrow({ flatObjectMetadata, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-field-metadata-entity-to-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-field-metadata-entity-to-flat-field-metadata.util.ts index f7f3d721a3..99f356f9df 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-field-metadata-entity-to-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-field-metadata-entity-to-flat-field-metadata.util.ts @@ -20,6 +20,9 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = < return { ...fieldMetadataWithoutRelations, + viewFieldIds: fieldMetadataEntity.viewFields.map( + (viewField) => viewField.id, + ), universalIdentifier: fieldMetadataWithoutRelations.standardId ?? fieldMetadataWithoutRelations.id, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util.ts index 7f643b9b15..dffa44ba9d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util.ts @@ -23,6 +23,7 @@ export const getDefaultFlatFieldMetadata = ({ const createdAt = new Date(); return { + viewFieldIds: [], description: createFieldInput.description ?? null, id: fieldMetadataId, icon: createFieldInput.icon ?? null, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/recompute-index-on-flat-field-metadata-name-update.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/recompute-index-on-flat-field-metadata-name-update.util.ts index 4ac5c29752..73a2346c7e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/recompute-index-on-flat-field-metadata-name-update.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/recompute-index-on-flat-field-metadata-name-update.util.ts @@ -1,8 +1,8 @@ import { isDefined } from 'twenty-shared/utils'; import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { generateFlatIndexMetadataWithNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/generate-flat-index.util'; @@ -35,10 +35,11 @@ export const recomputeIndexOnFlatFieldMetadataNameUpdate = ({ return []; } - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: flatObjectMetadata.fieldMetadataIds, + }); const optimisticObjectFlatFieldMetadatas = objectFlatFieldMetadatas.map( (flatFieldMetadata) => { if (flatFieldMetadata.id === fromFlatFieldMetadata.id) { diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts index 618b43c7f6..9c1dab7b76 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts @@ -4,13 +4,13 @@ import { isDefined } from 'twenty-shared/utils'; import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; @@ -50,10 +50,11 @@ export const validateFlatFieldMetadataNameAvailability = ({ remainingFlatEntityMapsToValidate?: FlatEntityMaps; }): FlatFieldMetadataValidationError[] => { const errors: FlatFieldMetadataValidationError[] = []; - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: flatObjectMetadata.fieldMetadataIds, + }); const reservedCompositeFieldsNames = getReservedCompositeFieldNames( objectFlatFieldMetadatas, ); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts index 7003b38e95..49f04c208a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service.ts @@ -8,6 +8,7 @@ import { CacheStorageService } from 'src/engine/core-modules/cache-storage/servi import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { fromIndexMetadataEntityToFlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/utils/from-index-metadata-entity-to-flat-index-metadata.util'; import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; @@ -38,27 +39,20 @@ export class WorkspaceFlatIndexMapCacheService extends WorkspaceFlatMapCacheServ workspaceId, }, withDeleted: true, + select: { + // Note: We need all IndexFieldMetadataEntity in order to build a FlatIndex + indexFieldMetadatas: true, + }, relations: ['indexFieldMetadatas'], }); - const flatIndexMaps = indexes.reduce>( - (flatEntityMaps, index) => { - const flatIndex = fromIndexMetadataEntityToFlatIndexMetadata(index); + return indexes.reduce((flatIndexMaps, indexEntity) => { + const flatIndex = fromIndexMetadataEntityToFlatIndexMetadata(indexEntity); - return { - byId: { - ...flatEntityMaps.byId, - [flatIndex.id]: flatIndex, - }, - idByUniversalIdentifier: { - ...flatEntityMaps.idByUniversalIdentifier, - [flatIndex.universalIdentifier]: flatIndex.id, - }, - }; - }, - EMPTY_FLAT_ENTITY_MAPS, - ); - - return flatIndexMaps; + return addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatIndex, + flatEntityMaps: flatIndexMaps, + }); + }, EMPTY_FLAT_ENTITY_MAPS); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock.ts index c4143a8234..d2315bdf77 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock.ts @@ -12,6 +12,7 @@ export const getFlatObjectMetadataMock = ( const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date; return { + viewIds: [], indexMetadataIds: [], fieldMetadataIds: [], description: 'default flat object metadata description', diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts index 3251b70469..32db807992 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service.ts @@ -39,7 +39,18 @@ export class WorkspaceFlatObjectMetadataMapCacheService extends WorkspaceFlatMap workspaceId, }, withDeleted: true, - relations: ['fields', 'indexMetadatas'], + select: { + fields: { + id: true, + }, + indexMetadatas: { + id: true, + }, + views: { + id: true, + }, + }, + relations: ['fields', 'indexMetadatas', 'views'], }); const flatObjectMetadataMaps = objectMetadatas.reduce< diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type.ts index 99674b207b..6b46f26214 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type.ts @@ -10,6 +10,7 @@ export const objectMetadataEntityRelationProperties = [ 'application', 'objectPermissions', 'fieldPermissions', + 'views', ] as const satisfies ObjectMetadataRelationProperties[]; type ObjectMetadataRelationProperties = ExtractRecordTypeOrmRelationProperties< @@ -24,4 +25,5 @@ export type FlatObjectMetadata = Omit< universalIdentifier: string; fieldMetadataIds: string[]; indexMetadataIds: string[]; + viewIds: string[]; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata-and-flat-field-metadatas-to-create.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata-and-flat-field-metadatas-to-create.util.ts index 8cebdfa324..98451c6998 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata-and-flat-field-metadatas-to-create.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata-and-flat-field-metadatas-to-create.util.ts @@ -54,6 +54,7 @@ export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCre const createdAt = new Date(); const flatObjectMetadataToCreate: FlatObjectMetadata = { fieldMetadataIds: [], + viewIds: [], indexMetadataIds: [], createdAt, updatedAt: createdAt, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-delete-object-input-to-flat-field-metadatas-to-delete.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-delete-object-input-to-flat-field-metadatas-to-delete.util.ts index 7b84c0390c..d5bb3a1e68 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-delete-object-input-to-flat-field-metadatas-to-delete.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-delete-object-input-to-flat-field-metadatas-to-delete.util.ts @@ -5,8 +5,8 @@ import { import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-relation-flat-field-metadatas-target-flat-field-metadata-or-throw.util'; import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util'; import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; @@ -52,10 +52,11 @@ export const fromDeleteObjectInputToFlatFieldMetadatasToDelete = ({ ); } - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata: flatObjectMetadataToDelete, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: flatObjectMetadataToDelete.fieldMetadataIds, + }); const flatFieldMetadatasToDelete = objectFlatFieldMetadatas.flatMap( (flatFieldMetadata) => { if (isMorphOrRelationFlatFieldMetadata(flatFieldMetadata)) { diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-entity-to-flat-object-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-entity-to-flat-object-metadata.util.ts index cb2e416347..f35ed7a17b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-entity-to-flat-object-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-entity-to-flat-object-metadata.util.ts @@ -16,6 +16,7 @@ export const fromObjectMetadataEntityToFlatObjectMetadata = ( return { ...objectMetadataEntityWithoutRelations, + viewIds: objectMetadataEntity.views.map((viewEntity) => viewEntity.id), indexMetadataIds: objectMetadataEntity.indexMetadatas.map( (indexEntity) => indexEntity.id, ), diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata-and-related-flat-entities.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata-and-related-flat-entities.util.ts new file mode 100644 index 0000000000..5fc38ea9b1 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata-and-related-flat-entities.util.ts @@ -0,0 +1,231 @@ +import { + extractAndSanitizeObjectStringFields, + isDefined, + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties, +} from 'twenty-shared/utils'; + +import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; +import { FLAT_OBJECT_METADATA_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-object-metadata/constants/flat-object-metadata-properties-to-compare.constant'; +import { type FlatObjectMetadataPropertiesToCompare } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata-properties-to-compare.type'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { recomputeIndexAfterFlatObjectMetadataSingularNameUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util'; +import { recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-view-field-identifier-after-flat-object-identifier-update.util'; +import { renameRelatedMorphFieldOnObjectNamesUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util'; +import { OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES } from 'src/engine/metadata-modules/object-metadata/constants/object-metadata-standard-overrides-properties.constant'; +import { type UpdateOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input'; +import { + ObjectMetadataException, + ObjectMetadataExceptionCode, +} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; +import { type ObjectMetadataStandardOverridesProperties } from 'src/engine/metadata-modules/object-metadata/types/object-metadata-standard-overrides-properties.types'; +import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util'; + +type FromUpdateObjectInputToFlatObjectMetadataArgs = { + updateObjectInput: UpdateOneObjectInput; +} & Pick< + AllFlatEntityMaps, + | 'flatIndexMaps' + | 'flatObjectMetadataMaps' + | 'flatFieldMetadataMaps' + | 'flatViewFieldMaps' + | 'flatViewMaps' +>; + +const objectMetadataEditableProperties = + FLAT_OBJECT_METADATA_PROPERTIES_TO_COMPARE.filter( + ( + property, + ): property is Exclude< + FlatObjectMetadataPropertiesToCompare, + 'standardOverrides' + > => property !== 'standardOverrides', + ); + +type UpdatedFlatObjectAndRelatedFlatEntities = { + flatObjectMetadata: FlatObjectMetadata; + otherObjectFlatFieldMetadataToUpdate: FlatFieldMetadata[]; + flatIndexMetadataToUpdate: FlatIndexMetadata[]; + flatViewFieldToUpdate: FlatViewField[]; + flatViewFieldToCreate: FlatViewField[]; +}; + +export const fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities = + ({ + flatObjectMetadataMaps: existingFlatObjectMetadataMaps, + updateObjectInput: rawUpdateObjectInput, + flatIndexMaps, + flatFieldMetadataMaps, + flatViewFieldMaps, + flatViewMaps, + }: FromUpdateObjectInputToFlatObjectMetadataArgs): UpdatedFlatObjectAndRelatedFlatEntities => { + const { id: objectMetadataIdToUpdate } = + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties( + rawUpdateObjectInput, + ['id'], + ); + const updatedEditableObjectProperties = + extractAndSanitizeObjectStringFields( + rawUpdateObjectInput.update, + objectMetadataEditableProperties, + ); + + const flatObjectMetadataToUpdate = findFlatEntityByIdInFlatEntityMaps({ + flatEntityMaps: existingFlatObjectMetadataMaps, + flatEntityId: objectMetadataIdToUpdate, + }); + + if (!isDefined(flatObjectMetadataToUpdate)) { + throw new ObjectMetadataException( + 'Object to update not found', + ObjectMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND, + ); + } + + if (isStandardMetadata(flatObjectMetadataToUpdate)) { + const invalidUpdatedProperties = Object.keys( + updatedEditableObjectProperties, + ).filter( + (property) => + !OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES.includes( + property as ObjectMetadataStandardOverridesProperties, + ), + ); + + if (invalidUpdatedProperties.length > 0) { + throw new ObjectMetadataException( + `Cannot edit standard object metadata properties: ${invalidUpdatedProperties.join(', ')}`, + ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + ); + } + + const updatedStandardFlatObjectMetadata = + OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES.reduce( + (acc, property) => { + const isPropertyUpdated = + updatedEditableObjectProperties[property] !== undefined; + + return { + ...acc, + standardOverrides: { + ...acc.standardOverrides, + ...(isPropertyUpdated + ? { [property]: updatedEditableObjectProperties[property] } + : {}), + }, + }; + }, + flatObjectMetadataToUpdate, + ); + + return { + flatObjectMetadata: updatedStandardFlatObjectMetadata, + otherObjectFlatFieldMetadataToUpdate: [], + flatIndexMetadataToUpdate: [], + flatViewFieldToUpdate: [], + flatViewFieldToCreate: [], + }; + } + + const initialAccumulator: UpdatedFlatObjectAndRelatedFlatEntities = { + flatObjectMetadata: flatObjectMetadataToUpdate, + otherObjectFlatFieldMetadataToUpdate: [], + flatIndexMetadataToUpdate: [], + flatViewFieldToUpdate: [], + flatViewFieldToCreate: [], + }; + + return objectMetadataEditableProperties.reduce( + ( + { + flatObjectMetadata, + otherObjectFlatFieldMetadataToUpdate, + flatIndexMetadataToUpdate, + flatViewFieldToUpdate, + flatViewFieldToCreate, + }, + property, + ) => { + const updatedPropertyValue = updatedEditableObjectProperties[property]; + const isPropertyUpdated = + updatedPropertyValue !== undefined && + flatObjectMetadata[property] !== updatedPropertyValue; + + if (!isPropertyUpdated) { + return { + flatObjectMetadata, + otherObjectFlatFieldMetadataToUpdate, + flatIndexMetadataToUpdate, + flatViewFieldToUpdate, + flatViewFieldToCreate, + }; + } + + const updatedFlatObjectMetadata = { + ...flatObjectMetadata, + [property]: updatedPropertyValue, + }; + + const newUpdatedOtherObjectFlatFieldMetadatas = + property === 'nameSingular' || property === 'namePlural' + ? renameRelatedMorphFieldOnObjectNamesUpdate({ + flatFieldMetadataMaps, + fromFlatObjectMetadata: updatedFlatObjectMetadata, + toFlatObjectMetadata: updatedFlatObjectMetadata, + }) + : []; + + const newUpdatedFlatIndexMetadatas = + property === 'nameSingular' + ? recomputeIndexAfterFlatObjectMetadataSingularNameUpdate({ + flatFieldMetadataMaps, + existingFlatObjectMetadata: flatObjectMetadataToUpdate, + flatIndexMaps, + updatedSingularName: updatedFlatObjectMetadata.nameSingular, + }) + : []; + + const { + flatViewFieldToCreate: newFlatViewFieldToCreate, + flatViewFieldToUpdate: newFlatViewFieldToUpdate, + } = + property === 'labelIdentifierFieldMetadataId' && + isDefined(updatedFlatObjectMetadata.labelIdentifierFieldMetadataId) + ? recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate({ + existingFlatObjectMetadata: flatObjectMetadataToUpdate, + flatViewFieldMaps, + flatViewMaps, + updatedLabelIdentifierFieldMetadataId: + updatedFlatObjectMetadata.labelIdentifierFieldMetadataId, + }) + : { + flatViewFieldToCreate: [], + flatViewFieldToUpdate: [], + }; + + return { + flatObjectMetadata: updatedFlatObjectMetadata, + otherObjectFlatFieldMetadataToUpdate: [ + ...otherObjectFlatFieldMetadataToUpdate, + ...newUpdatedOtherObjectFlatFieldMetadatas, + ], + flatViewFieldToUpdate: [ + ...flatViewFieldToUpdate, + ...newFlatViewFieldToUpdate, + ], + flatViewFieldToCreate: [ + ...flatViewFieldToCreate, + ...newFlatViewFieldToCreate, + ], + flatIndexMetadataToUpdate: [ + ...flatIndexMetadataToUpdate, + ...newUpdatedFlatIndexMetadatas, + ], + }; + }, + initialAccumulator, + ); + }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata.util.ts deleted file mode 100644 index f51f183513..0000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata.util.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { - extractAndSanitizeObjectStringFields, - isDefined, - trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties, -} from 'twenty-shared/utils'; - -import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; -import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; -import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; -import { FLAT_OBJECT_METADATA_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-object-metadata/constants/flat-object-metadata-properties-to-compare.constant'; -import { type FlatObjectMetadataPropertiesToCompare } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata-properties-to-compare.type'; -import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; -import { recomputeIndexAfterFlatObjectMetadataSingularNameUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util'; -import { renameRelatedMorphFieldOnObjectNamesUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util'; -import { OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES } from 'src/engine/metadata-modules/object-metadata/constants/object-metadata-standard-overrides-properties.constant'; -import { type UpdateOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input'; -import { - ObjectMetadataException, - ObjectMetadataExceptionCode, -} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; -import { type ObjectMetadataStandardOverridesProperties } from 'src/engine/metadata-modules/object-metadata/types/object-metadata-standard-overrides-properties.types'; -import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util'; - -type FromUpdateObjectInputToFlatObjectMetadataArgs = { - updateObjectInput: UpdateOneObjectInput; -} & Pick< - AllFlatEntityMaps, - 'flatIndexMaps' | 'flatObjectMetadataMaps' | 'flatFieldMetadataMaps' ->; - -const objectMetadataEditableProperties = - FLAT_OBJECT_METADATA_PROPERTIES_TO_COMPARE.filter( - ( - property, - ): property is Exclude< - FlatObjectMetadataPropertiesToCompare, - 'standardOverrides' - > => property !== 'standardOverrides', - ); - -type UpdatedFlatObjectAndOtherObjectFieldMetadatas = { - flatObjectMetadata: FlatObjectMetadata; - otherObjectFlatFieldMetadataToUpdate: FlatFieldMetadata[]; - flatIndexMetadataToUpdate: FlatIndexMetadata[]; -}; - -export const fromUpdateObjectInputToFlatObjectMetadata = ({ - flatObjectMetadataMaps: existingFlatObjectMetadataMaps, - updateObjectInput: rawUpdateObjectInput, - flatIndexMaps, - flatFieldMetadataMaps, -}: FromUpdateObjectInputToFlatObjectMetadataArgs): UpdatedFlatObjectAndOtherObjectFieldMetadatas => { - const { id: objectMetadataIdToUpdate } = - trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties( - rawUpdateObjectInput, - ['id'], - ); - const updatedEditableObjectProperties = extractAndSanitizeObjectStringFields( - rawUpdateObjectInput.update, - objectMetadataEditableProperties, - ); - - const flatObjectMetadataToUpdate = findFlatEntityByIdInFlatEntityMaps({ - flatEntityMaps: existingFlatObjectMetadataMaps, - flatEntityId: objectMetadataIdToUpdate, - }); - - if (!isDefined(flatObjectMetadataToUpdate)) { - throw new ObjectMetadataException( - 'Object to update not found', - ObjectMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND, - ); - } - - if (isStandardMetadata(flatObjectMetadataToUpdate)) { - const invalidUpdatedProperties = Object.keys( - updatedEditableObjectProperties, - ).filter( - (property) => - !OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES.includes( - property as ObjectMetadataStandardOverridesProperties, - ), - ); - - if (invalidUpdatedProperties.length > 0) { - throw new ObjectMetadataException( - `Cannot edit standard object metadata properties: ${invalidUpdatedProperties.join(', ')}`, - ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, - ); - } - - const updatedStandardFlatObjectdMetadata = - OBJECT_METADATA_STANDARD_OVERRIDES_PROPERTIES.reduce((acc, property) => { - const isPropertyUpdated = - updatedEditableObjectProperties[property] !== undefined; - - return { - ...acc, - standardOverrides: { - ...acc.standardOverrides, - ...(isPropertyUpdated - ? { [property]: updatedEditableObjectProperties[property] } - : {}), - }, - }; - }, flatObjectMetadataToUpdate); - - return { - flatObjectMetadata: updatedStandardFlatObjectdMetadata, - otherObjectFlatFieldMetadataToUpdate: [], - flatIndexMetadataToUpdate: [], - }; - } - - const initialAccumulator: UpdatedFlatObjectAndOtherObjectFieldMetadatas = { - flatObjectMetadata: flatObjectMetadataToUpdate, - otherObjectFlatFieldMetadataToUpdate: [], - flatIndexMetadataToUpdate: [], - }; - - return objectMetadataEditableProperties.reduce( - ( - { - flatObjectMetadata, - otherObjectFlatFieldMetadataToUpdate: otherObjectFlatFieldMetadatas, - flatIndexMetadataToUpdate, - }, - property, - ) => { - const updatedPropertyValue = updatedEditableObjectProperties[property]; - const isPropertyUpdated = - updatedPropertyValue !== undefined && - flatObjectMetadata[property] !== updatedPropertyValue; - - if (!isPropertyUpdated) { - return { - flatObjectMetadata, - otherObjectFlatFieldMetadataToUpdate: otherObjectFlatFieldMetadatas, - flatIndexMetadataToUpdate, - }; - } - - const updatedFlatObjectMetadata = { - ...flatObjectMetadata, - [property]: updatedPropertyValue, - }; - - const newUpdatedOtherObjectFlatFieldMetadatas = - property === 'nameSingular' || property === 'namePlural' - ? renameRelatedMorphFieldOnObjectNamesUpdate({ - flatFieldMetadataMaps, - fromFlatObjectMetadata: updatedFlatObjectMetadata, - toFlatObjectMetadata: updatedFlatObjectMetadata, - }) - : []; - - const newUpdatedFlatIndexMetadatas = - property === 'nameSingular' - ? recomputeIndexAfterFlatObjectMetadataSingularNameUpdate({ - flatFieldMetadataMaps, - existingFlatObjectMetadata: flatObjectMetadataToUpdate, - flatIndexMaps, - updatedSingularName: updatedFlatObjectMetadata.nameSingular, - }) - : []; - - return { - flatObjectMetadata: updatedFlatObjectMetadata, - otherObjectFlatFieldMetadataToUpdate: [ - ...otherObjectFlatFieldMetadatas, - ...newUpdatedOtherObjectFlatFieldMetadatas, - ], - flatIndexMetadataToUpdate: [ - ...flatIndexMetadataToUpdate, - ...newUpdatedFlatIndexMetadatas, - ], - }; - }, - initialAccumulator, - ); -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util.ts index df0742f4c7..a28a381519 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util.ts @@ -1,7 +1,7 @@ import { isDefined } from 'twenty-shared/utils'; import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { generateFlatIndexMetadataWithNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/generate-flat-index.util'; @@ -31,10 +31,11 @@ export const recomputeIndexAfterFlatObjectMetadataSingularNameUpdate = ({ nameSingular: updatedSingularName, }; - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata: optimisticFlatObjectMetadata, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: optimisticFlatObjectMetadata.fieldMetadataIds, + }); return allRelatedFlatIndexMetadata.map((flatIndex) => { const newIndex = generateFlatIndexMetadataWithNameOrThrow({ diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/recompute-view-field-identifier-after-flat-object-identifier-update.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/recompute-view-field-identifier-after-flat-object-identifier-update.util.ts new file mode 100644 index 0000000000..171a817d21 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/recompute-view-field-identifier-after-flat-object-identifier-update.util.ts @@ -0,0 +1,85 @@ +import { isDefined } from 'twenty-shared/utils'; +import { v4 } from 'uuid'; + +import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; + +type RecomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdateArgs = { + existingFlatObjectMetadata: FlatObjectMetadata; + updatedLabelIdentifierFieldMetadataId: string; +} & Pick; + +type FlatViewFieldToCreateAndUpdate = { + flatViewFieldToCreate: FlatViewField[]; + flatViewFieldToUpdate: FlatViewField[]; +}; +export const recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate = ({ + existingFlatObjectMetadata, + flatViewFieldMaps, + flatViewMaps, + updatedLabelIdentifierFieldMetadataId, +}: RecomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdateArgs): FlatViewFieldToCreateAndUpdate => { + const flatViews = findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatViewMaps, + flatEntityIds: existingFlatObjectMetadata.viewIds, + }); + + const accumulator: FlatViewFieldToCreateAndUpdate = { + flatViewFieldToCreate: [], + flatViewFieldToUpdate: [], + }; + + for (const flatView of flatViews) { + const flatViewFields = findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityIds: flatView.viewFieldIds, + flatEntityMaps: flatViewFieldMaps, + }); + const labelMetadataIdentifierViewField = flatViewFields.find( + (viewField) => + viewField.fieldMetadataId === updatedLabelIdentifierFieldMetadataId, + ); + + const ascSortedViewFieldPositions = flatViewFields + .map(({ position }) => position) + .sort((a, b) => a - b); + const lowestViewFieldPosition = + ascSortedViewFieldPositions.length > 0 + ? ascSortedViewFieldPositions[0] + : 0; + + if (!isDefined(labelMetadataIdentifierViewField)) { + const viewFieldId = v4(); + const createdAt = new Date(); + const flatViewFieldToCreate: FlatViewField = { + fieldMetadataId: updatedLabelIdentifierFieldMetadataId, + position: lowestViewFieldPosition - 1, + isVisible: true, + size: DEFAULT_VIEW_FIELD_SIZE, + viewId: flatView.id, + workspaceId: flatView.workspaceId, + id: viewFieldId, + createdAt: createdAt, + updatedAt: createdAt, + deletedAt: null, + universalIdentifier: viewFieldId, + aggregateOperation: null, + }; + + accumulator.flatViewFieldToCreate.push(flatViewFieldToCreate); + } else if ( + labelMetadataIdentifierViewField.position > lowestViewFieldPosition + ) { + const updatedFlatViewField = { + ...labelMetadataIdentifierViewField, + position: lowestViewFieldPosition - 1, + }; + + accumulator.flatViewFieldToUpdate.push(updatedFlatViewField); + } + } + + return accumulator; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util.ts index 8f8b3b52dc..f4db23211b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util.ts @@ -6,9 +6,9 @@ import { import { computeMorphRelationFieldName } from 'twenty-shared/utils'; import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { getFlatObjectMetadataTargetMorphRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-object-metadata/utils/get-flat-object-metadata-many-to-one-target-morph-relation-flat-field-metadatas-or-throw.util'; import { getMorphNameFromMorphFieldMetadataName } from 'src/engine/metadata-modules/flat-object-metadata/utils/get-morph-name-from-morph-field-metadata-name.util'; @@ -24,10 +24,11 @@ export const renameRelatedMorphFieldOnObjectNamesUpdate = ({ toFlatObjectMetadata, flatFieldMetadataMaps, }: RenameRelatedMorphFieldOnObjectNamesUpdateArgs): FlatFieldMetadata[] => { - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata: fromFlatObjectMetadata, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: fromFlatObjectMetadata.fieldMetadataIds, + }); const manyToOneMorphRelationFlatFieldMetadatas = getFlatObjectMetadataTargetMorphRelationFlatFieldMetadatasOrThrow({ flatFieldMetadataMaps, diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts index 3e0583aba4..0d478c9073 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts @@ -4,8 +4,10 @@ import { isDefined } from 'twenty-shared/utils'; import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service'; +import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util'; import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; import { ViewKey } from 'src/engine/core-modules/view/enums/view-key.enum'; @@ -14,12 +16,11 @@ import { FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view import { fromCreateViewFieldInputToFlatViewFieldToCreate } from 'src/engine/core-modules/view/flat-view/utils/from-create-view-field-input-to-flat-view-field-to-create.util'; import { fromCreateViewInputToFlatViewToCreate } from 'src/engine/core-modules/view/flat-view/utils/from-create-view-input-to-flat-view-to-create.util'; import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata-and-flat-field-metadatas-to-create.util'; import { fromDeleteObjectInputToFlatFieldMetadatasToDelete } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-delete-object-input-to-flat-field-metadatas-to-delete.util'; import { fromFlatObjectMetadataToObjectMetadataDto } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-object-metadata-dto.util'; -import { fromUpdateObjectInputToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata.util'; +import { fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-update-object-input-to-flat-object-metadata-and-related-flat-entities.util'; import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input'; import { DeleteOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/delete-object.input'; import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; @@ -55,6 +56,8 @@ export class ObjectMetadataServiceV2 { flatObjectMetadataMaps: existingFlatObjectMetadataMaps, flatIndexMaps: existingFlatIndexMaps, flatFieldMetadataMaps: existingFlatFieldMetadataMaps, + flatViewFieldMaps: existingFlatViewFieldMaps, + flatViewMaps: existingFlatViewMaps, } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( { workspaceId, @@ -62,6 +65,8 @@ export class ObjectMetadataServiceV2 { 'flatObjectMetadataMaps', 'flatIndexMaps', 'flatFieldMetadataMaps', + 'flatViewFieldMaps', + 'flatViewMaps', ], }, ); @@ -70,11 +75,15 @@ export class ObjectMetadataServiceV2 { flatObjectMetadata: optimisticallyUpdatedFlatObjectMetadata, otherObjectFlatFieldMetadataToUpdate: otherObjectFlatFieldMetadatas, flatIndexMetadataToUpdate, - } = fromUpdateObjectInputToFlatObjectMetadata({ + flatViewFieldToUpdate, + flatViewFieldToCreate, + } = fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities({ flatFieldMetadataMaps: existingFlatFieldMetadataMaps, flatObjectMetadataMaps: existingFlatObjectMetadataMaps, updateObjectInput, flatIndexMaps: existingFlatIndexMaps, + flatViewFieldMaps: existingFlatViewFieldMaps, + flatViewMaps: existingFlatViewMaps, }); const toFlatObjectMetadataMaps = addFlatEntityToFlatEntityMapsOrThrow({ @@ -106,6 +115,27 @@ export class ObjectMetadataServiceV2 { }), ); + const flatViewFieldMapsWithUpdated = flatViewFieldToUpdate.reduce( + (flatViewFieldMaps, flatViewField) => + replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: flatViewField, + flatEntityMaps: flatViewFieldMaps, + }), + getSubFlatEntityMapsOrThrow({ + flatEntityIds: flatViewFieldToUpdate.map(({ id }) => id), + flatEntityMaps: existingFlatViewFieldMaps, + }), + ); + + const toFlatViewFieldMaps = flatViewFieldToCreate.reduce( + (flatViewFieldMaps, flatViewField) => + addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatViewField, + flatEntityMaps: flatViewFieldMaps, + }), + flatViewFieldMapsWithUpdated, + ); + const validateAndBuildResult = await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( { @@ -122,6 +152,13 @@ export class ObjectMetadataServiceV2 { from: existingFlatFieldMetadataMaps, to: toFlatFieldMetadataMaps, }, + flatViewFieldMaps: { + from: existingFlatViewFieldMaps, + to: toFlatViewFieldMaps, + }, + }, + dependencyAllFlatEntityMaps: { + flatViewMaps: existingFlatViewMaps, }, buildOptions: { isSystemBuild: false, @@ -329,7 +366,7 @@ export class ObjectMetadataServiceV2 { const toFlatFieldMetadataMaps = [ ...flatFieldMetadataToCreateOnObject, ...relationTargetFlatFieldMetadataToCreate, - ].reduce( + ].reduce>( (flatFieldMaps, flatField) => addFlatEntityToFlatEntityMapsOrThrow({ flatEntity: flatField, @@ -353,13 +390,16 @@ export class ObjectMetadataServiceV2 { flatEntityMaps: existingFlatViewMaps, }); - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps: toFlatFieldMetadataMaps, - flatObjectMetadata: flatObjectMetadataToCreate, - }); const flatDefaultViewFieldsToCreate = await this.createDefaultFlatViewFields({ - objectFlatFieldMetadatas, + objectFlatFieldMetadatas: findManyFlatEntityByIdInFlatEntityMapsOrThrow( + { + flatEntityMaps: toFlatFieldMetadataMaps, + flatEntityIds: flatFieldMetadataToCreateOnObject.map( + ({ id }) => id, + ), + }, + ), viewId: flatDefaultViewToCreate.id, workspaceId, }); diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts index 321b1da1ed..14145077da 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.entity.ts @@ -13,6 +13,7 @@ import { import { type WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type'; import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; @@ -145,8 +146,7 @@ export class ObjectMetadataEntity implements Required { @OneToMany( () => ObjectPermissionEntity, - (objectPermission: ObjectPermissionEntity) => - objectPermission.objectMetadata, + (objectPermission) => objectPermission.objectMetadata, { cascade: true, }, @@ -155,10 +155,15 @@ export class ObjectMetadataEntity implements Required { @OneToMany( () => FieldPermissionEntity, - (fieldPermission: FieldPermissionEntity) => fieldPermission.objectMetadata, + (fieldPermission) => fieldPermission.objectMetadata, { cascade: true, }, ) fieldPermissions: Relation; + + @OneToMany(() => ViewEntity, (view) => view.objectMetadata, { + cascade: true, + }) + views: Relation; } diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-flat-field-metadatas-for-custom-object.util.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-flat-field-metadatas-for-custom-object.util.ts index 67cf2ab1c1..a58a38c9e8 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-flat-field-metadatas-for-custom-object.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-flat-field-metadatas-for-custom-object.util.ts @@ -27,6 +27,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const idField: FlatFieldMetadata = { type: FieldMetadataType.UUID, id: v4(), + viewFieldIds: [], isLabelSyncedWithName: false, isUnique: true, objectMetadataId, @@ -60,6 +61,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const nameField: FlatFieldMetadata = { type: FieldMetadataType.TEXT, id: v4(), + viewFieldIds: [], isLabelSyncedWithName: false, isUnique: false, objectMetadataId, @@ -93,6 +95,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const createdAtField: FlatFieldMetadata = { type: FieldMetadataType.DATE_TIME, id: v4(), + viewFieldIds: [], isLabelSyncedWithName: false, isUnique: false, objectMetadataId, @@ -126,6 +129,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const updatedAtField: FlatFieldMetadata = { type: FieldMetadataType.DATE_TIME, id: v4(), + viewFieldIds: [], isLabelSyncedWithName: false, isUnique: false, objectMetadataId, @@ -159,6 +163,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const deletedAtField: FlatFieldMetadata = { type: FieldMetadataType.DATE_TIME, id: v4(), + viewFieldIds: [], isLabelSyncedWithName: false, isUnique: false, objectMetadataId, @@ -192,6 +197,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const createdByField: FlatFieldMetadata = { type: FieldMetadataType.ACTOR, id: v4(), + viewFieldIds: [], isLabelSyncedWithName: false, isUnique: false, objectMetadataId, @@ -225,6 +231,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const positionField: FlatFieldMetadata = { type: FieldMetadataType.POSITION, id: v4(), + viewFieldIds: [], isLabelSyncedWithName: false, isUnique: false, objectMetadataId, @@ -257,6 +264,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({ const searchVectorField: FlatFieldMetadata = { type: FieldMetadataType.TS_VECTOR, + viewFieldIds: [], id: v4(), isLabelSyncedWithName: false, isUnique: false, diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-relation-flat-field-metadatas-for-custom-object.util.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-relation-flat-field-metadatas-for-custom-object.util.ts index 380a089d68..1e29ddbb1d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-relation-flat-field-metadatas-for-custom-object.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-relation-flat-field-metadatas-for-custom-object.util.ts @@ -63,6 +63,7 @@ const generateSourceFlatFieldMetadata = ({ } return { + viewFieldIds: [], createdAt, updatedAt: createdAt, defaultValue: null, @@ -127,6 +128,7 @@ const generateTargetFlatFieldMetadata = ({ return { morphId: null, + viewFieldIds: [], id: sourceFlatFieldMetadata.relationTargetFieldMetadataId, name: sourceFlatObjectMetadata.nameSingular, label: sourceFlatObjectMetadata.labelSingular, diff --git a/packages/twenty-server/src/engine/metadata-modules/utils/get-field-metadata-entity-from-cached-object-metadata-maps.util.ts b/packages/twenty-server/src/engine/metadata-modules/utils/get-field-metadata-entity-from-cached-object-metadata-maps.util.ts deleted file mode 100644 index c4ed4cc268..0000000000 --- a/packages/twenty-server/src/engine/metadata-modules/utils/get-field-metadata-entity-from-cached-object-metadata-maps.util.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { isDefined } from 'twenty-shared/utils'; - -import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { type IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity'; -import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { type CachedFieldMetadataEntity } from 'src/engine/metadata-modules/types/cached-field-metadata-entity'; -import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; - -export const getFieldMetadataEntityFromCachedObjectMetadataMaps = ({ - fieldMetadataId, - objectMetadataId, - objectMetadataMaps, -}: { - objectMetadataMaps: ObjectMetadataMaps; - objectMetadataId: string; - fieldMetadataId: string; -}): FieldMetadataEntity | undefined => { - const objectMetadataFromCache = objectMetadataMaps.byId[objectMetadataId]; - - if (!isDefined(objectMetadataFromCache)) { - return undefined; - } - - const fieldMetadataFromCache: CachedFieldMetadataEntity = - objectMetadataFromCache.fieldsById[fieldMetadataId]; - - if (!isDefined(fieldMetadataFromCache)) { - return undefined; - } - - // We need to determine if graphql will be able to handle relations crafting byitself - return { - ...fieldMetadataFromCache, - object: {} as ObjectMetadataEntity, - relationTargetFieldMetadata: null, - relationTargetObjectMetadata: null, - indexFieldMetadatas: {} as IndexFieldMetadataEntity, - fieldPermissions: [], - createdAt: new Date(fieldMetadataFromCache.createdAt), - updatedAt: new Date(fieldMetadataFromCache.updatedAt), - }; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts index b2056bab83..9a38dde550 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts @@ -14,9 +14,9 @@ import { import { aggregateOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/utils/aggregate-orchestrator-actions-report.util'; import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service'; import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service'; -import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/services/workspace-migration-v2-field-actions-builder.service'; +import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service'; import { WorkspaceMigrationV2IndexActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service'; -import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service'; +import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service'; import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service'; import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service'; import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service'; @@ -224,6 +224,8 @@ export class WorkspaceMigrationBuildOrchestratorService { optimisticAllFlatEntityMaps.flatViewMaps = viewResult.optimisticFlatEntityMaps; + optimisticAllFlatEntityMaps.flatObjectMetadataMaps = + viewResult.dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps; if (viewResult.status === 'fail') { orchestratorFailureReport.view.push(...viewResult.errors); @@ -242,6 +244,8 @@ export class WorkspaceMigrationBuildOrchestratorService { to: toFlatViewFieldMaps, buildOptions, dependencyOptimisticFlatEntityMaps: { + flatObjectMetadataMaps: + optimisticAllFlatEntityMaps.flatObjectMetadataMaps, flatFieldMetadataMaps: optimisticAllFlatEntityMaps.flatFieldMetadataMaps, flatViewMaps: optimisticAllFlatEntityMaps.flatViewMaps, @@ -254,6 +258,8 @@ export class WorkspaceMigrationBuildOrchestratorService { viewFieldResult.optimisticFlatEntityMaps; optimisticAllFlatEntityMaps.flatViewMaps = viewFieldResult.dependencyOptimisticFlatEntityMaps.flatViewMaps; + optimisticAllFlatEntityMaps.flatFieldMetadataMaps = + viewFieldResult.dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps; if (viewFieldResult.status === 'fail') { orchestratorFailureReport.viewField.push(...viewFieldResult.errors); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/metadata-entities-relation-targets.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/metadata-entities-relation-targets.type.ts index b26274a0ef..f10de44e29 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/metadata-entities-relation-targets.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/metadata-entities-relation-targets.type.ts @@ -1,3 +1,5 @@ +import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity'; +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { type DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { type IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity'; @@ -5,7 +7,6 @@ import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-meta import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type FieldPermissionEntity } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.entity'; import { type ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity'; -import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity'; export type MetadataEntitiesRelationTarget = | ObjectMetadataEntity @@ -15,4 +16,5 @@ export type MetadataEntitiesRelationTarget = | DataSourceEntity | ApplicationEntity | IndexMetadataEntity - | ObjectPermissionEntity; + | ObjectPermissionEntity + | ViewEntity; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/services/workspace-migration-v2-field-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service.ts similarity index 100% rename from packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/services/workspace-migration-v2-field-actions-builder.service.ts rename to packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service.ts diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service.ts similarity index 97% rename from packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service.ts rename to packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service.ts index f772b4cd13..1816d7f12f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service.ts @@ -19,9 +19,6 @@ export type ObjectMetadataRelatedFlatEntityMaps = Pick< 'flatFieldMetadataMaps' >; -// TODO find a solution in order to handle label indentifier validation -// export type ObjectMetadataRelatedFlatEntityMaps = undefined; - @Injectable() export class WorkspaceMigrationV2ObjectActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service< 'objectMetadata', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/types/view-field-related-flat-entity-maps.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/types/view-field-related-flat-entity-maps.type.ts index d695544991..e595a226b7 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/types/view-field-related-flat-entity-maps.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/types/view-field-related-flat-entity-maps.type.ts @@ -2,5 +2,5 @@ import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all export type ViewFieldRelatedFlatEntityMaps = Pick< AllFlatEntityMaps, - 'flatViewMaps' | 'flatFieldMetadataMaps' + 'flatViewMaps' | 'flatFieldMetadataMaps' | 'flatObjectMetadataMaps' >; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts index d550a505b1..18b34df2c1 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service.ts @@ -48,7 +48,7 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac > > { const validationResult = - await this.flatViewFieldValidatorService.validateFlatViewFieldCreation({ + this.flatViewFieldValidatorService.validateFlatViewFieldCreation({ dependencyOptimisticFlatEntityMaps, flatViewFieldToValidate, optimisticFlatViewFieldMaps, @@ -61,12 +61,30 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac }; } + const flatFieldMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: flatViewFieldToValidate.fieldMetadataId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + + const updatedFlatFieldMetadataMaps = + replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: { + ...flatFieldMetadata, + viewFieldIds: [ + ...flatFieldMetadata.viewFieldIds, + flatViewFieldToValidate.id, + ], + }, + flatEntityMaps: + dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + const flatView = findFlatEntityByIdInFlatEntityMapsOrThrow({ flatEntityId: flatViewFieldToValidate.viewId, flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewFields = replaceFlatEntityInFlatEntityMapsOrThrow({ + const updatedFlatViewMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ flatEntity: { ...flatView, viewFieldIds: [...flatView.viewFieldIds, flatViewFieldToValidate.id], @@ -82,7 +100,8 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac }, dependencyOptimisticFlatEntityMaps: { ...dependencyOptimisticFlatEntityMaps, - flatViewMaps: updatedFlatViewFields, + flatViewMaps: updatedFlatViewMaps, + flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, }, }; } @@ -115,12 +134,30 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac }; } + const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFieldToValidate.fieldMetadataId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + + const updatedFlatFieldMetadataMaps = isDefined(flatFieldMetadata) + ? replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: { + ...flatFieldMetadata, + viewFieldIds: flatFieldMetadata.viewFieldIds.filter( + (id) => id !== flatViewFieldToValidate.id, + ), + }, + flatEntityMaps: + dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }) + : dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps; + const flatView = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFieldToValidate.viewId, flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, }); - const updatedFlatViewFields = isDefined(flatView) + const updatedFlatViewMaps = isDefined(flatView) ? replaceFlatEntityInFlatEntityMapsOrThrow({ flatEntity: { ...flatView, @@ -140,7 +177,8 @@ export class WorkspaceMigrationV2ViewFieldActionsBuilderService extends Workspac }, dependencyOptimisticFlatEntityMaps: { ...dependencyOptimisticFlatEntityMaps, - flatViewMaps: updatedFlatViewFields, + flatViewMaps: updatedFlatViewMaps, + flatFieldMetadataMaps: updatedFlatFieldMetadataMaps, }, }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts index 09c0bd2722..d8ca841451 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service.ts @@ -1,6 +1,11 @@ import { Injectable } from '@nestjs/common'; +import { isDefined } from 'twenty-shared/utils'; + import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; import { FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type'; import { compareTwoFlatView } from 'src/engine/core-modules/view/flat-view/utils/compare-two-flat-view.util'; import { @@ -56,6 +61,19 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti ...validationResult, }; } + const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: flatViewToValidate.objectMetadataId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); + const updatedFlatObjectMetadataMaps = + replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: { + ...flatObjectMetadata, + viewIds: [...flatObjectMetadata.viewIds, flatViewToValidate.id], + }, + flatEntityMaps: + dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); return { status: 'success', @@ -63,7 +81,9 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti type: 'create_view', view: flatViewToValidate, }, - dependencyOptimisticFlatEntityMaps, + dependencyOptimisticFlatEntityMaps: { + flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, + }, }; } @@ -92,13 +112,33 @@ export class WorkspaceMigrationV2ViewActionsBuilderService extends WorkspaceEnti }; } + const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewToValidate.objectMetadataId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }); + + const updatedFlatObjectMetadataMaps = isDefined(flatObjectMetadata) + ? replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: { + ...flatObjectMetadata, + viewIds: flatObjectMetadata.viewIds.filter( + (id) => id !== flatViewToValidate.id, + ), + }, + flatEntityMaps: + dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps, + }) + : dependencyOptimisticFlatEntityMaps.flatObjectMetadataMaps; + return { status: 'success', action: { type: 'delete_view', viewId: flatViewToValidate.id, }, - dependencyOptimisticFlatEntityMaps, + dependencyOptimisticFlatEntityMaps: { + flatObjectMetadataMaps: updatedFlatObjectMetadataMaps, + }, }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts index b8e9baefc4..2b39773293 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts @@ -15,14 +15,16 @@ export type CreateViewFieldAction = { viewField: FlatViewField; }; +export type FlatViewFieldPropertiesUpdates = Array< + { + [P in FlatViewFieldPropertiesToCompare]: FlatViewFieldPropertyUpdate

; + }[FlatViewFieldPropertiesToCompare] +>; + export type UpdateViewFieldAction = { type: 'update_view_field'; viewFieldId: string; - updates: Array< - { - [P in FlatViewFieldPropertiesToCompare]: FlatViewFieldPropertyUpdate

; - }[FlatViewFieldPropertiesToCompare] - >; + updates: FlatViewFieldPropertiesUpdates; }; export type DeleteViewFieldAction = { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts index dce73b2b1b..d9d46857a1 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts @@ -9,7 +9,7 @@ import { validateFlatObjectMetadataIdentifiers } from 'src/engine/metadata-modul import { validateFlatObjectMetadataNameAndLabels } from 'src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-name-and-labels.util'; import { ObjectMetadataExceptionCode } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util'; -import { ObjectMetadataRelatedFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service'; +import { ObjectMetadataRelatedFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service'; import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; import { WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; import { FlatObjectPropertiesUpdates } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-object-action-v2'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts index 15fce382f8..883fddced7 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service.ts @@ -4,11 +4,14 @@ import { t } from '@lingui/core/macro'; import { isDefined } from 'twenty-shared/utils'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { ViewExceptionCode } from 'src/engine/core-modules/view/exceptions/view.exception'; import { FlatViewFieldMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-field-maps.type'; import { FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; +import { isViewFieldInLowestPosition } from 'src/engine/core-modules/view/flat-view/utils/is-view-field-in-lowest-position.util'; import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; import { ViewFieldRelatedFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/types/view-field-related-flat-entity-maps.type'; +import { validateLabelIdentifierFieldMetadataIdFlatViewField } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-label-identifier-field-metadata-id-flat-view-field.util'; type ViewFieldValidationArgs = { flatViewFieldToValidate: FlatViewField; @@ -19,53 +22,119 @@ type ViewFieldValidationArgs = { export class FlatViewFieldValidatorService { constructor() {} - // Should implement strict checking on field compared field and their integrity passing the update array would be the best public validateFlatViewFieldUpdate({ flatViewFieldToValidate: updatedFlatViewField, optimisticFlatViewFieldMaps, + dependencyOptimisticFlatEntityMaps: { + flatViewMaps, + flatObjectMetadataMaps, + }, }: ViewFieldValidationArgs): FailedFlatEntityValidation { - const errors = []; + const validationResult: FailedFlatEntityValidation = { + type: 'update_view_field', + errors: [], + flatEntityMinimalInformation: { + id: updatedFlatViewField.id, + }, + }; const existingFlatViewField = optimisticFlatViewFieldMaps.byId[updatedFlatViewField.id]; if (!isDefined(existingFlatViewField)) { - errors.push({ + validationResult.errors.push({ code: ViewExceptionCode.INVALID_VIEW_DATA, message: t`View field to update not found`, userFriendlyMessage: t`View field to update not found`, }); + + return validationResult; } - return { - type: 'update_view_field', - errors, - flatEntityMinimalInformation: { - id: updatedFlatViewField.id, - viewId: updatedFlatViewField.viewId, - fieldMetadataId: updatedFlatViewField.fieldMetadataId, - }, + validationResult.flatEntityMinimalInformation = { + id: updatedFlatViewField.id, + viewId: updatedFlatViewField.viewId, + fieldMetadataId: updatedFlatViewField.fieldMetadataId, }; + + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: updatedFlatViewField.viewId, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView)) { + validationResult.errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`View field to update parent view not found`, + userFriendlyMessage: t`View field to update parent view not found`, + }); + + return validationResult; + } + + const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatView.objectMetadataId, + flatEntityMaps: flatObjectMetadataMaps, + }); + + if (!isDefined(flatObjectMetadata)) { + validationResult.errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`View field to update parent view object not found`, + userFriendlyMessage: t`View field to update parent view object not found`, + }); + + return validationResult; + } + + if ( + flatObjectMetadata.labelIdentifierFieldMetadataId === + updatedFlatViewField.fieldMetadataId + ) { + const otherFlatViewFields = findManyFlatEntityByIdInFlatEntityMapsOrThrow( + { + flatEntityIds: flatView.viewFieldIds.filter( + (flatViewId) => flatViewId !== updatedFlatViewField.id, + ), + flatEntityMaps: optimisticFlatViewFieldMaps, + }, + ); + + validationResult.errors.push( + ...validateLabelIdentifierFieldMetadataIdFlatViewField({ + otherFlatViewFields, + flatViewFieldToValidate: updatedFlatViewField, + }), + ); + } + + return validationResult; } public validateFlatViewFieldDeletion({ optimisticFlatViewFieldMaps, flatViewFieldToValidate: { id: viewFieldIdToDelete }, }: ViewFieldValidationArgs): FailedFlatEntityValidation { - const errors = []; + const validationResult: FailedFlatEntityValidation = { + type: 'delete_view_field', + errors: [], + flatEntityMinimalInformation: { + id: viewFieldIdToDelete, + }, + }; const existingFlatViewField = optimisticFlatViewFieldMaps.byId[viewFieldIdToDelete]; if (!isDefined(existingFlatViewField)) { - errors.push({ + validationResult.errors.push({ code: ViewExceptionCode.INVALID_VIEW_DATA, message: t`View field to delete not found`, userFriendlyMessage: t`View field to delete not found`, }); } else { if (!isDefined(existingFlatViewField.deletedAt)) { - errors.push({ + validationResult.errors.push({ code: ViewExceptionCode.INVALID_VIEW_DATA, message: t`View field to delete has not been soft deleted`, userFriendlyMessage: t`View field to delete has not been soft deleted`, @@ -73,28 +142,31 @@ export class FlatViewFieldValidatorService { } } - return { - type: 'delete_view_field', - errors, - flatEntityMinimalInformation: { - id: viewFieldIdToDelete, - }, - }; + return validationResult; } - public async validateFlatViewFieldCreation({ + public validateFlatViewFieldCreation({ flatViewFieldToValidate, optimisticFlatViewFieldMaps, dependencyOptimisticFlatEntityMaps: { - flatViewMaps: optimisticFlatViewMaps, + flatViewMaps, flatFieldMetadataMaps, + flatObjectMetadataMaps, }, }: { flatViewFieldToValidate: FlatViewField; optimisticFlatViewFieldMaps: FlatViewFieldMaps; dependencyOptimisticFlatEntityMaps: ViewFieldRelatedFlatEntityMaps; - }): Promise> { - const errors = []; + }): FailedFlatEntityValidation { + const validationResult: FailedFlatEntityValidation = { + type: 'create_view_field', + errors: [], + flatEntityMinimalInformation: { + id: flatViewFieldToValidate.id, + viewId: flatViewFieldToValidate.viewId, + fieldMetadataId: flatViewFieldToValidate.fieldMetadataId, + }, + }; const existingFlatViewField = optimisticFlatViewFieldMaps.byId[flatViewFieldToValidate.id]; @@ -102,63 +174,100 @@ export class FlatViewFieldValidatorService { if (isDefined(existingFlatViewField)) { const flatViewFieldId = flatViewFieldToValidate.id; - errors.push({ + validationResult.errors.push({ code: ViewExceptionCode.INVALID_VIEW_DATA, message: t`View field metadata with id ${flatViewFieldId} already exists`, userFriendlyMessage: t`View field metadata already exists`, }); } - const relatedFlatView = - optimisticFlatViewMaps.byId[flatViewFieldToValidate.viewId]; - - if (!isDefined(relatedFlatView)) { - errors.push({ - code: ViewExceptionCode.INVALID_VIEW_DATA, - message: t`View not found`, - userFriendlyMessage: t`View not found`, - }); - } - - const relatedFlatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ + const flatFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ flatEntityId: flatViewFieldToValidate.fieldMetadataId, flatEntityMaps: flatFieldMetadataMaps, }); - if (!isDefined(relatedFlatFieldMetadata)) { - errors.push({ + if (!isDefined(flatFieldMetadata)) { + validationResult.errors.push({ code: ViewExceptionCode.INVALID_VIEW_DATA, message: t`Field metadata not found`, userFriendlyMessage: t`Field metadata not found`, }); } - const allFlatViewFields = Object.values( - optimisticFlatViewFieldMaps.byId, - ).filter(isDefined); - const matchingFlatView = allFlatViewFields.find( + const flatView = flatViewMaps.byId[flatViewFieldToValidate.viewId]; + + if (!isDefined(flatView)) { + validationResult.errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`View not found`, + userFriendlyMessage: t`View not found`, + }); + + return validationResult; + } + + const otherFlatViewFields = findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityIds: flatView.viewFieldIds, + flatEntityMaps: optimisticFlatViewFieldMaps, + }); + const equivalentExistingFlatViewFieldExists = otherFlatViewFields.some( (flatViewField) => flatViewField.viewId === flatViewFieldToValidate.viewId && flatViewField.fieldMetadataId === flatViewFieldToValidate.fieldMetadataId, ); - if (isDefined(matchingFlatView)) { - errors.push({ + if (equivalentExistingFlatViewFieldExists) { + validationResult.errors.push({ code: ViewExceptionCode.INVALID_VIEW_DATA, message: t`View field with same fieldmetadataId and viewId already exists`, userFriendlyMessage: t`View field already exists`, }); } - return { - type: 'create_view_field', - errors, - flatEntityMinimalInformation: { - id: flatViewFieldToValidate.id, - viewId: flatViewFieldToValidate.viewId, - fieldMetadataId: flatViewFieldToValidate.fieldMetadataId, - }, - }; + const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityMaps: flatObjectMetadataMaps, + flatEntityId: flatView.objectMetadataId, + }); + + if (!isDefined(flatObjectMetadata)) { + validationResult.errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`View field related view object metadata not found`, + userFriendlyMessage: t`View field related view object metadata not found`, + }); + + return validationResult; + } + + if ( + flatObjectMetadata.labelIdentifierFieldMetadataId === + flatViewFieldToValidate.fieldMetadataId + ) { + validationResult.errors.push( + ...validateLabelIdentifierFieldMetadataIdFlatViewField({ + flatViewFieldToValidate, + otherFlatViewFields, + }), + ); + } else if ( + otherFlatViewFields.some( + (flatViewField) => + flatViewField.fieldMetadataId === + flatObjectMetadata.labelIdentifierFieldMetadataId, + ) && + isViewFieldInLowestPosition({ + flatViewField: flatViewFieldToValidate, + otherFlatViewFields, + }) + ) { + validationResult.errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`View field position cannot be lower than label identifier view field position`, + userFriendlyMessage: t`View field position cannot be lower than label identifier view field position`, + }); + } + + return validationResult; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-label-identifier-field-metadata-id-flat-view-field.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-label-identifier-field-metadata-id-flat-view-field.util.ts new file mode 100644 index 0000000000..5848512c4b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/utils/validate-label-identifier-field-metadata-id-flat-view-field.util.ts @@ -0,0 +1,50 @@ +import { t } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; + +import { ViewExceptionCode } from 'src/engine/core-modules/view/exceptions/view.exception'; +import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; +import { isViewFieldInLowestPosition } from 'src/engine/core-modules/view/flat-view/utils/is-view-field-in-lowest-position.util'; +import { type FlatEntityValidationError } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; + +type ValidateLabelIdentifierFieldMetadataIdFlatViewFieldArgs = { + otherFlatViewFields: FlatViewField[]; + flatViewFieldToValidate: FlatViewField; +}; +export const validateLabelIdentifierFieldMetadataIdFlatViewField = ({ + otherFlatViewFields, + flatViewFieldToValidate, +}: ValidateLabelIdentifierFieldMetadataIdFlatViewFieldArgs): FlatEntityValidationError[] => { + const errors: FlatEntityValidationError[] = []; + + if ( + otherFlatViewFields.length > 0 && + !isViewFieldInLowestPosition({ + flatViewField: flatViewFieldToValidate, + otherFlatViewFields, + }) + ) { + errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`Label identifier view field has to be in the lowest position`, + userFriendlyMessage: t`Label identifier view field has to be in the lowest position`, + }); + } + + if (flatViewFieldToValidate.isVisible === false) { + errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`Label identifier view field has to be visible`, + userFriendlyMessage: t`Label identifier view field has to be visible`, + }); + } + + if (isDefined(flatViewFieldToValidate.deletedAt)) { + errors.push({ + code: ViewExceptionCode.INVALID_VIEW_DATA, + message: t`Label identifier view field cannot be deleted`, + userFriendlyMessage: t`Label identifier view field cannot be deleted`, + }); + } + + return errors; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts index 5dc5fa5473..cd283e8740 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts @@ -4,9 +4,9 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature- import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service'; import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service'; import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service'; -import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/services/workspace-migration-v2-field-actions-builder.service'; +import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service'; import { WorkspaceMigrationV2IndexActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service'; -import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service'; +import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/workspace-migration-v2-object-actions-builder.service'; import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service'; import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service'; import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/delete-object-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/delete-object-action-handler.service.ts index 202f8cfee5..da31008410 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/delete-object-action-handler.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/delete-object-action-handler.service.ts @@ -8,7 +8,7 @@ import { import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { isCompositeFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util'; import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; @@ -90,10 +90,11 @@ export class DeleteObjectActionHandlerService extends WorkspaceMigrationRunnerAc schemaName, tableName, }); - const { objectFlatFieldMetadatas } = findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata, - }); + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: flatObjectMetadata.fieldMetadataIds, + }); const enumOrCompositeFlatFieldMetadatas = objectFlatFieldMetadatas.filter( (field) => isEnumFlatFieldMetadata(field) || isCompositeFlatFieldMetadata(field), diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/update-object-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/update-object-action-handler.service.ts index 47060ac900..0e68a15835 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/update-object-action-handler.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/object/services/update-object-action-handler.service.ts @@ -7,8 +7,8 @@ import { import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; -import { findObjectFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util'; import { isCompositeFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util'; import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; @@ -121,10 +121,10 @@ export class UpdateObjectActionHandlerService extends WorkspaceMigrationRunnerAc newTableName, }); - const { objectFlatFieldMetadatas } = - findObjectFlatFieldMetadatasOrThrow({ - flatFieldMetadataMaps, - flatObjectMetadata: updatedObjectMetadata, + const objectFlatFieldMetadatas = + findManyFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityMaps: flatFieldMetadataMaps, + flatEntityIds: updatedObjectMetadata.fieldMetadataIds, }); const enumOrCompositeFlatFieldMetadatas = objectFlatFieldMetadatas.filter( diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts index eec43356b0..7bc4cdbdd9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/services/workspace-migration-runner-v2.service.ts @@ -85,7 +85,6 @@ export class WorkspaceMigrationRunnerV2Service { await queryRunner.commitTransaction(); this.logger.timeEnd('Runner', 'Transaction execution'); - this.logger.time('Runner', 'Cache invalidation'); const flatEntitiesCacheToInvalidate = [ ...new Set([ @@ -94,6 +93,10 @@ export class WorkspaceMigrationRunnerV2Service { ]), ]; + this.logger.time( + 'Runner', + `Cache invalidation ${flatEntitiesCacheToInvalidate.join()}`, + ); if ( flatEntitiesCacheToInvalidate.includes('flatObjectMetadataMaps') || flatEntitiesCacheToInvalidate.includes('flatFieldMetadataMaps') @@ -119,7 +122,10 @@ export class WorkspaceMigrationRunnerV2Service { ], }); - this.logger.timeEnd('Runner', 'Cache invalidation'); + this.logger.timeEnd( + 'Runner', + `Cache invalidation ${flatEntitiesCacheToInvalidate.join()}`, + ); this.logger.timeEnd('Runner', 'Total execution'); return allFlatEntityMaps; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts index 750ff045bf..7ccde7f91c 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts @@ -137,6 +137,7 @@ export class StandardFieldFactory { return [ { + viewFields: [], type: workspaceFieldMetadataArgs.type, standardId: workspaceFieldMetadataArgs.standardId, name: workspaceFieldMetadataArgs.name, @@ -186,6 +187,7 @@ export class StandardFieldFactory { } fieldMetadataCollection.push({ + viewFields: [], type: FieldMetadataType.RELATION, standardId: workspaceRelationMetadataArgs.standardId, name: workspaceRelationMetadataArgs.name, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util.ts index 905c4bd126..be58eda2be 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util.ts @@ -44,6 +44,7 @@ export const computeStandardFields = ( fields.push({ ...data, ...rest, + viewFields: [], standardId: relationStandardId, defaultValue: null, isNullable: true, diff --git a/packages/twenty-server/src/utils/__test__/get-field-metadata-entity.mock.ts b/packages/twenty-server/src/utils/__test__/get-field-metadata-entity.mock.ts index f36e8958a2..463e6f3001 100644 --- a/packages/twenty-server/src/utils/__test__/get-field-metadata-entity.mock.ts +++ b/packages/twenty-server/src/utils/__test__/get-field-metadata-entity.mock.ts @@ -19,6 +19,7 @@ export const getMockFieldMetadataEntity = < overrides: GetMockFieldMetadataEntityOverride, ): FieldMetadataEntity => { return { + viewFields: [], morphId: null, fieldPermissions: [], icon: null, 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 72050ad910..255facf0f9 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,6 +46,7 @@ export const getMockObjectMetadataEntity = ( targetRelationFields: [], standardOverrides: null, targetTableName: faker.string.uuid(), + views: [], ...overrides, }; }; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/failing-create-view-field-v2.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/failing-create-view-field-v2.integration-spec.ts deleted file mode 100644 index c3a50ccda5..0000000000 --- a/packages/twenty-server/test/integration/graphql/suites/view/failing-create-view-field-v2.integration-spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { createOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/create-one-core-view-field.util'; -import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; -import { - eachTestingContextFilter, - type EachTestingContext, -} from 'twenty-shared/testing'; -import { faker } from '@faker-js/faker'; - -import { type CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input'; - -import { - cleanupViewFieldTestV2, - setupViewFieldTestV2, - type ViewFieldTestSetup, -} from './utils/setup-view-field-test-v2.util'; - -describe('View Field Resolver - Failing Create Operation - v2', () => { - let testSetup: ViewFieldTestSetup; - - beforeAll(async () => { - testSetup = await setupViewFieldTestV2(); - }); - - afterAll(async () => { - await cleanupViewFieldTestV2(testSetup.testObjectMetadataId); - }); - - type CreateViewFieldTestCase = (testSetup: ViewFieldTestSetup) => { - input: CreateViewFieldInput; - }; - - const createViewFieldTestCases: EachTestingContext[] = - [ - { - title: 'non-existent field metadata', - context: (testSetup) => ({ - input: { - viewId: testSetup.testViewId, - fieldMetadataId: faker.string.uuid(), - }, - }), - }, - { - title: 'non-existent view metadata', - context: (testSetup) => ({ - input: { - viewId: faker.string.uuid(), - fieldMetadataId: testSetup.testFieldMetadataId, - }, - }), - }, - ]; - - it.each(eachTestingContextFilter(createViewFieldTestCases))( - 'should fail to create view field when $title', - async ({ context }) => { - const { input } = context(testSetup); - const response = await createOneCoreViewField({ - input, - expectToFail: true, - }); - - expect(response.errors).toBeDefined(); - expect(response.errors.length).toBe(1); - const [firstError] = response.errors; - - expect(firstError).toMatchSnapshot( - extractRecordIdsAndDatesAsExpectAny(firstError), - ); - }, - ); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap similarity index 66% rename from packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap index cf929eb4e8..71b69241c4 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap @@ -1,5 +1,57 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`View Field Resolver - Failing Create Operation - v2 Should fail to create a conflicting view field on view and field metadata 1`] = ` +{ + "extensions": { + "code": "BAD_USER_INPUT", + "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], + "fieldMetadata": [], + "index": [], + "objectMetadata": [], + "routeTrigger": [], + "serverlessFunction": [], + "view": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "View field with same fieldmetadataId and viewId already exists", + "userFriendlyMessage": "View field already exists", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], + }, + "message": "Validation failed for 0 object(s) and 0 field(s)", + "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, + "invalidFieldMetadata": 0, + "invalidIndex": 0, + "invalidObjectMetadata": 0, + "invalidRouteTrigger": 0, + "invalidServerlessFunction": 0, + "invalidView": 0, + "invalidViewField": 0, + "totalErrors": 0, + }, + "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", + }, + "message": "Multiple validation errors occurred while creating view field", + "name": "GraphQLError", +} +`; + exports[`View Field Resolver - Failing Create Operation - v2 should fail to create view field when non-existent field metadata 1`] = ` { "extensions": { diff --git a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-delete-view-field-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-delete-view-field-v2.integration-spec.ts.snap similarity index 100% rename from packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-delete-view-field-v2.integration-spec.ts.snap rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-delete-view-field-v2.integration-spec.ts.snap diff --git a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-destroy-view-field-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-destroy-view-field-v2.integration-spec.ts.snap similarity index 100% rename from packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-destroy-view-field-v2.integration-spec.ts.snap rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-destroy-view-field-v2.integration-spec.ts.snap diff --git a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-update-view-field-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-update-view-field-v2.integration-spec.ts.snap similarity index 100% rename from packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-update-view-field-v2.integration-spec.ts.snap rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-update-view-field-v2.integration-spec.ts.snap diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/object-identifier-update-side-effect-on-view-field.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/object-identifier-update-side-effect-on-view-field.integration-spec.ts.snap new file mode 100644 index 0000000000..78621d3046 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/object-identifier-update-side-effect-on-view-field.integration-spec.ts.snap @@ -0,0 +1,259 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`View Field Resolver - Successful object metadata identifier update side effect on view field Should not allow creating a view field with a position lower than the label identifier view field 1`] = ` +{ + "extensions": { + "code": "BAD_USER_INPUT", + "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], + "fieldMetadata": [], + "index": [], + "objectMetadata": [], + "routeTrigger": [], + "serverlessFunction": [], + "view": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "View field position cannot be lower than label identifier view field position", + "userFriendlyMessage": "View field position cannot be lower than label identifier view field position", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], + }, + "message": "Validation failed for 0 object(s) and 0 field(s)", + "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, + "invalidFieldMetadata": 0, + "invalidIndex": 0, + "invalidObjectMetadata": 0, + "invalidRouteTrigger": 0, + "invalidServerlessFunction": 0, + "invalidView": 0, + "invalidViewField": 0, + "totalErrors": 0, + }, + "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", + }, + "message": "Multiple validation errors occurred while creating view field", + "name": "GraphQLError", +} +`; + +exports[`View Field Resolver - Successful object metadata identifier update side effect on view field Should not allow deleting a label identifier view field 1`] = ` +{ + "extensions": { + "code": "BAD_USER_INPUT", + "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], + "fieldMetadata": [], + "index": [], + "objectMetadata": [], + "routeTrigger": [], + "serverlessFunction": [], + "view": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Label identifier view field cannot be deleted", + "userFriendlyMessage": "Label identifier view field cannot be deleted", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "update_view_field", + }, + ], + }, + "message": "Validation failed for 0 object(s) and 0 field(s)", + "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, + "invalidFieldMetadata": 0, + "invalidIndex": 0, + "invalidObjectMetadata": 0, + "invalidRouteTrigger": 0, + "invalidServerlessFunction": 0, + "invalidView": 0, + "invalidViewField": 0, + "totalErrors": 0, + }, + "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", + }, + "message": "Multiple validation errors occurred while deleting view field", + "name": "GraphQLError", +} +`; + +exports[`View Field Resolver - Successful object metadata identifier update side effect on view field Should not allow destroying a label identifier view field 1`] = ` +{ + "extensions": { + "code": "BAD_USER_INPUT", + "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], + "fieldMetadata": [], + "index": [], + "objectMetadata": [], + "routeTrigger": [], + "serverlessFunction": [], + "view": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "View field to delete has not been soft deleted", + "userFriendlyMessage": "View field to delete has not been soft deleted", + }, + ], + "flatEntityMinimalInformation": { + "id": Any, + }, + "status": "fail", + "type": "delete_view_field", + }, + ], + }, + "message": "Validation failed for 0 object(s) and 0 field(s)", + "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, + "invalidFieldMetadata": 0, + "invalidIndex": 0, + "invalidObjectMetadata": 0, + "invalidRouteTrigger": 0, + "invalidServerlessFunction": 0, + "invalidView": 0, + "invalidViewField": 0, + "totalErrors": 0, + }, + "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", + }, + "message": "Multiple validation errors occurred while deleting view field", + "name": "GraphQLError", +} +`; + +exports[`View Field Resolver - Successful object metadata identifier update side effect on view field Should not allow updating a label identifier view field visibility to false 1`] = ` +{ + "extensions": { + "code": "BAD_USER_INPUT", + "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], + "fieldMetadata": [], + "index": [], + "objectMetadata": [], + "routeTrigger": [], + "serverlessFunction": [], + "view": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Label identifier view field has to be visible", + "userFriendlyMessage": "Label identifier view field has to be visible", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "update_view_field", + }, + ], + }, + "message": "Validation failed for 0 object(s) and 0 field(s)", + "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, + "invalidFieldMetadata": 0, + "invalidIndex": 0, + "invalidObjectMetadata": 0, + "invalidRouteTrigger": 0, + "invalidServerlessFunction": 0, + "invalidView": 0, + "invalidViewField": 0, + "totalErrors": 0, + }, + "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", + }, + "message": "Multiple validation errors occurred while updating view field", + "name": "GraphQLError", +} +`; + +exports[`View Field Resolver - Successful object metadata identifier update side effect on view field Should not allow updating labelIdentifier view field with a position higher than existing other view field 1`] = ` +{ + "extensions": { + "code": "BAD_USER_INPUT", + "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], + "fieldMetadata": [], + "index": [], + "objectMetadata": [], + "routeTrigger": [], + "serverlessFunction": [], + "view": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Label identifier view field has to be in the lowest position", + "userFriendlyMessage": "Label identifier view field has to be in the lowest position", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "update_view_field", + }, + ], + }, + "message": "Validation failed for 0 object(s) and 0 field(s)", + "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, + "invalidFieldMetadata": 0, + "invalidIndex": 0, + "invalidObjectMetadata": 0, + "invalidRouteTrigger": 0, + "invalidServerlessFunction": 0, + "invalidView": 0, + "invalidViewField": 0, + "totalErrors": 0, + }, + "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", + }, + "message": "Multiple validation errors occurred while updating view field", + "name": "GraphQLError", +} +`; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-create-view-field-v2.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-create-view-field-v2.integration-spec.ts new file mode 100644 index 0000000000..37dceb8a75 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-create-view-field-v2.integration-spec.ts @@ -0,0 +1,149 @@ +import { faker } from '@faker-js/faker'; +import { createOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/create-one-core-view-field.util'; +import { deleteOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/delete-one-core-view-field.util'; +import { destroyOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/destroy-one-core-view-field.util'; +import { findCoreViewFields } from 'test/integration/metadata/suites/view-field/utils/find-core-view-fields.util'; +import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; +import { + eachTestingContextFilter, + type EachTestingContext, +} from 'twenty-shared/testing'; +import { + type ViewFieldTestSetup, + cleanupViewFieldTestV2, + setupViewFieldTestV2, +} from 'test/integration/graphql/suites/view/utils/setup-view-field-test-v2.util'; + +import { type CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input'; + +describe('View Field Resolver - Failing Create Operation - v2', () => { + let testSetup: ViewFieldTestSetup; + let createdFlatViewFieldIds: string[] = []; + + beforeAll(async () => { + testSetup = await setupViewFieldTestV2(); + }); + + afterEach(async () => { + for (const viewFieldId of createdFlatViewFieldIds) { + await deleteOneCoreViewField({ + input: { + id: viewFieldId, + }, + expectToFail: false, + }); + + await destroyOneCoreViewField({ + input: { + id: viewFieldId, + }, + expectToFail: false, + }); + } + }); + + afterAll(async () => { + await cleanupViewFieldTestV2(testSetup.testObjectMetadataId); + }); + + type CreateViewFieldTestCase = (testSetup: ViewFieldTestSetup) => { + input: CreateViewFieldInput; + }; + + const createViewFieldTestCases: EachTestingContext[] = + [ + { + title: 'non-existent field metadata', + context: (testSetup) => ({ + input: { + viewId: testSetup.testViewId, + fieldMetadataId: faker.string.uuid(), + }, + }), + }, + { + title: 'non-existent view metadata', + context: (testSetup) => ({ + input: { + viewId: faker.string.uuid(), + fieldMetadataId: testSetup.testFieldMetadataId, + }, + }), + }, + ]; + + it.each(eachTestingContextFilter(createViewFieldTestCases))( + 'should fail to create view field when $title', + async ({ context }) => { + const { input } = context(testSetup); + const response = await createOneCoreViewField({ + input, + expectToFail: true, + }); + + expect(response.errors).toBeDefined(); + expect(response.errors.length).toBe(1); + const [firstError] = response.errors; + + expect(firstError.extensions.code).not.toBe('INTERNAL_SERVER_ERROR'); + expect(firstError).toMatchSnapshot( + extractRecordIdsAndDatesAsExpectAny(firstError), + ); + }, + ); + + it('Should fail to create a conflicting view field on view and field metadata', async () => { + const viewFieldId = '20202020-7ace-42ee-aecf-2b1c1bd34bce'; + const { + data: { + createCoreViewField: { id: createdFlatViewFieldId }, + }, + } = await createOneCoreViewField({ + input: { + id: viewFieldId, + fieldMetadataId: testSetup.testFieldMetadataId, + viewId: testSetup.testViewId, + }, + expectToFail: false, + }); + + createdFlatViewFieldIds.push(createdFlatViewFieldId); + + const { + data: { getCoreViewFields }, + } = await findCoreViewFields({ + viewId: testSetup.testViewId, + expectToFail: false, + gqlFields: ` + id + fieldMetadataId + viewId + `, + }); + + expect(getCoreViewFields).toStrictEqual([ + { + id: viewFieldId, + fieldMetadataId: testSetup.testFieldMetadataId, + viewId: testSetup.testViewId, + }, + ]); + + const response = await createOneCoreViewField({ + input: { + fieldMetadataId: testSetup.testFieldMetadataId, + viewId: testSetup.testViewId, + }, + expectToFail: true, + }); + + expect(response.errors).toBeDefined(); + expect(response.errors.length).toBe(1); + const [firstError] = response.errors; + + expect(firstError.extensions.code).not.toBe('INTERNAL_SERVER_ERROR'); + expect(firstError).toMatchSnapshot( + extractRecordIdsAndDatesAsExpectAny(firstError), + ); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/view/failing-delete-view-field-v2.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-delete-view-field-v2.integration-spec.ts similarity index 95% rename from packages/twenty-server/test/integration/graphql/suites/view/failing-delete-view-field-v2.integration-spec.ts rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-delete-view-field-v2.integration-spec.ts index 4fc9107527..443a5d538d 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/failing-delete-view-field-v2.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-delete-view-field-v2.integration-spec.ts @@ -1,18 +1,17 @@ import { TEST_NOT_EXISTING_VIEW_FIELD_ID } from 'test/integration/constants/test-view-ids.constants'; import { deleteOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/delete-one-core-view-field.util'; +import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; import { eachTestingContextFilter, type EachTestingContext, } from 'twenty-shared/testing'; -import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; - -import { type DeleteViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/delete-view-field.input'; - import { + type ViewFieldTestSetup, cleanupViewFieldTestV2, setupViewFieldTestV2, - type ViewFieldTestSetup, -} from './utils/setup-view-field-test-v2.util'; +} from 'test/integration/graphql/suites/view/utils/setup-view-field-test-v2.util'; + +import { type DeleteViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/delete-view-field.input'; describe('View Field Resolver - Failing Delete Operation - v2', () => { let testSetup: ViewFieldTestSetup; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/failing-destroy-view-field-v2.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-destroy-view-field-v2.integration-spec.ts similarity index 95% rename from packages/twenty-server/test/integration/graphql/suites/view/failing-destroy-view-field-v2.integration-spec.ts rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-destroy-view-field-v2.integration-spec.ts index 73c2dcc288..645ce18ecb 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/failing-destroy-view-field-v2.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-destroy-view-field-v2.integration-spec.ts @@ -1,18 +1,17 @@ import { TEST_NOT_EXISTING_VIEW_FIELD_ID } from 'test/integration/constants/test-view-ids.constants'; import { destroyOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/destroy-one-core-view-field.util'; +import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; import { eachTestingContextFilter, type EachTestingContext, } from 'twenty-shared/testing'; -import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; - -import { type DestroyViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/destroy-view-field.input'; - import { + type ViewFieldTestSetup, cleanupViewFieldTestV2, setupViewFieldTestV2, - type ViewFieldTestSetup, -} from './utils/setup-view-field-test-v2.util'; +} from 'test/integration/graphql/suites/view/utils/setup-view-field-test-v2.util'; + +import { type DestroyViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/destroy-view-field.input'; describe('View Field Resolver - Failing Destroy Operation - v2', () => { let testSetup: ViewFieldTestSetup; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/failing-update-view-field-v2.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-update-view-field-v2.integration-spec.ts similarity index 95% rename from packages/twenty-server/test/integration/graphql/suites/view/failing-update-view-field-v2.integration-spec.ts rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-update-view-field-v2.integration-spec.ts index 014a668a6f..065018d194 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/failing-update-view-field-v2.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/failing-update-view-field-v2.integration-spec.ts @@ -1,18 +1,17 @@ import { TEST_NOT_EXISTING_VIEW_FIELD_ID } from 'test/integration/constants/test-view-ids.constants'; import { updateOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/update-one-core-view-field.util'; +import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; import { eachTestingContextFilter, type EachTestingContext, } from 'twenty-shared/testing'; -import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; - -import { type UpdateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/update-view-field.input'; - import { + type ViewFieldTestSetup, cleanupViewFieldTestV2, setupViewFieldTestV2, - type ViewFieldTestSetup, -} from './utils/setup-view-field-test-v2.util'; +} from 'test/integration/graphql/suites/view/utils/setup-view-field-test-v2.util'; + +import { type UpdateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/update-view-field.input'; describe('View Field Resolver - Failing Update Operation - v2', () => { let testSetup: ViewFieldTestSetup; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-field/object-identifier-update-side-effect-on-view-field.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field/object-identifier-update-side-effect-on-view-field.integration-spec.ts new file mode 100644 index 0000000000..e20e85d5b8 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/object-identifier-update-side-effect-on-view-field.integration-spec.ts @@ -0,0 +1,246 @@ +import { + type ViewFieldTestSetup, + cleanupViewFieldTestV2, + setupViewFieldTestV2, +} from 'test/integration/graphql/suites/view/utils/setup-view-field-test-v2.util'; +import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util'; +import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util'; +import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util'; +import { createOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/create-one-core-view-field.util'; +import { deleteOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/delete-one-core-view-field.util'; +import { destroyOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/destroy-one-core-view-field.util'; +import { findCoreViewFields } from 'test/integration/metadata/suites/view-field/utils/find-core-view-fields.util'; +import { updateOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/update-one-core-view-field.util'; +import { FieldMetadataType } from 'twenty-shared/types'; + +import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; + +describe('View Field Resolver - Successful object metadata identifier update side effect on view field', () => { + let testSetup: ViewFieldTestSetup & { + testLabelIdentifierViewFieldId: string; + }; + + beforeAll(async () => { + const { testFieldMetadataId, testObjectMetadataId, testViewId } = + await setupViewFieldTestV2(); + + await updateOneObjectMetadata({ + input: { + idToUpdate: testObjectMetadataId, + updatePayload: { + labelIdentifierFieldMetadataId: testFieldMetadataId, + }, + }, + expectToFail: false, + }); + + const { + data: { getCoreViewFields }, + } = await findCoreViewFields({ + viewId: testViewId, + expectToFail: false, + gqlFields: ` + id + fieldMetadataId + viewId + `, + }); + const testLabelIdentifierViewFieldId = getCoreViewFields[0].id; + + testSetup = { + testFieldMetadataId, + testObjectMetadataId, + testViewId, + testLabelIdentifierViewFieldId, + }; + }); + + afterAll(async () => { + await cleanupViewFieldTestV2(testSetup.testObjectMetadataId); + }); + + it('should create a view field on label identifier object metadata update if it does not exist on view', async () => { + const { testFieldMetadataId, testViewId } = testSetup; + const { + data: { getCoreViewFields }, + } = await findCoreViewFields({ + viewId: testViewId, + expectToFail: false, + gqlFields: ` + id + fieldMetadataId + viewId + `, + }); + + expect(getCoreViewFields).toMatchObject< + Pick[] + >([ + { + id: testSetup.testLabelIdentifierViewFieldId, + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, + }, + ]); + }); + + it('Should not allow deleting a label identifier view field', async () => { + const { errors } = await deleteOneCoreViewField({ + input: { id: testSetup.testLabelIdentifierViewFieldId }, + expectToFail: true, + }); + + expectOneNotInternalServerErrorSnapshot({ + errors, + }); + }); + + it('Should not allow destroying a label identifier view field', async () => { + const { errors } = await destroyOneCoreViewField({ + input: { id: testSetup.testLabelIdentifierViewFieldId }, + expectToFail: true, + }); + + expectOneNotInternalServerErrorSnapshot({ + errors, + }); + }); + + it('Should not allow updating a label identifier view field visibility to false', async () => { + const { errors } = await updateOneCoreViewField({ + input: { + id: testSetup.testLabelIdentifierViewFieldId, + update: { isVisible: false }, + }, + expectToFail: true, + }); + + expectOneNotInternalServerErrorSnapshot({ + errors, + }); + }); + + it('Should not allow creating a view field with a position lower than the label identifier view field', async () => { + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + expectToFail: false, + input: { + name: 'nonLabelIdentifierFieldFailing', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testSetup.testObjectMetadataId, + isLabelSyncedWithName: false, + }, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + const { errors } = await createOneCoreViewField({ + input: { + fieldMetadataId: fieldMetadataId, + viewId: testSetup.testViewId, + position: -42, + }, + expectToFail: true, + }); + + expectOneNotInternalServerErrorSnapshot({ + errors, + }); + }); + + it('Should not allow updating labelIdentifier view field with a position higher than existing other view field', async () => { + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + expectToFail: false, + input: { + name: 'nonLabelIdentifierFieldSuccessful', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testSetup.testObjectMetadataId, + isLabelSyncedWithName: false, + }, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + await createOneCoreViewField({ + input: { + fieldMetadataId: fieldMetadataId, + viewId: testSetup.testViewId, + position: 42, + }, + expectToFail: false, + }); + + const { errors } = await updateOneCoreViewField({ + input: { + id: testSetup.testLabelIdentifierViewFieldId, + update: { + position: 43, + }, + }, + expectToFail: true, + }); + + expectOneNotInternalServerErrorSnapshot({ + errors, + }); + }); + + it('Should update labelIdentifier view field with a position higher than existing other view field', async () => { + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + expectToFail: false, + input: { + name: 'justafield', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testSetup.testObjectMetadataId, + isLabelSyncedWithName: false, + }, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + await createOneCoreViewField({ + input: { + fieldMetadataId: fieldMetadataId, + viewId: testSetup.testViewId, + position: 42, + }, + expectToFail: false, + }); + + await updateOneCoreViewField({ + input: { + id: testSetup.testLabelIdentifierViewFieldId, + update: { + position: 41, + }, + }, + expectToFail: false, + }); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/view/successful-create-view-field-v2.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field/successful-create-view-field-v2.integration-spec.ts similarity index 98% rename from packages/twenty-server/test/integration/graphql/suites/view/successful-create-view-field-v2.integration-spec.ts rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/successful-create-view-field-v2.integration-spec.ts index 7f3965c087..0ea6b6325f 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/successful-create-view-field-v2.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/successful-create-view-field-v2.integration-spec.ts @@ -7,16 +7,15 @@ import { eachTestingContextFilter, } from 'twenty-shared/testing'; import { isDefined } from 'twenty-shared/utils'; +import { + type ViewFieldTestSetup, + cleanupViewFieldTestV2, + setupViewFieldTestV2, +} from 'test/integration/graphql/suites/view/utils/setup-view-field-test-v2.util'; import { type CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input'; import { type ViewFieldDTO } from 'src/engine/core-modules/view/dtos/view-field.dto'; -import { - cleanupViewFieldTestV2, - setupViewFieldTestV2, - type ViewFieldTestSetup, -} from './utils/setup-view-field-test-v2.util'; - type TestContext = { viewFieldInput: (testSetup: ViewFieldTestSetup) => CreateViewFieldInput; expected: Partial; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-field-resolver.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field/view-field-resolver.integration-spec.ts similarity index 100% rename from packages/twenty-server/test/integration/graphql/suites/view/view-field-resolver.integration-spec.ts rename to packages/twenty-server/test/integration/graphql/suites/view/view-field/view-field-resolver.integration-spec.ts diff --git a/packages/twenty-server/test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util.ts b/packages/twenty-server/test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util.ts new file mode 100644 index 0000000000..7379a364cc --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util.ts @@ -0,0 +1,17 @@ +import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; + +import { type BaseGraphQLError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; + +export const expectOneNotInternalServerErrorSnapshot = ({ + errors, +}: { + errors: BaseGraphQLError[]; +}) => { + expect(errors.length).toBe(1); + const [firstError] = errors; + + expect(firstError.extensions.code).not.toBe('INTERNAL_SERVER_ERROR'); + expect(firstError).toMatchSnapshot( + extractRecordIdsAndDatesAsExpectAny(firstError), + ); +}; diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap index 13f100c0d6..26db3207ee 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap @@ -355,7 +355,239 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -732,7 +964,239 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1109,7 +1573,239 @@ exports[`Object metadata creation should fail v2 when labelPlural is empty 1`] = "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1486,7 +2182,239 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1863,7 +2791,239 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2240,7 +3400,239 @@ exports[`Object metadata creation should fail v2 when labelSingular is empty 1`] "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2618,7 +4010,239 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] = "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2996,7 +4620,239 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3403,7 +5259,239 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3780,7 +5868,239 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -4157,7 +6477,239 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -4539,7 +7091,239 @@ exports[`Object metadata creation should fail v2 when namePlural is an empty str "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -4921,7 +7705,239 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -5363,7 +8379,239 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -5805,7 +9053,239 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -6212,7 +9692,239 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -6619,7 +10331,239 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -7061,7 +11005,239 @@ exports[`Object metadata creation should fail v2 when nameSingular is an empty s "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -7503,7 +11679,239 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -7881,7 +12289,239 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] = "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -8259,7 +12899,239 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res "type": "create_view", }, ], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View not found", + "userFriendlyMessage": "View not found", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap index 36ddc0a97b..f4c9cafd7c 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap @@ -31,7 +31,24 @@ exports[`Object metadata update should fail when labelIdentifier is not a TEXT o "routeTrigger": [], "serverlessFunction": [], "view": [], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "View field position cannot be lower than label identifier view field position", + "userFriendlyMessage": "View field position cannot be lower than label identifier view field position", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -85,7 +102,29 @@ exports[`Object metadata update should fail when labelIdentifier is not a known "routeTrigger": [], "serverlessFunction": [], "view": [], - "viewField": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "Field metadata not found", + "userFriendlyMessage": "Field metadata not found", + }, + { + "code": "INVALID_VIEW_DATA", + "message": "View field position cannot be lower than label identifier view field position", + "userFriendlyMessage": "View field position cannot be lower than label identifier view field position", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts index 6a66ad343c..ebbbfbe695 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/rename-custom-object.integration-spec.ts @@ -90,6 +90,7 @@ describe('Custom object renaming', () => { // Act const { data } = await createOneObjectMetadata({ + expectToFail: false, input: CUSTOM_OBJECT, gqlFields: ` id @@ -141,6 +142,7 @@ describe('Custom object renaming', () => { // Act const { data } = await updateOneObjectMetadata({ + expectToFail: false, gqlFields: ` nameSingular labelSingular diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/view-side-effect-on-object-metadata-creation.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/view-side-effect-on-object-metadata-creation.integration-spec.ts new file mode 100644 index 0000000000..a6338c5c56 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/view-side-effect-on-object-metadata-creation.integration-spec.ts @@ -0,0 +1,98 @@ +import { CUSTOM_OBJECT_DISHES } from 'test/integration/metadata/suites/object-metadata/constants/custom-object-dishes.constants'; +import { type CreateOneObjectFactoryInput } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata-query-factory.util'; +import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util'; +import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util'; +import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util'; +import { findCoreViewFields } from 'test/integration/metadata/suites/view-field/utils/find-core-view-fields.util'; +import { findCoreViews } from 'test/integration/metadata/suites/view/utils/find-core-views.util'; +import { isDefined } from 'twenty-shared/utils'; + +import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type'; + +describe('View side effect on object creation', () => { + let createdObjectMetadataId: string | undefined = undefined; + + afterEach(async () => { + if (!isDefined(createdObjectMetadataId)) { + return; + } + await updateOneObjectMetadata({ + expectToFail: false, + input: { + idToUpdate: createdObjectMetadataId, + updatePayload: { + isActive: false, + }, + }, + }); + + await deleteOneObjectMetadata({ + input: { idToDelete: createdObjectMetadataId }, + expectToFail: false, + }); + + createdObjectMetadataId = undefined; + }); + it('should create a view and view field for default custom objects standard fields on object metadata creation', async () => { + const { + labelPlural, + description, + labelSingular, + namePlural, + nameSingular, + } = CUSTOM_OBJECT_DISHES; + const createObjectInput: CreateOneObjectFactoryInput = { + labelPlural, + description, + labelSingular, + namePlural, + nameSingular, + icon: 'IconBuildingSkyscraper', + isLabelSyncedWithName: false, + }; + const objectCreationGqlFields = ` + id + labelPlural + description + labelSingular + namePlural + nameSingular + icon + isLabelSyncedWithName + `; + + const { + data: { createOneObject }, + } = await createOneObjectMetadata({ + expectToFail: false, + input: createObjectInput, + gqlFields: objectCreationGqlFields, + }); + + createdObjectMetadataId = createOneObject.id; + + const { + data: { getCoreViews: createdViews }, + } = await findCoreViews({ + objectMetadataId: createdObjectMetadataId, + expectToFail: false, + }); + + expect(createdViews).toBeDefined(); + expect(createdViews.length).toBe(1); + const [firstView] = createdViews; + + expect(firstView).toMatchObject>({ + objectMetadataId: createdObjectMetadataId, + }); + + const { + data: { getCoreViewFields: createdViewFields }, + } = await findCoreViewFields({ + viewId: firstView.id, + expectToFail: false, + }); + + expect(createdViewFields.length).toBe(11); + }); +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-field/utils/find-core-view-fields-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-field/utils/find-core-view-fields-query-factory.util.ts new file mode 100644 index 0000000000..58a4a0157e --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-field/utils/find-core-view-fields-query-factory.util.ts @@ -0,0 +1,21 @@ +import gql from 'graphql-tag'; +import { VIEW_FIELD_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; + +export const findCoreViewFieldsQueryFactory = ({ + gqlFields = VIEW_FIELD_GQL_FIELDS, + viewId, +}: { + gqlFields?: string; + viewId: string; +}) => ({ + query: gql` + query GetCoreViewFields($viewId: String!) { + getCoreViewFields(viewId: $viewId) { + ${gqlFields} + } + } + `, + variables: { + viewId, + }, +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-field/utils/find-core-view-fields.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-field/utils/find-core-view-fields.util.ts new file mode 100644 index 0000000000..cac3d1088b --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-field/utils/find-core-view-fields.util.ts @@ -0,0 +1,42 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { findCoreViewFieldsQueryFactory } from 'test/integration/metadata/suites/view-field/utils/find-core-view-fields-query-factory.util'; +import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type'; +import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util'; +import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util'; + +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; + +export const findCoreViewFields = async ({ + viewId, + gqlFields, + expectToFail, +}: { + viewId: string; + gqlFields?: string; + expectToFail?: boolean; +}): CommonResponseBody<{ + getCoreViewFields: ViewFieldEntity[]; +}> => { + const graphqlOperation = findCoreViewFieldsQueryFactory({ + viewId, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: 'View Field search should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: 'View Field search has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +}; diff --git a/packages/twenty-server/test/integration/metadata/suites/view/utils/find-core-views-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view/utils/find-core-views-query-factory.util.ts new file mode 100644 index 0000000000..d0f8d7236d --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view/utils/find-core-views-query-factory.util.ts @@ -0,0 +1,19 @@ +import gql from 'graphql-tag'; +import { VIEW_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; + +export const findCoreViewsQueryFactory = ({ + gqlFields = VIEW_GQL_FIELDS, + objectMetadataId, +}: { + gqlFields?: string; + objectMetadataId?: string; +}) => ({ + query: gql` + query GetCoreViews($objectMetadataId: String) { + getCoreViews(objectMetadataId: $objectMetadataId) { + ${gqlFields} + } + } + `, + variables: objectMetadataId ? { objectMetadataId } : {}, +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view/utils/find-core-views.util.ts b/packages/twenty-server/test/integration/metadata/suites/view/utils/find-core-views.util.ts new file mode 100644 index 0000000000..a0df11d4bc --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view/utils/find-core-views.util.ts @@ -0,0 +1,42 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { findCoreViewsQueryFactory } from 'test/integration/metadata/suites/view/utils/find-core-views-query-factory.util'; +import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type'; +import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util'; +import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util'; + +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; + +export const findCoreViews = async ({ + objectMetadataId, + gqlFields, + expectToFail, +}: { + objectMetadataId?: string; + gqlFields?: string; + expectToFail?: boolean; +}): CommonResponseBody<{ + getCoreViews: ViewEntity[]; +}> => { + const graphqlOperation = findCoreViewsQueryFactory({ + objectMetadataId, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: 'View search should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: 'View search has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +};