From a0a575fa0b852702693be451b570d8ed1bb26962 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Wed, 23 Jul 2025 13:43:27 +0200 Subject: [PATCH] Improve FieldMetadataEntity defaultValue, settings and options typing (#13320) # Introduction Following https://github.com/twentyhq/twenty/pull/13264, this PR introduces several `fieldMetadataEntity` typing enhancement suggestions. Mainly any nullable field metadata entity properties are now either nullable or defined. Or never if field is dynamically required or not depending on the field metadata type This enhance DevX ## Standards - field enum ( `MULTI_SELECT`, `SELECT`, `RATING` ) will never have `options` set to `NULL` in db - field `RELATION` or `MORH_RELATION` won't ever have its relation fields set to `NULL` in db - field of any type `settings`, even if possibly defined, can still be `NULL` in db - field of any type `defaultValue`, even if possibly defined, can still be `NULL` in db It coud be interesting to guard these standards by adding dedicated pg constraints on each field ## TypesScript type tests added coverage for each `settings`, `defaultValue`, and `options` depending on the current `fieldMetadata` Honestly I don' know if this typescript assertions test file is not overkill, but regarding metadata staticness it might be very interesting to have this guard ## Possible improvements - We could type as `unknown` instead of "all" on `FieldMetadataType` inferrance - We still need to deprecate remaining duplicated entities such as `Index/Field/MetadataInterface` etc not a huge refactor neither urgent --- .../__mocks__/object-metadata-item.mock.ts | 1 - .../__mocks__/mockPersonObjectMetadata.ts | 9 +- .../__tests__/get-field-type.utils.spec.ts | 3 +- ...ld-metadata-to-graphql-query.utils.spec.ts | 19 +- .../mocks/opportunity-field-maps.mock.ts | 44 +-- .../check-filter-enum-values.spec.ts | 3 +- .../__tests__/parse-filter.utils.spec.ts | 5 +- .../__tests__/filter-input.factory.spec.ts | 7 +- .../compute-cursor-arg-filter.utils.spec.ts | 7 +- .../mockObjectMetadataItemsWithFieldMaps.ts | 11 +- .../field-metadata/dtos/field-metadata.dto.ts | 2 +- .../field-metadata/field-metadata.entity.ts | 13 +- .../before-update-one-field.hook.spec.ts | 10 +- .../field-metadata-default-value.interface.ts | 2 +- .../field-metadata-options.interface.ts | 2 +- .../field-metadata-settings.interface.ts | 11 +- .../field-metadata-enum-validation.service.ts | 15 +- .../field-metadata-morph-relation.service.ts | 2 +- .../field-metadata-relation.service.ts | 36 +- .../field-metadata-validation.service.ts | 37 ++- .../services/field-metadata.service.ts | 2 +- .../types/field-metadata-entity-test.type.ts | 307 +++++++++++++++++- .../field-metadata-validation.service.spec.ts | 19 +- .../object-metadata/object-metadata.entity.ts | 2 +- .../object-metadata-field-relation.service.ts | 5 +- .../field-permissions.service.spec.ts | 3 +- .../remote-table-relations.service.ts | 28 +- .../__tests__/get-flat-field-metadata.mock.ts | 12 +- .../workspace-migration-builder.spec.ts.snap | 177 ++++++---- ...space-migration-builder-field-test-case.ts | 10 +- ...pace-migration-builder-object-test-case.ts | 2 + .../factories/standard-field.factory.ts | 5 +- .../utils/compute-standard-fields.util.ts | 2 + .../get-field-metadata-entity.mock.ts | 8 +- .../src/types/NullablePartial.ts | 3 + packages/twenty-shared/src/types/index.ts | 1 + 36 files changed, 611 insertions(+), 214 deletions(-) create mode 100644 packages/twenty-shared/src/types/NullablePartial.ts diff --git a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts index 4fe2615379..bbdb192546 100644 --- a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts +++ b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts @@ -131,7 +131,6 @@ export const fieldRelationMock = getMockFieldMetadataEntity({ type: FieldMetadataType.RELATION, label: 'Field Relation', isNullable: true, - defaultValue: null, settings: { relationType: RelationType.MANY_TO_ONE, joinColumnName: 'fieldRelationId', diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/__mocks__/mockPersonObjectMetadata.ts b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/__mocks__/mockPersonObjectMetadata.ts index cbc495d4ed..63209e3661 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/__mocks__/mockPersonObjectMetadata.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-query-runner/__mocks__/mockPersonObjectMetadata.ts @@ -1,7 +1,6 @@ import { FieldMetadataType } from 'twenty-shared/types'; import { WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; import { getMockObjectMetadataItemWithFieldsMaps } from 'src/utils/__test__/get-object-metadata-item-with-fields-maps.mock'; @@ -57,7 +56,7 @@ export const mockPersonObjectMetadataWithFieldMaps = ( isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), 'emails-id': getMockFieldMetadataEntity({ workspaceId, objectMetadataId: '', @@ -75,7 +74,7 @@ export const mockPersonObjectMetadataWithFieldMaps = ( isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), 'linkedinLink-id': getMockFieldMetadataEntity({ workspaceId, objectMetadataId: '', @@ -95,7 +94,7 @@ export const mockPersonObjectMetadataWithFieldMaps = ( isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), 'jobTitle-id': getMockFieldMetadataEntity({ workspaceId, objectMetadataId: '', @@ -111,6 +110,6 @@ export const mockPersonObjectMetadataWithFieldMaps = ( isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), }, }); diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/get-field-type.utils.spec.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/get-field-type.utils.spec.ts index 4f07077c9a..7830c675f4 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/get-field-type.utils.spec.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/get-field-type.utils.spec.ts @@ -5,7 +5,6 @@ import { objectMetadataItemMock, } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { getFieldType } from 'src/engine/api/rest/core/query-builder/utils/get-field-type.utils'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; @@ -25,7 +24,7 @@ describe('getFieldType', () => { }); const fieldsById: FieldMetadataMap = { - 'field-number-id': completeFieldNumberMock as FieldMetadataEntity, + 'field-number-id': completeFieldNumberMock, }; const mockObjectMetadataWithFieldMaps = { diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/map-field-metadata-to-graphql-query.utils.spec.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/map-field-metadata-to-graphql-query.utils.spec.ts index 813e65bf9c..09e3bc0c2d 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/map-field-metadata-to-graphql-query.utils.spec.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/map-field-metadata-to-graphql-query.utils.spec.ts @@ -1,6 +1,6 @@ import { FieldMetadataType } from 'twenty-shared/types'; -import { FieldMetadataDefaultSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; +import { FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; import { @@ -10,7 +10,6 @@ import { objectMetadataItemMock, } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; @@ -60,9 +59,9 @@ describe('mapFieldMetadataToGraphqlQuery', () => { }); const fieldsById: FieldMetadataMap = { - 'field-number-id': typedFieldNumberMock as FieldMetadataEntity, - 'field-text-id': typedFieldTextMock as FieldMetadataEntity, - 'field-currency-id': typedFieldCurrencyMock as FieldMetadataEntity, + 'field-number-id': typedFieldNumberMock, + 'field-text-id': typedFieldTextMock, + 'field-currency-id': typedFieldCurrencyMock, }; const typedObjectMetadataItem: ObjectMetadataItemWithFieldMaps = { @@ -90,19 +89,19 @@ describe('mapFieldMetadataToGraphqlQuery', () => { expect( mapFieldMetadataToGraphqlQuery( objectMetadataMapsMock, - typedFieldNumberMock as FieldMetadataEntity, + typedFieldNumberMock, ), ).toEqual('fieldNumber'); expect( mapFieldMetadataToGraphqlQuery( objectMetadataMapsMock, - typedFieldTextMock as FieldMetadataEntity, + typedFieldTextMock, ), ).toEqual('fieldText'); expect( mapFieldMetadataToGraphqlQuery( objectMetadataMapsMock, - typedFieldCurrencyMock as FieldMetadataEntity, + typedFieldCurrencyMock, ), ).toEqual(` fieldCurrency @@ -132,8 +131,8 @@ describe('mapFieldMetadataToGraphqlQuery', () => { fieldMetadataType === FieldMetadataType.MORPH_RELATION ? ({ relationType: RelationType.MANY_TO_ONE, - } as FieldMetadataDefaultSettings) - : undefined, + } as FieldMetadataRelationSettings) + : null, }); expect( diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/mocks/opportunity-field-maps.mock.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/mocks/opportunity-field-maps.mock.ts index af78bf96d6..9d70f7476d 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/mocks/opportunity-field-maps.mock.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/mocks/opportunity-field-maps.mock.ts @@ -4,7 +4,6 @@ import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/in import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; import { getMockObjectMetadataItemWithFieldsMaps } from 'src/utils/__test__/get-object-metadata-item-with-fields-maps.mock'; @@ -50,7 +49,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-5eef-417a-b517-ebeedaa8e10b': getMockFieldMetadataEntity({ id: '20202020-5eef-417a-b517-ebeedaa8e10b', workspaceId, @@ -69,7 +68,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-597c-44d3-98ec-ea71aea5256b': getMockFieldMetadataEntity({ id: '20202020-597c-44d3-98ec-ea71aea5256b', workspaceId, @@ -88,7 +87,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-9b94-454a-94ca-8afb09c68faf': getMockFieldMetadataEntity({ id: '20202020-9b94-454a-94ca-8afb09c68faf', workspaceId, @@ -144,7 +143,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-30a5-4d8e-9b93-12d31ece0aaa': getMockFieldMetadataEntity({ id: '20202020-30a5-4d8e-9b93-12d31ece0aaa', workspaceId, @@ -163,7 +162,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-f95f-424f-ab32-65961e8e9635': getMockFieldMetadataEntity({ id: '20202020-f95f-424f-ab32-65961e8e9635', workspaceId, @@ -182,7 +181,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-5e10-4780-babb-38a465ac546c': getMockFieldMetadataEntity({ id: '20202020-5e10-4780-babb-38a465ac546c', workspaceId, @@ -201,7 +200,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-8f4a-4f8d-822e-90fe72f75b79': getMockFieldMetadataEntity({ id: '20202020-8f4a-4f8d-822e-90fe72f75b79', workspaceId, @@ -220,7 +219,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-f120-4b59-b239-f7f1d8eb243e': getMockFieldMetadataEntity({ id: '20202020-f120-4b59-b239-f7f1d8eb243e', workspaceId, @@ -240,7 +239,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: false, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-dcc8-4318-9756-b87377692561': getMockFieldMetadataEntity({ id: '20202020-dcc8-4318-9756-b87377692561', workspaceId, @@ -260,7 +259,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: false, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-1694-4f8b-8760-61a5ff330022': getMockFieldMetadataEntity({ id: '20202020-1694-4f8b-8760-61a5ff330022', workspaceId, @@ -280,7 +279,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: false, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-4f52-4dea-a116-723f9bf7f082': getMockFieldMetadataEntity({ id: '20202020-4f52-4dea-a116-723f9bf7f082', workspaceId, @@ -288,7 +287,6 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = type: FieldMetadataType.RELATION, name: 'pointOfContact', label: 'Point of Contact', - defaultValue: null, description: 'The point of contact for this opportunity', icon: 'IconUser', settings: { @@ -304,7 +302,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-fc02-4be2-be1a-e121daf5400d': getMockFieldMetadataEntity({ id: '20202020-fc02-4be2-be1a-e121daf5400d', workspaceId, @@ -312,7 +310,6 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = type: FieldMetadataType.RELATION, name: 'company', label: 'Company', - defaultValue: null, description: 'The company this opportunity is associated with', icon: 'IconBuildingSkyscraper', settings: { @@ -328,7 +325,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-fd9f-48f0-bd5f-5b0fec6a5de4': getMockFieldMetadataEntity({ id: '20202020-fd9f-48f0-bd5f-5b0fec6a5de4', workspaceId, @@ -336,7 +333,6 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = type: FieldMetadataType.RELATION, name: 'favorites', label: 'Favorites', - defaultValue: null, description: 'Users who favorited this opportunity', icon: 'IconStar', settings: { @@ -351,7 +347,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-88ab-4138-98ce-80533bb423e3': getMockFieldMetadataEntity({ id: '20202020-88ab-4138-98ce-80533bb423e3', workspaceId, @@ -359,7 +355,6 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = type: FieldMetadataType.RELATION, name: 'taskTargets', label: 'Task Targets', - defaultValue: null, description: 'Tasks targeting this opportunity', icon: 'IconCheckbox', settings: { @@ -374,7 +369,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-4258-422b-b35b-db3f090af8da': getMockFieldMetadataEntity({ id: '20202020-4258-422b-b35b-db3f090af8da', workspaceId, @@ -382,7 +377,6 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = type: FieldMetadataType.RELATION, name: 'noteTargets', label: 'Note Targets', - defaultValue: null, description: 'Notes targeting this opportunity', icon: 'IconNotes', settings: { @@ -397,7 +391,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-16ca-40a7-a1ba-712975c916cd': getMockFieldMetadataEntity({ id: '20202020-16ca-40a7-a1ba-712975c916cd', workspaceId, @@ -405,7 +399,6 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = type: FieldMetadataType.RELATION, name: 'attachments', label: 'Attachments', - defaultValue: null, description: 'Attachments for this opportunity', icon: 'IconPaperclip', settings: { @@ -420,7 +413,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), '20202020-92a5-47bf-a38d-c1c72b2c3e4d': getMockFieldMetadataEntity({ id: '20202020-92a5-47bf-a38d-c1c72b2c3e4d', workspaceId, @@ -428,7 +421,6 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = type: FieldMetadataType.RELATION, name: 'timelineActivities', label: 'Timeline Activities', - defaultValue: null, description: 'Timeline activities for this opportunity', icon: 'IconTimeline', settings: { @@ -443,7 +435,7 @@ export const OPPORTUNITY_WITH_FIELDS_MAPS = isLabelSyncedWithName: true, createdAt: new Date('2025-06-27T12:55:13.271Z'), updatedAt: new Date('2025-06-27T12:55:13.271Z'), - }) as FieldMetadataEntity, + }), }, fieldIdByName: { name: '20202020-c2f1-4435-adca-22931f8b41b6', diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/check-filter-enum-values.spec.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/check-filter-enum-values.spec.ts index bb8d321a5c..cfe5fabefc 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/check-filter-enum-values.spec.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/check-filter-enum-values.spec.ts @@ -5,7 +5,6 @@ import { objectMetadataItemMock, } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { checkFilterEnumValues } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/check-filter-enum-values'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; @@ -26,7 +25,7 @@ describe('checkFilterEnumValues', () => { }); const fieldsById: FieldMetadataMap = { - 'field-select-id': completeFieldSelectMock as FieldMetadataEntity, + 'field-select-id': completeFieldSelectMock, }; const mockObjectMetadataWithFieldMaps = { diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/parse-filter.utils.spec.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/parse-filter.utils.spec.ts index 7cd0d0048d..56d79c056c 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/parse-filter.utils.spec.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/filter-utils/__tests__/parse-filter.utils.spec.ts @@ -4,7 +4,6 @@ import { objectMetadataItemMock, } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { parseFilter } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter.utils'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; @@ -39,8 +38,8 @@ describe('parseFilter', () => { }); const fieldsById: FieldMetadataMap = { - 'field-number-id': completeFieldNumberMock as FieldMetadataEntity, - 'field-text-id': completeFieldTextMock as FieldMetadataEntity, + 'field-number-id': completeFieldNumberMock, + 'field-text-id': completeFieldTextMock, }; const mockObjectMetadataWithFieldMaps: ObjectMetadataItemWithFieldMaps = { diff --git a/packages/twenty-server/src/engine/api/rest/input-factories/__tests__/filter-input.factory.spec.ts b/packages/twenty-server/src/engine/api/rest/input-factories/__tests__/filter-input.factory.spec.ts index c7b220825f..51e45a4de4 100644 --- a/packages/twenty-server/src/engine/api/rest/input-factories/__tests__/filter-input.factory.spec.ts +++ b/packages/twenty-server/src/engine/api/rest/input-factories/__tests__/filter-input.factory.spec.ts @@ -7,7 +7,6 @@ import { objectMetadataMapItemMock, } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { FilterInputFactory } from 'src/engine/api/rest/input-factories/filter-input.factory'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map'; import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; @@ -27,7 +26,7 @@ describe('FilterInputFactory', () => { isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); const completeFieldTextMock = getMockFieldMetadataEntity({ workspaceId, @@ -41,7 +40,7 @@ describe('FilterInputFactory', () => { isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); const completeFieldCurrencyMock = getMockFieldMetadataEntity({ workspaceId, @@ -55,7 +54,7 @@ describe('FilterInputFactory', () => { isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); const fieldsById: FieldMetadataMap = { 'field-number-id': completeFieldNumberMock, diff --git a/packages/twenty-server/src/engine/api/utils/__tests__/compute-cursor-arg-filter.utils.spec.ts b/packages/twenty-server/src/engine/api/utils/__tests__/compute-cursor-arg-filter.utils.spec.ts index 8deb8ef579..9b2c04ebff 100644 --- a/packages/twenty-server/src/engine/api/utils/__tests__/compute-cursor-arg-filter.utils.spec.ts +++ b/packages/twenty-server/src/engine/api/utils/__tests__/compute-cursor-arg-filter.utils.spec.ts @@ -4,7 +4,6 @@ import { OrderByDirection } from 'src/engine/api/graphql/workspace-query-builder import { GraphqlQueryRunnerException } from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception'; import { computeCursorArgFilter } from 'src/engine/api/utils/compute-cursor-arg-filter.utils'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; import { getMockObjectMetadataItemWithFieldsMaps } from 'src/utils/__test__/get-object-metadata-item-with-fields-maps.mock'; @@ -44,7 +43,7 @@ describe('computeCursorArgFilter', () => { isNullable: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), 'age-id': getMockFieldMetadataEntity({ workspaceId: 'workspace-id', objectMetadataId: 'object-id', @@ -56,7 +55,7 @@ describe('computeCursorArgFilter', () => { isNullable: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), 'fullname-id': getMockFieldMetadataEntity({ workspaceId: 'workspace-id', objectMetadataId: 'object-id', @@ -68,7 +67,7 @@ describe('computeCursorArgFilter', () => { isNullable: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), }, }); diff --git a/packages/twenty-server/src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps.ts b/packages/twenty-server/src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps.ts index 0ed9df1077..297b2a8e82 100644 --- a/packages/twenty-server/src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps.ts +++ b/packages/twenty-server/src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps.ts @@ -1,6 +1,5 @@ import { FieldMetadataType } from 'twenty-shared/types'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { getMockFieldMetadataEntity } from 'src/utils/__test__/get-field-metadata-entity.mock'; import { getMockObjectMetadataItemWithFieldsMaps } from 'src/utils/__test__/get-object-metadata-item-with-fields-maps.mock'; @@ -47,7 +46,7 @@ export const mockObjectMetadataItemsWithFieldMaps = [ isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), }, fieldIdByName: { name: 'nameFieldMetadataId', @@ -90,7 +89,7 @@ export const mockObjectMetadataItemsWithFieldMaps = [ isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), domainNameFieldMetadataId: getMockFieldMetadataEntity({ workspaceId, objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c', @@ -110,7 +109,7 @@ export const mockObjectMetadataItemsWithFieldMaps = [ isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), }, fieldIdByName: { name: 'nameFieldMetadataId', @@ -154,7 +153,7 @@ export const mockObjectMetadataItemsWithFieldMaps = [ isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), imageIdentifierFieldMetadataId: getMockFieldMetadataEntity({ workspaceId, objectMetadataId: '20202020-3d75-4aab-bacd-ee176c5f63ca', @@ -170,7 +169,7 @@ export const mockObjectMetadataItemsWithFieldMaps = [ isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity, + }), }, fieldIdByName: { name: 'nameFieldMetadataId', diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts index 24b2c4fca9..a91b32137f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto.ts @@ -133,7 +133,7 @@ export class FieldMetadataDTO { // @Validate(IsFieldMetadataOptions) @IsOptional() @Field(() => GraphQLJSON, { nullable: true }) - options?: FieldMetadataOptions | null; + options?: FieldMetadataOptions; @IsOptional() @Field(() => GraphQLJSON, { nullable: true }) 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 a2aef4b48d..fd3e1b8372 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 @@ -24,7 +24,7 @@ import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permis type IsRelationType = IsExactly extends true - ? null | Ttype + ? null | Ttype // Could be improved to be | unknown : T extends FieldMetadataType.RELATION ? Ttype : T extends FieldMetadataType.MORPH_RELATION @@ -53,7 +53,8 @@ type IsRelationType = // TODO add some documentation about this entity export class FieldMetadataEntity< T extends FieldMetadataType = FieldMetadataType, -> { +> implements Required +{ @PrimaryGeneratedColumn('uuid') id: string; @@ -84,7 +85,7 @@ export class FieldMetadataEntity< label: string; @Column({ nullable: true, type: 'jsonb' }) - defaultValue: FieldMetadataDefaultValue | null; + defaultValue: FieldMetadataDefaultValue; @Column({ nullable: true, type: 'text' }) description: string | null; @@ -93,13 +94,13 @@ export class FieldMetadataEntity< icon: string | null; @Column({ type: 'jsonb', nullable: true }) - standardOverrides?: FieldStandardOverridesDTO | null; + standardOverrides: FieldStandardOverridesDTO | null; @Column('jsonb', { nullable: true }) - options: FieldMetadataOptions | null; + options: FieldMetadataOptions; @Column('jsonb', { nullable: true }) - settings?: FieldMetadataSettings | null; + settings: FieldMetadataSettings; @Column({ default: false }) isCustom: boolean; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/hooks/__tests__/before-update-one-field.hook.spec.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/hooks/__tests__/before-update-one-field.hook.spec.ts index d3a5d16a2e..626102b828 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/hooks/__tests__/before-update-one-field.hook.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/hooks/__tests__/before-update-one-field.hook.spec.ts @@ -110,7 +110,7 @@ describe('BeforeUpdateOneField', () => { isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); jest .spyOn(fieldMetadataService, 'findOneWithinWorkspace') @@ -147,7 +147,7 @@ describe('BeforeUpdateOneField', () => { isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); jest .spyOn(fieldMetadataService, 'findOneWithinWorkspace') @@ -182,7 +182,7 @@ describe('BeforeUpdateOneField', () => { isLabelSyncedWithName: true, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); jest .spyOn(fieldMetadataService, 'findOneWithinWorkspace') @@ -230,7 +230,7 @@ describe('BeforeUpdateOneField', () => { }, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); jest .spyOn(fieldMetadataService, 'findOneWithinWorkspace') @@ -277,7 +277,7 @@ describe('BeforeUpdateOneField', () => { isLabelSyncedWithName: false, createdAt: new Date(), updatedAt: new Date(), - }) as FieldMetadataEntity; + }); jest .spyOn(fieldMetadataService, 'findOneWithinWorkspace') diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts index 730fc139b7..6d0646f71a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface.ts @@ -73,7 +73,7 @@ export type FieldMetadataDefaultValue< T extends FieldMetadataType = FieldMetadataType, > = IsExactly extends true - ? FieldMetadataDefaultValueForAnyType + ? FieldMetadataDefaultValueForAnyType | null // Could be improved to be | unknown : T extends keyof FieldMetadataDefaultValueMapping ? FieldMetadataDefaultValueForType : never; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface.ts index cdc4c32404..5bdb9ece92 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface.ts @@ -15,7 +15,7 @@ export type FieldMetadataOptions< T extends FieldMetadataType = FieldMetadataType, > = IsExactly extends true - ? FieldMetadataDefaultOption[] | FieldMetadataComplexOption[] + ? null | (FieldMetadataDefaultOption[] | FieldMetadataComplexOption[]) // Could be improved to be | unknown : T extends keyof FieldMetadataOptionsMapping ? FieldMetadataOptionsMapping[T] : never; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts index d69c9a6926..9fb86ea656 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface.ts @@ -9,10 +9,6 @@ export enum NumberDataType { BIGINT = 'bigint', } -export type FieldMetadataDefaultSettings = { - isForeignKey?: boolean; -}; - export enum DateDisplayFormat { RELATIVE = 'RELATIVE', USER_SETTINGS = 'USER_SETTINGS', @@ -54,11 +50,14 @@ type FieldMetadataSettingsMapping = { [FieldMetadataType.MORPH_RELATION]: FieldMetadataRelationSettings; }; +export type AllFieldMetadataSettings = + FieldMetadataSettingsMapping[keyof FieldMetadataSettingsMapping]; + export type FieldMetadataSettings< T extends FieldMetadataType = FieldMetadataType, > = IsExactly extends true - ? FieldMetadataDefaultSettings + ? null | AllFieldMetadataSettings // Could be improved to be | unknown : T extends keyof FieldMetadataSettingsMapping - ? FieldMetadataSettingsMapping[T] & FieldMetadataDefaultSettings + ? FieldMetadataSettingsMapping[T] | null : never; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-enum-validation.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-enum-validation.service.ts index ea42f14a45..eb766e644a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-enum-validation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-enum-validation.service.ts @@ -137,12 +137,17 @@ export class FieldMetadataEnumValidationService { ); } - private validateDuplicates(options: FieldMetadataOptions) { + private validateDuplicates( + options: FieldMetadataOptions, + ) { const fieldsToCheckForDuplicates = [ 'position', 'id', 'value', - ] as const satisfies (keyof FieldMetadataOptions[number])[]; + ] as const satisfies (keyof ( + | FieldMetadataDefaultOption[] + | FieldMetadataComplexOption[] + )[number])[]; const duplicatedValidators = fieldsToCheckForDuplicates.map< Validator >((field) => ({ @@ -178,7 +183,7 @@ export class FieldMetadataEnumValidationService { } private validateSelectDefaultValue( - options: FieldMetadataOptions, + options: FieldMetadataOptions, defaultValue: unknown, ) { if (typeof defaultValue !== 'string') { @@ -209,7 +214,7 @@ export class FieldMetadataEnumValidationService { } private validateMultiSelectDefaultValue( - options: FieldMetadataOptions, + options: FieldMetadataOptions, defaultValue: unknown, ) { if (!Array.isArray(defaultValue)) { @@ -241,7 +246,7 @@ export class FieldMetadataEnumValidationService { private validateFieldMetadataDefaultValue( fieldType: EnumFieldMetadataType, - options: FieldMetadataOptions, + options: FieldMetadataOptions, defaultValue: unknown, ) { switch (fieldType) { diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts index 645c9aa52d..c422e8ea2c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts @@ -8,8 +8,8 @@ import { v4 } from 'uuid'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataException, FieldMetadataExceptionCode, diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-relation.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-relation.service.ts index 92900bc97f..43bcdca647 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-relation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-relation.service.ts @@ -8,6 +8,7 @@ import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; import { v4 } from 'uuid'; +import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; @@ -313,6 +314,7 @@ export class FieldMetadataRelationService { }); } + // TODO refactor and strictly type computeCustomRelationFieldMetadataForCreation({ fieldMetadataInput, relationCreationPayload, @@ -332,13 +334,23 @@ export class FieldMetadataRelationService { FieldMetadataType.MORPH_RELATION, ); + const defaultIcon = 'IconRelationOneToMany'; + const isManyToOne = isRelation && relationCreationPayload?.type === RelationType.MANY_TO_ONE; - const isOneToMany = - isRelation && relationCreationPayload?.type === RelationType.ONE_TO_MANY; - - const defaultIcon = 'IconRelationOneToMany'; + const settings = isManyToOne + ? { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName, + } + : { + ...(fieldMetadataInput.settings as FieldMetadataSettings< + FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION + >), + relationType: RelationType.ONE_TO_MANY, + }; return { ...fieldMetadataInput, @@ -346,21 +358,7 @@ export class FieldMetadataRelationService { relationCreationPayload, relationTargetObjectMetadataId: relationCreationPayload?.targetObjectMetadataId, - settings: { - ...fieldMetadataInput.settings, - ...(isOneToMany - ? { - relationType: RelationType.ONE_TO_MANY, - } - : {}), - ...(isManyToOne - ? { - relationType: RelationType.MANY_TO_ONE, - onDelete: RelationOnDeleteAction.SET_NULL, - joinColumnName, - } - : {}), - }, + settings, }; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-validation.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-validation.service.ts index 5c0bdf3952..2467bd79f0 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-validation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-validation.service.ts @@ -77,32 +77,37 @@ export class FieldMetadataValidationService { }) { switch (fieldType) { case FieldMetadataType.NUMBER: - await this.validateSettings( - NumberSettingsValidation, + await this.validateSettings({ + type: FieldMetadataType.NUMBER, + validator: NumberSettingsValidation, settings, - ); + }); break; case FieldMetadataType.TEXT: - await this.validateSettings( - TextSettingsValidation, + await this.validateSettings({ + type: FieldMetadataType.TEXT, + validator: TextSettingsValidation, settings, - ); + }); break; default: break; } } - private async validateSettings( - validator: ClassConstructor< - Type extends FieldMetadataType.NUMBER - ? NumberSettingsValidation - : Type extends FieldMetadataType.TEXT - ? TextSettingsValidation - : never - >, - settings: FieldMetadataSettings, - ) { + private async validateSettings< + Type extends FieldMetadataType, + TValidator extends ClassConstructor, + TFieldMetadataType extends FieldMetadataType, + >({ + type: _type, + settings, + validator, + }: { + validator: TValidator; + settings: FieldMetadataSettings; + type: TFieldMetadataType; + }) { try { const settingsInstance = plainToInstance(validator, settings); diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service.ts index ccdfd0c113..446cdae95a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service.ts @@ -9,13 +9,13 @@ import { DataSource, FindOneOptions, In, Repository } from 'typeorm'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; import { DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input'; import { UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataException, FieldMetadataExceptionCode, diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/field-metadata-entity-test.type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/field-metadata-entity-test.type.ts index 36f2fec138..24dfe30e57 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/field-metadata-entity-test.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/field-metadata-entity-test.type.ts @@ -1,7 +1,24 @@ import { Expect, HasAllProperties } from 'twenty-shared/testing'; -import { FieldMetadataType } from 'twenty-shared/types'; +import { FieldMetadataType, NullablePartial } from 'twenty-shared/types'; import { Relation as TypeOrmRelation } from 'typeorm'; +import { + AllFieldMetadataSettings, + FieldMetadataDateSettings, + FieldMetadataDateTimeSettings, + FieldMetadataNumberSettings, + FieldMetadataRelationSettings, + FieldMetadataTextSettings, +} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; +import { + FieldMetadataDefaultValueForAnyType, + FieldMetadataDefaultValueForType, +} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface'; + +import { + FieldMetadataComplexOption, + FieldMetadataDefaultOption, +} from 'src/engine/metadata-modules/field-metadata/dtos/options.input'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; @@ -19,6 +36,8 @@ type NotDefinedRelationRecord = { relationTargetObjectMetadata: never; }; +type AbstractFieldMetadata = FieldMetadataEntity; + type UUIDFieldMetadata = FieldMetadataEntity; type TextFieldMetadata = FieldMetadataEntity; @@ -64,7 +83,7 @@ type MorphRelationFieldMetadata = FieldMetadataEntity; // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars -type Assertions = [ +type RelationAssertions = [ Expect>, Expect>, Expect>, @@ -87,4 +106,288 @@ type Assertions = [ Expect>, Expect>, + + Expect< + HasAllProperties< + AbstractFieldMetadata, + NullablePartial + > + >, +]; + +// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars +type SettingsAssertions = [ + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + + Expect< + HasAllProperties< + TextFieldMetadata, + { settings: FieldMetadataTextSettings | null } + > + >, + Expect< + HasAllProperties< + NumberFieldMetadata, + { settings: FieldMetadataNumberSettings | null } + > + >, + Expect< + HasAllProperties< + DateFieldMetadata, + { settings: FieldMetadataDateSettings | null } + > + >, + Expect< + HasAllProperties< + DateTimeFieldMetadata, + { settings: FieldMetadataDateTimeSettings | null } + > + >, + + Expect< + HasAllProperties< + RelationFieldMetadata, + { settings: FieldMetadataRelationSettings | null } + > + >, + Expect< + HasAllProperties< + MorphRelationFieldMetadata, + { settings: FieldMetadataRelationSettings | null } + > + >, + + Expect< + HasAllProperties< + AbstractFieldMetadata, + { settings: AllFieldMetadataSettings | null } + > + >, +]; + +// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars +type DefaultValueAssertions = [ + Expect< + HasAllProperties< + UUIDFieldMetadata, + { defaultValue: FieldMetadataDefaultValueForType } + > + >, + Expect< + HasAllProperties< + TextFieldMetadata, + { defaultValue: FieldMetadataDefaultValueForType } + > + >, + Expect< + HasAllProperties< + NumberFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + BooleanFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + DateFieldMetadata, + { defaultValue: FieldMetadataDefaultValueForType } + > + >, + Expect< + HasAllProperties< + DateTimeFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + CurrencyFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + FullNameFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + RatingFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + SelectFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + MultiSelectFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + PositionFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + RawJsonFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + RichTextFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + ActorFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + ArrayFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + PhonesFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + EmailsFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + Expect< + HasAllProperties< + LinksFieldMetadata, + { + defaultValue: FieldMetadataDefaultValueForType; + } + > + >, + + Expect>, + Expect>, + + Expect< + HasAllProperties< + AbstractFieldMetadata, + { defaultValue: FieldMetadataDefaultValueForAnyType | null } + > + >, +]; + +// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars +type OptionsAssertions = [ + Expect< + HasAllProperties< + RatingFieldMetadata, + { options: FieldMetadataDefaultOption[] } + > + >, + Expect< + HasAllProperties< + SelectFieldMetadata, + { options: FieldMetadataComplexOption[] } + > + >, + Expect< + HasAllProperties< + MultiSelectFieldMetadata, + { options: FieldMetadataComplexOption[] } + > + >, + + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + Expect>, + + Expect>, + Expect>, + + Expect< + HasAllProperties< + AbstractFieldMetadata, + { + options: + | null + | (FieldMetadataDefaultOption[] | FieldMetadataComplexOption[]); + } + > + >, ]; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/__tests__/field-metadata-validation.service.spec.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/__tests__/field-metadata-validation.service.spec.ts index 4de8fb537e..754cea83ec 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/__tests__/field-metadata-validation.service.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/__tests__/field-metadata-validation.service.spec.ts @@ -28,7 +28,10 @@ describe('FieldMetadataValidationService', () => { }); it('should validate NUMBER settings successfully', async () => { - const settings = { decimals: 2, type: 'number' } as FieldMetadataSettings; + const settings: FieldMetadataSettings = { + decimals: 2, + type: 'number', + }; await expect( service.validateSettingsOrThrow({ @@ -39,7 +42,10 @@ describe('FieldMetadataValidationService', () => { }); it('should throw an error for invalid NUMBER settings', async () => { - const settings = { type: 'invalidType' } as FieldMetadataSettings; + const settings: FieldMetadataSettings = { + // @ts-expect-error expected invalid payload below + type: 'invalidType', + }; await expect( service.validateSettingsOrThrow({ @@ -50,7 +56,9 @@ describe('FieldMetadataValidationService', () => { }); it('should validate TEXT settings successfully', async () => { - const settings = { displayedMaxRows: 10 } as FieldMetadataSettings; + const settings: FieldMetadataSettings = { + displayedMaxRows: 10, + }; await expect( service.validateSettingsOrThrow({ @@ -61,9 +69,10 @@ describe('FieldMetadataValidationService', () => { }); it('should throw an error for invalid TEXT settings', async () => { - const settings = { + const settings: FieldMetadataSettings = { + // @ts-expect-error expected invalid payload below displayedMaxRows: 'NotANumber', - } as FieldMetadataSettings; + }; await expect( service.validateSettingsOrThrow({ 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 24e6fb4891..ef10860efe 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 @@ -27,7 +27,7 @@ import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permi 'namePlural', 'workspaceId', ]) -export class ObjectMetadataEntity { +export class ObjectMetadataEntity implements Required { @PrimaryGeneratedColumn('uuid') id: string; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts index 138bc3e764..f3be1a2b12 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts @@ -6,7 +6,6 @@ import { capitalize, isDefined } from 'twenty-shared/utils'; import { QueryRunner, Repository } from 'typeorm'; import { v4 as uuidV4 } from 'uuid'; -import { FieldMetadataDefaultSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @@ -228,7 +227,7 @@ export class ObjectMetadataFieldRelationService { id: targetFieldMetadataToUpdate.id, ...targetFieldMetadataUpdateData, settings: { - ...(targetFieldMetadataToUpdate.settings as FieldMetadataDefaultSettings), + ...targetFieldMetadataToUpdate.settings, ...(isTargetFieldMetadataManyToOneRelation ? { joinColumnName: `${sourceObjectMetadata.nameSingular}Id`, @@ -260,7 +259,7 @@ export class ObjectMetadataFieldRelationService { id: sourceFieldMetadataToUpdate.id, ...sourceFieldMetadataUpdateData, settings: { - ...(sourceFieldMetadataToUpdate.settings as FieldMetadataDefaultSettings), + ...sourceFieldMetadataToUpdate.settings, ...(isSourceFieldMetadataManyToOneRelation ? { joinColumnName: `${targetObjectMetadata.nameSingular}Id`, diff --git a/packages/twenty-server/src/engine/metadata-modules/object-permission/field-permission/__tests__/field-permissions.service.spec.ts b/packages/twenty-server/src/engine/metadata-modules/object-permission/field-permission/__tests__/field-permissions.service.spec.ts index 9f1bb73578..64d5326c99 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-permission/field-permission/__tests__/field-permissions.service.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-permission/field-permission/__tests__/field-permissions.service.spec.ts @@ -8,7 +8,6 @@ import { fieldTextMock, objectMetadataItemMock, } from 'src/engine/api/__mocks__/object-metadata-item.mock'; -import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { UpsertFieldPermissionsInput } from 'src/engine/metadata-modules/object-permission/dtos/upsert-field-permissions.input'; import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.entity'; import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service'; @@ -127,7 +126,7 @@ describe('FieldPermissionService', () => { objectMetadataId: testObjectMetadataId, workspaceId: testWorkspaceId, id: '20202020-0000-0000-0000-000000000003', - }) as FieldMetadataEntity, + }), }, fieldIdByJoinColumnName: {}, fieldIdByName: {}, diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service.ts index cb5a0ce61c..3d7aa65dee 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service.ts @@ -3,6 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { FieldMetadataType } from 'twenty-shared/types'; import { In, Repository } from 'typeorm'; +import { isDefined } from 'twenty-shared/utils'; import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; @@ -175,7 +176,14 @@ export class RemoteTableRelationsService { isNullable: true, isSystem: true, defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, + ...(isDefined(objectPrimaryKeyFieldSettings) + ? { + settings: { + ...objectPrimaryKeyFieldSettings, + isForeignKey: true, + }, + } + : {}), }, ); @@ -215,7 +223,14 @@ export class RemoteTableRelationsService { isNullable: true, isSystem: true, defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, + ...(isDefined(objectPrimaryKeyFieldSettings) + ? { + settings: { + ...objectPrimaryKeyFieldSettings, + isForeignKey: true, + }, + } + : {}), }, ); @@ -255,7 +270,14 @@ export class RemoteTableRelationsService { isNullable: true, isSystem: true, defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, + ...(isDefined(objectPrimaryKeyFieldSettings) + ? { + settings: { + ...objectPrimaryKeyFieldSettings, + isForeignKey: true, + }, + } + : {}), }, ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/__tests__/get-flat-field-metadata.mock.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/__tests__/get-flat-field-metadata.mock.ts index 34b56ff290..90f01d2faf 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/__tests__/get-flat-field-metadata.mock.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/__tests__/get-flat-field-metadata.mock.ts @@ -6,19 +6,16 @@ import { FlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migrat type FlatFieldMetadataOverrides< T extends FieldMetadataType = FieldMetadataType, > = Required< - Pick, 'uniqueIdentifier' | 'objectMetadataId'> + Pick, 'uniqueIdentifier' | 'objectMetadataId' | 'type'> > & Partial>; -export const getFlatFieldMetadataMock = < - T extends FieldMetadataType = FieldMetadataType.TEXT, ->( +export const getFlatFieldMetadataMock = ( overrides: FlatFieldMetadataOverrides, -): FlatFieldMetadata => { +): FlatFieldMetadata => { const createdAt = faker.date.anytime(); return { - type: FieldMetadataType.TEXT as T, createdAt, description: 'default flat field metadata description', icon: 'icon', @@ -32,7 +29,8 @@ export const getFlatFieldMetadataMock = < isLabelSyncedWithName: false, isSystem: false, standardId: null, - standardOverrides: undefined, + standardOverrides: null, + settings: null, updatedAt: createdAt, workspaceId: faker.string.uuid(), defaultValue: null, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap index 76d589d569..32b4904c55 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap @@ -25,8 +25,9 @@ exports[`Workspace migration builder field actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -58,8 +59,9 @@ exports[`Workspace migration builder field actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -85,8 +87,9 @@ exports[`Workspace migration builder field actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -112,8 +115,9 @@ exports[`Workspace migration builder field actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -139,8 +143,9 @@ exports[`Workspace migration builder field actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -166,8 +171,9 @@ exports[`Workspace migration builder field actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -226,8 +232,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -259,8 +266,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -319,8 +327,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": Any, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": Any, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "RELATION", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -352,8 +361,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": Any, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": Any, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "RELATION", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -412,8 +422,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -445,8 +456,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -472,8 +484,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -499,8 +512,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -526,8 +540,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -553,8 +568,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -580,8 +596,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -662,8 +679,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": Any, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": Any, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "RELATION", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -695,8 +713,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -722,8 +741,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -749,8 +769,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -776,8 +797,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -803,8 +825,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -830,8 +853,9 @@ exports[`Workspace migration builder field actions test suite It should build an "relationTargetFieldMetadataId": Any, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": Any, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "RELATION", "uniqueIdentifier": "field-metadata-unique-identifier-1", "updatedAt": Any, @@ -1038,8 +1062,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -1065,8 +1090,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -1092,8 +1118,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -1119,8 +1146,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -1146,8 +1174,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -1201,8 +1230,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -1234,8 +1264,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -1261,8 +1292,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -1288,8 +1320,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -1315,8 +1348,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -1342,8 +1376,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -1397,8 +1432,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -1430,8 +1466,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -1457,8 +1494,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -1484,8 +1522,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -1511,8 +1550,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -1538,8 +1578,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -1593,8 +1634,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -1626,8 +1668,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -1653,8 +1696,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -1680,8 +1724,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -1707,8 +1752,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -1734,8 +1780,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -1789,8 +1836,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -1822,8 +1870,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -1849,8 +1898,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -1876,8 +1926,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -1903,8 +1954,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -1930,8 +1982,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -1985,8 +2038,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, @@ -2018,8 +2072,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_0", "updatedAt": Any, @@ -2045,8 +2100,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_1", "updatedAt": Any, @@ -2072,8 +2128,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_2", "updatedAt": Any, @@ -2099,8 +2156,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_3", "updatedAt": Any, @@ -2126,8 +2184,9 @@ exports[`Workspace migration builder object actions test suite It should build a "relationTargetFieldMetadataId": undefined, "relationTargetObjectMetadata": undefined, "relationTargetObjectMetadataId": undefined, + "settings": null, "standardId": null, - "standardOverrides": undefined, + "standardOverrides": null, "type": "TEXT", "uniqueIdentifier": "field_4", "updatedAt": Any, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts index 4e0adfae31..9e7b7c3f14 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts @@ -12,6 +12,7 @@ const basicFlatFieldMetadatas = Array.from({ length: 5 }, (_value, index) => getFlatFieldMetadataMock({ objectMetadataId: basicObjectMetadataId, uniqueIdentifier: `field_${index}`, + type: FieldMetadataType.TEXT, }), ); @@ -110,7 +111,6 @@ const relationTestCases: WorkspaceMigrationBuilderTestCase[] = [ type: FieldMetadataType.RELATION, settings: { relationType: RelationType.MANY_TO_ONE, - isForeignKey: true, joinColumnName: 'column-name', onDelete: undefined, }, @@ -129,7 +129,7 @@ const relationTestCases: WorkspaceMigrationBuilderTestCase[] = [ { ...flatObjectMetadata, flatFieldMetadatas: [ - getFlatFieldMetadataMock({ + { ...updatedFieldMetadata, settings: { relationType: RelationType.ONE_TO_MANY, @@ -139,7 +139,7 @@ const relationTestCases: WorkspaceMigrationBuilderTestCase[] = [ }, relationTargetFieldMetadataId: faker.string.uuid(), relationTargetObjectMetadataId: faker.string.uuid(), - }), + }, ], }, ], @@ -158,6 +158,7 @@ const basicCrudTestCases: WorkspaceMigrationBuilderTestCase[] = [ const flatFieldMetadata = getFlatFieldMetadataMock({ uniqueIdentifier: 'field-metadata-unique-identifier-1', + type: FieldMetadataType.TEXT, objectMetadataId, }); const flatObjectMetadata = getFlatObjectMetadataMock({ @@ -189,6 +190,7 @@ const basicCrudTestCases: WorkspaceMigrationBuilderTestCase[] = [ const flatFieldMetadata = getFlatFieldMetadataMock({ uniqueIdentifier: 'field-metadata-unique-identifier-1', + type: FieldMetadataType.TEXT, objectMetadataId, }); const flatObjectMetadata = getFlatObjectMetadataMock({ @@ -228,6 +230,7 @@ const basicCrudTestCases: WorkspaceMigrationBuilderTestCase[] = [ const flatFieldMetadata = getFlatFieldMetadataMock({ uniqueIdentifier: 'field-metadata-unique-identifier-1', + type: FieldMetadataType.TEXT, objectMetadataId, }); const flatObjectMetadata = getFlatObjectMetadataMock({ @@ -264,6 +267,7 @@ export const WORKSPACE_MIGRATION_FIELD_BUILDER_TEST_CASES: WorkspaceMigrationBui const objectMetadataId = faker.string.uuid(); const flatFieldMetadata = getFlatFieldMetadataMock({ uniqueIdentifier: 'field-metadata-unique-identifier-1', + type: FieldMetadataType.TEXT, objectMetadataId, }); const from = [ diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-object-test-case.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-object-test-case.ts index 4e3bdfbdcc..49ea9ea20c 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-object-test-case.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-object-test-case.ts @@ -1,4 +1,5 @@ import { faker } from '@faker-js/faker'; +import { FieldMetadataType } from 'twenty-shared/types'; import { getFlatFieldMetadataMock } from 'src/engine/workspace-manager/workspace-migration-v2/__tests__/get-flat-field-metadata.mock'; import { getFlatObjectMetadataMock } from 'src/engine/workspace-manager/workspace-migration-v2/__tests__/get-flat-object-metadata.mock'; @@ -66,6 +67,7 @@ export const WORKSPACE_MIGRATION_OBJECT_BUILDER_TEST_CASES: WorkspaceMigrationBu { length: 5 }, (_value, index) => getFlatFieldMetadataMock({ + type: FieldMetadataType.TEXT, objectMetadataId, uniqueIdentifier: `field_${index}`, }), 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 4285ded7c1..86263228fa 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 @@ -145,7 +145,8 @@ export class StandardFieldFactory { description: workspaceFieldMetadataArgs.description, defaultValue: workspaceFieldMetadataArgs.defaultValue ?? null, options: workspaceFieldMetadataArgs.options ?? null, - settings: workspaceFieldMetadataArgs.settings, + settings: workspaceFieldMetadataArgs.settings ?? null, + standardOverrides: null, workspaceId: context.workspaceId, isNullable: workspaceFieldMetadataArgs.isNullable, isUnique: workspaceFieldMetadataArgs.isUnique, @@ -205,6 +206,8 @@ export class StandardFieldFactory { relationTargetFieldMetadataId: null, relationTargetObjectMetadata: null, relationTargetObjectMetadataId: null, + settings: null, // accurate ? looks weird for this to be undefined even for standard fields ? + standardOverrides: null, }); return fieldMetadataCollection; 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 a3ce8568d4..4883c7c76d 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 @@ -54,6 +54,8 @@ export const computeStandardFields = ( relationTargetFieldMetadataId: null, relationTargetObjectMetadata: null, relationTargetObjectMetadataId: null, + settings: null, + standardOverrides: null, }); } } else { 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 ab18d01483..9007891cca 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 @@ -8,15 +8,17 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat type GetMockFieldMetadataEntityOverride< T extends FieldMetadataType = FieldMetadataType, > = Partial> & - Required, 'workspaceId' | 'objectMetadataId'>>; + Required< + Pick, 'workspaceId' | 'objectMetadataId' | 'type'> + >; +// Should be renamed to abstract export const getMockFieldMetadataEntity = < T extends FieldMetadataType = FieldMetadataType.TEXT, >( overrides: GetMockFieldMetadataEntityOverride, -): FieldMetadataEntity => { +): FieldMetadataEntity => { return { - type: FieldMetadataType.TEXT as T, fieldPermissions: [], icon: null, indexFieldMetadatas: {} as IndexFieldMetadataEntity, diff --git a/packages/twenty-shared/src/types/NullablePartial.ts b/packages/twenty-shared/src/types/NullablePartial.ts new file mode 100644 index 0000000000..369da30f3f --- /dev/null +++ b/packages/twenty-shared/src/types/NullablePartial.ts @@ -0,0 +1,3 @@ +export type NullablePartial = { + [P in keyof T]: T[P] | null; +}; \ No newline at end of file diff --git a/packages/twenty-shared/src/types/index.ts b/packages/twenty-shared/src/types/index.ts index fd7d2c0abd..83cee42c13 100644 --- a/packages/twenty-shared/src/types/index.ts +++ b/packages/twenty-shared/src/types/index.ts @@ -11,6 +11,7 @@ export type { ConfigVariableValue } from './ConfigVariableValue'; export { ConnectedAccountProvider } from './ConnectedAccountProvider'; export { FieldMetadataType } from './FieldMetadataType'; export type { IsExactly } from './IsExactly'; +export type { NullablePartial } from './NullablePartial'; export type { ObjectRecordsPermissions } from './ObjectRecordsPermissions'; export type { ObjectRecordsPermissionsByRoleId } from './ObjectRecordsPermissionsByRoleId'; export type { RestrictedFields } from './RestrictedFields';