Deprecate ObjectMetadataInterface and improve entity typing (#13310)

# Introduction
Following `FieldMetadataInterface` deprecation in
https://github.com/twentyhq/twenty/pull/13264
As for the previous PR will rename and remove all the file in a
secondary PR to avoid conflicts and over loading this one

## Improvements
Removed optional properties from the `objectMetadataEntity` model and
added utils to retrieve test data

## Notes
By touching to `ObjectMetadataDTO` I would have expected a twenty-front
codegenerated types mutation, but it does not seem to be granular enough
to null/undefined coercion
This commit is contained in:
Paul Rastoin
2025-07-21 17:53:17 +02:00
committed by GitHub
parent 79f3fbb016
commit 1536ed3434
23 changed files with 1031 additions and 909 deletions

View File

@ -2,114 +2,115 @@ 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 { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
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';
const workspaceId = '20202020-1c25-4d02-bf25-6aeccf7ea419';
export const mockPersonObjectMetadataWithFieldMaps = (
duplicateCriteria: WorkspaceEntityDuplicateCriteria[],
): ObjectMetadataItemWithFieldMaps => ({
id: '',
icon: 'Icon123',
standardId: '',
nameSingular: 'person',
namePlural: 'people',
labelSingular: 'Person',
labelPlural: 'People',
description: 'A person',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
duplicateCriteria: duplicateCriteria,
labelIdentifierFieldMetadataId: '',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldIdByName: {
name: 'name-id',
emails: 'emails-id',
linkedinLink: 'linkedinLink-id',
jobTitle: 'jobTitle-id',
},
fieldIdByJoinColumnName: {},
fieldsById: {
'name-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'name-id',
type: FieldMetadataType.FULL_NAME,
name: 'name',
label: 'Name',
defaultValue: {
lastName: "''",
firstName: "''",
},
description: "Contact's name",
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'emails-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'emails-id',
type: FieldMetadataType.EMAILS,
name: 'emails',
label: 'Emails',
defaultValue: {
primaryEmail: "''",
additionalEmails: null,
},
description: "Contact's Emails",
isCustom: false,
isNullable: true,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'linkedinLink-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'linkedinLink-id',
type: FieldMetadataType.LINKS,
name: 'linkedinLink',
label: 'Linkedin',
defaultValue: {
primaryLinkUrl: "''",
secondaryLinks: [],
primaryLinkLabel: "''",
},
description: "Contact's Linkedin account",
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'jobTitle-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'jobTitle-id',
type: FieldMetadataType.TEXT,
name: 'jobTitle',
label: 'Job Title',
defaultValue: "''",
description: "Contact's job title",
isCustom: false,
isNullable: false,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
});
) =>
getMockObjectMetadataItemWithFieldsMaps({
id: '',
icon: 'Icon123',
standardId: '',
nameSingular: 'person',
namePlural: 'people',
labelSingular: 'Person',
labelPlural: 'People',
description: 'A person',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
duplicateCriteria: duplicateCriteria,
labelIdentifierFieldMetadataId: '',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldIdByName: {
name: 'name-id',
emails: 'emails-id',
linkedinLink: 'linkedinLink-id',
jobTitle: 'jobTitle-id',
},
fieldIdByJoinColumnName: {},
fieldsById: {
'name-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'name-id',
type: FieldMetadataType.FULL_NAME,
name: 'name',
label: 'Name',
defaultValue: {
lastName: "''",
firstName: "''",
},
description: "Contact's name",
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'emails-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'emails-id',
type: FieldMetadataType.EMAILS,
name: 'emails',
label: 'Emails',
defaultValue: {
primaryEmail: "''",
additionalEmails: null,
},
description: "Contact's Emails",
isCustom: false,
isNullable: true,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'linkedinLink-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'linkedinLink-id',
type: FieldMetadataType.LINKS,
name: 'linkedinLink',
label: 'Linkedin',
defaultValue: {
primaryLinkUrl: "''",
secondaryLinks: [],
primaryLinkLabel: "''",
},
description: "Contact's Linkedin account",
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'jobTitle-id': getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '',
id: 'jobTitle-id',
type: FieldMetadataType.TEXT,
name: 'jobTitle',
label: 'Job Title',
defaultValue: "''",
description: "Contact's job title",
isCustom: false,
isNullable: false,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
});

View File

@ -5,467 +5,468 @@ import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metada
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 { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
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';
const workspaceId = '20202020-1c25-4d02-bf25-6aeccf7ea419';
const objectMetadataId = '20202020-6e2c-42f6-a83c-cc58d776af88';
export const OPPORTUNITY_WITH_FIELDS_MAPS = {
id: objectMetadataId,
nameSingular: 'opportunity',
namePlural: 'opportunities',
labelSingular: 'Opportunity',
labelPlural: 'Opportunities',
description: 'An opportunity',
icon: 'IconTargetArrow',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: '20202020-c2f1-4435-adca-22931f8b41b6',
imageIdentifierFieldMetadataId: null,
workspaceId,
indexMetadatas: [],
fieldsById: {
'20202020-c2f1-4435-adca-22931f8b41b6': getMockFieldMetadataEntity({
id: '20202020-c2f1-4435-adca-22931f8b41b6',
workspaceId,
objectMetadataId,
type: FieldMetadataType.TEXT,
name: 'name',
label: 'Name',
defaultValue: "''",
description: 'The opportunity name',
icon: 'IconTargetArrow',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.CURRENCY,
name: 'amount',
label: 'Amount',
defaultValue: { amountMicros: null, currencyCode: "''" },
description: 'Opportunity amount',
icon: 'IconCurrencyDollar',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'closeDate',
label: 'Close date',
defaultValue: null,
description: 'Opportunity close date',
icon: 'IconCalendarEvent',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.SELECT,
name: 'stage',
label: 'Stage',
defaultValue: "'NEW'",
description: 'Opportunity stage',
icon: 'IconProgressCheck',
options: [
{
id: '20202020-dba8-4975-81bd-b29a41c0a387',
color: 'red',
label: 'New',
value: 'NEW',
position: 0,
export const OPPORTUNITY_WITH_FIELDS_MAPS =
getMockObjectMetadataItemWithFieldsMaps({
id: objectMetadataId,
nameSingular: 'opportunity',
namePlural: 'opportunities',
labelSingular: 'Opportunity',
labelPlural: 'Opportunities',
description: 'An opportunity',
icon: 'IconTargetArrow',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: '20202020-c2f1-4435-adca-22931f8b41b6',
imageIdentifierFieldMetadataId: null,
workspaceId,
indexMetadatas: [],
fieldsById: {
'20202020-c2f1-4435-adca-22931f8b41b6': getMockFieldMetadataEntity({
id: '20202020-c2f1-4435-adca-22931f8b41b6',
workspaceId,
objectMetadataId,
type: FieldMetadataType.TEXT,
name: 'name',
label: 'Name',
defaultValue: "''",
description: 'The opportunity name',
icon: 'IconTargetArrow',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.CURRENCY,
name: 'amount',
label: 'Amount',
defaultValue: { amountMicros: null, currencyCode: "''" },
description: 'Opportunity amount',
icon: 'IconCurrencyDollar',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'closeDate',
label: 'Close date',
defaultValue: null,
description: 'Opportunity close date',
icon: 'IconCalendarEvent',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.SELECT,
name: 'stage',
label: 'Stage',
defaultValue: "'NEW'",
description: 'Opportunity stage',
icon: 'IconProgressCheck',
options: [
{
id: '20202020-dba8-4975-81bd-b29a41c0a387',
color: 'red',
label: 'New',
value: 'NEW',
position: 0,
},
{
id: '20202020-1c9d-490c-940c-bf47addcd6a1',
color: 'purple',
label: 'Screening',
value: 'SCREENING',
position: 1,
},
{
id: '20202020-1368-438b-8702-6d5e5727a888',
color: 'sky',
label: 'Meeting',
value: 'MEETING',
position: 2,
},
{
id: '20202020-41e4-4b4e-a038-f02645f55767',
color: 'turquoise',
label: 'Proposal',
value: 'PROPOSAL',
position: 3,
},
{
id: '20202020-8acf-4934-8519-42f7c9133cd5',
color: 'yellow',
label: 'Customer',
value: 'CUSTOMER',
position: 4,
},
],
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.POSITION,
name: 'position',
label: 'Position',
defaultValue: 0,
description: 'Opportunity record position',
icon: 'IconHierarchy2',
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.ACTOR,
name: 'createdBy',
label: 'Created by',
defaultValue: { name: "'System'", source: "'MANUAL'" },
description: 'The creator of the record',
icon: 'IconCreativeCommonsSa',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.TEXT,
name: 'searchVector',
label: 'Search vector',
defaultValue: null,
description: 'Field used for full-text search',
icon: 'IconUser',
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.UUID,
name: 'id',
label: 'Id',
defaultValue: 'uuid',
description: 'Id',
icon: 'Icon123',
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'createdAt',
label: 'Creation date',
defaultValue: 'now',
description: 'Creation date',
icon: 'IconCalendar',
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'updatedAt',
label: 'Last update',
defaultValue: 'now',
description: 'Last time the record was changed',
icon: 'IconCalendarClock',
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'deletedAt',
label: 'Deletion date',
defaultValue: null,
description: 'Record deletion date',
icon: 'IconCalendarOff',
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'pointOfContact',
label: 'Point of Contact',
defaultValue: null,
description: 'The point of contact for this opportunity',
icon: 'IconUser',
settings: {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'pointOfContactId',
onDelete: RelationOnDeleteAction.CASCADE,
},
{
id: '20202020-1c9d-490c-940c-bf47addcd6a1',
color: 'purple',
label: 'Screening',
value: 'SCREENING',
position: 1,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'company',
label: 'Company',
defaultValue: null,
description: 'The company this opportunity is associated with',
icon: 'IconBuildingSkyscraper',
settings: {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
onDelete: RelationOnDeleteAction.CASCADE,
},
{
id: '20202020-1368-438b-8702-6d5e5727a888',
color: 'sky',
label: 'Meeting',
value: 'MEETING',
position: 2,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'favorites',
label: 'Favorites',
defaultValue: null,
description: 'Users who favorited this opportunity',
icon: 'IconStar',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
{
id: '20202020-41e4-4b4e-a038-f02645f55767',
color: 'turquoise',
label: 'Proposal',
value: 'PROPOSAL',
position: 3,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'taskTargets',
label: 'Task Targets',
defaultValue: null,
description: 'Tasks targeting this opportunity',
icon: 'IconCheckbox',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
{
id: '20202020-8acf-4934-8519-42f7c9133cd5',
color: 'yellow',
label: 'Customer',
value: 'CUSTOMER',
position: 4,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'noteTargets',
label: 'Note Targets',
defaultValue: null,
description: 'Notes targeting this opportunity',
icon: 'IconNotes',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
],
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.POSITION,
name: 'position',
label: 'Position',
defaultValue: 0,
description: 'Opportunity record position',
icon: 'IconHierarchy2',
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.ACTOR,
name: 'createdBy',
label: 'Created by',
defaultValue: { name: "'System'", source: "'MANUAL'" },
description: 'The creator of the record',
icon: 'IconCreativeCommonsSa',
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.TEXT,
name: 'searchVector',
label: 'Search vector',
defaultValue: null,
description: 'Field used for full-text search',
icon: 'IconUser',
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
isUnique: false,
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({
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'attachments',
label: 'Attachments',
defaultValue: null,
description: 'Attachments for this opportunity',
icon: 'IconPaperclip',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'timelineActivities',
label: 'Timeline Activities',
defaultValue: null,
description: 'Timeline activities for this opportunity',
icon: 'IconTimeline',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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',
amount: '20202020-5eef-417a-b517-ebeedaa8e10b',
closeDate: '20202020-597c-44d3-98ec-ea71aea5256b',
stage: '20202020-9b94-454a-94ca-8afb09c68faf',
position: '20202020-30a5-4d8e-9b93-12d31ece0aaa',
createdBy: '20202020-f95f-424f-ab32-65961e8e9635',
searchVector: '20202020-5e10-4780-babb-38a465ac546c',
id: '20202020-8f4a-4f8d-822e-90fe72f75b79',
workspaceId,
objectMetadataId,
type: FieldMetadataType.UUID,
name: 'id',
label: 'Id',
defaultValue: 'uuid',
description: 'Id',
icon: 'Icon123',
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'createdAt',
label: 'Creation date',
defaultValue: 'now',
description: 'Creation date',
icon: 'IconCalendar',
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'updatedAt',
label: 'Last update',
defaultValue: 'now',
description: 'Last time the record was changed',
icon: 'IconCalendarClock',
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.DATE_TIME,
name: 'deletedAt',
label: 'Deletion date',
defaultValue: null,
description: 'Record deletion date',
icon: 'IconCalendarOff',
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'pointOfContact',
label: 'Point of Contact',
defaultValue: null,
description: 'The point of contact for this opportunity',
icon: 'IconUser',
settings: {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'pointOfContactId',
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'company',
label: 'Company',
defaultValue: null,
description: 'The company this opportunity is associated with',
icon: 'IconBuildingSkyscraper',
settings: {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'favorites',
label: 'Favorites',
defaultValue: null,
description: 'Users who favorited this opportunity',
icon: 'IconStar',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'taskTargets',
label: 'Task Targets',
defaultValue: null,
description: 'Tasks targeting this opportunity',
icon: 'IconCheckbox',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'noteTargets',
label: 'Note Targets',
defaultValue: null,
description: 'Notes targeting this opportunity',
icon: 'IconNotes',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'attachments',
label: 'Attachments',
defaultValue: null,
description: 'Attachments for this opportunity',
icon: 'IconPaperclip',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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,
objectMetadataId,
type: FieldMetadataType.RELATION,
name: 'timelineActivities',
label: 'Timeline Activities',
defaultValue: null,
description: 'Timeline activities for this opportunity',
icon: 'IconTimeline',
settings: {
relationType: RelationType.ONE_TO_MANY,
onDelete: RelationOnDeleteAction.CASCADE,
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
isUnique: false,
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',
amount: '20202020-5eef-417a-b517-ebeedaa8e10b',
closeDate: '20202020-597c-44d3-98ec-ea71aea5256b',
stage: '20202020-9b94-454a-94ca-8afb09c68faf',
position: '20202020-30a5-4d8e-9b93-12d31ece0aaa',
createdBy: '20202020-f95f-424f-ab32-65961e8e9635',
searchVector: '20202020-5e10-4780-babb-38a465ac546c',
id: '20202020-8f4a-4f8d-822e-90fe72f75b79',
createdAt: '20202020-f120-4b59-b239-f7f1d8eb243e',
updatedAt: '20202020-dcc8-4318-9756-b87377692561',
deletedAt: '20202020-1694-4f8b-8760-61a5ff330022',
pointOfContact: '20202020-4f52-4dea-a116-723f9bf7f082',
company: '20202020-fc02-4be2-be1a-e121daf5400d',
favorites: '20202020-fd9f-48f0-bd5f-5b0fec6a5de4',
taskTargets: '20202020-88ab-4138-98ce-80533bb423e3',
noteTargets: '20202020-4258-422b-b35b-db3f090af8da',
attachments: '20202020-16ca-40a7-a1ba-712975c916cd',
timelineActivities: '20202020-92a5-47bf-a38d-c1c72b2c3e4d',
},
fieldIdByJoinColumnName: {
pointOfContactId: '20202020-4f52-4dea-a116-723f9bf7f082',
companyId: '20202020-fc02-4be2-be1a-e121daf5400d',
},
} as const satisfies ObjectMetadataItemWithFieldMaps;
createdAt: '20202020-f120-4b59-b239-f7f1d8eb243e',
updatedAt: '20202020-dcc8-4318-9756-b87377692561',
deletedAt: '20202020-1694-4f8b-8760-61a5ff330022',
pointOfContact: '20202020-4f52-4dea-a116-723f9bf7f082',
company: '20202020-fc02-4be2-be1a-e121daf5400d',
favorites: '20202020-fd9f-48f0-bd5f-5b0fec6a5de4',
taskTargets: '20202020-88ab-4138-98ce-80533bb423e3',
noteTargets: '20202020-4258-422b-b35b-db3f090af8da',
attachments: '20202020-16ca-40a7-a1ba-712975c916cd',
timelineActivities: '20202020-92a5-47bf-a38d-c1c72b2c3e4d',
},
fieldIdByJoinColumnName: {
pointOfContactId: '20202020-4f52-4dea-a116-723f9bf7f082',
companyId: '20202020-fc02-4be2-be1a-e121daf5400d',
},
});

View File

@ -5,71 +5,72 @@ 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 { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
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';
describe('computeCursorArgFilter', () => {
const objectMetadataItemWithFieldMaps = {
id: 'object-id',
workspaceId: 'workspace-id',
nameSingular: 'person',
namePlural: 'people',
isCustom: false,
isRemote: false,
labelSingular: 'Person',
labelPlural: 'People',
targetTableName: 'person',
indexMetadatas: [],
isSystem: false,
isActive: true,
isAuditLogged: false,
isSearchable: false,
fieldIdByJoinColumnName: {},
icon: 'Icon123',
fieldIdByName: {
name: 'name-id',
age: 'age-id',
fullName: 'fullname-id',
},
fieldsById: {
'name-id': getMockFieldMetadataEntity({
workspaceId: 'workspace-id',
objectMetadataId: 'object-id',
id: 'name-id',
type: FieldMetadataType.TEXT,
name: 'name',
label: 'Name',
isLabelSyncedWithName: true,
isNullable: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'age-id': getMockFieldMetadataEntity({
workspaceId: 'workspace-id',
objectMetadataId: 'object-id',
id: 'age-id',
type: FieldMetadataType.NUMBER,
name: 'age',
label: 'Age',
isLabelSyncedWithName: true,
isNullable: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'fullname-id': getMockFieldMetadataEntity({
workspaceId: 'workspace-id',
objectMetadataId: 'object-id',
id: 'fullname-id',
type: FieldMetadataType.FULL_NAME,
name: 'fullName',
label: 'Full Name',
isLabelSyncedWithName: true,
isNullable: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
} satisfies ObjectMetadataItemWithFieldMaps;
const objectMetadataItemWithFieldMaps =
getMockObjectMetadataItemWithFieldsMaps({
id: 'object-id',
workspaceId: 'workspace-id',
nameSingular: 'person',
namePlural: 'people',
isCustom: false,
isRemote: false,
labelSingular: 'Person',
labelPlural: 'People',
targetTableName: 'person',
indexMetadatas: [],
isSystem: false,
isActive: true,
isAuditLogged: false,
isSearchable: false,
fieldIdByJoinColumnName: {},
icon: 'Icon123',
fieldIdByName: {
name: 'name-id',
age: 'age-id',
fullName: 'fullname-id',
},
fieldsById: {
'name-id': getMockFieldMetadataEntity({
workspaceId: 'workspace-id',
objectMetadataId: 'object-id',
id: 'name-id',
type: FieldMetadataType.TEXT,
name: 'name',
label: 'Name',
isLabelSyncedWithName: true,
isNullable: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'age-id': getMockFieldMetadataEntity({
workspaceId: 'workspace-id',
objectMetadataId: 'object-id',
id: 'age-id',
type: FieldMetadataType.NUMBER,
name: 'age',
label: 'Age',
isLabelSyncedWithName: true,
isNullable: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
'fullname-id': getMockFieldMetadataEntity({
workspaceId: 'workspace-id',
objectMetadataId: 'object-id',
id: 'fullname-id',
type: FieldMetadataType.FULL_NAME,
name: 'fullName',
label: 'Full Name',
isLabelSyncedWithName: true,
isNullable: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
});
describe('basic cursor filtering', () => {
it('should return empty array when cursor is empty', () => {

View File

@ -1,206 +1,205 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
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';
import { getMockObjectMetadataItemWithFieldsMaps } from 'src/utils/__test__/get-object-metadata-item-with-fields-maps.mock';
const workspaceId = '20202020-0000-0000-0000-000000000000';
export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMaps[] =
[
{
id: '20202020-8dec-43d5-b2ff-6eef05095bec',
standardId: '',
nameSingular: 'person',
namePlural: 'people',
labelSingular: 'Person',
labelPlural: 'People',
description: 'A person',
icon: 'test-person-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldsById: {
nameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-8dec-43d5-b2ff-6eef05095bec',
id: 'nameFieldMetadataId',
type: FieldMetadataType.FULL_NAME,
icon: 'test-field-icon',
name: 'name',
label: 'Name',
defaultValue: {
lastName: "''",
firstName: "''",
},
description: "Contact's name",
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
fieldIdByName: {
name: 'nameFieldMetadataId',
},
fieldIdByJoinColumnName: {},
export const mockObjectMetadataItemsWithFieldMaps = [
getMockObjectMetadataItemWithFieldsMaps({
id: '20202020-8dec-43d5-b2ff-6eef05095bec',
standardId: '',
nameSingular: 'person',
namePlural: 'people',
labelSingular: 'Person',
labelPlural: 'People',
description: 'A person',
icon: 'test-person-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldsById: {
nameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-8dec-43d5-b2ff-6eef05095bec',
id: 'nameFieldMetadataId',
type: FieldMetadataType.FULL_NAME,
icon: 'test-field-icon',
name: 'name',
label: 'Name',
defaultValue: {
lastName: "''",
firstName: "''",
},
description: "Contact's name",
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
{
id: '20202020-c03c-45d6-a4b0-04afe1357c5c',
standardId: '',
nameSingular: 'company',
namePlural: 'companies',
labelSingular: 'Company',
labelPlural: 'Companies',
description: 'A company',
icon: 'test-company-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldsById: {
nameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c',
id: 'nameFieldMetadataId',
type: FieldMetadataType.TEXT,
icon: 'test-field-icon',
name: 'name',
label: 'Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
domainNameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c',
id: 'domainNameFieldMetadataId',
type: FieldMetadataType.LINKS,
icon: 'test-field-icon',
name: 'domainName',
label: 'Domain Name',
defaultValue: {
primaryLinkLabel: '',
primaryLinkUrl: '',
secondaryLinks: [],
},
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
fieldIdByName: {
name: 'nameFieldMetadataId',
domainName: 'domainNameFieldMetadataId',
},
fieldIdByJoinColumnName: {},
fieldIdByName: {
name: 'nameFieldMetadataId',
},
{
id: '20202020-3d75-4aab-bacd-ee176c5f63ca',
standardId: '',
nameSingular: 'regular-custom-object',
namePlural: 'regular-custom-objects',
labelSingular: 'Regular Custom Object',
labelPlural: 'Regular Custom Objects',
description: 'A regular custom object',
icon: 'test-regular-custom-object-icon',
targetTableName: 'DEPRECATED',
isCustom: true,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
imageIdentifierFieldMetadataId: 'imageIdentifierFieldMetadataId',
workspaceId,
indexMetadatas: [],
fieldsById: {
nameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-3d75-4aab-bacd-ee176c5f63ca',
id: 'nameFieldMetadataId',
type: FieldMetadataType.TEXT,
icon: 'test-field-icon',
name: 'name',
label: 'Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
imageIdentifierFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-3d75-4aab-bacd-ee176c5f63ca',
id: 'imageIdentifierFieldMetadataId',
type: FieldMetadataType.TEXT,
icon: 'test-field-icon',
name: 'imageIdentifierFieldName',
label: 'Image Identifier Field Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
fieldIdByName: {
name: 'nameFieldMetadataId',
imageIdentifierFieldName: 'imageIdentifierFieldMetadataId',
},
fieldIdByJoinColumnName: {},
fieldIdByJoinColumnName: {},
}),
getMockObjectMetadataItemWithFieldsMaps({
id: '20202020-c03c-45d6-a4b0-04afe1357c5c',
standardId: '',
nameSingular: 'company',
namePlural: 'companies',
labelSingular: 'Company',
labelPlural: 'Companies',
description: 'A company',
icon: 'test-company-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldsById: {
nameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c',
id: 'nameFieldMetadataId',
type: FieldMetadataType.TEXT,
icon: 'test-field-icon',
name: 'name',
label: 'Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
domainNameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c',
id: 'domainNameFieldMetadataId',
type: FieldMetadataType.LINKS,
icon: 'test-field-icon',
name: 'domainName',
label: 'Domain Name',
defaultValue: {
primaryLinkLabel: '',
primaryLinkUrl: '',
secondaryLinks: [],
},
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
{
id: '20202020-540c-4397-b872-2a90ea2fb809',
standardId: '',
nameSingular: 'non-searchable-object',
namePlural: 'non-searchable-objects',
labelSingular: '',
labelPlural: '',
description: '',
icon: 'test-non-searchable-object-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: true,
isAuditLogged: true,
isSearchable: false,
labelIdentifierFieldMetadataId: '',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldsById: {},
fieldIdByName: {},
fieldIdByJoinColumnName: {},
fieldIdByName: {
name: 'nameFieldMetadataId',
domainName: 'domainNameFieldMetadataId',
},
];
fieldIdByJoinColumnName: {},
}),
getMockObjectMetadataItemWithFieldsMaps({
id: '20202020-3d75-4aab-bacd-ee176c5f63ca',
standardId: '',
nameSingular: 'regular-custom-object',
namePlural: 'regular-custom-objects',
labelSingular: 'Regular Custom Object',
labelPlural: 'Regular Custom Objects',
description: 'A regular custom object',
icon: 'test-regular-custom-object-icon',
targetTableName: 'DEPRECATED',
isCustom: true,
isRemote: false,
isActive: true,
isSystem: false,
isAuditLogged: true,
isSearchable: true,
labelIdentifierFieldMetadataId: 'nameFieldMetadataId',
imageIdentifierFieldMetadataId: 'imageIdentifierFieldMetadataId',
workspaceId,
indexMetadatas: [],
fieldsById: {
nameFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-3d75-4aab-bacd-ee176c5f63ca',
id: 'nameFieldMetadataId',
type: FieldMetadataType.TEXT,
icon: 'test-field-icon',
name: 'name',
label: 'Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
imageIdentifierFieldMetadataId: getMockFieldMetadataEntity({
workspaceId,
objectMetadataId: '20202020-3d75-4aab-bacd-ee176c5f63ca',
id: 'imageIdentifierFieldMetadataId',
type: FieldMetadataType.TEXT,
icon: 'test-field-icon',
name: 'imageIdentifierFieldName',
label: 'Image Identifier Field Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
createdAt: new Date(),
updatedAt: new Date(),
}) as FieldMetadataEntity,
},
fieldIdByName: {
name: 'nameFieldMetadataId',
imageIdentifierFieldName: 'imageIdentifierFieldMetadataId',
},
fieldIdByJoinColumnName: {},
}),
getMockObjectMetadataItemWithFieldsMaps({
id: '20202020-540c-4397-b872-2a90ea2fb809',
standardId: '',
nameSingular: 'non-searchable-object',
namePlural: 'non-searchable-objects',
labelSingular: '',
labelPlural: '',
description: '',
icon: 'test-non-searchable-object-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: true,
isAuditLogged: true,
isSearchable: false,
labelIdentifierFieldMetadataId: '',
imageIdentifierFieldMetadataId: '',
workspaceId,
indexMetadatas: [],
fieldsById: {},
fieldIdByName: {},
fieldIdByJoinColumnName: {},
}),
];

View File

@ -1,7 +1,7 @@
import { objectRecordChangedValues } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-values';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { getMockObjectMetadataItemWithFieldsMaps } from 'src/utils/__test__/get-object-metadata-item-with-fields-maps.mock';
const mockObjectMetadata: ObjectMetadataItemWithFieldMaps = {
const mockObjectMetadata = getMockObjectMetadataItemWithFieldsMaps({
id: '1',
icon: 'Icon123',
nameSingular: 'Object',
@ -21,7 +21,7 @@ const mockObjectMetadata: ObjectMetadataItemWithFieldMaps = {
isSearchable: true,
indexMetadatas: [],
fieldIdByJoinColumnName: {},
};
});
describe('objectRecordChangedValues', () => {
it('detects changes in scalar values correctly', () => {

View File

@ -142,7 +142,7 @@ const computeSchemaComponent = ({
const result: OpenAPIV3_1.SchemaObject = {
type: 'object',
description: item.description,
description: item.description ?? undefined,
properties: convertObjectMetadataToSchemaProperties({
item,
forResponse,

View File

@ -7,13 +7,13 @@ import { isDefined } from 'twenty-shared/utils';
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
import { IndexMetadataInterface } from 'src/engine/metadata-modules/index-metadata/interfaces/index-metadata.interface';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
import { filterMorphRelationDuplicateFieldsDTO } from 'src/engine/dataloaders/utils/filter-morph-relation-duplicate-fields.util';
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { FieldMetadataMorphRelationService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service';
import { FieldMetadataRelationService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata-relation.service';
import { fromFieldMetadataEntityToFieldMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-field-metadata-entity-to-fieldMetadata-dto.util';
import { fromFieldMetadataEntityToFieldMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-field-metadata-entity-to-field-metadata-dto.util';
import { resolveFieldMetadataStandardOverride } from 'src/engine/metadata-modules/field-metadata/utils/resolve-field-metadata-standard-override.util';
import { IndexFieldMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-field-metadata.dto';
import { IndexMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-metadata.dto';

View File

@ -39,7 +39,8 @@ import {
import { BeforeUpdateOneField } from 'src/engine/metadata-modules/field-metadata/hooks/before-update-one-field.hook';
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service';
import { fieldMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/field-metadata/utils/field-metadata-graphql-api-exception-handler.util';
import { fromFieldMetadataEntityToFieldMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-field-metadata-entity-to-fieldMetadata-dto.util';
import { fromFieldMetadataEntityToFieldMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-field-metadata-entity-to-field-metadata-dto.util';
import { fromObjectMetadataEntityToObjectMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-object-metadata-entity-to-object-metadata-dto.util';
import { SettingPermissionType } from 'src/engine/metadata-modules/permissions/constants/setting-permission-type.constants';
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
import { isMorphRelationFieldMetadataType } from 'src/engine/utils/is-morph-relation-field-metadata-type.util';
@ -162,8 +163,10 @@ export class FieldMetadataResolver {
return {
type: fieldMetadata.settings.relationType,
sourceObjectMetadata,
targetObjectMetadata,
sourceObjectMetadata:
fromObjectMetadataEntityToObjectMetadataDto(sourceObjectMetadata),
targetObjectMetadata:
fromObjectMetadataEntityToObjectMetadataDto(targetObjectMetadata),
sourceFieldMetadata:
fromFieldMetadataEntityToFieldMetadataDto(sourceFieldMetadata),
targetFieldMetadata:
@ -203,8 +206,12 @@ export class FieldMetadataResolver {
return morphRelations.map<RelationDTO>((morphRelation) => ({
type: settings.relationType,
sourceObjectMetadata: morphRelation.sourceObjectMetadata,
targetObjectMetadata: morphRelation.targetObjectMetadata,
sourceObjectMetadata: fromObjectMetadataEntityToObjectMetadataDto(
morphRelation.sourceObjectMetadata,
),
targetObjectMetadata: fromObjectMetadataEntityToObjectMetadataDto(
morphRelation.targetObjectMetadata,
),
sourceFieldMetadata: fromFieldMetadataEntityToFieldMetadataDto(
morphRelation.sourceFieldMetadata,
),

View File

@ -1,28 +1,3 @@
import { IndexMetadataInterface } from 'src/engine/metadata-modules/index-metadata/interfaces/index-metadata.interface';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
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';
export interface ObjectMetadataInterface {
id: string;
standardId?: string | null;
workspaceId: string;
nameSingular: string;
namePlural: string;
labelSingular: string;
labelPlural: string;
description?: string;
icon: string;
targetTableName: string;
fields: FieldMetadataEntity[];
indexMetadatas: IndexMetadataInterface[];
isSystem: boolean;
isCustom: boolean;
isActive: boolean;
isRemote: boolean;
isAuditLogged: boolean;
isSearchable: boolean;
duplicateCriteria?: WorkspaceEntityDuplicateCriteria[];
labelIdentifierFieldMetadataId?: string | null;
imageIdentifierFieldMetadataId?: string | null;
}
export interface ObjectMetadataInterface extends ObjectMetadataEntity {}

View File

@ -18,7 +18,6 @@ export const fromFieldMetadataEntityToFieldMetadataDto = (
return {
...rest,
// Should we ? seems to be typed a dateString from classValidator, should be typed as string in TypeScript ?
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
description: description ?? undefined,

View File

@ -0,0 +1,28 @@
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
export const fromObjectMetadataEntityToObjectMetadataDto = (
objectMetadataEntity: ObjectMetadataEntity,
): ObjectMetadataDTO => {
const {
createdAt,
updatedAt,
description,
icon,
standardOverrides,
shortcut,
duplicateCriteria,
...rest
} = objectMetadataEntity;
return {
...rest,
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
description: description ?? undefined,
icon: icon ?? undefined,
standardOverrides: standardOverrides ?? undefined,
shortcut: shortcut ?? undefined,
duplicateCriteria: duplicateCriteria ?? undefined,
};
};

View File

@ -51,16 +51,16 @@ export class ObjectMetadataDTO {
labelPlural: string;
@Field({ nullable: true })
description: string;
description?: string;
@Field({ nullable: true })
icon: string;
icon?: string;
@Field(() => ObjectStandardOverridesDTO, { nullable: true })
standardOverrides?: ObjectStandardOverridesDTO;
@Field({ nullable: true })
shortcut: string;
shortcut?: string;
@FilterableField()
isCustom: boolean;

View File

@ -195,7 +195,7 @@ export class BeforeUpdateOneObject<T extends UpdateObjectPayload>
update: StandardObjectUpdate;
overrideKey: 'labelSingular' | 'labelPlural' | 'description' | 'icon';
newValue: string;
originalValue: string;
originalValue: string | null;
locale?: keyof typeof APP_LOCALES | undefined;
}): boolean {
if (locale && locale !== SOURCE_LOCALE) {
@ -224,7 +224,7 @@ export class BeforeUpdateOneObject<T extends UpdateObjectPayload>
update: StandardObjectUpdate,
overrideKey: 'labelSingular' | 'labelPlural' | 'description' | 'icon',
newValue: string,
originalValue: string,
originalValue: string | null,
locale: keyof typeof APP_LOCALES,
): boolean {
const messageId = generateMessageId(originalValue ?? '');
@ -254,7 +254,7 @@ export class BeforeUpdateOneObject<T extends UpdateObjectPayload>
update: StandardObjectUpdate,
overrideKey: 'labelSingular' | 'labelPlural' | 'description' | 'icon',
newValue: string,
originalValue: string,
originalValue: string | null,
): boolean {
if (newValue !== originalValue) {
return false;

View File

@ -10,8 +10,6 @@ import {
UpdateDateColumn,
} from 'typeorm';
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
import { WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type';
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@ -29,7 +27,7 @@ import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permi
'namePlural',
'workspaceId',
])
export class ObjectMetadataEntity implements ObjectMetadataInterface {
export class ObjectMetadataEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@ -52,14 +50,17 @@ export class ObjectMetadataEntity implements ObjectMetadataInterface {
labelPlural: string;
@Column({ nullable: true, type: 'text' })
description: string;
description: string | null;
@Column({ nullable: true })
icon: string;
@Column({ nullable: true, type: 'varchar' })
icon: string | null;
@Column({ type: 'jsonb', nullable: true })
standardOverrides?: ObjectStandardOverridesDTO;
standardOverrides: ObjectStandardOverridesDTO | null;
/**
* @deprecated
*/
@Column({ nullable: false })
targetTableName: string;
@ -82,16 +83,16 @@ export class ObjectMetadataEntity implements ObjectMetadataInterface {
isSearchable: boolean;
@Column({ type: 'jsonb', nullable: true })
duplicateCriteria?: WorkspaceEntityDuplicateCriteria[];
duplicateCriteria: WorkspaceEntityDuplicateCriteria[] | null;
@Column({ nullable: true })
shortcut: string;
@Column({ nullable: true, type: 'varchar' })
shortcut: string | null;
@Column({ nullable: true, type: 'uuid' })
labelIdentifierFieldMetadataId?: string | null;
labelIdentifierFieldMetadataId: string | null;
@Column({ nullable: true, type: 'uuid' })
imageIdentifierFieldMetadataId?: string | null;
imageIdentifierFieldMetadataId: string | null;
@Column({ default: false })
isLabelSyncedWithName: boolean;

View File

@ -1,5 +1,7 @@
import { Injectable } from '@nestjs/common';
import { isDefined } from 'twenty-shared/utils';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
@ -99,7 +101,9 @@ export class ObjectMetadataRelatedRecordsService {
{ objectMetadataId: updatedObjectMetadata.id, key: 'INDEX' },
{
name: `All ${updatedObjectMetadata.labelPlural}`,
icon: updatedObjectMetadata.icon,
...(isDefined(updatedObjectMetadata.icon)
? { icon: updatedObjectMetadata.icon }
: {}),
},
);
}

View File

@ -44,8 +44,12 @@ export class StandardObjectFactory {
}
return {
...workspaceEntityMetadataArgs,
// TODO: Remove targetTableName when we remove the old metadata
labelIdentifierFieldMetadataId: null,
imageIdentifierFieldMetadataId: null,
duplicateCriteria: [],
...workspaceEntityMetadataArgs,
description: workspaceEntityMetadataArgs.description ?? null,
targetTableName: 'DEPRECATED',
workspaceId: context.workspaceId,
dataSourceId: context.dataSourceId,

View File

@ -5,17 +5,29 @@ import {
PartialFieldMetadata,
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface';
export type PartialWorkspaceEntity = Omit<
export type PartialWorkspaceEntity = Pick<
ObjectMetadataInterface,
'id' | 'standardId' | 'fields' | 'isActive'
| 'workspaceId'
| 'nameSingular'
| 'namePlural'
| 'labelSingular'
| 'labelPlural'
| 'description'
| 'icon'
| 'targetTableName'
| 'indexMetadatas'
| 'isSystem'
| 'isCustom'
| 'isRemote'
| 'isAuditLogged'
| 'isSearchable'
| 'duplicateCriteria'
| 'labelIdentifierFieldMetadataId'
| 'imageIdentifierFieldMetadataId'
> & {
standardId: string;
icon?: string;
workspaceId: string;
dataSourceId: string;
fields: (PartialFieldMetadata | PartialComputedFieldMetadata)[];
labelIdentifierStandardId?: string | null;
imageIdentifierStandardId?: string | null;
};
export type ComputedPartialWorkspaceEntity = Omit<

View File

@ -1,9 +1,9 @@
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
import { ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import {
BaseOutputSchema,
RecordOutputSchema,
} from 'src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type';
import { ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { generateObjectRecordFields } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields';
const generateFakeObjectRecordEventWithPrefix = ({
@ -26,7 +26,8 @@ const generateFakeObjectRecordEventWithPrefix = ({
return {
object: {
isLeaf: true,
icon: objectMetadataInfo.objectMetadataItemWithFieldsMaps.icon,
icon:
objectMetadataInfo.objectMetadataItemWithFieldsMaps.icon ?? undefined,
label: objectMetadataInfo.objectMetadataItemWithFieldsMaps.labelSingular,
value: objectMetadataInfo.objectMetadataItemWithFieldsMaps.description,
nameSingular:

View File

@ -12,7 +12,8 @@ export const generateFakeObjectRecord = ({
return {
object: {
isLeaf: true,
icon: objectMetadataInfo.objectMetadataItemWithFieldsMaps.icon,
icon:
objectMetadataInfo.objectMetadataItemWithFieldsMaps.icon ?? undefined,
label: objectMetadataInfo.objectMetadataItemWithFieldsMaps.labelSingular,
value: objectMetadataInfo.objectMetadataItemWithFieldsMaps.description,
nameSingular:

View File

@ -1,12 +1,13 @@
import { Test, TestingModule } from '@nestjs/testing';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { AutomatedTriggerType } from 'src/modules/workflow/common/standard-objects/workflow-automated-trigger.workspace-entity';
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { DatabaseEventTriggerListener } from 'src/modules/workflow/workflow-trigger/automated-trigger/listeners/database-event-trigger.listener';
import { WorkflowTriggerJob } from 'src/modules/workflow/workflow-trigger/jobs/workflow-trigger.job';
import { getMockObjectMetadataEntity } from 'src/utils/__test__/get-object-metadata-entity.mock';
import { getMockObjectMetadataItemWithFieldsMaps } from 'src/utils/__test__/get-object-metadata-item-with-fields-maps.mock';
describe('DatabaseEventTriggerListener', () => {
let listener: DatabaseEventTriggerListener;
@ -54,27 +55,28 @@ describe('DatabaseEventTriggerListener', () => {
},
},
},
objectMetadataItemWithFieldsMaps: {
id: 'test-object-metadata',
workspaceId: 'test-workspace',
nameSingular: 'testObject',
namePlural: 'testObjects',
labelSingular: 'Test Object',
labelPlural: 'Test Objects',
description: 'Test object for testing',
fieldIdByJoinColumnName: {},
fieldsById: {},
fieldIdByName: {},
indexMetadatas: [],
targetTableName: 'test_objects',
isSystem: false,
isCustom: false,
isActive: true,
isRemote: false,
isAuditLogged: true,
isSearchable: true,
icon: 'Icon123',
} satisfies ObjectMetadataItemWithFieldMaps,
objectMetadataItemWithFieldsMaps:
getMockObjectMetadataItemWithFieldsMaps({
id: 'test-object-metadata',
workspaceId: 'test-workspace',
nameSingular: 'testObject',
namePlural: 'testObjects',
labelSingular: 'Test Object',
labelPlural: 'Test Objects',
description: 'Test object for testing',
indexMetadatas: [],
targetTableName: 'test_objects',
isSystem: false,
isCustom: false,
isActive: true,
isRemote: false,
isAuditLogged: true,
isSearchable: true,
icon: 'Icon123',
fieldIdByJoinColumnName: {},
fieldsById: {},
fieldIdByName: {},
}),
}),
},
},
@ -97,7 +99,7 @@ describe('DatabaseEventTriggerListener', () => {
events: [
{
recordId: 'test-record',
objectMetadata: {
objectMetadata: getMockObjectMetadataEntity({
id: 'test-object-metadata',
workspaceId,
nameSingular: 'testObject',
@ -117,7 +119,7 @@ describe('DatabaseEventTriggerListener', () => {
fields: [],
indexMetadatas: [],
icon: 'Icon123',
},
}),
properties: {
updatedFields: ['field1', 'field2'],
before: { field1: 'old', field2: 'old' },

View File

@ -0,0 +1,48 @@
import { faker } from '@faker-js/faker';
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
export type GetMockObjectMetadataEntityOverride =
Partial<ObjectMetadataEntity> &
Required<
Pick<
ObjectMetadataEntity,
'nameSingular' | 'namePlural' | 'id' | 'workspaceId'
>
>;
export const getMockObjectMetadataEntity = (
overrides: GetMockObjectMetadataEntityOverride,
): ObjectMetadataEntity => {
return {
createdAt: new Date(),
updatedAt: new Date(),
dataSource: {} as DataSourceEntity,
dataSourceId: faker.string.uuid(),
description: 'default object metadata description',
duplicateCriteria: [],
fieldPermissions: [],
fields: [],
icon: null,
imageIdentifierFieldMetadataId: null,
labelIdentifierFieldMetadataId: null,
indexMetadatas: [],
isActive: true,
isAuditLogged: true,
isCustom: true,
isLabelSyncedWithName: false,
isRemote: false,
isSearchable: true,
isSystem: false,
labelPlural: 'Default mock plural label',
labelSingular: 'Default mock plural singular',
objectPermissions: [],
shortcut: null,
standardId: null,
targetRelationFields: [],
standardOverrides: null,
targetTableName: faker.string.uuid(),
...overrides,
};
};

View File

@ -0,0 +1,37 @@
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import {
GetMockObjectMetadataEntityOverride,
getMockObjectMetadataEntity,
} from 'src/utils/__test__/get-object-metadata-entity.mock';
type GetMockObjectMetadataItemWithFielsMapsOverride =
GetMockObjectMetadataEntityOverride &
Required<
Pick<
ObjectMetadataItemWithFieldMaps,
| 'fieldsById'
| 'fieldIdByJoinColumnName'
| 'fieldIdByName'
| 'indexMetadatas'
>
>;
export const getMockObjectMetadataItemWithFieldsMaps = ({
fieldsById,
fieldIdByJoinColumnName,
fieldIdByName,
indexMetadatas,
...objectMetadataOverrides
}: GetMockObjectMetadataItemWithFielsMapsOverride): ObjectMetadataItemWithFieldMaps => {
const { fields: _fields, ...objectMetadata } = getMockObjectMetadataEntity(
objectMetadataOverrides,
);
return {
...objectMetadata,
fieldsById,
fieldIdByJoinColumnName,
fieldIdByName,
indexMetadatas,
};
};

View File

@ -13,6 +13,7 @@ import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metada
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { getMockObjectMetadataEntity } from 'src/utils/__test__/get-object-metadata-entity.mock';
export interface AgentToolTestContext {
module: TestingModule;
@ -130,7 +131,7 @@ export const createAgentToolTestModule =
isEditable: true,
} as RoleEntity;
const testObjectMetadata = {
const testObjectMetadata = getMockObjectMetadataEntity({
id: 'test-object-id',
standardId: null,
dataSourceId: 'test-data-source-id',
@ -158,7 +159,7 @@ export const createAgentToolTestModule =
dataSource: {} as any,
objectPermissions: [],
fieldPermissions: [],
};
});
return {
module,