From 28cdb02fbb48a282edbfcd62f7185f16198f8413 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Thu, 4 Dec 2025 17:39:12 +0100 Subject: [PATCH] Twenty standard application Objects and fields as `allFlatEntityMaps` ID non-agnostic (#16298) # Introduction Related to https://github.com/twentyhq/core-team-issues/issues/1995 This PR introduces the basis of the `twentyStandard` application as code on demand, it's highly tied to `ids` where it will becomes workspace agnostic following the builder and runner `universalIdentifier` refactor later. The goal here to allow computing the `allFlatEntityMaps` `to` of the `twentyStandard` application on a empty workspace ( workspace creation ). Allowing installing the twenty standard app through a workspace migration instead of passing by the sync metadata Nothing done will be run in production for the moment if it's not the small validation refactor we've introduced Please note that everything introduced here will be replaced at some point by a twenty app instance when the twenty sdk is mature enough to handle of the edge cases we need here ## How we've proceeded We've been iterating over every workspace entity both objects and their fields, and transpiled them to flatEntity. Being sure we migrate the defaultValue, settings and so on accordingly. We've also compute all the ids in prior of the whole entities computation so we don't face any hoisting issue. ## Current state At the moment only handling all of the 29 standard objects and their fields Settings a unique universalIdentifier for all of them Will come views, agent role targets and so on later ## `workspace:compute-twenty-standard-migration` command This command allow generating a workspace migration that will result in installing the twenty standard app in an empty workspace It's temporary and aims to allow debugging for the moment we might not keep it in the future as it is right now It contains debug writeFileSync which is expected no worries greptile ## `LabelFieldMetadataIdentifierId` Small refactor allowing defining the label identifier field metadata id of a uuid field metadata type for system object, as some of our standard object don't have a name field and don't aim to Also please note that we might remove this build options later in the sake of the currently installed universal identifier application that we could compare with the deterministic twenty standard one ## `runFlatFieldMetadataValidators` Deprecated this pattern which was redundant and not v2 friendly pattern ## Current errors that will address in upcoming PR Current standard objects and fields metadata does not pass the validation that we have in place, as historically the sync metadata would directly consume the repositories and would just ignore the validation. This is about to change. Will handle the below errors in dedicated PRs as they will required upgrade commands in order to migrate the data, or will handle that from the sync metadata instead still to be determined but nothing critical here - camel case field metadata name - options label invalid format ```json { "status": "fail", "report": { "fieldMetadata": [ { "status": "fail", "errors": [ { "code": "INVALID_FIELD_INPUT", "message": "Name should be in camelCase", "userFriendlyMessage": { "id": "P+jdmX", "message": "Name should be in camelCase" }, "value": "iCalUID" } ], "flatEntityMinimalInformation": { "id": "68dd83cd-92c8-4233-bb28-47939bab6124", "name": "iCalUID", "objectMetadataId": "11c16ab6-9176-439e-a2db-a12c5a58a524" }, "type": "create_field" }, { "status": "fail", "errors": [ { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"email\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "email" } }, "value": "email" }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"sms\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "sms" } }, "value": "sms" } ], "flatEntityMinimalInformation": { "id": "e3caaf2a-e07d-4146-8dfc-9eef904e82c9", "name": "type", "objectMetadataId": "4b777de5-4c7b-4af4-9b92-655c0f87512b" }, "type": "create_field" }, { "status": "fail", "errors": [ { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"incoming\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "incoming" } }, "value": "incoming" }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"outgoing\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "outgoing" } }, "value": "outgoing" } ], "flatEntityMinimalInformation": { "id": "d96233a4-93be-45ea-9548-3b50f3c700cf", "name": "direction", "objectMetadataId": "480a648a-d2e5-482a-992f-ef053e1b4bb0" }, "type": "create_field" }, { "status": "fail", "errors": [ { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"from\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "from" } }, "value": "from" }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"to\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "to" } }, "value": "to" }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"cc\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "cc" } }, "value": "cc" }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case \"bcc\"", "userFriendlyMessage": { "id": "UBPzFQ", "message": "Value must be in UPPER_CASE and follow snake_case \"{sanitizedValue}\"", "values": { "sanitizedValue": "bcc" } }, "value": "bcc" } ], "flatEntityMinimalInformation": { "id": "961c598e-67c3-452d-8bb2-b92c0bc64404", "name": "role", "objectMetadataId": "8af8a13c-ff97-4cd3-b70d-52a7dc2924b4" }, "type": "create_field" }, { "status": "fail", "errors": [ { "code": "INVALID_FIELD_INPUT", "message": "Label must not contain a comma", "userFriendlyMessage": { "id": "k731jp", "message": "Label must not contain a comma" }, "value": "Commas and dot (1,234.56)" }, { "code": "INVALID_FIELD_INPUT", "message": "Label must not contain a comma", "userFriendlyMessage": { "id": "k731jp", "message": "Label must not contain a comma" }, "value": "Spaces and comma (1 234,56)" }, { "code": "INVALID_FIELD_INPUT", "message": "Label must not contain a comma", "userFriendlyMessage": { "id": "k731jp", "message": "Label must not contain a comma" }, "value": "Dots and comma (1.234,56)" } ], "flatEntityMinimalInformation": { "id": "7fa20caf-2597-42e3-84e5-15a91b125b9b", "name": "numberFormat", "objectMetadataId": "a6974302-9e72-461c-aa09-9390f4ff16fc" }, "type": "create_field" } ], "objectMetadata": [], "view": [], "viewField": [], "viewGroup": [], "index": [], "serverlessFunction": [], "cronTrigger": [], "databaseEventTrigger": [], "routeTrigger": [], "viewFilter": [], "role": [], "roleTarget": [], "agent": [] } } ``` --- ...ty-standard-workspace-migration.command.ts | 79 +++ .../commands/database-command.module.ts | 4 + ...ate-twenty-standard-application.command.ts | 2 +- .../application/application.service.ts | 2 +- ...run-flat-field-metadata-validators.util.ts | 27 - .../validate-enum-flat-field-metadata.util.ts | 360 +++++----- ...t-field-metadata-name-availability.util.ts | 8 +- .../validate-flat-field-metadata-name.util.ts | 87 ++- ...lation-flat-field-join-column-name.util.ts | 4 + ...ph-or-relation-flat-field-metadata.util.ts | 2 + ...un-flat-object-metadata-validators.util.ts | 27 - ...e-flat-object-metadata-identifiers.util.ts | 33 +- ...alidate-flat-object-metadata-label.util.ts | 49 +- ...validate-flat-object-metadata-name.util.ts | 74 ++- .../types/flat-metadata-validator.type.ts | 6 - ...name-flat-metadata-validators.constants.ts | 41 -- .../dev-seeder/services/dev-seeder.service.ts | 2 +- .../views/calendar-events-all.view.ts | 2 +- .../views/companies-all.view.ts | 2 +- .../views/dashboards-all.view.ts | 2 +- .../views/message-threads-all.view.ts | 2 +- .../views/messages-all.view.ts | 2 +- .../views/notes-all.view.ts | 2 +- .../views/opportunities-all.view.ts | 2 +- .../views/opportunity-by-stage.view.ts | 2 +- .../views/people-all.view.ts | 2 +- .../views/tasks-all.view.ts | 2 +- .../views/tasks-assigned-to-me.ts | 2 +- .../views/tasks-by-status.view.ts | 2 +- .../views/timeline-activities-all.view.ts | 2 +- .../views/workflow-runs-all.view.ts | 2 +- .../views/workflow-versions-all.view.ts | 2 +- .../views/workflows-all.view.ts | 2 +- .../views/workspace-members-all.view.ts | 2 +- .../constants/standard-object.constant.ts | 167 +---- .../constants/twenty-standard-applications.ts | 0 .../all-standard-object-field-name.type.ts | 5 + .../types/all-standard-object-name.type.ts | 3 + ...-standard-flat-field-metadata-maps.util.ts | 116 ++++ ...standard-flat-object-metadata-maps.util.ts | 35 + ...hment-standard-flat-field-metadata.util.ts | 399 ++++++++++++ ...klist-standard-flat-field-metadata.util.ts | 134 ++++ ...ation-standard-flat-field-metadata.util.ts | 160 +++++ ...annel-standard-flat-field-metadata.util.ts | 389 +++++++++++ ...ipant-standard-flat-field-metadata.util.ts | 226 +++++++ ...event-standard-flat-field-metadata.util.ts | 291 +++++++++ ...mpany-standard-flat-field-metadata.util.ts | 433 ++++++++++++ ...count-standard-flat-field-metadata.util.ts | 289 ++++++++ ...board-standard-flat-field-metadata.util.ts | 222 +++++++ ...older-standard-flat-field-metadata.util.ts | 141 ++++ ...orite-standard-flat-field-metadata.util.ts | 364 +++++++++++ ...ation-standard-flat-field-metadata.util.ts | 200 ++++++ ...annel-standard-flat-field-metadata.util.ts | 504 ++++++++++++++ ...older-standard-flat-field-metadata.util.ts | 219 +++++++ ...ipant-standard-flat-field-metadata.util.ts | 201 ++++++ ...ssage-standard-flat-field-metadata.util.ts | 220 +++++++ ...hread-standard-flat-field-metadata.util.ts | 121 ++++ ...-note-standard-flat-field-metadata.util.ts | 260 ++++++++ ...arget-standard-flat-field-metadata.util.ts | 199 ++++++ ...unity-standard-flat-field-metadata.util.ts | 355 ++++++++++ ...erson-standard-flat-field-metadata.util.ts | 466 +++++++++++++ ...-task-standard-flat-field-metadata.util.ts | 323 +++++++++ ...arget-standard-flat-field-metadata.util.ts | 199 ++++++ ...ivity-standard-flat-field-metadata.util.ts | 402 ++++++++++++ ...igger-standard-flat-field-metadata.util.ts | 149 +++++ ...w-run-standard-flat-field-metadata.util.ts | 339 ++++++++++ ...kflow-standard-flat-field-metadata.util.ts | 320 +++++++++ ...rsion-standard-flat-field-metadata.util.ts | 267 ++++++++ ...ember-standard-flat-field-metadata.util.ts | 510 +++++++++++++++ ...reate-standard-field-flat-metadata.util.ts | 109 ++++ ...eate-standard-flat-object-metadata.util.ts | 616 ++++++++++++++++++ ...eate-standard-object-flat-metadata.util.ts | 86 +++ ...ndard-relation-field-flat-metadata.util.ts | 118 ++++ ...tadata-id-by-object-and-field-name.util.ts | 43 ++ ...plication-all-flat-entity-maps.constant.ts | 93 +++ .../flat-field-metadata-validator.service.ts | 12 +- .../flat-object-metadata-validator.service.ts | 4 + ...and-workspace-creation.integration-spec.ts | 2 +- ...-metadata-enum-v2.integration-spec.ts.snap | 61 +- ...field-metadata-v2.integration-spec.ts.snap | 63 +- ...bject-metadata-v2.integration-spec.ts.snap | 17 + ...e-object-metadata.integration-spec.ts.snap | 81 +++ ...te-one-object-metadata.integration-spec.ts | 43 +- .../LabelIdentifierFieldMetadataTypes.ts | 1 + 84 files changed, 10312 insertions(+), 506 deletions(-) create mode 100644 packages/twenty-server/src/database/commands/compute-twenty-standard-workspace-migration.command.ts delete mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/run-flat-field-metadata-validators.util.ts delete mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/run-flat-object-metadata-validators.util.ts delete mode 100644 packages/twenty-server/src/engine/metadata-modules/types/flat-metadata-validator.type.ts delete mode 100644 packages/twenty-server/src/engine/metadata-modules/utils/constants/metadata-name-flat-metadata-validators.constants.ts rename packages/twenty-server/src/engine/{core-modules/application => workspace-manager/twenty-standard-application}/constants/standard-object.constant.ts (91%) rename packages/twenty-server/src/engine/{core-modules/application => workspace-manager/twenty-standard-application}/constants/twenty-standard-applications.ts (100%) create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-field-metadata-maps.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-object-metadata-maps.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-attachment-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-blocklist-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-event-association-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-participant-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-company-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-connected-account-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-dashboard-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-folder-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-message-association-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-folder-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-participant-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-thread-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-target-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-opportunity-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-person-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-target-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-timeline-activity-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-automated-trigger-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-run-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-version-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workspace-member-standard-flat-field-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-flat-object-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-object-flat-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant.ts diff --git a/packages/twenty-server/src/database/commands/compute-twenty-standard-workspace-migration.command.ts b/packages/twenty-server/src/database/commands/compute-twenty-standard-workspace-migration.command.ts new file mode 100644 index 00000000000..93defc7bcfc --- /dev/null +++ b/packages/twenty-server/src/database/commands/compute-twenty-standard-workspace-migration.command.ts @@ -0,0 +1,79 @@ +import { Logger } from '@nestjs/common'; + +import { writeFileSync } from 'fs'; + +import { Command, CommandRunner } from 'nest-commander'; +import { WorkspaceMigrationV2ExceptionCode } from 'twenty-shared/metadata'; + +import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; +import { computeTwentyStandardApplicationAllFlatEntityMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant'; +import { WorkspaceMigrationBuildOrchestratorService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service'; +import { WorkspaceMigrationV2Exception } from 'src/engine/workspace-manager/workspace-migration.exception'; + +@Command({ + name: 'workspace:compute-twenty-standard-migration', + description: 'Compute Twenty standard workspace migration.', +}) +export class ComputeTwentyStandardWorkspaceMigrationCommand extends CommandRunner { + private readonly logger = new Logger( + ComputeTwentyStandardWorkspaceMigrationCommand.name, + ); + + constructor( + private readonly workspaceMigrationBuildOrchestratorService: WorkspaceMigrationBuildOrchestratorService, + ) { + super(); + } + + async run(): Promise { + this.logger.log('Starting compute Twenty standard workspace migration...'); + + // TODO: Implement migration logic here + const workspaceId = '20202020-ef6f-4118-953c-2b027324b54a'; + const twentyStandardAllFlatEntityMaps = + computeTwentyStandardApplicationAllFlatEntityMaps({ + createdAt: new Date(), + workspaceId, + }); + + writeFileSync( + `${Date.now()}-all-flat-entity-maps.json`, + JSON.stringify(twentyStandardAllFlatEntityMaps, null, 2), + ); + + const validateAndBuildResult = + await this.workspaceMigrationBuildOrchestratorService + .buildWorkspaceMigration({ + buildOptions: { + isSystemBuild: true, + }, + fromToAllFlatEntityMaps: { + flatObjectMetadataMaps: { + from: createEmptyFlatEntityMaps(), + to: twentyStandardAllFlatEntityMaps.flatObjectMetadataMaps, + }, + flatFieldMetadataMaps: { + from: createEmptyFlatEntityMaps(), + to: twentyStandardAllFlatEntityMaps.flatFieldMetadataMaps, + }, + }, + workspaceId, + }) + .catch((error) => { + this.logger.error(error); + throw new WorkspaceMigrationV2Exception( + WorkspaceMigrationV2ExceptionCode.BUILDER_INTERNAL_SERVER_ERROR, + error.message, + ); + }); + + writeFileSync( + `${Date.now()}validate-and-build-result.json`, + JSON.stringify(validateAndBuildResult, null, 2), + ); + + this.logger.log( + 'Compute Twenty standard workspace migration completed successfully.', + ); + } +} diff --git a/packages/twenty-server/src/database/commands/database-command.module.ts b/packages/twenty-server/src/database/commands/database-command.module.ts index 2b59ea5e21f..16f0cbfd493 100644 --- a/packages/twenty-server/src/database/commands/database-command.module.ts +++ b/packages/twenty-server/src/database/commands/database-command.module.ts @@ -1,6 +1,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { ComputeTwentyStandardWorkspaceMigrationCommand } from 'src/database/commands/compute-twenty-standard-workspace-migration.command'; import { CronRegisterAllCommand } from 'src/database/commands/cron-register-all.command'; import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command'; import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question'; @@ -22,6 +23,7 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/ import { DevSeederModule } from 'src/engine/workspace-manager/dev-seeder/dev-seeder.module'; import { WorkspaceCleanerModule } from 'src/engine/workspace-manager/workspace-cleaner/workspace-cleaner.module'; import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; +import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module'; import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module'; import { MessagingImportManagerModule } from 'src/modules/messaging/message-import-manager/messaging-import-manager.module'; import { WorkflowRunQueueModule } from 'src/modules/workflow/workflow-runner/workflow-run-queue/workflow-run-queue.module'; @@ -51,10 +53,12 @@ import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/au CronTriggerModule, DatabaseEventTriggerModule, WorkspaceCleanerModule, + WorkspaceMigrationV2Module, TrashCleanupModule, PublicDomainModule, ], providers: [ + ComputeTwentyStandardWorkspaceMigrationCommand, DataSeedWorkspaceCommand, ConfirmationQuestion, CronRegisterAllCommand, diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-11/1-11-create-twenty-standard-application.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-11/1-11-create-twenty-standard-application.command.ts index 78f4312f0ce..2c464eb6131 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-11/1-11-create-twenty-standard-application.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-11/1-11-create-twenty-standard-application.command.ts @@ -7,10 +7,10 @@ import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/ import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner'; import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity'; import { ApplicationService } from 'src/engine/core-modules/application/application.service'; -import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications'; import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications'; @Command({ name: 'upgrade:1-11:create-twenty-standard-application', diff --git a/packages/twenty-server/src/engine/core-modules/application/application.service.ts b/packages/twenty-server/src/engine/core-modules/application/application.service.ts index 619aac3032c..dabd0524a2d 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application.service.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application.service.ts @@ -10,10 +10,10 @@ import { ApplicationException, ApplicationExceptionCode, } from 'src/engine/core-modules/application/application.exception'; -import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications'; import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; import { ALL_FLAT_ENTITY_MAPS_PROPERTIES } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-maps-properties.constant'; import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service'; +import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications'; @Injectable() export class ApplicationService { diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/run-flat-field-metadata-validators.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/run-flat-field-metadata-validators.util.ts deleted file mode 100644 index 7887b347125..00000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/run-flat-field-metadata-validators.util.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { t } from '@lingui/core/macro'; - -import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; -import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; -import { type FlatMetadataValidator } from 'src/engine/metadata-modules/types/flat-metadata-validator.type'; - -export const runFlatFieldMetadataValidators = ({ - elementToValidate, - validators, -}: { - elementToValidate: T; - validators: FlatMetadataValidator[]; -}): FlatFieldMetadataValidationError[] => { - return validators.flatMap(({ validator, message }) => { - const isInvalid = validator(elementToValidate); - - if (isInvalid) { - return { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: t(message), - value: elementToValidate, - }; - } - - return []; - }); -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-enum-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-enum-flat-field-metadata.util.ts index d96826fbcaa..e0782da2cbc 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-enum-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-enum-flat-field-metadata.util.ts @@ -4,8 +4,8 @@ import { QUOTED_STRING_REGEX } from 'twenty-shared/constants'; import { FieldMetadataType, type EnumFieldMetadataType, - type NonNullableRequired, type FieldMetadataOptions, + type NonNullableRequired, } from 'twenty-shared/types'; import { assertUnreachable, isDefined } from 'twenty-shared/utils'; import { z } from 'zod'; @@ -18,128 +18,159 @@ import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-me import { type FlatFieldMetadataTypeValidationArgs } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-type-validator.type'; import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { runFlatFieldMetadataValidators } from 'src/engine/metadata-modules/flat-field-metadata/utils/run-flat-field-metadata-validators.util'; -import { type FlatMetadataValidator } from 'src/engine/metadata-modules/types/flat-metadata-validator.type'; -import { - beneathDatabaseIdentifierMinimumLength, - exceedsDatabaseIdentifierMaximumLength, -} from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils'; +import { IDENTIFIER_MAX_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-max-char-length.constants'; +import { IDENTIFIER_MIN_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-min-char-length.constants'; import { isSnakeCaseString } from 'src/utils/is-snake-case-string'; const validateMetadataOptionId = (sanitizedId?: string) => { - const validators: FlatMetadataValidator[] = [ - { - validator: (id) => !isDefined(id), - message: msg`Option id is required`, - }, - { - validator: (id) => !z.string().uuid().safeParse(id).success, - message: msg`Option id is invalid`, - }, - ]; + const errors: FlatFieldMetadataValidationError[] = []; - return runFlatFieldMetadataValidators({ - elementToValidate: sanitizedId, - validators, - }); + if (!isDefined(sanitizedId)) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option id is required`, + userFriendlyMessage: msg`Option id is required`, + }); + } + + if (!z.string().uuid().safeParse(sanitizedId).success) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option id is invalid`, + userFriendlyMessage: msg`Option id is invalid`, + value: sanitizedId, + }); + } + + return errors; }; const validateMetadataOptionLabel = ( sanitizedLabel: string, ): FlatFieldMetadataValidationError[] => { + const errors: FlatFieldMetadataValidationError[] = []; + if (!isDefined(sanitizedLabel)) { - return [ - { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: t`Option label is required`, - userFriendlyMessage: msg`Option label is required`, - }, - ]; + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option label is required`, + userFriendlyMessage: msg`Option label is required`, + }); + + return errors; } if (!isNonEmptyString(sanitizedLabel)) { - return [ - { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: t`Option label must be a string of at least one character`, - userFriendlyMessage: msg`Option label format not supported`, - value: sanitizedLabel, - }, - ]; + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option label must be a string of at least one character`, + userFriendlyMessage: msg`Option label format not supported`, + value: sanitizedLabel, + }); + + return errors; } - const validators: FlatMetadataValidator[] = [ - { - validator: exceedsDatabaseIdentifierMaximumLength, - message: msg`Option label exceeds 63 characters`, - }, - { - validator: beneathDatabaseIdentifierMinimumLength, - message: msg`Option label "${sanitizedLabel}" is beneath 1 character`, - }, - { - validator: (label) => label.includes(','), - message: msg`Label must not contain a comma`, - }, - { - validator: (label) => !isNonEmptyString(label) || label === ' ', - message: msg`Label must not be empty`, - }, - ]; + if (sanitizedLabel.length > IDENTIFIER_MAX_CHAR_LENGTH) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option label exceeds 63 characters`, + userFriendlyMessage: msg`Option label exceeds 63 characters`, + value: sanitizedLabel, + }); + } - return runFlatFieldMetadataValidators({ - elementToValidate: sanitizedLabel, - validators, - }); + if (sanitizedLabel.length < IDENTIFIER_MIN_CHAR_LENGTH) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option label "${sanitizedLabel}" is beneath 1 character`, + userFriendlyMessage: msg`Option label "${sanitizedLabel}" is beneath 1 character`, + value: sanitizedLabel, + }); + } + + if (sanitizedLabel.includes(',')) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Label must not contain a comma`, + userFriendlyMessage: msg`Label must not contain a comma`, + value: sanitizedLabel, + }); + } + + if (!isNonEmptyString(sanitizedLabel) || sanitizedLabel === ' ') { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Label must not be empty`, + userFriendlyMessage: msg`Label must not be empty`, + value: sanitizedLabel, + }); + } + + return errors; }; const validateMetadataOptionValue = ( sanitizedValue: string, ): FlatFieldMetadataValidationError[] => { + const errors: FlatFieldMetadataValidationError[] = []; + if (!isDefined(sanitizedValue)) { - return [ - { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: t`Option value is required`, - userFriendlyMessage: msg`Option value is required`, - }, - ]; + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option value is required`, + userFriendlyMessage: msg`Option value is required`, + }); + + return errors; } if (!isNonEmptyString(sanitizedValue)) { - return [ - { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: t`Option value must be a string of at least one character`, - userFriendlyMessage: msg`Option value format not supported`, - }, - ]; + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option value must be a string of at least one character`, + userFriendlyMessage: msg`Option value format not supported`, + value: sanitizedValue, + }); + + return errors; } - const validators: FlatMetadataValidator[] = [ - { - validator: exceedsDatabaseIdentifierMaximumLength, - message: msg`Option value exceeds 63 characters`, - }, - { - validator: beneathDatabaseIdentifierMinimumLength, - message: msg`Option value "${sanitizedValue}" is beneath 1 character`, - }, - { - validator: (value) => !isSnakeCaseString(value), - message: msg`Value must be in UPPER_CASE and follow snake_case "${sanitizedValue}"`, - }, - ]; + if (sanitizedValue.length > IDENTIFIER_MAX_CHAR_LENGTH) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option value exceeds 63 characters`, + userFriendlyMessage: msg`Option value exceeds 63 characters`, + value: sanitizedValue, + }); + } - return runFlatFieldMetadataValidators({ - elementToValidate: sanitizedValue, - validators, - }); + if (sanitizedValue.length < IDENTIFIER_MIN_CHAR_LENGTH) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Option value "${sanitizedValue}" is beneath 1 character`, + userFriendlyMessage: msg`Option value "${sanitizedValue}" is beneath 1 character`, + value: sanitizedValue, + }); + } + + if (!isSnakeCaseString(sanitizedValue)) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Value must be in UPPER_CASE and follow snake_case "${sanitizedValue}"`, + userFriendlyMessage: msg`Value must be in UPPER_CASE and follow snake_case "${sanitizedValue}"`, + value: sanitizedValue, + }); + } + + return errors; }; const validateDuplicates = ( options: FieldMetadataOptions, ) => { + const errors: FlatFieldMetadataValidationError[] = []; + const fieldsToCheckForDuplicates = [ 'position', 'id', @@ -148,20 +179,22 @@ const validateDuplicates = ( | FieldMetadataDefaultOption[] | FieldMetadataComplexOption[] )[number])[]; - const duplicatedValidators = fieldsToCheckForDuplicates.map< - FlatMetadataValidator< - FieldMetadataDefaultOption[] | FieldMetadataComplexOption[] - > - >((field) => ({ - message: msg`Duplicated option ${field}`, - validator: () => - new Set(options.map((option) => option[field])).size !== options.length, - })); - return runFlatFieldMetadataValidators({ - elementToValidate: options, - validators: duplicatedValidators, - }); + for (const field of fieldsToCheckForDuplicates) { + const hasDuplicates = + new Set(options.map((option) => option[field])).size !== options.length; + + if (hasDuplicates) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Duplicated option ${field}`, + userFriendlyMessage: msg`Duplicated option ${field}`, + value: options, + }); + } + } + + return errors; }; const validateFieldMetadataInputOptions = ( @@ -200,35 +233,43 @@ const validateSelectDefaultValue = ({ options: FieldMetadataOptions; defaultValue: string | string[]; }): FlatFieldMetadataValidationError[] => { + const errors: FlatFieldMetadataValidationError[] = []; + if (typeof defaultValue !== 'string') { - return [ - { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: `Default value for select must be a string got ${defaultValue}`, - userFriendlyMessage: msg`Default value must be a string`, - value: defaultValue, - }, - ]; + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: `Default value for select must be a string got ${defaultValue}`, + userFriendlyMessage: msg`Default value must be a string`, + value: defaultValue, + }); + + return errors; } - const validators: FlatMetadataValidator[] = [ - { - validator: (value: string) => !QUOTED_STRING_REGEX.test(value), - message: msg`Default value should be as quoted string`, - }, - { - validator: (value: string) => - !options.some( - (option) => option.value === value.replace(QUOTED_STRING_REGEX, '$1'), - ), - message: msg`Default value "${defaultValue}" must be one of the option values`, - }, - ]; + if (!QUOTED_STRING_REGEX.test(defaultValue)) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Default value should be as quoted string`, + userFriendlyMessage: msg`Default value should be as quoted string`, + value: defaultValue, + }); + } - return runFlatFieldMetadataValidators({ - elementToValidate: defaultValue, - validators, - }); + const matchesOptionValue = options.some( + (option) => + option.value === defaultValue.replace(QUOTED_STRING_REGEX, '$1'), + ); + + if (!matchesOptionValue) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Default value "${defaultValue}" must be one of the option values`, + userFriendlyMessage: msg`Default value "${defaultValue}" must be one of the option values`, + value: defaultValue, + }); + } + + return errors; }; const validateMultiSelectDefaultValue = ({ @@ -238,40 +279,49 @@ const validateMultiSelectDefaultValue = ({ options: FieldMetadataOptions; multiSelectDefaultValue: unknown; }): FlatFieldMetadataValidationError[] => { + const errors: FlatFieldMetadataValidationError[] = []; + if (!Array.isArray(multiSelectDefaultValue)) { - return [ - { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - userFriendlyMessage: msg`Multi-select field default value must be an array`, - message: `Default value for multi-select must be an array got ${multiSelectDefaultValue}`, - value: multiSelectDefaultValue, - }, - ]; + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + userFriendlyMessage: msg`Multi-select field default value must be an array`, + message: `Default value for multi-select must be an array got ${multiSelectDefaultValue}`, + value: multiSelectDefaultValue, + }); + + return errors; } - const validators: FlatMetadataValidator[] = [ - { - validator: (values) => values.length === 0, - message: msg`If defined default value must contain at least one value`, - }, - { - validator: (values) => new Set(values).size !== values.length, - message: msg`Default values must be unique`, - }, - ]; + if (multiSelectDefaultValue.length === 0) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`If defined default value must contain at least one value`, + userFriendlyMessage: msg`If defined default value must contain at least one value`, + value: multiSelectDefaultValue, + }); + } - return [ - runFlatFieldMetadataValidators({ - elementToValidate: multiSelectDefaultValue, - validators, - }), - multiSelectDefaultValue.flatMap((defaultValue) => - validateSelectDefaultValue({ + if ( + new Set(multiSelectDefaultValue).size !== multiSelectDefaultValue.length + ) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Default values must be unique`, + userFriendlyMessage: msg`Default values must be unique`, + value: multiSelectDefaultValue, + }); + } + + for (const defaultValue of multiSelectDefaultValue) { + errors.push( + ...validateSelectDefaultValue({ defaultValue, options, }), - ), - ].flat(); + ); + } + + return errors; }; const validateFieldMetadataDefaultValue = ({ diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts index af9b4bc430f..7458455059a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util.ts @@ -11,6 +11,7 @@ import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modul import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { getObjectFieldNamesAndJoinColumnNames } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-object-field-names-and-join-column-names.util'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; const getReservedCompositeFieldNames = ( objectFlatFieldMetadatas: FlatFieldMetadata[], @@ -39,7 +40,9 @@ export const validateFlatFieldMetadataNameAvailability = ({ name, flatFieldMetadataMaps, flatObjectMetadata, + buildOptions, }: { + buildOptions: WorkspaceMigrationBuilderOptions; name: string; flatObjectMetadata: FlatObjectMetadata; flatFieldMetadataMaps: FlatEntityMaps; @@ -54,7 +57,10 @@ export const validateFlatFieldMetadataNameAvailability = ({ objectFlatFieldMetadatas, ); - if (reservedCompositeFieldsNames.includes(name)) { + if ( + !buildOptions.isSystemBuild && + reservedCompositeFieldsNames.includes(name) + ) { errors.push({ code: FieldMetadataExceptionCode.RESERVED_KEYWORD, message: `Name "${name}" is reserved composite field name`, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name.util.ts index 8a169397e1c..d6618275ac9 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name.util.ts @@ -1,21 +1,76 @@ +import { msg, t } from '@lingui/core/macro'; +import camelCase from 'lodash.camelcase'; +import { RESERVED_METADATA_NAME_KEYWORDS } from 'twenty-shared/metadata'; + import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; -import { METADATA_NAME_VALIDATORS } from 'src/engine/metadata-modules/utils/constants/metadata-name-flat-metadata-validators.constants'; +import { IDENTIFIER_MAX_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-max-char-length.constants'; +import { IDENTIFIER_MIN_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-min-char-length.constants'; +import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; -export const validateFlatFieldMetadataName = ( - name: string, -): FlatFieldMetadataValidationError[] => - METADATA_NAME_VALIDATORS.flatMap(({ validator, message }) => { - const isInvalid = validator(name); +const STARTS_WITH_LOWER_CASE_AND_CONTAINS_ONLY_CAPS_AND_LOWER_LETTERS_AND_NUMBER_STRING_REGEX = + /^[a-z][a-zA-Z0-9]*$/; - if (isInvalid) { - return { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: message.message ?? '', - userFriendlyMessage: message, - value: name, - }; - } +export const validateFlatFieldMetadataName = ({ + buildOptions, + name, +}: { + name: string; + buildOptions: WorkspaceMigrationBuilderOptions; +}): FlatFieldMetadataValidationError[] => { + const errors: FlatFieldMetadataValidationError[] = []; - return []; - }); + if (name.length > IDENTIFIER_MAX_CHAR_LENGTH) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Name is too long`, + userFriendlyMessage: msg`Name is too long`, + value: name, + }); + } + + if (name.length < IDENTIFIER_MIN_CHAR_LENGTH) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Name is too short`, + userFriendlyMessage: msg`Name is too short`, + value: name, + }); + } + + if (name !== camelCase(name)) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Name should be in camelCase`, + userFriendlyMessage: msg`Name should be in camelCase`, + value: name, + }); + } + + if ( + !name.match( + STARTS_WITH_LOWER_CASE_AND_CONTAINS_ONLY_CAPS_AND_LOWER_LETTERS_AND_NUMBER_STRING_REGEX, + ) + ) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`Name is not valid: it must start with lowercase letter and contain only alphanumeric letters`, + userFriendlyMessage: msg`Name is not valid: it must start with lowercase letter and contain only alphanumeric letters`, + value: name, + }); + } + + if ( + !buildOptions.isSystemBuild && + RESERVED_METADATA_NAME_KEYWORDS.includes(name) + ) { + errors.push({ + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: t`This name is reserved. Use a different name or the system will add "Custom" suffix.`, + userFriendlyMessage: msg`This name is reserved. Use a different name or the system will add "Custom" suffix.`, + value: name, + }); + } + + return errors; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-join-column-name.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-join-column-name.util.ts index 8eb68de1618..59a9ce69690 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-join-column-name.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-join-column-name.util.ts @@ -9,6 +9,7 @@ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/ import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { validateFlatFieldMetadataNameAvailability } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name-availability.util'; +import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; export const validateMorphOrRelationFlatFieldJoinColumName = ({ flatFieldMetadata, @@ -16,7 +17,9 @@ export const validateMorphOrRelationFlatFieldJoinColumName = ({ flatFieldMetadataMaps, flatObjectMetadataMaps, }, + buildOptions, }: { + buildOptions: WorkspaceMigrationBuilderOptions; flatFieldMetadata: FlatFieldMetadata; optimisticFlatEntityMapsAndRelatedFlatEntityMaps: MetadataFlatEntityAndRelatedFlatEntityMapsForValidation<'fieldMetadata'>; }): FlatFieldMetadataValidationError[] => { @@ -55,6 +58,7 @@ export const validateMorphOrRelationFlatFieldJoinColumName = ({ name: flatFieldMetadata.settings.joinColumnName, flatFieldMetadataMaps, flatObjectMetadata, + buildOptions, }), ); break; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts index 8e38ca121d3..391bcb5d3f2 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-or-relation-flat-field-metadata.util.ts @@ -18,6 +18,7 @@ export const validateMorphOrRelationFlatFieldMetadata = ({ }, updates, remainingFlatEntityMapsToValidate, + buildOptions, }: FlatFieldMetadataTypeValidationArgs): FlatFieldMetadataValidationError[] => { const { relationTargetFieldMetadataId, relationTargetObjectMetadataId } = flatFieldMetadataToValidate; @@ -92,6 +93,7 @@ export const validateMorphOrRelationFlatFieldMetadata = ({ ) errors.push( ...validateMorphOrRelationFlatFieldJoinColumName({ + buildOptions, flatFieldMetadata: flatFieldMetadataToValidate, optimisticFlatEntityMapsAndRelatedFlatEntityMaps: { flatFieldMetadataMaps, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/run-flat-object-metadata-validators.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/run-flat-object-metadata-validators.util.ts deleted file mode 100644 index c3fc5fa9ede..00000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/run-flat-object-metadata-validators.util.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { t } from '@lingui/core/macro'; - -import { type FlatObjectMetadataValidationError } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata-validation-error.type'; -import { ObjectMetadataExceptionCode } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; -import { type FlatMetadataValidator } from 'src/engine/metadata-modules/types/flat-metadata-validator.type'; - -export const runFlatObjectMetadataValidators = ({ - elementToValidate, - validators, -}: { - elementToValidate: T; - validators: FlatMetadataValidator[]; -}): FlatObjectMetadataValidationError[] => { - return validators.flatMap(({ validator, message }) => { - const isInvalid = validator(elementToValidate); - - if (isInvalid) { - return { - code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, - message: t(message), - value: elementToValidate, - }; - } - - return []; - }); -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-identifiers.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-identifiers.util.ts index ab0e2c35153..09486a787f4 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-identifiers.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-identifiers.util.ts @@ -3,23 +3,28 @@ import { isDefined, isLabelIdentifierFieldMetadataTypes, } from 'twenty-shared/utils'; +import { FieldMetadataType } from 'twenty-shared/types'; import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; import { type FlatObjectMetadataValidationError } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata-validation-error.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { ObjectMetadataExceptionCode } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; +import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; export const validateFlatObjectMetadataIdentifiers = ({ flatObjectMetadata, flatFieldMetadataMaps, + buildOptions, }: { flatObjectMetadata: Pick< FlatObjectMetadata, 'labelIdentifierFieldMetadataId' | 'imageIdentifierFieldMetadataId' >; flatFieldMetadataMaps: FlatEntityMaps; + buildOptions: WorkspaceMigrationBuilderOptions; }) => { const errors: FlatObjectMetadataValidationError[] = []; @@ -40,13 +45,27 @@ export const validateFlatObjectMetadataIdentifiers = ({ 'labelIdentifierFieldMetadataId validation failed: related field metadata not found', userFriendlyMessage: msg`Field declared as label identifier not found`, }); - } else if (!isLabelIdentifierFieldMetadataTypes(flatFieldMetadata.type)) { - errors.push({ - code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, - message: - 'labelIdentifierFieldMetadataId validation failed: field type not compatible', - userFriendlyMessage: msg`Field cannot be used as label identifier`, - }); + } else { + if (!isLabelIdentifierFieldMetadataTypes(flatFieldMetadata.type)) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: + 'labelIdentifierFieldMetadataId validation failed: field type not compatible', + userFriendlyMessage: msg`Field cannot be used as label identifier`, + }); + } + + if ( + !buildOptions.isSystemBuild && + isFlatFieldMetadataOfType(flatFieldMetadata, FieldMetadataType.UUID) + ) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: + 'labelIdentifierFieldMetadataId validation failed: field type uuid is reserved for system object metadata', + userFriendlyMessage: msg`Field cannot be used as label identifier`, + }); + } } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-label.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-label.util.ts index e18f52b76a2..b796533661a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-label.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-label.util.ts @@ -3,13 +3,9 @@ import { msg } from '@lingui/core/macro'; import { type FlatObjectMetadataValidationError } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata-validation-error.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { type ObjectMetadataMinimalInformation } from 'src/engine/metadata-modules/flat-object-metadata/types/object-metadata-minimal-information.type'; -import { runFlatObjectMetadataValidators } from 'src/engine/metadata-modules/flat-object-metadata/utils/run-flat-object-metadata-validators.util'; import { ObjectMetadataExceptionCode } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; -import { type FlatMetadataValidator } from 'src/engine/metadata-modules/types/flat-metadata-validator.type'; -import { - beneathDatabaseIdentifierMinimumLength, - exceedsDatabaseIdentifierMaximumLength, -} from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils'; +import { IDENTIFIER_MAX_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-max-char-length.constants'; +import { IDENTIFIER_MIN_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-min-char-length.constants'; export const validateFlatObjectMetadataLabel = ({ labelPlural, @@ -17,26 +13,31 @@ export const validateFlatObjectMetadataLabel = ({ }: Pick & ObjectMetadataMinimalInformation): FlatObjectMetadataValidationError[] => { const errors: FlatObjectMetadataValidationError[] = []; - const validators: FlatMetadataValidator[] = [ - { - validator: (label) => beneathDatabaseIdentifierMinimumLength(label), - message: msg`Object label is too short`, - }, - { - validator: (label) => exceedsDatabaseIdentifierMaximumLength(label), - message: msg`Object label is too long`, - }, - ]; - errors.push( - ...[labelSingular, labelPlural].flatMap((label) => - runFlatObjectMetadataValidators({ - elementToValidate: label, - validators, - }), - ), - ); + // Validate both labelSingular and labelPlural + for (const label of [labelSingular, labelPlural]) { + // Length too short check + if (label.length < IDENTIFIER_MIN_CHAR_LENGTH) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: `Object label is too short`, + userFriendlyMessage: msg`Object label is too short`, + value: label, + }); + } + // Length too long check + if (label.length > IDENTIFIER_MAX_CHAR_LENGTH) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: `Object label is too long`, + userFriendlyMessage: msg`Object label is too long`, + value: label, + }); + } + } + + // Check if labels are identical const labelsAreIdentical = labelSingular.trim().toLowerCase() === labelPlural.trim().toLowerCase(); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-name.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-name.util.ts index 2decbc1245d..162b6dcba24 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-name.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-name.util.ts @@ -1,11 +1,16 @@ import { msg } from '@lingui/core/macro'; +import camelCase from 'lodash.camelcase'; +import { RESERVED_METADATA_NAME_KEYWORDS } from 'twenty-shared/metadata'; import { type FlatObjectMetadataValidationError } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata-validation-error.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { type ObjectMetadataMinimalInformation } from 'src/engine/metadata-modules/flat-object-metadata/types/object-metadata-minimal-information.type'; -import { runFlatObjectMetadataValidators } from 'src/engine/metadata-modules/flat-object-metadata/utils/run-flat-object-metadata-validators.util'; import { ObjectMetadataExceptionCode } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; -import { METADATA_NAME_VALIDATORS } from 'src/engine/metadata-modules/utils/constants/metadata-name-flat-metadata-validators.constants'; +import { IDENTIFIER_MAX_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-max-char-length.constants'; +import { IDENTIFIER_MIN_CHAR_LENGTH } from 'src/engine/metadata-modules/utils/constants/identifier-min-char-length.constants'; + +const STARTS_WITH_LOWER_CASE_AND_CONTAINS_ONLY_CAPS_AND_LOWER_LETTERS_AND_NUMBER_STRING_REGEX = + /^[a-z][a-zA-Z0-9]*$/; export const validateFlatObjectMetadataNames = ({ namePlural, @@ -14,15 +19,64 @@ export const validateFlatObjectMetadataNames = ({ ObjectMetadataMinimalInformation) => { const errors: FlatObjectMetadataValidationError[] = []; - errors.push( - ...[nameSingular, namePlural].flatMap((name) => - runFlatObjectMetadataValidators({ - elementToValidate: name, - validators: METADATA_NAME_VALIDATORS, - }), - ), - ); + // Validate both nameSingular and namePlural + for (const name of [nameSingular, namePlural]) { + // Length too long check + if (name.length > IDENTIFIER_MAX_CHAR_LENGTH) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: `Name is too long`, + userFriendlyMessage: msg`Name is too long`, + value: name, + }); + } + // Length too short check + if (name.length < IDENTIFIER_MIN_CHAR_LENGTH) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: `Name is too short`, + userFriendlyMessage: msg`Name is too short`, + value: name, + }); + } + + // CamelCase check + if (name !== camelCase(name)) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: `Name should be in camelCase`, + userFriendlyMessage: msg`Name should be in camelCase`, + value: name, + }); + } + + // Format check + if ( + !name.match( + STARTS_WITH_LOWER_CASE_AND_CONTAINS_ONLY_CAPS_AND_LOWER_LETTERS_AND_NUMBER_STRING_REGEX, + ) + ) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: `Name is not valid: it must start with lowercase letter and contain only alphanumeric letters`, + userFriendlyMessage: msg`Name is not valid: it must start with lowercase letter and contain only alphanumeric letters`, + value: name, + }); + } + + // Reserved keywords check + if (RESERVED_METADATA_NAME_KEYWORDS.includes(name)) { + errors.push({ + code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + message: `This name is reserved. Use a different name or the system will add "Custom" suffix.`, + userFriendlyMessage: msg`This name is reserved. Use a different name or the system will add "Custom" suffix.`, + value: name, + }); + } + } + + // Check if names are identical const namesAreIdentical = namePlural.trim().toLowerCase() === nameSingular.trim().toLowerCase(); diff --git a/packages/twenty-server/src/engine/metadata-modules/types/flat-metadata-validator.type.ts b/packages/twenty-server/src/engine/metadata-modules/types/flat-metadata-validator.type.ts deleted file mode 100644 index 7c5c3ad1877..00000000000 --- a/packages/twenty-server/src/engine/metadata-modules/types/flat-metadata-validator.type.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type MessageDescriptor } from '@lingui/core'; - -export type FlatMetadataValidator = { - validator: (value: T) => boolean; - message: MessageDescriptor; -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/utils/constants/metadata-name-flat-metadata-validators.constants.ts b/packages/twenty-server/src/engine/metadata-modules/utils/constants/metadata-name-flat-metadata-validators.constants.ts deleted file mode 100644 index 0a0d5940a11..00000000000 --- a/packages/twenty-server/src/engine/metadata-modules/utils/constants/metadata-name-flat-metadata-validators.constants.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { msg } from '@lingui/core/macro'; -import camelCase from 'lodash.camelcase'; -import { RESERVED_METADATA_NAME_KEYWORDS } from 'twenty-shared/metadata'; - -import { type FlatMetadataValidator } from 'src/engine/metadata-modules/types/flat-metadata-validator.type'; -import { - beneathDatabaseIdentifierMinimumLength, - exceedsDatabaseIdentifierMaximumLength, -} from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils'; - -const STARTS_WITH_LOWER_CASE_AND_CONTAINS_ONLY_CAPS_AND_LOWER_LETTERS_AND_NUMBER_STRING_REGEX = - /^[a-z][a-zA-Z0-9]*$/; - -export const METADATA_NAME_VALIDATORS: FlatMetadataValidator[] = [ - { - message: msg`Name is too long`, - validator: (name) => exceedsDatabaseIdentifierMaximumLength(name), - }, - { - message: msg`Name is too short`, - validator: (name) => beneathDatabaseIdentifierMinimumLength(name), - }, - { - message: msg`Name should be in camelCase`, - validator: (name) => name !== camelCase(name), - }, - { - message: msg`Name is not valid: it must start with lowercase letter and contain only alphanumeric letters`, - validator: (name) => - !name.match( - STARTS_WITH_LOWER_CASE_AND_CONTAINS_ONLY_CAPS_AND_LOWER_LETTERS_AND_NUMBER_STRING_REGEX, - ), - }, - { - // Safety net: Catch any reserved keywords that bypass frontend sanitization - // (e.g., programmatic API access, old clients) - // Frontend auto-adds "Custom" suffix, so properly formed requests will pass - message: msg`This name is reserved. Use a different name or the system will add "Custom" suffix.`, - validator: (name) => RESERVED_METADATA_NAME_KEYWORDS.includes(name), - }, -]; diff --git a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/services/dev-seeder.service.ts b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/services/dev-seeder.service.ts index 39627d3a01c..bbc40dee35d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/services/dev-seeder.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/services/dev-seeder.service.ts @@ -5,7 +5,6 @@ import { isDefined } from 'twenty-shared/utils'; import { DataSource } from 'typeorm'; import { ApplicationService } from 'src/engine/core-modules/application/application.service'; -import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications'; 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 { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @@ -23,6 +22,7 @@ import { seedPageLayoutWidgets } from 'src/engine/workspace-manager/dev-seeder/c import { seedPageLayouts } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layouts.util'; import { DevSeederDataService } from 'src/engine/workspace-manager/dev-seeder/data/services/dev-seeder-data.service'; import { DevSeederMetadataService } from 'src/engine/workspace-manager/dev-seeder/metadata/services/dev-seeder-metadata.service'; +import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications'; import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service'; @Injectable() diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view.ts index df26bd59dad..e470ed90025 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, CALENDAR_EVENT_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view.ts index 1965ab72992..69dbcdd2425 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view.ts @@ -3,11 +3,11 @@ import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, COMPANY_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view.ts index 199fa25aaca..3b6159c568d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, DASHBOARD_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view.ts index e39299c4eb1..07263ddb530 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, MESSAGE_THREAD_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view.ts index 207b8b5f803..7c479f68d1e 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, MESSAGE_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts index f53b136173f..49efbd40bab 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view.ts @@ -2,10 +2,10 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, NOTE_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view.ts index 2f1c0d3b329..b06ab6e0f85 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view.ts @@ -3,10 +3,10 @@ import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; export const opportunitiesAllView = ({ diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view.ts index f11b6ede32a..8d7f72950bc 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view.ts @@ -3,10 +3,10 @@ import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; export const opportunitiesByStageView = ({ diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts index ca70c4bb70f..df1c5f4d483 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view.ts @@ -3,10 +3,10 @@ import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, PERSON_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts index e941be78d99..e9b6cc0491d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view.ts @@ -2,10 +2,10 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, TASK_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-assigned-to-me.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-assigned-to-me.ts index e4c061f421c..eff9814fdde 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-assigned-to-me.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-assigned-to-me.ts @@ -3,10 +3,10 @@ import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { ViewFilterOperand } from 'twenty-shared/types'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, TASK_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-by-status.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-by-status.view.ts index 654cb12189f..438bd0f2f7a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-by-status.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-by-status.view.ts @@ -2,10 +2,10 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, TASK_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/timeline-activities-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/timeline-activities-all.view.ts index e70afdd47e9..7b5040c9899 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/timeline-activities-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/timeline-activities-all.view.ts @@ -2,12 +2,12 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { TIMELINE_ACTIVITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; export const timelineActivitiesAllView = ({ diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-runs-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-runs-all.view.ts index d01ebc510c9..bf1338ef9a2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-runs-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-runs-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { WORKFLOW_RUN_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; export const workflowRunsAllView = ({ diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view.ts index 68be7c95fc8..061f37423a3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, WORKFLOW_VERSION_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts index 53243dcdd19..949d8b69f27 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, WORKFLOW_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view.ts index 74c6ccefbe5..f47a7f0157b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view.ts @@ -2,11 +2,11 @@ import { msg } from '@lingui/core/macro'; import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata'; import { v4 } from 'uuid'; -import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant'; import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface'; import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; import { BASE_OBJECT_STANDARD_FIELD_IDS, WORKSPACE_MEMBER_STANDARD_FIELD_IDS, diff --git a/packages/twenty-server/src/engine/core-modules/application/constants/standard-object.constant.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant.ts similarity index 91% rename from packages/twenty-server/src/engine/core-modules/application/constants/standard-object.constant.ts rename to packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant.ts index 7a5fdadd937..839aeab20cd 100644 --- a/packages/twenty-server/src/engine/core-modules/application/constants/standard-object.constant.ts +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant.ts @@ -25,12 +25,6 @@ import { TASK_STANDARD_FIELD_IDS, TASK_TARGET_STANDARD_FIELD_IDS, TIMELINE_ACTIVITY_STANDARD_FIELD_IDS, - VIEW_FIELD_STANDARD_FIELD_IDS, - VIEW_FILTER_GROUP_STANDARD_FIELD_IDS, - VIEW_FILTER_STANDARD_FIELD_IDS, - VIEW_GROUP_STANDARD_FIELD_IDS, - VIEW_SORT_STANDARD_FIELD_IDS, - VIEW_STANDARD_FIELD_IDS, WORKFLOW_AUTOMATED_TRIGGER_STANDARD_FIELD_IDS, WORKFLOW_RUN_STANDARD_FIELD_IDS, WORKFLOW_STANDARD_FIELD_IDS, @@ -630,6 +624,9 @@ export const STANDARD_OBJECTS = { universalIdentifier: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageThreadExternalId, }, + direction: { + universalIdentifier: '75c9b0f7-9e76-44d4-a2f9-47051e61eec7', + }, }, views: {}, }, @@ -808,10 +805,6 @@ export const STANDARD_OBJECTS = { universalIdentifier: MESSAGE_THREAD_STANDARD_FIELD_IDS.messageChannelMessageAssociations, }, - messageThreadSubscribers: { - universalIdentifier: - MESSAGE_THREAD_STANDARD_FIELD_IDS.messageThreadSubscribers, - }, }, views: { allMessageThreads: { @@ -1351,7 +1344,6 @@ export const STANDARD_OBJECTS = { happensAt: { universalIdentifier: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.happensAt, }, - type: { universalIdentifier: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.type }, name: { universalIdentifier: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.name }, properties: { universalIdentifier: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.properties, @@ -1423,140 +1415,6 @@ export const STANDARD_OBJECTS = { }, }, }, - view: { - universalIdentifier: STANDARD_OBJECT_IDS.view, - fields: { - name: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.name }, - objectMetadataId: { - universalIdentifier: VIEW_STANDARD_FIELD_IDS.objectMetadataId, - }, - type: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.type }, - key: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.key }, - icon: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.icon }, - kanbanFieldMetadataId: { - universalIdentifier: VIEW_STANDARD_FIELD_IDS.kanbanFieldMetadataId, - }, - kanbanAggregateOperation: { - universalIdentifier: VIEW_STANDARD_FIELD_IDS.kanbanAggregateOperation, - }, - kanbanAggregateOperationFieldMetadataId: { - universalIdentifier: - VIEW_STANDARD_FIELD_IDS.kanbanAggregateOperationFieldMetadataId, - }, - mainGroupByFieldMetadataId: { - universalIdentifier: VIEW_STANDARD_FIELD_IDS.mainGroupByFieldMetadataId, - }, - position: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.position }, - isCompact: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.isCompact }, - openRecordIn: { - universalIdentifier: VIEW_STANDARD_FIELD_IDS.openRecordIn, - }, - viewFields: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.viewFields }, - viewGroups: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.viewGroups }, - viewFilters: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.viewFilters }, - viewFilterGroups: { - universalIdentifier: VIEW_STANDARD_FIELD_IDS.viewFilterGroups, - }, - viewSorts: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.viewSorts }, - favorites: { universalIdentifier: VIEW_STANDARD_FIELD_IDS.favorites }, - anyFieldFilterValue: { - universalIdentifier: VIEW_STANDARD_FIELD_IDS.anyFieldFilterValue, - }, - }, - views: {}, - }, - viewField: { - universalIdentifier: STANDARD_OBJECT_IDS.viewField, - fields: { - fieldMetadataId: { - universalIdentifier: VIEW_FIELD_STANDARD_FIELD_IDS.fieldMetadataId, - }, - isVisible: { - universalIdentifier: VIEW_FIELD_STANDARD_FIELD_IDS.isVisible, - }, - size: { universalIdentifier: VIEW_FIELD_STANDARD_FIELD_IDS.size }, - position: { universalIdentifier: VIEW_FIELD_STANDARD_FIELD_IDS.position }, - view: { universalIdentifier: VIEW_FIELD_STANDARD_FIELD_IDS.view }, - aggregateOperation: { - universalIdentifier: VIEW_FIELD_STANDARD_FIELD_IDS.aggregateOperation, - }, - }, - views: {}, - }, - viewFilter: { - universalIdentifier: STANDARD_OBJECT_IDS.viewFilter, - fields: { - fieldMetadataId: { - universalIdentifier: VIEW_FILTER_STANDARD_FIELD_IDS.fieldMetadataId, - }, - operand: { universalIdentifier: VIEW_FILTER_STANDARD_FIELD_IDS.operand }, - value: { universalIdentifier: VIEW_FILTER_STANDARD_FIELD_IDS.value }, - displayValue: { - universalIdentifier: VIEW_FILTER_STANDARD_FIELD_IDS.displayValue, - }, - view: { universalIdentifier: VIEW_FILTER_STANDARD_FIELD_IDS.view }, - viewFilterGroupId: { - universalIdentifier: VIEW_FILTER_STANDARD_FIELD_IDS.viewFilterGroupId, - }, - positionInViewFilterGroup: { - universalIdentifier: - VIEW_FILTER_STANDARD_FIELD_IDS.positionInViewFilterGroup, - }, - subFieldName: { - universalIdentifier: VIEW_FILTER_STANDARD_FIELD_IDS.subFieldName, - }, - }, - views: {}, - }, - viewFilterGroup: { - universalIdentifier: STANDARD_OBJECT_IDS.viewFilterGroup, - fields: { - view: { universalIdentifier: VIEW_FILTER_GROUP_STANDARD_FIELD_IDS.view }, - parentViewFilterGroupId: { - universalIdentifier: - VIEW_FILTER_GROUP_STANDARD_FIELD_IDS.parentViewFilterGroupId, - }, - logicalOperator: { - universalIdentifier: - VIEW_FILTER_GROUP_STANDARD_FIELD_IDS.logicalOperator, - }, - positionInViewFilterGroup: { - universalIdentifier: - VIEW_FILTER_GROUP_STANDARD_FIELD_IDS.positionInViewFilterGroup, - }, - }, - views: {}, - }, - viewGroup: { - universalIdentifier: STANDARD_OBJECT_IDS.viewGroup, - fields: { - fieldMetadataId: { - universalIdentifier: VIEW_GROUP_STANDARD_FIELD_IDS.fieldMetadataId, - }, - fieldValue: { - universalIdentifier: VIEW_GROUP_STANDARD_FIELD_IDS.fieldValue, - }, - isVisible: { - universalIdentifier: VIEW_GROUP_STANDARD_FIELD_IDS.isVisible, - }, - position: { universalIdentifier: VIEW_GROUP_STANDARD_FIELD_IDS.position }, - view: { universalIdentifier: VIEW_GROUP_STANDARD_FIELD_IDS.view }, - }, - views: {}, - }, - viewSort: { - universalIdentifier: STANDARD_OBJECT_IDS.viewSort, - fields: { - fieldMetadataId: { - universalIdentifier: VIEW_SORT_STANDARD_FIELD_IDS.fieldMetadataId, - }, - direction: { - universalIdentifier: VIEW_SORT_STANDARD_FIELD_IDS.direction, - }, - view: { universalIdentifier: VIEW_SORT_STANDARD_FIELD_IDS.view }, - }, - views: {}, - }, workflow: { universalIdentifier: STANDARD_OBJECT_IDS.workflow, fields: { @@ -1818,14 +1676,6 @@ export const STANDARD_OBJECTS = { userId: { universalIdentifier: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userId, }, - authoredActivities: { - universalIdentifier: - WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredActivities, - }, - assignedActivities: { - universalIdentifier: - WORKSPACE_MEMBER_STANDARD_FIELD_IDS.assignedActivities, - }, assignedTasks: { universalIdentifier: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.assignedTasks, }, @@ -1840,10 +1690,6 @@ export const STANDARD_OBJECTS = { universalIdentifier: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredAttachments, }, - authoredComments: { - universalIdentifier: - WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredComments, - }, connectedAccounts: { universalIdentifier: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.connectedAccounts, @@ -1863,13 +1709,6 @@ export const STANDARD_OBJECTS = { universalIdentifier: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timelineActivities, }, - auditLogs: { - universalIdentifier: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.auditLogs, - }, - messageThreadSubscribers: { - universalIdentifier: - WORKSPACE_MEMBER_STANDARD_FIELD_IDS.messageThreadSubscribers, - }, timeZone: { universalIdentifier: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timeZone, }, diff --git a/packages/twenty-server/src/engine/core-modules/application/constants/twenty-standard-applications.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/application/constants/twenty-standard-applications.ts rename to packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications.ts diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type.ts new file mode 100644 index 00000000000..d8ece89bded --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type.ts @@ -0,0 +1,5 @@ +import { type STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; +import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type'; + +export type AllStandardObjectFieldName = + keyof (typeof STANDARD_OBJECTS)[T]['fields']; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type.ts new file mode 100644 index 00000000000..c91ae13ce5b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type.ts @@ -0,0 +1,3 @@ +import { type STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; + +export type AllStandardObjectName = keyof typeof STANDARD_OBJECTS; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-field-metadata-maps.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-field-metadata-maps.util.ts new file mode 100644 index 00000000000..97caabd0262 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-field-metadata-maps.util.ts @@ -0,0 +1,116 @@ +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type'; +import { buildAttachmentStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-attachment-standard-flat-field-metadata.util'; +import { buildBlocklistStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-blocklist-standard-flat-field-metadata.util'; +import { buildCalendarChannelEventAssociationStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-event-association-standard-flat-field-metadata.util'; +import { buildCalendarChannelStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-standard-flat-field-metadata.util'; +import { buildCalendarEventParticipantStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-participant-standard-flat-field-metadata.util'; +import { buildCalendarEventStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-standard-flat-field-metadata.util'; +import { buildCompanyStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-company-standard-flat-field-metadata.util'; +import { buildConnectedAccountStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-connected-account-standard-flat-field-metadata.util'; +import { buildDashboardStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-dashboard-standard-flat-field-metadata.util'; +import { buildFavoriteFolderStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-folder-standard-flat-field-metadata.util'; +import { buildFavoriteStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-standard-flat-field-metadata.util'; +import { buildMessageChannelMessageAssociationStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-message-association-standard-flat-field-metadata.util'; +import { buildMessageChannelStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-standard-flat-field-metadata.util'; +import { buildMessageFolderStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-message-folder-standard-flat-field-metadata.util'; +import { buildMessageParticipantStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-message-participant-standard-flat-field-metadata.util'; +import { buildMessageStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-message-standard-flat-field-metadata.util'; +import { buildMessageThreadStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-message-thread-standard-flat-field-metadata.util'; +import { buildNoteStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-note-standard-flat-field-metadata.util'; +import { buildNoteTargetStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-note-target-standard-flat-field-metadata.util'; +import { buildOpportunityStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-opportunity-standard-flat-field-metadata.util'; +import { buildPersonStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-person-standard-flat-field-metadata.util'; +import { buildTaskStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-task-standard-flat-field-metadata.util'; +import { buildTaskTargetStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-task-target-standard-flat-field-metadata.util'; +import { buildTimelineActivityStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-timeline-activity-standard-flat-field-metadata.util'; +import { buildWorkflowAutomatedTriggerStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-automated-trigger-standard-flat-field-metadata.util'; +import { buildWorkflowRunStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-run-standard-flat-field-metadata.util'; +import { buildWorkflowStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-standard-flat-field-metadata.util'; +import { buildWorkflowVersionStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-version-standard-flat-field-metadata.util'; +import { buildWorkspaceMemberStandardFlatFieldMetadatas } from 'src/engine/workspace-manager/twenty-standard-application/utils/compute-workspace-member-standard-flat-field-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +type BuildStandardFlatFieldMetadataMapsArgs = { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}; + +type StandardFlatFieldMetadataBuilder = ( + args: BuildStandardFlatFieldMetadataMapsArgs, +) => Record; + +const STANDARD_FLAT_FIELD_METADATA_BUILDERS_BY_OBJECT_NAME = { + attachment: buildAttachmentStandardFlatFieldMetadatas, + blocklist: buildBlocklistStandardFlatFieldMetadatas, + calendarChannelEventAssociation: + buildCalendarChannelEventAssociationStandardFlatFieldMetadatas, + calendarChannel: buildCalendarChannelStandardFlatFieldMetadatas, + calendarEventParticipant: + buildCalendarEventParticipantStandardFlatFieldMetadatas, + calendarEvent: buildCalendarEventStandardFlatFieldMetadatas, + company: buildCompanyStandardFlatFieldMetadatas, + connectedAccount: buildConnectedAccountStandardFlatFieldMetadatas, + dashboard: buildDashboardStandardFlatFieldMetadatas, + favorite: buildFavoriteStandardFlatFieldMetadatas, + favoriteFolder: buildFavoriteFolderStandardFlatFieldMetadatas, + message: buildMessageStandardFlatFieldMetadatas, + messageChannel: buildMessageChannelStandardFlatFieldMetadatas, + messageChannelMessageAssociation: + buildMessageChannelMessageAssociationStandardFlatFieldMetadatas, + messageFolder: buildMessageFolderStandardFlatFieldMetadatas, + messageParticipant: buildMessageParticipantStandardFlatFieldMetadatas, + messageThread: buildMessageThreadStandardFlatFieldMetadatas, + note: buildNoteStandardFlatFieldMetadatas, + noteTarget: buildNoteTargetStandardFlatFieldMetadatas, + opportunity: buildOpportunityStandardFlatFieldMetadatas, + person: buildPersonStandardFlatFieldMetadatas, + task: buildTaskStandardFlatFieldMetadatas, + taskTarget: buildTaskTargetStandardFlatFieldMetadatas, + timelineActivity: buildTimelineActivityStandardFlatFieldMetadatas, + workflow: buildWorkflowStandardFlatFieldMetadatas, + workflowAutomatedTrigger: + buildWorkflowAutomatedTriggerStandardFlatFieldMetadatas, + workflowRun: buildWorkflowRunStandardFlatFieldMetadatas, + workflowVersion: buildWorkflowVersionStandardFlatFieldMetadatas, + workspaceMember: buildWorkspaceMemberStandardFlatFieldMetadatas, +} satisfies Record; + +const createEmptyFlatFieldMetadataMaps = + (): FlatEntityMaps => ({ + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }); + +export const buildStandardFlatFieldMetadataMaps = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: BuildStandardFlatFieldMetadataMapsArgs): FlatEntityMaps => { + const builderArgs = { + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, + }; + + // Collect all field metadatas from all standard objects + const allFieldMetadatas: FlatFieldMetadata[] = Object.values( + STANDARD_FLAT_FIELD_METADATA_BUILDERS_BY_OBJECT_NAME, + ).flatMap((builder) => Object.values(builder(builderArgs))); + + // Build maps using addFlatEntityToFlatEntityMapsOrThrow to prevent duplicate IDs + let flatFieldMetadataMaps = createEmptyFlatFieldMetadataMaps(); + + for (const fieldMetadata of allFieldMetadatas) { + flatFieldMetadataMaps = addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: fieldMetadata, + flatEntityMaps: flatFieldMetadataMaps, + }); + } + + return flatFieldMetadataMaps; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-object-metadata-maps.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-object-metadata-maps.util.ts new file mode 100644 index 00000000000..2059ba6e304 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-object-metadata-maps.util.ts @@ -0,0 +1,35 @@ +import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { + type BuildStandardFlatObjectMetadatasArgs, + STANDARD_FLAT_OBJECT_METADATA_BUILDERS_BY_OBJECT_NAME, +} from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-flat-object-metadata.util'; + +const createEmptyFlatObjectMetadataMaps = + (): FlatEntityMaps => ({ + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }); + +export const buildStandardFlatObjectMetadataMaps = ( + args: BuildStandardFlatObjectMetadatasArgs, +): FlatEntityMaps => { + // Collect all object metadatas from all standard objects + const allObjectMetadatas: FlatObjectMetadata[] = Object.values( + STANDARD_FLAT_OBJECT_METADATA_BUILDERS_BY_OBJECT_NAME, + ).map((builder) => builder(args)); + + // Build maps using addFlatEntityToFlatEntityMapsOrThrow to prevent duplicate IDs + let flatObjectMetadataMaps = createEmptyFlatObjectMetadataMaps(); + + for (const objectMetadata of allObjectMetadatas) { + flatObjectMetadataMaps = addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: objectMetadata, + flatEntityMaps: flatObjectMetadataMaps, + }); + } + + return flatObjectMetadataMaps; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-attachment-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-attachment-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..7e5498ce2ed --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-attachment-standard-flat-field-metadata.util.ts @@ -0,0 +1,399 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildAttachmentStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Attachment-specific fields + name: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'Attachment name', + icon: 'IconFileUpload', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + fullPath: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'fullPath', + type: FieldMetadataType.TEXT, + label: 'Full path', + description: 'Attachment full path', + icon: 'IconLink', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + type: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'type', + type: FieldMetadataType.TEXT, + label: 'Type (deprecated)', + description: 'Attachment type (deprecated - use fileCategory)', + icon: 'IconList', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + fileCategory: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'fileCategory', + type: FieldMetadataType.SELECT, + label: 'File category', + description: 'Attachment file category', + icon: 'IconList', + isNullable: false, + defaultValue: "'OTHER'", + options: [ + { value: 'ARCHIVE', label: 'Archive', position: 0, color: 'gray' }, + { value: 'AUDIO', label: 'Audio', position: 1, color: 'pink' }, + { value: 'IMAGE', label: 'Image', position: 2, color: 'yellow' }, + { + value: 'PRESENTATION', + label: 'Presentation', + position: 3, + color: 'orange', + }, + { + value: 'SPREADSHEET', + label: 'Spreadsheet', + position: 4, + color: 'turquoise', + }, + { + value: 'TEXT_DOCUMENT', + label: 'Text Document', + position: 5, + color: 'blue', + }, + { value: 'VIDEO', label: 'Video', position: 6, color: 'purple' }, + { value: 'OTHER', label: 'Other', position: 7, color: 'gray' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + author: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'author', + label: 'Author', + description: 'Attachment author (deprecated - use createdBy)', + icon: 'IconCircleUser', + isNullable: true, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'authoredAttachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'authorId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + activity: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'activity', + label: 'Activity', + description: 'Attachment activity', + icon: 'IconNotes', + isNullable: true, + createdAt, + // Activity is deprecated, pointing to a non-existent target + targetObjectName: 'note', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'activityId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + task: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'task', + label: 'Task', + description: 'Attachment task', + icon: 'IconNotes', + isNullable: true, + createdAt, + targetObjectName: 'task', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'taskId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + note: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'note', + label: 'Note', + description: 'Attachment note', + icon: 'IconNotes', + isNullable: true, + createdAt, + targetObjectName: 'note', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'noteId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + person: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'person', + label: 'Person', + description: 'Attachment person', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'personId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + company: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'company', + label: 'Company', + description: 'Attachment company', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'company', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'companyId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + opportunity: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'opportunity', + label: 'Opportunity', + description: 'Attachment opportunity', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'opportunity', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'opportunityId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + dashboard: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'dashboard', + label: 'Dashboard', + description: 'Attachment dashboard', + icon: 'IconLayout', + isNullable: true, + createdAt, + targetObjectName: 'dashboard', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'dashboardId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflow: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'workflow', + label: 'Workflow', + description: 'Attachment workflow', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + targetObjectName: 'workflow', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + custom: createStandardRelationFieldFlatMetadata({ + objectName: 'attachment', + workspaceId, + options: { + fieldName: 'custom', + label: 'Custom', + description: 'Attachment custom object', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + // Custom is a dynamic relation, pointing to custom objects + targetObjectName: 'note', + targetFieldName: 'attachments', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'customId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-blocklist-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-blocklist-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..93afcb0369c --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-blocklist-standard-flat-field-metadata.util.ts @@ -0,0 +1,134 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildBlocklistStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'blocklist', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'blocklist', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'blocklist', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'blocklist', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Blocklist-specific fields + handle: createStandardFieldFlatMetadata({ + objectName: 'blocklist', + workspaceId, + options: { + fieldName: 'handle', + type: FieldMetadataType.TEXT, + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + workspaceMember: createStandardRelationFieldFlatMetadata({ + objectName: 'blocklist', + workspaceId, + options: { + fieldName: 'workspaceMember', + label: 'WorkspaceMember', + description: 'WorkspaceMember', + icon: 'IconCircleUser', + isNullable: false, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'blocklist', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'workspaceMemberId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-event-association-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-event-association-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..f196f40c53b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-event-association-standard-flat-field-metadata.util.ts @@ -0,0 +1,160 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildCalendarChannelEventAssociationStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'calendarChannelEventAssociation'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + eventExternalId: createStandardFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'eventExternalId', + type: FieldMetadataType.TEXT, + label: 'Event external ID', + description: 'Event external ID', + icon: 'IconCalendar', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + recurringEventExternalId: createStandardFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'recurringEventExternalId', + type: FieldMetadataType.TEXT, + label: 'Recurring Event ID', + description: 'Recurring Event ID', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarChannel: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'calendarChannel', + label: 'Channel ID', + description: 'Channel ID', + icon: 'IconCalendar', + isNullable: false, + createdAt, + targetObjectName: 'calendarChannel', + targetFieldName: 'calendarChannelEventAssociations', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'calendarChannelId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarEvent: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarChannelEventAssociation', + workspaceId, + options: { + fieldName: 'calendarEvent', + label: 'Event ID', + description: 'Event ID', + icon: 'IconCalendar', + isNullable: false, + createdAt, + targetObjectName: 'calendarEvent', + targetFieldName: 'calendarChannelEventAssociations', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'calendarEventId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..00d6b16c682 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-channel-standard-flat-field-metadata.util.ts @@ -0,0 +1,389 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildCalendarChannelStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'calendarChannel'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + handle: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'handle', + type: FieldMetadataType.TEXT, + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + visibility: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'visibility', + type: FieldMetadataType.SELECT, + label: 'Visibility', + description: 'Visibility', + icon: 'IconEyeglass', + isNullable: false, + defaultValue: "'SHARE_EVERYTHING'", + options: [ + { value: 'METADATA', label: 'Metadata', position: 0, color: 'green' }, + { + value: 'SHARE_EVERYTHING', + label: 'Share Everything', + position: 1, + color: 'orange', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isContactAutoCreationEnabled: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'isContactAutoCreationEnabled', + type: FieldMetadataType.BOOLEAN, + label: 'Is Contact Auto Creation Enabled', + description: 'Is Contact Auto Creation Enabled', + icon: 'IconUserCircle', + isNullable: false, + defaultValue: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + contactAutoCreationPolicy: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'contactAutoCreationPolicy', + type: FieldMetadataType.SELECT, + label: 'Contact auto creation policy', + description: + 'Automatically create records for people you participated with in an event.', + icon: 'IconUserCircle', + isNullable: false, + defaultValue: "'AS_PARTICIPANT_AND_ORGANIZER'", + options: [ + { + value: 'AS_PARTICIPANT_AND_ORGANIZER', + label: 'As Participant and Organizer', + color: 'green', + position: 0, + }, + { + value: 'AS_PARTICIPANT', + label: 'As Participant', + color: 'orange', + position: 1, + }, + { + value: 'AS_ORGANIZER', + label: 'As Organizer', + color: 'blue', + position: 2, + }, + { value: 'NONE', label: 'None', color: 'red', position: 3 }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isSyncEnabled: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'isSyncEnabled', + type: FieldMetadataType.BOOLEAN, + label: 'Is Sync Enabled', + description: 'Is Sync Enabled', + icon: 'IconRefresh', + isNullable: false, + defaultValue: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncCursor: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'syncCursor', + type: FieldMetadataType.TEXT, + label: 'Sync Cursor', + description: + 'Sync Cursor. Used for syncing events from the calendar provider', + icon: 'IconReload', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncStatus: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'syncStatus', + type: FieldMetadataType.SELECT, + label: 'Sync status', + description: 'Sync status', + icon: 'IconStatusChange', + isNullable: true, + options: [ + { value: 'ONGOING', label: 'Ongoing', position: 1, color: 'yellow' }, + { + value: 'NOT_SYNCED', + label: 'Not Synced', + position: 2, + color: 'blue', + }, + { value: 'ACTIVE', label: 'Active', position: 3, color: 'green' }, + { + value: 'FAILED_INSUFFICIENT_PERMISSIONS', + label: 'Failed Insufficient Permissions', + position: 4, + color: 'red', + }, + { + value: 'FAILED_UNKNOWN', + label: 'Failed Unknown', + position: 5, + color: 'red', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncStage: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'syncStage', + type: FieldMetadataType.SELECT, + label: 'Sync stage', + description: 'Sync stage', + icon: 'IconStatusChange', + isNullable: false, + defaultValue: "'PENDING_CONFIGURATION'", + options: [ + { + value: 'CALENDAR_EVENT_LIST_FETCH_PENDING', + label: 'Calendar event list fetch pending', + position: 0, + color: 'blue', + }, + { + value: 'CALENDAR_EVENT_LIST_FETCH_SCHEDULED', + label: 'Calendar event list fetch scheduled', + position: 1, + color: 'green', + }, + { + value: 'CALENDAR_EVENT_LIST_FETCH_ONGOING', + label: 'Calendar event list fetch ongoing', + position: 2, + color: 'orange', + }, + { + value: 'CALENDAR_EVENTS_IMPORT_PENDING', + label: 'Calendar events import pending', + position: 3, + color: 'blue', + }, + { + value: 'CALENDAR_EVENTS_IMPORT_SCHEDULED', + label: 'Calendar events import scheduled', + position: 4, + color: 'green', + }, + { + value: 'CALENDAR_EVENTS_IMPORT_ONGOING', + label: 'Calendar events import ongoing', + position: 5, + color: 'orange', + }, + { value: 'FAILED', label: 'Failed', position: 6, color: 'red' }, + { + value: 'PENDING_CONFIGURATION', + label: 'Pending configuration', + position: 9, + color: 'gray', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncStageStartedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'syncStageStartedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Sync stage started at', + description: 'Sync stage started at', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'syncedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last sync date', + description: 'Last sync date', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + throttleFailureCount: createStandardFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'throttleFailureCount', + type: FieldMetadataType.NUMBER, + label: 'Throttle Failure Count', + description: 'Throttle Failure Count', + icon: 'IconX', + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + connectedAccount: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'connectedAccount', + label: 'Connected Account', + description: 'Connected Account', + icon: 'IconUserCircle', + isNullable: false, + createdAt, + targetObjectName: 'connectedAccount', + targetFieldName: 'calendarChannels', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'connectedAccountId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarChannelEventAssociations: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarChannel', + workspaceId, + options: { + fieldName: 'calendarChannelEventAssociations', + label: 'Calendar Channel Event Associations', + description: 'Calendar Channel Event Associations', + icon: 'IconCalendar', + isNullable: false, + createdAt, + targetObjectName: 'calendarChannelEventAssociation', + targetFieldName: 'calendarChannel', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-participant-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-participant-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..87b0948f35e --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-participant-standard-flat-field-metadata.util.ts @@ -0,0 +1,226 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildCalendarEventParticipantStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'calendarEventParticipant'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + handle: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'handle', + type: FieldMetadataType.TEXT, + label: 'Handle', + description: 'Handle', + icon: 'IconMail', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + displayName: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'displayName', + type: FieldMetadataType.TEXT, + label: 'Display Name', + description: 'Display Name', + icon: 'IconUser', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isOrganizer: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'isOrganizer', + type: FieldMetadataType.BOOLEAN, + label: 'Is Organizer', + description: 'Is Organizer', + icon: 'IconUser', + isNullable: false, + defaultValue: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + responseStatus: createStandardFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'responseStatus', + type: FieldMetadataType.SELECT, + label: 'Response Status', + description: 'Response Status', + icon: 'IconUser', + isNullable: false, + defaultValue: "'NEEDS_ACTION'", + options: [ + { + value: 'NEEDS_ACTION', + label: 'Needs Action', + position: 0, + color: 'orange', + }, + { value: 'DECLINED', label: 'Declined', position: 1, color: 'red' }, + { + value: 'TENTATIVE', + label: 'Tentative', + position: 2, + color: 'yellow', + }, + { value: 'ACCEPTED', label: 'Accepted', position: 3, color: 'green' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarEvent: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'calendarEvent', + label: 'Event ID', + description: 'Event ID', + icon: 'IconCalendar', + isNullable: false, + createdAt, + targetObjectName: 'calendarEvent', + targetFieldName: 'calendarEventParticipants', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'calendarEventId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + person: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'person', + label: 'Person', + description: 'Person', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'calendarEventParticipants', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'personId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workspaceMember: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarEventParticipant', + workspaceId, + options: { + fieldName: 'workspaceMember', + label: 'Workspace Member', + description: 'Workspace Member', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'calendarEventParticipants', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'workspaceMemberId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..09b5e893d08 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-calendar-event-standard-flat-field-metadata.util.ts @@ -0,0 +1,291 @@ +import { FieldMetadataType, RelationType } from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildCalendarEventStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + title: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'title', + type: FieldMetadataType.TEXT, + label: 'Title', + description: 'Title', + icon: 'IconH1', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isCanceled: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'isCanceled', + type: FieldMetadataType.BOOLEAN, + label: 'Is canceled', + description: 'Is canceled', + icon: 'IconCalendarCancel', + isNullable: false, + defaultValue: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isFullDay: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'isFullDay', + type: FieldMetadataType.BOOLEAN, + label: 'Is Full Day', + description: 'Is Full Day', + icon: 'IconHours24', + isNullable: false, + defaultValue: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + startsAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'startsAt', + type: FieldMetadataType.DATE_TIME, + label: 'Start Date', + description: 'Start Date', + icon: 'IconCalendarClock', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + endsAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'endsAt', + type: FieldMetadataType.DATE_TIME, + label: 'End Date', + description: 'End Date', + icon: 'IconCalendarClock', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + externalCreatedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'externalCreatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation DateTime', + description: 'Creation DateTime', + icon: 'IconCalendarPlus', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + externalUpdatedAt: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'externalUpdatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Update DateTime', + description: 'Update DateTime', + icon: 'IconCalendarCog', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + description: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'description', + type: FieldMetadataType.TEXT, + label: 'Description', + description: 'Description', + icon: 'IconFileDescription', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + location: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'location', + type: FieldMetadataType.TEXT, + label: 'Location', + description: 'Location', + icon: 'IconMapPin', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + iCalUID: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'iCalUID', + type: FieldMetadataType.TEXT, + label: 'iCal UID', + description: 'iCal UID', + icon: 'IconKey', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + conferenceSolution: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'conferenceSolution', + type: FieldMetadataType.TEXT, + label: 'Conference Solution', + description: 'Conference Solution', + icon: 'IconScreenShare', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + conferenceLink: createStandardFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'conferenceLink', + type: FieldMetadataType.LINKS, + label: 'Meet Link', + description: 'Meet Link', + icon: 'IconLink', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarChannelEventAssociations: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'calendarChannelEventAssociations', + label: 'Calendar Channel Event Associations', + description: 'Calendar Channel Event Associations', + icon: 'IconCalendar', + isNullable: false, + createdAt, + targetObjectName: 'calendarChannelEventAssociation', + targetFieldName: 'calendarEvent', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarEventParticipants: createStandardRelationFieldFlatMetadata({ + objectName: 'calendarEvent', + workspaceId, + options: { + fieldName: 'calendarEventParticipants', + label: 'Event Participants', + description: 'Event Participants', + icon: 'IconUserCircle', + isNullable: false, + createdAt, + targetObjectName: 'calendarEventParticipant', + targetFieldName: 'calendarEvent', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-company-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-company-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..34076976141 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-company-standard-flat-field-metadata.util.ts @@ -0,0 +1,433 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildCompanyStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Company-specific fields + name: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'The company name', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + domainName: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'domainName', + type: FieldMetadataType.LINKS, + label: 'Domain Name', + description: + 'The company website URL. We use this url to fetch the company icon', + icon: 'IconLink', + isNullable: true, + isUnique: true, + settings: { + maxNumberOfValues: 1, + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + address: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'address', + type: FieldMetadataType.ADDRESS, + label: 'Address', + description: 'Address of the company', + icon: 'IconMap', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + addressOld: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'addressOld', + type: FieldMetadataType.TEXT, + label: 'Address (deprecated)', + description: + 'Address of the company - deprecated in favor of new address field', + icon: 'IconMap', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + employees: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'employees', + type: FieldMetadataType.NUMBER, + label: 'Employees', + description: 'Number of employees in the company', + icon: 'IconUsers', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + linkedinLink: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'linkedinLink', + type: FieldMetadataType.LINKS, + label: 'Linkedin', + description: 'The company Linkedin account', + icon: 'IconBrandLinkedin', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + xLink: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'xLink', + type: FieldMetadataType.LINKS, + label: 'X', + description: 'The company Twitter/X account', + icon: 'IconBrandX', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + annualRecurringRevenue: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'annualRecurringRevenue', + type: FieldMetadataType.CURRENCY, + label: 'ARR', + description: + 'Annual Recurring Revenue: The actual or estimated annual revenue of the company', + icon: 'IconMoneybag', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + idealCustomerProfile: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'idealCustomerProfile', + type: FieldMetadataType.BOOLEAN, + label: 'ICP', + description: + 'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you', + icon: 'IconTarget', + isNullable: false, + defaultValue: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Company record position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + people: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'people', + label: 'People', + description: 'People linked to the company.', + icon: 'IconUsers', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'company', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + accountOwner: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'accountOwner', + label: 'Account Owner', + description: + 'Your team member responsible for managing the company account', + icon: 'IconUserCircle', + isNullable: true, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'accountOwnerForCompanies', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'accountOwnerId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + taskTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'taskTargets', + label: 'Tasks', + description: 'Tasks tied to the company', + icon: 'IconCheckbox', + isUIReadOnly: true, + isNullable: true, + createdAt, + targetObjectName: 'taskTarget', + targetFieldName: 'company', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + noteTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'noteTargets', + label: 'Notes', + description: 'Notes tied to the company', + icon: 'IconNotes', + isUIReadOnly: true, + isNullable: true, + createdAt, + targetObjectName: 'noteTarget', + targetFieldName: 'company', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + opportunities: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'opportunities', + label: 'Opportunities', + description: 'Opportunities linked to the company.', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'opportunity', + targetFieldName: 'company', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the company', + icon: 'IconHeart', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'company', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + attachments: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the company', + icon: 'IconFileImport', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'company', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'company', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities linked to the company', + icon: 'IconIconTimelineEvent', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'company', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-connected-account-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-connected-account-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..609d9a8b058 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-connected-account-standard-flat-field-metadata.util.ts @@ -0,0 +1,289 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildConnectedAccountStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'connectedAccount'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + handle: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'handle', + type: FieldMetadataType.TEXT, + label: 'handle', + description: 'The account handle (email, username, phone number, etc.)', + icon: 'IconMail', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + provider: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'provider', + type: FieldMetadataType.TEXT, + label: 'provider', + description: 'The account provider', + icon: 'IconSettings', + isNullable: false, + defaultValue: "'google'", + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + accessToken: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'accessToken', + type: FieldMetadataType.TEXT, + label: 'Access Token', + description: 'Messaging provider access token', + icon: 'IconKey', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + refreshToken: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'refreshToken', + type: FieldMetadataType.TEXT, + label: 'Refresh Token', + description: 'Messaging provider refresh token', + icon: 'IconKey', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + lastSyncHistoryId: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'lastSyncHistoryId', + type: FieldMetadataType.TEXT, + label: 'Last sync history ID', + description: 'Last sync history ID', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + authFailedAt: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'authFailedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Auth failed at', + description: 'Auth failed at', + icon: 'IconX', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + lastCredentialsRefreshedAt: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'lastCredentialsRefreshedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last credentials refreshed at', + description: 'Last credentials refreshed at', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + handleAliases: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'handleAliases', + type: FieldMetadataType.TEXT, + label: 'Handle Aliases', + description: 'Handle Aliases', + icon: 'IconMail', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + scopes: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'scopes', + type: FieldMetadataType.ARRAY, + label: 'Scopes', + description: 'Scopes', + icon: 'IconSettings', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + connectionParameters: createStandardFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'connectionParameters', + type: FieldMetadataType.RAW_JSON, + label: 'Custom Connection Parameters', + description: 'JSON object containing custom connection parameters', + icon: 'IconSettings', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + accountOwner: createStandardRelationFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'accountOwner', + label: 'Account Owner', + description: 'Account Owner', + icon: 'IconUserCircle', + isNullable: false, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'connectedAccounts', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'accountOwnerId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannels: createStandardRelationFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'messageChannels', + label: 'Message Channels', + description: 'Message Channels', + icon: 'IconMessage', + isNullable: false, + createdAt, + targetObjectName: 'messageChannel', + targetFieldName: 'connectedAccount', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarChannels: createStandardRelationFieldFlatMetadata({ + objectName: 'connectedAccount', + workspaceId, + options: { + fieldName: 'calendarChannels', + label: 'Calendar Channels', + description: 'Calendar Channels', + icon: 'IconCalendar', + isNullable: false, + createdAt, + targetObjectName: 'calendarChannel', + targetFieldName: 'connectedAccount', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-dashboard-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-dashboard-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..8e52f9320f1 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-dashboard-standard-flat-field-metadata.util.ts @@ -0,0 +1,222 @@ +import { FieldMetadataType, RelationType } from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildDashboardStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Dashboard-specific fields + title: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'title', + type: FieldMetadataType.TEXT, + label: 'Title', + description: 'Dashboard title', + icon: 'IconNotes', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Dashboard record Position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + pageLayoutId: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'pageLayoutId', + type: FieldMetadataType.UUID, + label: 'Page Layout ID', + description: 'Dashboard page layout', + icon: 'IconLayout', + isNullable: true, + isUIReadOnly: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline activities linked to the dashboard', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'dashboard', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the dashboard', + icon: 'IconHeart', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'dashboard', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + attachments: createStandardRelationFieldFlatMetadata({ + objectName: 'dashboard', + workspaceId, + options: { + fieldName: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the dashboard', + icon: 'IconFileImport', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'dashboard', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-folder-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-folder-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..a57d51ff1ec --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-folder-standard-flat-field-metadata.util.ts @@ -0,0 +1,141 @@ +import { FieldMetadataType, RelationType } from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildFavoriteFolderStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'favoriteFolder'>, + FlatFieldMetadata +> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'favoriteFolder', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'favoriteFolder', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'favoriteFolder', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'favoriteFolder', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // FavoriteFolder-specific fields + position: createStandardFieldFlatMetadata({ + objectName: 'favoriteFolder', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.NUMBER, + label: 'Position', + description: 'Favorite folder position', + icon: 'IconList', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + name: createStandardFieldFlatMetadata({ + objectName: 'favoriteFolder', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'Name of the favorite folder', + icon: 'IconText', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'favoriteFolder', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites in this folder', + icon: 'IconHeart', + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'favoriteFolder', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..2f7d90b4177 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-favorite-standard-flat-field-metadata.util.ts @@ -0,0 +1,364 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildFavoriteStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Favorite-specific fields + position: createStandardFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.NUMBER, + label: 'Position', + description: 'Favorite position', + icon: 'IconList', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + view: createStandardFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'view', + type: FieldMetadataType.UUID, + label: 'ViewId', + description: 'ViewId', + icon: 'IconView', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + forWorkspaceMember: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'forWorkspaceMember', + label: 'Workspace Member', + description: 'Favorite workspace member', + icon: 'IconCircleUser', + isNullable: true, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'forWorkspaceMemberId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + person: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'person', + label: 'Person', + description: 'Favorite person', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'personId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + company: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'company', + label: 'Company', + description: 'Favorite company', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'company', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'companyId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + opportunity: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'opportunity', + label: 'Opportunity', + description: 'Favorite opportunity', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'opportunity', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'opportunityId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflow: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'workflow', + label: 'Workflow', + description: 'Favorite workflow', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + targetObjectName: 'workflow', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflowVersion: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'workflowVersion', + label: 'Workflow', + description: 'Favorite workflow version', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + targetObjectName: 'workflowVersion', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowVersionId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflowRun: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'workflowRun', + label: 'Workflow', + description: 'Favorite workflow run', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + targetObjectName: 'workflowRun', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowRunId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + task: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'task', + label: 'Task', + description: 'Favorite task', + icon: 'IconCheckbox', + isNullable: true, + createdAt, + targetObjectName: 'task', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'taskId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + note: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'note', + label: 'Note', + description: 'Favorite note', + icon: 'IconNotes', + isNullable: true, + createdAt, + targetObjectName: 'note', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'noteId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + dashboard: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'dashboard', + label: 'Dashboard', + description: 'Favorite dashboard', + icon: 'IconLayoutDashboard', + isNullable: true, + createdAt, + targetObjectName: 'dashboard', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'dashboardId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favoriteFolder: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'favoriteFolder', + label: 'Favorite Folder', + description: 'The folder this favorite belongs to', + icon: 'IconFolder', + isNullable: true, + createdAt, + targetObjectName: 'favoriteFolder', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'favoriteFolderId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + custom: createStandardRelationFieldFlatMetadata({ + objectName: 'favorite', + workspaceId, + options: { + fieldName: 'custom', + label: 'Custom', + description: 'Favorite custom object', + icon: 'IconHeart', + isNullable: true, + createdAt, + targetObjectName: 'note', + targetFieldName: 'favorites', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'customId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-message-association-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-message-association-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..065b7fc882e --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-message-association-standard-flat-field-metadata.util.ts @@ -0,0 +1,200 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildMessageChannelMessageAssociationStandardFlatFieldMetadatas = + ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, + }: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; + }): Record< + AllStandardObjectFieldName<'messageChannelMessageAssociation'>, + FlatFieldMetadata + > => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageExternalId: createStandardFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'messageExternalId', + type: FieldMetadataType.TEXT, + label: 'Message External Id', + description: 'Message id from the messaging provider', + icon: 'IconHash', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageThreadExternalId: createStandardFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'messageThreadExternalId', + type: FieldMetadataType.TEXT, + label: 'Thread External Id', + description: 'Thread id from the messaging provider', + icon: 'IconHash', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + direction: createStandardFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'direction', + type: FieldMetadataType.SELECT, + label: 'Direction', + description: 'Message Direction', + icon: 'IconDirection', + isNullable: false, + defaultValue: "'incoming'", + options: [ + { value: 'incoming', label: 'Incoming', position: 0, color: 'green' }, + { value: 'outgoing', label: 'Outgoing', position: 1, color: 'blue' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannel: createStandardRelationFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'messageChannel', + label: 'Message Channel Id', + description: 'Message Channel Id', + icon: 'IconHash', + isNullable: true, + createdAt, + targetObjectName: 'messageChannel', + targetFieldName: 'messageChannelMessageAssociations', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'messageChannelId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageThread: createStandardRelationFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'messageThread', + label: 'Message Thread Id', + description: 'Message Thread Id', + icon: 'IconHash', + isNullable: true, + createdAt, + targetObjectName: 'messageThread', + targetFieldName: 'messageChannelMessageAssociations', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'messageThreadId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + message: createStandardRelationFieldFlatMetadata({ + objectName: 'messageChannelMessageAssociation', + workspaceId, + options: { + fieldName: 'message', + label: 'Message Id', + description: 'Message Id', + icon: 'IconHash', + isNullable: true, + createdAt, + targetObjectName: 'message', + targetFieldName: 'messageChannelMessageAssociations', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'messageId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + }); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..f9e638577bc --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-channel-standard-flat-field-metadata.util.ts @@ -0,0 +1,504 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildMessageChannelStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'messageChannel'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + visibility: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'visibility', + type: FieldMetadataType.SELECT, + label: 'Visibility', + description: 'Visibility', + icon: 'IconEyeglass', + isNullable: false, + defaultValue: "'SHARE_EVERYTHING'", + options: [ + { value: 'METADATA', label: 'Metadata', position: 0, color: 'green' }, + { value: 'SUBJECT', label: 'Subject', position: 1, color: 'blue' }, + { + value: 'SHARE_EVERYTHING', + label: 'Share Everything', + position: 2, + color: 'orange', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + handle: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'handle', + type: FieldMetadataType.TEXT, + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + type: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'type', + type: FieldMetadataType.SELECT, + label: 'Type', + description: 'Channel Type', + icon: 'IconMessage', + isNullable: false, + defaultValue: "'email'", + options: [ + { value: 'email', label: 'Email', position: 0, color: 'green' }, + { value: 'sms', label: 'SMS', position: 1, color: 'blue' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isContactAutoCreationEnabled: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'isContactAutoCreationEnabled', + type: FieldMetadataType.BOOLEAN, + label: 'Is Contact Auto Creation Enabled', + description: 'Is Contact Auto Creation Enabled', + icon: 'IconUserCircle', + isNullable: false, + defaultValue: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + contactAutoCreationPolicy: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'contactAutoCreationPolicy', + type: FieldMetadataType.SELECT, + label: 'Contact auto creation policy', + description: + 'Automatically create People records when receiving or sending emails', + icon: 'IconUserCircle', + isNullable: false, + defaultValue: "'SENT'", + options: [ + { + value: 'SENT_AND_RECEIVED', + label: 'Sent and Received', + position: 0, + color: 'green', + }, + { value: 'SENT', label: 'Sent', position: 1, color: 'blue' }, + { value: 'NONE', label: 'None', position: 2, color: 'red' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageFolderImportPolicy: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'messageFolderImportPolicy', + type: FieldMetadataType.SELECT, + label: 'Message folder import policy', + description: 'Message folder import policy', + icon: 'IconFolder', + isNullable: false, + defaultValue: "'ALL_FOLDERS'", + options: [ + { + value: 'ALL_FOLDERS', + label: 'All folders', + position: 0, + color: 'green', + }, + { + value: 'SELECTED_FOLDERS', + label: 'Selected folders', + position: 1, + color: 'blue', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + excludeNonProfessionalEmails: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'excludeNonProfessionalEmails', + type: FieldMetadataType.BOOLEAN, + label: 'Exclude non professional emails', + description: 'Exclude non professional emails', + icon: 'IconBriefcase', + isNullable: false, + defaultValue: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + excludeGroupEmails: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'excludeGroupEmails', + type: FieldMetadataType.BOOLEAN, + label: 'Exclude group emails', + description: 'Exclude group emails', + icon: 'IconUsersGroup', + isNullable: false, + defaultValue: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + pendingGroupEmailsAction: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'pendingGroupEmailsAction', + type: FieldMetadataType.SELECT, + label: 'Pending group emails action', + description: 'Pending action for group emails', + icon: 'IconUsersGroup', + isNullable: false, + defaultValue: "'NONE'", + options: [ + { + value: 'GROUP_EMAILS_DELETION', + label: 'Group emails deletion', + position: 0, + color: 'red', + }, + { + value: 'GROUP_EMAILS_IMPORT', + label: 'Group emails import', + position: 1, + color: 'green', + }, + { value: 'NONE', label: 'None', position: 2, color: 'blue' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isSyncEnabled: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'isSyncEnabled', + type: FieldMetadataType.BOOLEAN, + label: 'Is Sync Enabled', + description: 'Is Sync Enabled', + icon: 'IconRefresh', + isNullable: false, + defaultValue: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncCursor: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'syncCursor', + type: FieldMetadataType.TEXT, + label: 'Last sync cursor', + description: 'Last sync cursor', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncedAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'syncedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last sync date', + description: 'Last sync date', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncStatus: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'syncStatus', + type: FieldMetadataType.SELECT, + label: 'Sync status', + description: 'Sync status', + icon: 'IconStatusChange', + isNullable: true, + options: [ + { value: 'ONGOING', label: 'Ongoing', position: 1, color: 'yellow' }, + { + value: 'NOT_SYNCED', + label: 'Not Synced', + position: 2, + color: 'blue', + }, + { value: 'ACTIVE', label: 'Active', position: 3, color: 'green' }, + { + value: 'FAILED_INSUFFICIENT_PERMISSIONS', + label: 'Failed Insufficient Permissions', + position: 4, + color: 'red', + }, + { + value: 'FAILED_UNKNOWN', + label: 'Failed Unknown', + position: 5, + color: 'red', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncStage: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'syncStage', + type: FieldMetadataType.SELECT, + label: 'Sync stage', + description: 'Sync stage', + icon: 'IconStatusChange', + isNullable: false, + defaultValue: "'PENDING_CONFIGURATION'", + options: [ + { + value: 'MESSAGE_LIST_FETCH_PENDING', + label: 'Messages list fetch pending', + position: 0, + color: 'blue', + }, + { + value: 'MESSAGE_LIST_FETCH_SCHEDULED', + label: 'Messages list fetch scheduled', + position: 1, + color: 'green', + }, + { + value: 'MESSAGE_LIST_FETCH_ONGOING', + label: 'Messages list fetch ongoing', + position: 2, + color: 'orange', + }, + { + value: 'MESSAGES_IMPORT_PENDING', + label: 'Messages import pending', + position: 3, + color: 'blue', + }, + { + value: 'MESSAGES_IMPORT_SCHEDULED', + label: 'Messages import scheduled', + position: 4, + color: 'green', + }, + { + value: 'MESSAGES_IMPORT_ONGOING', + label: 'Messages import ongoing', + position: 5, + color: 'orange', + }, + { value: 'FAILED', label: 'Failed', position: 6, color: 'red' }, + { + value: 'PENDING_CONFIGURATION', + label: 'Pending configuration', + position: 7, + color: 'gray', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncStageStartedAt: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'syncStageStartedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Sync stage started at', + description: 'Sync stage started at', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + throttleFailureCount: createStandardFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'throttleFailureCount', + type: FieldMetadataType.NUMBER, + label: 'Throttle Failure Count', + description: 'Throttle Failure Count', + icon: 'IconX', + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + connectedAccount: createStandardRelationFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'connectedAccount', + label: 'Connected Account', + description: 'Connected Account', + icon: 'IconUserCircle', + isNullable: false, + createdAt, + targetObjectName: 'connectedAccount', + targetFieldName: 'messageChannels', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'connectedAccountId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannelMessageAssociations: createStandardRelationFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'messageChannelMessageAssociations', + label: 'Message Channel Association', + description: 'Messages from the channel.', + icon: 'IconMessage', + isNullable: true, + createdAt, + targetObjectName: 'messageChannelMessageAssociation', + targetFieldName: 'messageChannel', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageFolders: createStandardRelationFieldFlatMetadata({ + objectName: 'messageChannel', + workspaceId, + options: { + fieldName: 'messageFolders', + label: 'Message Folders', + description: 'Message Folders', + icon: 'IconFolder', + isNullable: true, + createdAt, + targetObjectName: 'messageFolder', + targetFieldName: 'messageChannel', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-folder-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-folder-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..cd9df8f5247 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-folder-standard-flat-field-metadata.util.ts @@ -0,0 +1,219 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildMessageFolderStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + name: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'Folder name', + icon: 'IconFolder', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + syncCursor: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'syncCursor', + type: FieldMetadataType.TEXT, + label: 'Sync Cursor', + description: 'Sync Cursor', + icon: 'IconHash', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isSentFolder: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'isSentFolder', + type: FieldMetadataType.BOOLEAN, + label: 'Is Sent Folder', + description: 'Is Sent Folder', + icon: 'IconCheck', + isNullable: false, + defaultValue: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + isSynced: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'isSynced', + type: FieldMetadataType.BOOLEAN, + label: 'Is Synced', + description: 'Is Synced', + icon: 'IconCheck', + isNullable: false, + defaultValue: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + parentFolderId: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'parentFolderId', + type: FieldMetadataType.TEXT, + label: 'Parent Folder ID', + description: 'Parent Folder ID', + icon: 'IconFolder', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + externalId: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'externalId', + type: FieldMetadataType.TEXT, + label: 'External ID', + description: 'External ID', + icon: 'IconHash', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + pendingSyncAction: createStandardFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'pendingSyncAction', + type: FieldMetadataType.SELECT, + label: 'Pending Sync Action', + description: 'Pending action for folder sync', + icon: 'IconReload', + isNullable: false, + defaultValue: "'NONE'", + options: [ + { + value: 'FOLDER_DELETION', + label: 'Folder deletion', + position: 0, + color: 'red', + }, + { value: 'NONE', label: 'None', position: 1, color: 'blue' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannel: createStandardRelationFieldFlatMetadata({ + objectName: 'messageFolder', + workspaceId, + options: { + fieldName: 'messageChannel', + label: 'Message Channel', + description: 'Message Channel', + icon: 'IconMessage', + isNullable: false, + createdAt, + targetObjectName: 'messageChannel', + targetFieldName: 'messageFolders', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'messageChannelId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-participant-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-participant-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..83ebc1671f8 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-participant-standard-flat-field-metadata.util.ts @@ -0,0 +1,201 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildMessageParticipantStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'messageParticipant'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + role: createStandardFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'role', + type: FieldMetadataType.SELECT, + label: 'Role', + description: 'Role', + icon: 'IconAt', + isNullable: false, + defaultValue: "'from'", + options: [ + { value: 'from', label: 'From', position: 0, color: 'green' }, + { value: 'to', label: 'To', position: 1, color: 'blue' }, + { value: 'cc', label: 'Cc', position: 2, color: 'orange' }, + { value: 'bcc', label: 'Bcc', position: 3, color: 'red' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + handle: createStandardFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'handle', + type: FieldMetadataType.TEXT, + label: 'Handle', + description: 'Handle', + icon: 'IconAt', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + displayName: createStandardFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'displayName', + type: FieldMetadataType.TEXT, + label: 'Display Name', + description: 'Display Name', + icon: 'IconUser', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + message: createStandardRelationFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'message', + label: 'Message', + description: 'Message', + icon: 'IconMessage', + isNullable: false, + createdAt, + targetObjectName: 'message', + targetFieldName: 'messageParticipants', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'messageId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + person: createStandardRelationFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'person', + label: 'Person', + description: 'Person', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'messageParticipants', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'personId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workspaceMember: createStandardRelationFieldFlatMetadata({ + objectName: 'messageParticipant', + workspaceId, + options: { + fieldName: 'workspaceMember', + label: 'Workspace Member', + description: 'Workspace member', + icon: 'IconCircleUser', + isNullable: true, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'messageParticipants', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'workspaceMemberId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..32206e94d15 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-standard-flat-field-metadata.util.ts @@ -0,0 +1,220 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildMessageStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + headerMessageId: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'headerMessageId', + type: FieldMetadataType.TEXT, + label: 'Header message Id', + description: 'Message id from the message header', + icon: 'IconHash', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + direction: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'direction', + type: FieldMetadataType.SELECT, + label: 'Direction', + description: 'Message Direction', + icon: 'IconDirection', + isNullable: false, + defaultValue: "'INCOMING'", + options: [ + { value: 'INCOMING', label: 'Incoming', position: 0, color: 'green' }, + { value: 'OUTGOING', label: 'Outgoing', position: 1, color: 'blue' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + subject: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'subject', + type: FieldMetadataType.TEXT, + label: 'Subject', + description: 'Subject', + icon: 'IconMessage', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + text: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'text', + type: FieldMetadataType.TEXT, + label: 'Text', + description: 'Text', + icon: 'IconMessage', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + receivedAt: createStandardFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'receivedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Received At', + description: 'The date the message was received', + icon: 'IconCalendar', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageThread: createStandardRelationFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'messageThread', + label: 'Message Thread Id', + description: 'Message Thread Id', + icon: 'IconHash', + isNullable: true, + createdAt, + targetObjectName: 'messageThread', + targetFieldName: 'messages', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'messageThreadId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageParticipants: createStandardRelationFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'messageParticipants', + label: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isNullable: true, + createdAt, + targetObjectName: 'messageParticipant', + targetFieldName: 'message', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannelMessageAssociations: createStandardRelationFieldFlatMetadata({ + objectName: 'message', + workspaceId, + options: { + fieldName: 'messageChannelMessageAssociations', + label: 'Message Channel Association', + description: 'Messages from the channel.', + icon: 'IconMessage', + isNullable: true, + createdAt, + targetObjectName: 'messageChannelMessageAssociation', + targetFieldName: 'message', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-thread-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-thread-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..2dc23a23ef1 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-message-thread-standard-flat-field-metadata.util.ts @@ -0,0 +1,121 @@ +import { FieldMetadataType, RelationType } from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildMessageThreadStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'messageThread', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'messageThread', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'messageThread', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'messageThread', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messages: createStandardRelationFieldFlatMetadata({ + objectName: 'messageThread', + workspaceId, + options: { + fieldName: 'messages', + label: 'Messages', + description: 'Messages from the thread.', + icon: 'IconMessage', + isNullable: true, + createdAt, + targetObjectName: 'message', + targetFieldName: 'messageThread', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannelMessageAssociations: createStandardRelationFieldFlatMetadata({ + objectName: 'messageThread', + workspaceId, + options: { + fieldName: 'messageChannelMessageAssociations', + label: 'Message Channel Association', + description: 'Messages from the channel.', + icon: 'IconMessage', + isNullable: true, + createdAt, + targetObjectName: 'messageChannelMessageAssociation', + targetFieldName: 'messageThread', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..eae7ca09ed0 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-standard-flat-field-metadata.util.ts @@ -0,0 +1,260 @@ +import { FieldMetadataType, RelationType } from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildNoteStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Note-specific fields + position: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Note record position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + title: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'title', + type: FieldMetadataType.TEXT, + label: 'Title', + description: 'Note title', + icon: 'IconNotes', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + body: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'body', + type: FieldMetadataType.TEXT, + label: 'Body (deprecated)', + description: 'Note body (deprecated - use bodyV2)', + icon: 'IconFilePencil', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + bodyV2: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'bodyV2', + type: FieldMetadataType.RICH_TEXT_V2, + label: 'Body', + description: 'Note body', + icon: 'IconFilePencil', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + noteTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'noteTargets', + label: 'Relations', + description: 'Note targets', + icon: 'IconArrowUpRight', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'noteTarget', + targetFieldName: 'note', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + attachments: createStandardRelationFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'attachments', + label: 'Attachments', + description: 'Note attachments', + icon: 'IconFileImport', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'note', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities linked to the note.', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'note', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'note', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the note', + icon: 'IconHeart', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'note', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-target-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-target-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..36e6fe64943 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-note-target-standard-flat-field-metadata.util.ts @@ -0,0 +1,199 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildNoteTargetStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + note: createStandardRelationFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'note', + label: 'Note', + description: 'NoteTarget note', + icon: 'IconNotes', + isNullable: true, + createdAt, + targetObjectName: 'note', + targetFieldName: 'noteTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'noteId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + person: createStandardRelationFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'person', + label: 'Person', + description: 'NoteTarget person', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'noteTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'personId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + company: createStandardRelationFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'company', + label: 'Company', + description: 'NoteTarget company', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'company', + targetFieldName: 'noteTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'companyId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + opportunity: createStandardRelationFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'opportunity', + label: 'Opportunity', + description: 'NoteTarget opportunity', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'opportunity', + targetFieldName: 'noteTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'opportunityId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + custom: createStandardRelationFieldFlatMetadata({ + objectName: 'noteTarget', + workspaceId, + options: { + fieldName: 'custom', + label: 'Custom', + description: 'NoteTarget custom object', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + // Custom is a dynamic relation + targetObjectName: 'note', + targetFieldName: 'noteTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'customId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-opportunity-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-opportunity-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..05f40531d7c --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-opportunity-standard-flat-field-metadata.util.ts @@ -0,0 +1,355 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildOpportunityStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Opportunity-specific fields + name: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'The opportunity name', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + amount: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'amount', + type: FieldMetadataType.CURRENCY, + label: 'Amount', + description: 'Opportunity amount', + icon: 'IconCurrencyDollar', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + closeDate: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'closeDate', + type: FieldMetadataType.DATE_TIME, + label: 'Close date', + description: 'Opportunity close date', + icon: 'IconCalendarEvent', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + stage: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'stage', + type: FieldMetadataType.SELECT, + label: 'Stage', + description: 'Opportunity stage', + icon: 'IconProgressCheck', + isNullable: false, + defaultValue: "'NEW'", + options: [ + { value: 'NEW', label: 'New', position: 0, color: 'red' }, + { + value: 'SCREENING', + label: 'Screening', + position: 1, + color: 'purple', + }, + { value: 'MEETING', label: 'Meeting', position: 2, color: 'sky' }, + { + value: 'PROPOSAL', + label: 'Proposal', + position: 3, + color: 'turquoise', + }, + { value: 'CUSTOMER', label: 'Customer', position: 4, color: 'yellow' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Opportunity record position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + pointOfContact: createStandardRelationFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'pointOfContact', + label: 'Point of Contact', + description: 'Opportunity point of contact', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'pointOfContactForOpportunities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'pointOfContactId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + company: createStandardRelationFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'company', + label: 'Company', + description: 'Opportunity company', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'company', + targetFieldName: 'opportunities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'companyId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the opportunity', + icon: 'IconHeart', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'opportunity', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + taskTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'taskTargets', + label: 'Tasks', + description: 'Tasks tied to the opportunity', + icon: 'IconCheckbox', + isUIReadOnly: true, + isNullable: true, + createdAt, + targetObjectName: 'taskTarget', + targetFieldName: 'opportunity', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + noteTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'noteTargets', + label: 'Notes', + description: 'Notes tied to the opportunity', + icon: 'IconNotes', + isUIReadOnly: true, + isNullable: true, + createdAt, + targetObjectName: 'noteTarget', + targetFieldName: 'opportunity', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + attachments: createStandardRelationFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the opportunity', + icon: 'IconFileImport', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'opportunity', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'opportunity', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities linked to the opportunity.', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'opportunity', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-person-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-person-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..4579c221038 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-person-standard-flat-field-metadata.util.ts @@ -0,0 +1,466 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildPersonStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Person-specific fields + name: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.FULL_NAME, + label: 'Name', + description: "Contact's name", + icon: 'IconUser', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + email: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'email', + type: FieldMetadataType.TEXT, + label: 'Email', + description: "Contact's Email (deprecated)", + icon: 'IconMail', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + emails: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'emails', + type: FieldMetadataType.EMAILS, + label: 'Emails', + description: "Contact's Emails", + icon: 'IconMail', + isNullable: true, + isUnique: true, + settings: { + maxNumberOfValues: 1, + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + linkedinLink: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'linkedinLink', + type: FieldMetadataType.LINKS, + label: 'Linkedin', + description: "Contact's Linkedin account", + icon: 'IconBrandLinkedin', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + xLink: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'xLink', + type: FieldMetadataType.LINKS, + label: 'X', + description: "Contact's X/Twitter account", + icon: 'IconBrandX', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + jobTitle: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'jobTitle', + type: FieldMetadataType.TEXT, + label: 'Job Title', + description: "Contact's job title", + icon: 'IconBriefcase', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + phone: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'phone', + type: FieldMetadataType.TEXT, + label: 'Phone', + description: "Contact's phone number (deprecated)", + icon: 'IconPhone', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + phones: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'phones', + type: FieldMetadataType.PHONES, + label: 'Phones', + description: "Contact's phone numbers", + icon: 'IconPhone', + isNullable: true, + settings: { + maxNumberOfValues: 1, + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + city: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'city', + type: FieldMetadataType.TEXT, + label: 'City', + description: "Contact's city", + icon: 'IconMap', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + avatarUrl: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'avatarUrl', + type: FieldMetadataType.TEXT, + label: 'Avatar', + description: "Contact's avatar", + icon: 'IconFileUpload', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Person record Position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + company: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'company', + label: 'Company', + description: "Contact's company", + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'company', + targetFieldName: 'people', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'companyId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + pointOfContactForOpportunities: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'pointOfContactForOpportunities', + label: 'Opportunities', + description: + 'List of opportunities for which that person is the point of contact', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'opportunity', + targetFieldName: 'pointOfContact', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + taskTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'taskTargets', + label: 'Tasks', + description: 'Tasks tied to the contact', + icon: 'IconCheckbox', + isUIReadOnly: true, + isNullable: true, + createdAt, + targetObjectName: 'taskTarget', + targetFieldName: 'person', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + noteTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'noteTargets', + label: 'Notes', + description: 'Notes tied to the contact', + icon: 'IconNotes', + isUIReadOnly: true, + isNullable: true, + createdAt, + targetObjectName: 'noteTarget', + targetFieldName: 'person', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the contact', + icon: 'IconHeart', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'person', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + attachments: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the contact.', + icon: 'IconFileImport', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'person', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageParticipants: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'messageParticipants', + label: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'messageParticipant', + targetFieldName: 'person', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarEventParticipants: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'calendarEventParticipants', + label: 'Calendar Event Participants', + description: 'Calendar Event Participants', + icon: 'IconCalendar', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'calendarEventParticipant', + targetFieldName: 'person', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Events', + description: 'Events linked to the person', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'person', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'person', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..1abf774b127 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-standard-flat-field-metadata.util.ts @@ -0,0 +1,323 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildTaskStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Task-specific fields + position: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Task record position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + title: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'title', + type: FieldMetadataType.TEXT, + label: 'Title', + description: 'Task title', + icon: 'IconNotes', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + body: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'body', + type: FieldMetadataType.TEXT, + label: 'Body (deprecated)', + description: 'Task body (deprecated - use bodyV2)', + icon: 'IconFilePencil', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + bodyV2: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'bodyV2', + type: FieldMetadataType.RICH_TEXT_V2, + label: 'Body', + description: 'Task body', + icon: 'IconFilePencil', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + dueAt: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'dueAt', + type: FieldMetadataType.DATE_TIME, + label: 'Due Date', + description: 'Task due date', + icon: 'IconCalendarEvent', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + status: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'status', + type: FieldMetadataType.SELECT, + label: 'Status', + description: 'Task status', + icon: 'IconCheck', + isNullable: true, + defaultValue: "'TODO'", + options: [ + { value: 'TODO', label: 'To do', position: 0, color: 'sky' }, + { + value: 'IN_PROGRESS', + label: 'In progress', + position: 1, + color: 'purple', + }, + { value: 'DONE', label: 'Done', position: 2, color: 'green' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + taskTargets: createStandardRelationFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'taskTargets', + label: 'Relations', + description: 'Task targets', + icon: 'IconArrowUpRight', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'taskTarget', + targetFieldName: 'task', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + attachments: createStandardRelationFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'attachments', + label: 'Attachments', + description: 'Task attachments', + icon: 'IconFileImport', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'task', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + assignee: createStandardRelationFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'assignee', + label: 'Assignee', + description: 'Task assignee', + icon: 'IconUserCircle', + isNullable: true, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'assignedTasks', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'assigneeId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline Activities linked to the task.', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'task', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'task', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the task', + icon: 'IconHeart', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'task', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-target-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-target-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..63e87a2765b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-task-target-standard-flat-field-metadata.util.ts @@ -0,0 +1,199 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildTaskTargetStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { + displayFormat: 'RELATIVE', + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + task: createStandardRelationFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'task', + label: 'Task', + description: 'TaskTarget task', + icon: 'IconCheckbox', + isNullable: true, + createdAt, + targetObjectName: 'task', + targetFieldName: 'taskTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'taskId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + person: createStandardRelationFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'person', + label: 'Person', + description: 'TaskTarget person', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'taskTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'personId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + company: createStandardRelationFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'company', + label: 'Company', + description: 'TaskTarget company', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'company', + targetFieldName: 'taskTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'companyId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + opportunity: createStandardRelationFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'opportunity', + label: 'Opportunity', + description: 'TaskTarget opportunity', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'opportunity', + targetFieldName: 'taskTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'opportunityId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + custom: createStandardRelationFieldFlatMetadata({ + objectName: 'taskTarget', + workspaceId, + options: { + fieldName: 'custom', + label: 'Custom', + description: 'TaskTarget custom object', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + // Custom is a dynamic relation + targetObjectName: 'task', + targetFieldName: 'taskTargets', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'customId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-timeline-activity-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-timeline-activity-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..f332fea36a3 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-timeline-activity-standard-flat-field-metadata.util.ts @@ -0,0 +1,402 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildTimelineActivityStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'timelineActivity'>, + FlatFieldMetadata +> => ({ + // Base fields from BaseWorkspaceEntity + id: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // TimelineActivity-specific fields + happensAt: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'happensAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + defaultValue: 'now', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + name: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Event name', + description: 'Event name', + icon: 'IconAbc', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + properties: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'properties', + type: FieldMetadataType.RAW_JSON, + label: 'Event details', + description: 'Json value for event details', + icon: 'IconListDetails', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + linkedRecordCachedName: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'linkedRecordCachedName', + type: FieldMetadataType.TEXT, + label: 'Linked Record cached name', + description: 'Cached record name', + icon: 'IconAbc', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + linkedRecordId: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'linkedRecordId', + type: FieldMetadataType.UUID, + label: 'Linked Record id', + description: 'Linked Record id', + icon: 'IconAbc', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + linkedObjectMetadataId: createStandardFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'linkedObjectMetadataId', + type: FieldMetadataType.UUID, + label: 'Linked Object Metadata Id', + description: 'Linked Object Metadata Id', + icon: 'IconAbc', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + + // Relation fields + workspaceMember: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'workspaceMember', + label: 'Workspace Member', + description: 'Event workspace member', + icon: 'IconCircleUser', + isNullable: true, + createdAt, + targetObjectName: 'workspaceMember', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workspaceMemberId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + person: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'person', + label: 'Person', + description: 'Event person', + icon: 'IconUser', + isNullable: true, + createdAt, + targetObjectName: 'person', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'personId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + company: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'company', + label: 'Company', + description: 'Event company', + icon: 'IconBuildingSkyscraper', + isNullable: true, + createdAt, + targetObjectName: 'company', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'companyId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + opportunity: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'opportunity', + label: 'Opportunity', + description: 'Event opportunity', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'opportunity', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'opportunityId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + note: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'note', + label: 'Note', + description: 'Event note', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'note', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'noteId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + task: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'task', + label: 'Task', + description: 'Event task', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'task', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'taskId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflow: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'workflow', + label: 'Workflow', + description: 'Event workflow', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'workflow', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflowVersion: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'workflowVersion', + label: 'WorkflowVersion', + description: 'Event workflow version', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'workflowVersion', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowVersionId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflowRun: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'workflowRun', + label: 'Workflow Run', + description: 'Event workflow run', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'workflowRun', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowRunId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + dashboard: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'dashboard', + label: 'Dashboard', + description: 'Event dashboard', + icon: 'IconTargetArrow', + isNullable: true, + createdAt, + targetObjectName: 'dashboard', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'dashboardId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + custom: createStandardRelationFieldFlatMetadata({ + objectName: 'timelineActivity', + workspaceId, + options: { + fieldName: 'custom', + label: 'Custom', + description: 'Timeline Activity custom object', + icon: 'IconTimeline', + isNullable: true, + createdAt, + targetObjectName: 'note', + targetFieldName: 'timelineActivities', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'customId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-automated-trigger-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-automated-trigger-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..2ff5c05e3f2 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-automated-trigger-standard-flat-field-metadata.util.ts @@ -0,0 +1,149 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildWorkflowAutomatedTriggerStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'workflowAutomatedTrigger'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'workflowAutomatedTrigger', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'workflowAutomatedTrigger', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowAutomatedTrigger', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowAutomatedTrigger', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + type: createStandardFieldFlatMetadata({ + objectName: 'workflowAutomatedTrigger', + workspaceId, + options: { + fieldName: 'type', + type: FieldMetadataType.SELECT, + label: 'Automated Trigger Type', + description: 'The workflow automated trigger type', + icon: 'IconSettingsAutomation', + isNullable: false, + options: [ + { + value: 'DATABASE_EVENT', + label: 'Database Event', + position: 0, + color: 'green', + }, + { value: 'CRON', label: 'Cron', position: 1, color: 'blue' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + settings: createStandardFieldFlatMetadata({ + objectName: 'workflowAutomatedTrigger', + workspaceId, + options: { + fieldName: 'settings', + type: FieldMetadataType.RAW_JSON, + label: 'Settings', + description: 'The workflow automated trigger settings', + icon: 'IconSettings', + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflow: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowAutomatedTrigger', + workspaceId, + options: { + fieldName: 'workflow', + label: 'Workflow', + description: 'WorkflowAutomatedTrigger workflow', + icon: 'IconSettingsAutomation', + isNullable: false, + createdAt, + targetObjectName: 'workflow', + targetFieldName: 'automatedTriggers', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-run-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-run-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..0d33fe1b5c3 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-run-standard-flat-field-metadata.util.ts @@ -0,0 +1,339 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildWorkflowRunStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + name: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'Name of the workflow run', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + enqueuedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'enqueuedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Workflow run enqueued at', + description: 'Workflow run enqueued at', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + startedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'startedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Workflow run started at', + description: 'Workflow run started at', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + endedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'endedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Workflow run ended at', + description: 'Workflow run ended at', + icon: 'IconHistory', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + status: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'status', + type: FieldMetadataType.SELECT, + label: 'Workflow run status', + description: 'Workflow run status', + icon: 'IconStatusChange', + isNullable: false, + defaultValue: "'NOT_STARTED'", + options: [ + { + value: 'NOT_STARTED', + label: 'Not started', + position: 0, + color: 'gray', + }, + { value: 'RUNNING', label: 'Running', position: 1, color: 'yellow' }, + { value: 'COMPLETED', label: 'Completed', position: 2, color: 'green' }, + { value: 'FAILED', label: 'Failed', position: 3, color: 'red' }, + { value: 'ENQUEUED', label: 'Enqueued', position: 4, color: 'blue' }, + { value: 'STOPPING', label: 'Stopping', position: 5, color: 'orange' }, + { value: 'STOPPED', label: 'Stopped', position: 6, color: 'gray' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Executed by', + description: 'The executor of the workflow', + icon: 'IconCreativeCommonsSa', + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + state: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'state', + type: FieldMetadataType.RAW_JSON, + label: 'State', + description: 'State of the workflow run', + icon: 'IconHierarchy2', + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + context: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'context', + type: FieldMetadataType.RAW_JSON, + label: 'Context', + description: 'Context of the workflow run', + icon: 'IconHierarchy2', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + output: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'output', + type: FieldMetadataType.RAW_JSON, + label: 'Output', + description: 'Output of the workflow run', + icon: 'IconHierarchy2', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Workflow run position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflowVersion: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'workflowVersion', + label: 'Workflow version', + description: 'Workflow version linked to the run.', + icon: 'IconVersions', + isNullable: false, + createdAt, + targetObjectName: 'workflowVersion', + targetFieldName: 'runs', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName: 'workflowVersionId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflow: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'workflow', + label: 'Workflow', + description: 'Workflow linked to the run.', + icon: 'IconSettingsAutomation', + isNullable: false, + createdAt, + targetObjectName: 'workflow', + targetFieldName: 'runs', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the workflow run', + icon: 'IconHeart', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'workflowRun', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowRun', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline activities linked to the run', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'workflowRun', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..028e20aba47 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-standard-flat-field-metadata.util.ts @@ -0,0 +1,320 @@ +import { FieldMetadataType, RelationType } from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildWorkflowStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record, FlatFieldMetadata> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + name: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'The workflow name', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + lastPublishedVersionId: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'lastPublishedVersionId', + type: FieldMetadataType.TEXT, + label: 'Last published Version Id', + description: 'The workflow last published version id', + icon: 'IconVersions', + isNullable: true, + isUIReadOnly: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + statuses: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'statuses', + type: FieldMetadataType.MULTI_SELECT, + label: 'Statuses', + description: 'The current statuses of the workflow versions', + icon: 'IconStatusChange', + isNullable: true, + isUIReadOnly: true, + options: [ + { value: 'DRAFT', label: 'Draft', position: 0, color: 'yellow' }, + { value: 'ACTIVE', label: 'Active', position: 1, color: 'green' }, + { + value: 'DEACTIVATED', + label: 'Deactivated', + position: 2, + color: 'gray', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Workflow record position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdBy: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'createdBy', + type: FieldMetadataType.ACTOR, + label: 'Created by', + description: 'The creator of the record', + icon: 'IconCreativeCommonsSa', + isUIReadOnly: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + versions: createStandardRelationFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'versions', + label: 'Versions', + description: 'Workflow versions linked to the workflow.', + icon: 'IconVersions', + isUIReadOnly: true, + isNullable: false, + createdAt, + targetObjectName: 'workflowVersion', + targetFieldName: 'workflow', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + runs: createStandardRelationFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'runs', + label: 'Runs', + description: 'Workflow runs linked to the workflow.', + icon: 'IconRun', + isUIReadOnly: true, + isNullable: false, + createdAt, + targetObjectName: 'workflowRun', + targetFieldName: 'workflow', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + eventListeners: createStandardRelationFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'eventListeners', + label: 'Event Listeners', + description: 'Workflow event listeners linked to the workflow.', + icon: 'IconSettingsAutomation', + isSystem: true, + isUIReadOnly: true, + isNullable: false, + createdAt, + targetObjectName: 'workflowAutomatedTrigger', + targetFieldName: 'workflow', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + automatedTriggers: createStandardRelationFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'automatedTriggers', + label: 'Automated Triggers', + description: 'Workflow automated triggers linked to the workflow.', + icon: 'IconSettingsAutomation', + isSystem: true, + isUIReadOnly: true, + isNullable: false, + createdAt, + targetObjectName: 'workflowAutomatedTrigger', + targetFieldName: 'workflow', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the workflow', + icon: 'IconHeart', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'workflow', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline activities linked to the workflow', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'workflow', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + attachments: createStandardRelationFieldFlatMetadata({ + objectName: 'workflow', + workspaceId, + options: { + fieldName: 'attachments', + label: 'Attachments', + description: 'Attachments linked to the workflow', + icon: 'IconFileUpload', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'workflow', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-version-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-version-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..5de787e94df --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workflow-version-standard-flat-field-metadata.util.ts @@ -0,0 +1,267 @@ +import { + FieldMetadataType, + RelationOnDeleteAction, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildWorkflowVersionStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'workflowVersion'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + name: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'The workflow version name', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + trigger: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'trigger', + type: FieldMetadataType.RAW_JSON, + label: 'Version trigger', + description: 'Json object to provide trigger', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + steps: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'steps', + type: FieldMetadataType.RAW_JSON, + label: 'Version steps', + description: 'Json object to provide steps', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + status: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'status', + type: FieldMetadataType.SELECT, + label: 'Version status', + description: 'The workflow version status', + icon: 'IconStatusChange', + isNullable: false, + defaultValue: "'DRAFT'", + options: [ + { value: 'DRAFT', label: 'Draft', position: 0, color: 'yellow' }, + { value: 'ACTIVE', label: 'Active', position: 1, color: 'green' }, + { + value: 'DEACTIVATED', + label: 'Deactivated', + position: 2, + color: 'orange', + }, + { value: 'ARCHIVED', label: 'Archived', position: 3, color: 'gray' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Workflow version position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + workflow: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'workflow', + label: 'Workflow', + description: 'WorkflowVersion workflow', + icon: 'IconSettingsAutomation', + isNullable: true, + createdAt, + targetObjectName: 'workflow', + targetFieldName: 'versions', + settings: { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.CASCADE, + joinColumnName: 'workflowId', + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + runs: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'runs', + label: 'Runs', + description: 'Workflow runs linked to the version.', + icon: 'IconRun', + isNullable: true, + createdAt, + targetObjectName: 'workflowRun', + targetFieldName: 'workflowVersion', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the workflow version', + icon: 'IconHeart', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'workflowVersion', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'workflowVersion', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Timeline Activities', + description: 'Timeline activities linked to the version', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'workflowVersion', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workspace-member-standard-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workspace-member-standard-flat-field-metadata.util.ts new file mode 100644 index 00000000000..ae310b2d095 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/compute-workspace-member-standard-flat-field-metadata.util.ts @@ -0,0 +1,510 @@ +import { + FieldMetadataType, + NumberDataType, + RelationType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { createStandardFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util'; +import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({ + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): Record< + AllStandardObjectFieldName<'workspaceMember'>, + FlatFieldMetadata +> => ({ + id: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'id', + type: FieldMetadataType.UUID, + label: 'Id', + description: 'Id', + icon: 'Icon123', + isSystem: true, + isNullable: false, + isUIReadOnly: true, + defaultValue: 'uuid', + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + createdAt: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'createdAt', + type: FieldMetadataType.DATE_TIME, + label: 'Creation date', + description: 'Creation date', + icon: 'IconCalendar', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + updatedAt: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'updatedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Last update', + description: 'Last time the record was changed', + icon: 'IconCalendarClock', + isNullable: false, + isUIReadOnly: true, + defaultValue: 'now', + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + deletedAt: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'deletedAt', + type: FieldMetadataType.DATE_TIME, + label: 'Deleted at', + description: 'Date when the record was deleted', + icon: 'IconCalendarMinus', + isNullable: true, + isUIReadOnly: true, + settings: { displayFormat: 'RELATIVE' }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + position: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'position', + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Workspace member position', + icon: 'IconHierarchy2', + isSystem: true, + isNullable: false, + defaultValue: 0, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + name: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'name', + type: FieldMetadataType.FULL_NAME, + label: 'Name', + description: 'Workspace member name', + icon: 'IconCircleUser', + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + colorScheme: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'colorScheme', + type: FieldMetadataType.TEXT, + label: 'Color Scheme', + description: 'Preferred color scheme', + icon: 'IconColorSwatch', + isSystem: true, + isNullable: false, + defaultValue: "'System'", + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + locale: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'locale', + type: FieldMetadataType.TEXT, + label: 'Language', + description: 'Preferred language', + icon: 'IconLanguage', + isSystem: true, + isNullable: false, + defaultValue: "'en'", + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + avatarUrl: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'avatarUrl', + type: FieldMetadataType.TEXT, + label: 'Avatar Url', + description: 'Workspace member avatar', + icon: 'IconFileUpload', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + userEmail: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'userEmail', + type: FieldMetadataType.TEXT, + label: 'User Email', + description: 'Related user email address', + icon: 'IconMail', + isSystem: true, + isNullable: true, + isUnique: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarStartDay: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'calendarStartDay', + type: FieldMetadataType.NUMBER, + label: 'Start of the week', + description: "User's preferred start day of the week", + icon: 'IconCalendar', + isSystem: true, + isNullable: false, + defaultValue: 7, + settings: { + dataType: NumberDataType.INT, + }, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + userId: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'userId', + type: FieldMetadataType.UUID, + label: 'User Id', + description: 'Associated User Id', + icon: 'IconCircleUsers', + isSystem: true, + isNullable: false, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timeZone: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'timeZone', + type: FieldMetadataType.TEXT, + label: 'Time zone', + description: 'User time zone', + icon: 'IconTimezone', + isSystem: true, + isNullable: false, + defaultValue: "'system'", + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + dateFormat: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'dateFormat', + type: FieldMetadataType.SELECT, + label: 'Date format', + description: "User's preferred date format", + icon: 'IconCalendarEvent', + isSystem: true, + isNullable: false, + defaultValue: "'SYSTEM'", + options: [ + { value: 'SYSTEM', label: 'System', position: 0, color: 'turquoise' }, + { + value: 'MONTH_FIRST', + label: 'Month First', + position: 1, + color: 'red', + }, + { + value: 'DAY_FIRST', + label: 'Day First', + position: 2, + color: 'purple', + }, + { value: 'YEAR_FIRST', label: 'Year First', position: 3, color: 'sky' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timeFormat: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'timeFormat', + type: FieldMetadataType.SELECT, + label: 'Time format', + description: "User's preferred time format", + icon: 'IconClock2', + isSystem: true, + isNullable: false, + defaultValue: "'SYSTEM'", + options: [ + { value: 'SYSTEM', label: 'System', position: 0, color: 'sky' }, + { value: 'HOUR_24', label: '24HRS', position: 1, color: 'red' }, + { value: 'HOUR_12', label: '12HRS', position: 2, color: 'purple' }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + numberFormat: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'numberFormat', + type: FieldMetadataType.SELECT, + label: 'Number format', + description: "User's preferred number format", + icon: 'IconNumbers', + isSystem: true, + isNullable: false, + defaultValue: "'SYSTEM'", + options: [ + { value: 'SYSTEM', label: 'System', position: 0, color: 'turquoise' }, + { + value: 'COMMAS_AND_DOT', + label: 'Commas and dot (1,234.56)', + position: 1, + color: 'blue', + }, + { + value: 'SPACES_AND_COMMA', + label: 'Spaces and comma (1 234,56)', + position: 2, + color: 'green', + }, + { + value: 'DOTS_AND_COMMA', + label: 'Dots and comma (1.234,56)', + position: 3, + color: 'orange', + }, + { + value: 'APOSTROPHE_AND_DOT', + label: "Apostrophe and dot (1'234.56)", + position: 4, + color: 'purple', + }, + ], + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + searchVector: createStandardFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'searchVector', + type: FieldMetadataType.TS_VECTOR, + label: 'Search vector', + description: 'Field used for full-text search', + icon: 'IconUser', + isSystem: true, + isNullable: true, + createdAt, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + assignedTasks: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'assignedTasks', + label: 'Assigned tasks', + description: 'Tasks assigned to the workspace member', + icon: 'IconCheckbox', + isNullable: false, + createdAt, + targetObjectName: 'task', + targetFieldName: 'assignee', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + favorites: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'favorites', + label: 'Favorites', + description: 'Favorites linked to the workspace member', + icon: 'IconHeart', + isNullable: false, + createdAt, + targetObjectName: 'favorite', + targetFieldName: 'forWorkspaceMember', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + accountOwnerForCompanies: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'accountOwnerForCompanies', + label: 'Account Owner For Companies', + description: 'Account owner for companies', + icon: 'IconBriefcase', + isNullable: false, + createdAt, + targetObjectName: 'company', + targetFieldName: 'accountOwner', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + authoredAttachments: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'authoredAttachments', + label: 'Authored attachments', + description: 'Attachments created by the workspace member', + icon: 'IconFileImport', + isSystem: true, + isNullable: false, + createdAt, + targetObjectName: 'attachment', + targetFieldName: 'author', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + connectedAccounts: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'connectedAccounts', + label: 'Connected accounts', + description: 'Connected accounts', + icon: 'IconAt', + isNullable: false, + createdAt, + targetObjectName: 'connectedAccount', + targetFieldName: 'accountOwner', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + messageParticipants: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'messageParticipants', + label: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isNullable: false, + createdAt, + targetObjectName: 'messageParticipant', + targetFieldName: 'workspaceMember', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + blocklist: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'blocklist', + label: 'Blocklist', + description: 'Blocklisted handles', + icon: 'IconForbid2', + isNullable: false, + createdAt, + targetObjectName: 'blocklist', + targetFieldName: 'workspaceMember', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + calendarEventParticipants: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'calendarEventParticipants', + label: 'Calendar Event Participants', + description: 'Calendar Event Participants', + icon: 'IconCalendar', + isNullable: false, + createdAt, + targetObjectName: 'calendarEventParticipant', + targetFieldName: 'workspaceMember', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivities: createStandardRelationFieldFlatMetadata({ + objectName: 'workspaceMember', + workspaceId, + options: { + fieldName: 'timelineActivities', + label: 'Events', + description: 'Events linked to the workspace member', + icon: 'IconTimelineEvent', + isSystem: true, + isNullable: true, + createdAt, + targetObjectName: 'timelineActivity', + targetFieldName: 'workspaceMember', + settings: { + relationType: RelationType.ONE_TO_MANY, + }, + }, + standardFieldMetadataIdByObjectAndFieldName, + }), +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util.ts new file mode 100644 index 00000000000..f469975849e --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-field-flat-metadata.util.ts @@ -0,0 +1,109 @@ +import { + type FieldMetadataComplexOption, + type FieldMetadataDefaultOption, + type FieldMetadataDefaultValueForAnyType, + type FieldMetadataType, +} from 'twenty-shared/types'; +import { v4 } from 'uuid'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; +import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +const TWENTY_STANDARD_APPLICATION_ID = + TWENTY_STANDARD_APPLICATION.universalIdentifier; + +export type CreateStandardFieldOptions = { + fieldName: AllStandardObjectFieldName; + type: Exclude; + label: string; + description: string; + icon: string; + isSystem?: boolean; + isNullable?: boolean; + isUnique?: boolean; + isUIReadOnly?: boolean; + defaultValue?: FieldMetadataDefaultValueForAnyType; + settings?: Record | null; + options?: FieldMetadataDefaultOption[] | FieldMetadataComplexOption[] | null; + createdAt: Date; +}; + +export type CreateStandardFieldArgs = { + objectName: O; + workspaceId: string; + options: CreateStandardFieldOptions; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}; + +export const createStandardFieldFlatMetadata = < + O extends AllStandardObjectName, +>({ + objectName, + workspaceId, + options, + standardFieldMetadataIdByObjectAndFieldName, +}: CreateStandardFieldArgs): FlatFieldMetadata => { + const { + fieldName, + type, + label, + description, + icon, + isSystem = false, + isNullable = true, + isUnique = false, + isUIReadOnly = false, + defaultValue = null, + settings = null, + options: fieldOptions = null, + createdAt, + } = options; + + const objectFields = STANDARD_OBJECTS[objectName].fields; + const fieldDefinition = objectFields[fieldName as keyof typeof objectFields]; + const fieldIds = + standardFieldMetadataIdByObjectAndFieldName[objectName].fields; + + const name = fieldName.toString(); + + return { + id: fieldIds[fieldName], + universalIdentifier: fieldDefinition.universalIdentifier, + standardId: null, + applicationId: TWENTY_STANDARD_APPLICATION_ID, + workspaceId, + objectMetadataId: + standardFieldMetadataIdByObjectAndFieldName[objectName].id, + type, + name, + label, + description, + icon, + isCustom: false, + isActive: true, + isSystem, + isNullable, + isUnique, + isUIReadOnly, + isLabelSyncedWithName: false, + standardOverrides: null, + defaultValue, + settings, + options: fieldOptions?.map((option) => ({ ...option, id: v4() })) ?? null, + relationTargetFieldMetadataId: null, + relationTargetObjectMetadataId: null, + morphId: null, + viewFieldIds: [], + viewFilterIds: [], + viewGroupIds: [], + kanbanAggregateOperationViewIds: [], + calendarViewIds: [], + mainGroupByFieldMetadataViewIds: [], + createdAt, + updatedAt: createdAt, + }; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-flat-object-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-flat-object-metadata.util.ts new file mode 100644 index 00000000000..77f5b5b2504 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-flat-object-metadata.util.ts @@ -0,0 +1,616 @@ +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; +import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; +import { createStandardObjectFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/create-standard-object-flat-metadata.util'; + +export type BuildStandardFlatObjectMetadatasArgs = { + createdAt: Date; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}; + +export type StandardFlatObjectMetadataBuilder = ( + args: BuildStandardFlatObjectMetadatasArgs, +) => FlatObjectMetadata; + +/** + * Record mapping each standard object name to its corresponding object metadata builder. + * Using `satisfies` ensures type safety: if a new standard object is added to STANDARD_OBJECTS, + * TypeScript will error until a builder is added here. + */ +export const STANDARD_FLAT_OBJECT_METADATA_BUILDERS_BY_OBJECT_NAME = { + attachment: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.attachment.universalIdentifier, + standardId: STANDARD_OBJECTS.attachment.universalIdentifier, + nameSingular: 'attachment', + namePlural: 'attachments', + labelSingular: 'Attachment', + labelPlural: 'Attachments', + description: 'An attachment', + icon: 'IconFileImport', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + blocklist: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.blocklist.universalIdentifier, + standardId: STANDARD_OBJECTS.blocklist.universalIdentifier, + nameSingular: 'blocklist', + namePlural: 'blocklists', + labelSingular: 'Blocklist', + labelPlural: 'Blocklists', + description: 'Blocklist', + icon: 'IconForbid2', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'handle', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + calendarChannelEventAssociation: ( + args: BuildStandardFlatObjectMetadatasArgs, + ) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.calendarChannelEventAssociation.universalIdentifier, + standardId: + STANDARD_OBJECTS.calendarChannelEventAssociation.universalIdentifier, + nameSingular: 'calendarChannelEventAssociation', + namePlural: 'calendarChannelEventAssociations', + labelSingular: 'Calendar Channel Event Association', + labelPlural: 'Calendar Channel Event Associations', + description: 'Calendar Channel Event Associations', + icon: 'IconCalendar', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + calendarChannel: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.calendarChannel.universalIdentifier, + standardId: STANDARD_OBJECTS.calendarChannel.universalIdentifier, + nameSingular: 'calendarChannel', + namePlural: 'calendarChannels', + labelSingular: 'Calendar Channel', + labelPlural: 'Calendar Channels', + description: 'Calendar Channels', + icon: 'IconCalendar', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'handle', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + calendarEventParticipant: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.calendarEventParticipant.universalIdentifier, + standardId: + STANDARD_OBJECTS.calendarEventParticipant.universalIdentifier, + nameSingular: 'calendarEventParticipant', + namePlural: 'calendarEventParticipants', + labelSingular: 'Calendar event participant', + labelPlural: 'Calendar event participants', + description: 'Calendar event participants', + icon: 'IconCalendar', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'handle', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + calendarEvent: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.calendarEvent.universalIdentifier, + standardId: STANDARD_OBJECTS.calendarEvent.universalIdentifier, + nameSingular: 'calendarEvent', + namePlural: 'calendarEvents', + labelSingular: 'Calendar event', + labelPlural: 'Calendar events', + description: 'Calendar events', + icon: 'IconCalendar', + isSystem: true, + isAuditLogged: false, + isUIReadOnly: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'title', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + company: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.company.universalIdentifier, + standardId: STANDARD_OBJECTS.company.universalIdentifier, + nameSingular: 'company', + namePlural: 'companies', + labelSingular: 'Company', + labelPlural: 'Companies', + description: 'A company', + icon: 'IconBuildingSkyscraper', + isSearchable: true, + shortcut: 'C', + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + connectedAccount: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.connectedAccount.universalIdentifier, + standardId: STANDARD_OBJECTS.connectedAccount.universalIdentifier, + nameSingular: 'connectedAccount', + namePlural: 'connectedAccounts', + labelSingular: 'Connected Account', + labelPlural: 'Connected Accounts', + description: 'A connected account', + icon: 'IconAt', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'handle', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + dashboard: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.dashboard.universalIdentifier, + standardId: STANDARD_OBJECTS.dashboard.universalIdentifier, + nameSingular: 'dashboard', + namePlural: 'dashboards', + labelSingular: 'Dashboard', + labelPlural: 'Dashboards', + description: 'A dashboard', + icon: 'IconLayoutDashboard', + isSearchable: true, + shortcut: 'D', + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'title', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + favorite: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.favorite.universalIdentifier, + standardId: STANDARD_OBJECTS.favorite.universalIdentifier, + nameSingular: 'favorite', + namePlural: 'favorites', + labelSingular: 'Favorite', + labelPlural: 'Favorites', + description: 'A favorite', + icon: 'IconHeart', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + favoriteFolder: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.favoriteFolder.universalIdentifier, + standardId: STANDARD_OBJECTS.favoriteFolder.universalIdentifier, + nameSingular: 'favoriteFolder', + namePlural: 'favoriteFolders', + labelSingular: 'Favorite Folder', + labelPlural: 'Favorite Folders', + description: 'A favorite folder', + icon: 'IconFolder', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannelMessageAssociation: ( + args: BuildStandardFlatObjectMetadatasArgs, + ) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.messageChannelMessageAssociation.universalIdentifier, + standardId: + STANDARD_OBJECTS.messageChannelMessageAssociation.universalIdentifier, + nameSingular: 'messageChannelMessageAssociation', + namePlural: 'messageChannelMessageAssociations', + labelSingular: 'Message Channel Message Association', + labelPlural: 'Message Channel Message Associations', + description: 'Message Synced with a Message Channel', + icon: 'IconMessage', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + messageChannel: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.messageChannel.universalIdentifier, + standardId: STANDARD_OBJECTS.messageChannel.universalIdentifier, + nameSingular: 'messageChannel', + namePlural: 'messageChannels', + labelSingular: 'Message Channel', + labelPlural: 'Message Channels', + description: 'Message Channels', + icon: 'IconMessage', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'handle', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + messageFolder: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.messageFolder.universalIdentifier, + standardId: STANDARD_OBJECTS.messageFolder.universalIdentifier, + nameSingular: 'messageFolder', + namePlural: 'messageFolders', + labelSingular: 'Message Folder', + labelPlural: 'Message Folders', + description: 'Message Folders', + icon: 'IconFolder', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + messageParticipant: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.messageParticipant.universalIdentifier, + standardId: STANDARD_OBJECTS.messageParticipant.universalIdentifier, + nameSingular: 'messageParticipant', + namePlural: 'messageParticipants', + labelSingular: 'Message Participant', + labelPlural: 'Message Participants', + description: 'Message Participants', + icon: 'IconUserCircle', + isSystem: true, + isAuditLogged: false, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'handle', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + messageThread: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.messageThread.universalIdentifier, + standardId: STANDARD_OBJECTS.messageThread.universalIdentifier, + nameSingular: 'messageThread', + namePlural: 'messageThreads', + labelSingular: 'Message Thread', + labelPlural: 'Message Threads', + description: 'Message Thread', + icon: 'IconMessage', + isSystem: true, + isAuditLogged: false, + isUIReadOnly: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + message: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.message.universalIdentifier, + standardId: STANDARD_OBJECTS.message.universalIdentifier, + nameSingular: 'message', + namePlural: 'messages', + labelSingular: 'Message', + labelPlural: 'Messages', + description: 'Message', + icon: 'IconMessage', + isSystem: true, + isAuditLogged: false, + isUIReadOnly: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'subject', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + note: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.note.universalIdentifier, + standardId: STANDARD_OBJECTS.note.universalIdentifier, + nameSingular: 'note', + namePlural: 'notes', + labelSingular: 'Note', + labelPlural: 'Notes', + description: 'A note', + icon: 'IconNotes', + isSearchable: true, + shortcut: 'N', + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'title', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + noteTarget: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.noteTarget.universalIdentifier, + standardId: STANDARD_OBJECTS.noteTarget.universalIdentifier, + nameSingular: 'noteTarget', + namePlural: 'noteTargets', + labelSingular: 'Note Target', + labelPlural: 'Note Targets', + description: 'A note target', + icon: 'IconCheckbox', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + opportunity: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.opportunity.universalIdentifier, + standardId: STANDARD_OBJECTS.opportunity.universalIdentifier, + nameSingular: 'opportunity', + namePlural: 'opportunities', + labelSingular: 'Opportunity', + labelPlural: 'Opportunities', + description: 'An opportunity', + icon: 'IconTargetArrow', + isSearchable: true, + shortcut: 'O', + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + person: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.person.universalIdentifier, + standardId: STANDARD_OBJECTS.person.universalIdentifier, + nameSingular: 'person', + namePlural: 'people', + labelSingular: 'Person', + labelPlural: 'People', + description: 'A person', + icon: 'IconUser', + isSearchable: true, + shortcut: 'P', + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + task: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.task.universalIdentifier, + standardId: STANDARD_OBJECTS.task.universalIdentifier, + nameSingular: 'task', + namePlural: 'tasks', + labelSingular: 'Task', + labelPlural: 'Tasks', + description: 'A task', + icon: 'IconCheckbox', + isSearchable: true, + shortcut: 'T', + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'title', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + taskTarget: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.taskTarget.universalIdentifier, + standardId: STANDARD_OBJECTS.taskTarget.universalIdentifier, + nameSingular: 'taskTarget', + namePlural: 'taskTargets', + labelSingular: 'Task Target', + labelPlural: 'Task Targets', + description: 'A task target', + icon: 'IconCheckbox', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + timelineActivity: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.timelineActivity.universalIdentifier, + standardId: STANDARD_OBJECTS.timelineActivity.universalIdentifier, + nameSingular: 'timelineActivity', + namePlural: 'timelineActivities', + labelSingular: 'Timeline Activity', + labelPlural: 'Timeline Activities', + description: + 'Aggregated / filtered event to be displayed on the timeline', + icon: 'IconTimelineEvent', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + workflow: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.workflow.universalIdentifier, + standardId: STANDARD_OBJECTS.workflow.universalIdentifier, + nameSingular: 'workflow', + namePlural: 'workflows', + labelSingular: 'Workflow', + labelPlural: 'Workflows', + description: 'A workflow', + icon: 'IconSettingsAutomation', + isSearchable: true, + shortcut: 'W', + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + workflowAutomatedTrigger: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.workflowAutomatedTrigger.universalIdentifier, + standardId: + STANDARD_OBJECTS.workflowAutomatedTrigger.universalIdentifier, + nameSingular: 'workflowAutomatedTrigger', + namePlural: 'workflowAutomatedTriggers', + labelSingular: 'Workflow Automated Trigger', + labelPlural: 'Workflow Automated Triggers', + description: 'A workflow automated trigger', + icon: 'IconSettingsAutomation', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'id', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + workflowRun: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: STANDARD_OBJECTS.workflowRun.universalIdentifier, + standardId: STANDARD_OBJECTS.workflowRun.universalIdentifier, + nameSingular: 'workflowRun', + namePlural: 'workflowRuns', + labelSingular: 'Workflow Run', + labelPlural: 'Workflow Runs', + description: 'A workflow run', + icon: 'IconHistoryToggle', + isSearchable: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + workflowVersion: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.workflowVersion.universalIdentifier, + standardId: STANDARD_OBJECTS.workflowVersion.universalIdentifier, + nameSingular: 'workflowVersion', + namePlural: 'workflowVersions', + labelSingular: 'Workflow Version', + labelPlural: 'Workflow Versions', + description: 'A workflow version', + icon: 'IconVersions', + isSearchable: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), + workspaceMember: (args: BuildStandardFlatObjectMetadatasArgs) => + createStandardObjectFlatMetadata({ + options: { + universalIdentifier: + STANDARD_OBJECTS.workspaceMember.universalIdentifier, + standardId: STANDARD_OBJECTS.workspaceMember.universalIdentifier, + nameSingular: 'workspaceMember', + namePlural: 'workspaceMembers', + labelSingular: 'Workspace Member', + labelPlural: 'Workspace Members', + description: 'A workspace member', + icon: 'IconUserCircle', + isSystem: true, + createdAt: args.createdAt, + labelIdentifierFieldMetadataName: 'name', + }, + workspaceId: args.workspaceId, + standardFieldMetadataIdByObjectAndFieldName: + args.standardFieldMetadataIdByObjectAndFieldName, + }), +} satisfies Record; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-object-flat-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-object-flat-metadata.util.ts new file mode 100644 index 00000000000..fc2910ab027 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-object-flat-metadata.util.ts @@ -0,0 +1,86 @@ +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +const TWENTY_STANDARD_APPLICATION_ID = + TWENTY_STANDARD_APPLICATION.universalIdentifier; + +export const createStandardObjectFlatMetadata = < + T extends AllStandardObjectName, +>({ + options: { + universalIdentifier, + standardId, + nameSingular, + namePlural, + labelSingular, + labelPlural, + description, + icon, + isSystem = false, + isSearchable = false, + isAuditLogged = true, + isUIReadOnly = false, + shortcut = null, + createdAt, + labelIdentifierFieldMetadataName, + }, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, +}: { + options: { + universalIdentifier: string; + standardId: string; + nameSingular: T; + namePlural: string; + labelSingular: string; + labelPlural: string; + description: string; + icon: string; + isSystem?: boolean; + isSearchable?: boolean; + isAuditLogged?: boolean; + isUIReadOnly?: boolean; + shortcut?: string | null; + createdAt: Date; + labelIdentifierFieldMetadataName: AllStandardObjectFieldName; + }; + workspaceId: string; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}): FlatObjectMetadata => ({ + universalIdentifier, + standardId, + applicationId: TWENTY_STANDARD_APPLICATION_ID, + workspaceId, + nameSingular, + namePlural, + labelSingular, + labelPlural, + description, + icon, + isCustom: false, + isRemote: false, + isActive: true, + isSystem, + isSearchable, + isAuditLogged, + isUIReadOnly, + isLabelSyncedWithName: false, + standardOverrides: null, + duplicateCriteria: null, + shortcut, + labelIdentifierFieldMetadataId: + standardFieldMetadataIdByObjectAndFieldName[nameSingular].fields[ + labelIdentifierFieldMetadataName + ], + imageIdentifierFieldMetadataId: null, + targetTableName: 'DEPRECATED', + fieldMetadataIds: [], + indexMetadataIds: [], + viewIds: [], + createdAt, + updatedAt: createdAt, + id: standardFieldMetadataIdByObjectAndFieldName[nameSingular].id, +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util.ts new file mode 100644 index 00000000000..3052cd0d01b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/create-standard-relation-field-flat-metadata.util.ts @@ -0,0 +1,118 @@ +import { + type FieldMetadataComplexOption, + type FieldMetadataDefaultOption, + type FieldMetadataDefaultValueForAnyType, + type FieldMetadataSettings, + FieldMetadataType, +} from 'twenty-shared/types'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; +import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type'; +import { type StandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +const TWENTY_STANDARD_APPLICATION_ID = + TWENTY_STANDARD_APPLICATION.universalIdentifier; + +export type CreateStandardRelationFieldOptions< + O extends AllStandardObjectName, + T extends AllStandardObjectName, +> = { + fieldName: AllStandardObjectFieldName; + label: string; + description: string; + icon: string; + targetObjectName: T; + targetFieldName: AllStandardObjectFieldName; + isSystem?: boolean; + isNullable?: boolean; + isUIReadOnly?: boolean; + defaultValue?: FieldMetadataDefaultValueForAnyType; + settings: FieldMetadataSettings; + options?: FieldMetadataDefaultOption[] | FieldMetadataComplexOption[] | null; + createdAt: Date; +}; + +export type CreateStandardRelationFieldArgs< + O extends AllStandardObjectName, + T extends AllStandardObjectName, +> = { + objectName: O; + workspaceId: string; + options: CreateStandardRelationFieldOptions; + standardFieldMetadataIdByObjectAndFieldName: StandardFieldMetadataIdByObjectAndFieldName; +}; + +export const createStandardRelationFieldFlatMetadata = < + O extends AllStandardObjectName, + T extends AllStandardObjectName, +>({ + objectName, + workspaceId, + options, + standardFieldMetadataIdByObjectAndFieldName, +}: CreateStandardRelationFieldArgs): FlatFieldMetadata => { + const { + fieldName, + label, + description, + icon, + targetObjectName, + targetFieldName, + isSystem = false, + isNullable = true, + isUIReadOnly = false, + defaultValue = null, + settings, + options: fieldOptions = null, + createdAt, + } = options; + + const objectFields = STANDARD_OBJECTS[objectName].fields; + const fieldDefinition = objectFields[fieldName as keyof typeof objectFields]; + const fieldIds = + standardFieldMetadataIdByObjectAndFieldName[objectName].fields; + + const targetFieldIds = + standardFieldMetadataIdByObjectAndFieldName[targetObjectName].fields; + + return { + id: fieldIds[fieldName as keyof typeof fieldIds], + universalIdentifier: fieldDefinition.universalIdentifier, + standardId: null, + applicationId: TWENTY_STANDARD_APPLICATION_ID, + workspaceId, + objectMetadataId: + standardFieldMetadataIdByObjectAndFieldName[objectName].id, + type: FieldMetadataType.RELATION, + name: fieldName.toString(), + label, + description, + icon, + isCustom: false, + isActive: true, + isSystem, + isNullable, + isUnique: false, + isUIReadOnly, + isLabelSyncedWithName: false, + standardOverrides: null, + defaultValue, + settings, + options: fieldOptions, + relationTargetFieldMetadataId: targetFieldIds[targetFieldName], + relationTargetObjectMetadataId: + standardFieldMetadataIdByObjectAndFieldName[targetObjectName].id, + morphId: null, + viewFieldIds: [], + viewFilterIds: [], + viewGroupIds: [], + kanbanAggregateOperationViewIds: [], + calendarViewIds: [], + mainGroupByFieldMetadataViewIds: [], + createdAt, + updatedAt: createdAt, + }; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util.ts new file mode 100644 index 00000000000..a2389358671 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util.ts @@ -0,0 +1,43 @@ +import { v4 } from 'uuid'; + +import { STANDARD_OBJECTS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-object.constant'; +import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type'; +import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type'; + +export type StandardFieldMetadataIdByObjectAndFieldName = { + [O in AllStandardObjectName]: { + id: string; + fields: Record, string>; + }; +}; + +// TODO remove once we have refactored the builder to iterate over universalIdentifier only +export const getStandardFieldMetadataIdByObjectAndFieldName = + (): StandardFieldMetadataIdByObjectAndFieldName => { + const result = {} as StandardFieldMetadataIdByObjectAndFieldName; + + for (const objectName of Object.keys( + STANDARD_OBJECTS, + ) as AllStandardObjectName[]) { + const fieldNames = Object.keys( + STANDARD_OBJECTS[objectName].fields, + ) as AllStandardObjectFieldName[]; + + const fieldIds = {} as Record< + AllStandardObjectFieldName, + string + >; + + for (const fieldName of fieldNames) { + fieldIds[fieldName] = v4(); + } + + result[objectName] = { + // @ts-expect-error ignore this + fields: fieldIds, + id: v4(), + }; + } + + return result; + }; diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant.ts new file mode 100644 index 00000000000..379ef276c41 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant.ts @@ -0,0 +1,93 @@ +import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type'; +import { buildStandardFlatFieldMetadataMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-field-metadata-maps.util'; +import { buildStandardFlatObjectMetadataMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/build-standard-flat-object-metadata-maps.util'; +import { getStandardFieldMetadataIdByObjectAndFieldName } from 'src/engine/workspace-manager/twenty-standard-application/utils/get-standard-field-metadata-id-by-object-and-field-name.util'; + +export const computeTwentyStandardApplicationAllFlatEntityMaps = ({ + createdAt, + workspaceId, +}: { + createdAt: Date; + workspaceId: string; +}): AllFlatEntityMaps => { + const standardFieldMetadataIdByObjectAndFieldName = + getStandardFieldMetadataIdByObjectAndFieldName(); + + const builderArgs = { + createdAt, + workspaceId, + standardFieldMetadataIdByObjectAndFieldName, + }; + + // Build object metadata maps using addFlatEntityToFlatEntityMapsOrThrow to prevent duplicate IDs + const flatObjectMetadataMaps = + buildStandardFlatObjectMetadataMaps(builderArgs); + + // Build field metadata maps using addFlatEntityToFlatEntityMapsOrThrow to prevent duplicate IDs + const flatFieldMetadataMaps = buildStandardFlatFieldMetadataMaps(builderArgs); + + return { + flatAgentMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatCronTriggerMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatDatabaseEventTriggerMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatFieldMetadataMaps, + flatIndexMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatObjectMetadataMaps, + flatRoleMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatRoleTargetMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatRouteTriggerMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatServerlessFunctionMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatViewFieldMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatViewFilterMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatViewGroupMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + flatViewMaps: { + byId: {}, + idByUniversalIdentifier: {}, + universalIdentifiersByApplicationId: {}, + }, + }; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts index 6e3d45f382c..5a230abcb3b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service.ts @@ -131,11 +131,15 @@ export class FlatFieldMetadataValidatorService { if (updates.some((update) => update.property === 'name')) { validationResult.errors.push( - ...validateFlatFieldMetadataName(flatFieldMetadataToValidate.name), + ...validateFlatFieldMetadataName({ + name: flatFieldMetadataToValidate.name, + buildOptions, + }), ...validateFlatFieldMetadataNameAvailability({ name: flatFieldMetadataToValidate.name, flatFieldMetadataMaps: optimisticFlatFieldMetadataMaps, flatObjectMetadata, + buildOptions, }), ); } @@ -307,6 +311,7 @@ export class FlatFieldMetadataValidatorService { name: flatFieldMetadataToValidate.name, flatFieldMetadataMaps: optimisticFlatFieldMetadataMaps, flatObjectMetadata: parentFlatObjectMetadata, + buildOptions, }), ); } @@ -324,7 +329,10 @@ export class FlatFieldMetadataValidatorService { } validationResult.errors.push( - ...validateFlatFieldMetadataName(flatFieldMetadataToValidate.name), + ...validateFlatFieldMetadataName({ + name: flatFieldMetadataToValidate.name, + buildOptions, + }), ); validationResult.errors.push( diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts index 1a49d705e6f..f0d15a9efc9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-object-metadata-validator.service.ts @@ -19,6 +19,7 @@ export class FlatObjectMetadataValidatorService { public validateFlatObjectMetadataUpdate({ flatEntityId, flatEntityUpdates, + buildOptions, optimisticFlatEntityMapsAndRelatedFlatEntityMaps: { flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, flatFieldMetadataMaps, @@ -85,6 +86,7 @@ export class FlatObjectMetadataValidatorService { ...validateFlatObjectMetadataIdentifiers({ flatObjectMetadata: updatedFlatObjectMetadata, flatFieldMetadataMaps, + buildOptions, }), ); } @@ -154,6 +156,7 @@ export class FlatObjectMetadataValidatorService { flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, flatFieldMetadataMaps, }, + buildOptions, }: FlatEntityValidationArgs< typeof ALL_METADATA_NAME.objectMetadata >): FailedFlatEntityValidation { @@ -192,6 +195,7 @@ export class FlatObjectMetadataValidatorService { ...validateFlatObjectMetadataIdentifiers({ flatObjectMetadata: flatObjectMetadataToValidate, flatFieldMetadataMaps, + buildOptions, }), ); objectValidationResult.errors.push( diff --git a/packages/twenty-server/test/integration/graphql/suites/workspace/successful-user-and-workspace-creation.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/workspace/successful-user-and-workspace-creation.integration-spec.ts index 3b62d125202..2fc70af8fbe 100644 --- a/packages/twenty-server/test/integration/graphql/suites/workspace/successful-user-and-workspace-creation.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/workspace/successful-user-and-workspace-creation.integration-spec.ts @@ -12,7 +12,7 @@ import { jestExpectToBeDefined } from 'test/utils/jest-expect-to-be-defined.util import { isDefined } from 'twenty-shared/utils'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; -import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications'; +import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications'; describe('Successful user and workspace creation', () => { let createdUserAccessToken: string | undefined; diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap index 954f54fb52d..9410a84430f 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap @@ -149,6 +149,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Label must not contain a comma", + "userFriendlyMessage": "Label must not contain a comma", "value": "Option ,1", }, ], @@ -215,6 +216,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option id", + "userFriendlyMessage": "Duplicated option id", "value": [ { "color": "green", @@ -296,6 +298,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option position", + "userFriendlyMessage": "Duplicated option position", "value": [ { "color": "green", @@ -377,6 +380,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -458,6 +462,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -539,6 +544,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "If defined default value must contain at least one value", + "userFriendlyMessage": "If defined default value must contain at least one value", "value": [], }, ], @@ -672,11 +678,13 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -743,6 +751,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -877,6 +886,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -942,21 +952,25 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "invalid", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "invalid" must be one of the option values", + "userFriendlyMessage": "Default value "invalid" must be one of the option values", "value": "invalid", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "format", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "format" must be one of the option values", + "userFriendlyMessage": "Default value "format" must be one of the option values", "value": "format", }, ], @@ -1023,6 +1037,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "not a uuid", }, ], @@ -1089,6 +1104,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", "value": "Option 1 and some other things, /", }, ], @@ -1289,6 +1305,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": 22222, }, ], @@ -1423,6 +1440,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": 22222, }, ], "flatEntityMinimalInformation": { @@ -1488,11 +1506,12 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option id is required", - "value": null, + "userFriendlyMessage": "Option id is required", }, { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": null, }, ], @@ -1758,11 +1777,13 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -1829,6 +1850,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -1963,6 +1985,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -2028,11 +2051,13 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", + "userFriendlyMessage": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2099,6 +2124,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2165,6 +2191,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option label exceeds 63 characters", + "userFriendlyMessage": "Option label exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2231,11 +2258,13 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Option value exceeds 63 characters", + "userFriendlyMessage": "Option value exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2501,6 +2530,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should { "code": "INVALID_FIELD_INPUT", "message": "Default value "'UNKNOWN_OPTION'" must be one of the option values", + "userFriendlyMessage": "Default value "'UNKNOWN_OPTION'" must be one of the option values", "value": "'UNKNOWN_OPTION'", }, ], @@ -2567,11 +2597,13 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "invalid", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "invalid" must be one of the option values", + "userFriendlyMessage": "Default value "invalid" must be one of the option values", "value": "invalid", }, ], @@ -2638,6 +2670,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value "'OPTION_424242'" must be one of the option values", + "userFriendlyMessage": "Default value "'OPTION_424242'" must be one of the option values", "value": "'OPTION_424242'", }, ], @@ -2704,6 +2737,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Label must not contain a comma", + "userFriendlyMessage": "Label must not contain a comma", "value": "Option ,1", }, ], @@ -2770,6 +2804,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option id", + "userFriendlyMessage": "Duplicated option id", "value": [ { "color": "green", @@ -2851,6 +2886,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option position", + "userFriendlyMessage": "Duplicated option position", "value": [ { "color": "green", @@ -2932,6 +2968,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -3013,6 +3050,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -3161,11 +3199,13 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -3232,6 +3272,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -3366,6 +3407,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -3431,6 +3473,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "not a uuid", }, ], @@ -3497,6 +3540,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", "value": "Option 1 and some other things, /", }, ], @@ -3630,6 +3674,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": 22222, }, ], @@ -3764,6 +3809,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": 22222, }, ], "flatEntityMinimalInformation": { @@ -3829,11 +3875,12 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is required", - "value": null, + "userFriendlyMessage": "Option id is required", }, { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": null, }, ], @@ -4099,11 +4146,13 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -4170,6 +4219,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -4304,6 +4354,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -4369,11 +4420,13 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", + "userFriendlyMessage": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4440,6 +4493,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4506,6 +4560,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option label exceeds 63 characters", + "userFriendlyMessage": "Option label exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4572,11 +4627,13 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail { "code": "INVALID_FIELD_INPUT", "message": "Option value exceeds 63 characters", + "userFriendlyMessage": "Option value exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap index a89b01358ce..ddb8599f96d 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap @@ -149,6 +149,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Label must not contain a comma", + "userFriendlyMessage": "Label must not contain a comma", "value": "Option ,1", }, ], @@ -215,6 +216,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option id", + "userFriendlyMessage": "Duplicated option id", "value": [ { "color": "green", @@ -296,6 +298,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option position", + "userFriendlyMessage": "Duplicated option position", "value": [ { "color": "green", @@ -377,6 +380,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -458,6 +462,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -539,6 +544,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "If defined default value must contain at least one value", + "userFriendlyMessage": "If defined default value must contain at least one value", "value": [], }, ], @@ -672,11 +678,13 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -743,6 +751,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -877,6 +886,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -942,21 +952,25 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "invalid", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "invalid" must be one of the option values", + "userFriendlyMessage": "Default value "invalid" must be one of the option values", "value": "invalid", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "format", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "format" must be one of the option values", + "userFriendlyMessage": "Default value "format" must be one of the option values", "value": "format", }, ], @@ -1023,6 +1037,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "not a uuid", }, ], @@ -1089,6 +1104,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", "value": "Option 1 and some other things, /", }, ], @@ -1289,6 +1305,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": 22222, }, ], @@ -1423,6 +1440,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": 22222, }, ], "flatEntityMinimalInformation": { @@ -1488,11 +1506,12 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option id is required", - "value": null, + "userFriendlyMessage": "Option id is required", }, { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": null, }, ], @@ -1691,11 +1710,13 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -1762,6 +1783,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -1896,6 +1918,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -1961,11 +1984,13 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", + "userFriendlyMessage": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2032,6 +2057,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2098,6 +2124,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option label exceeds 63 characters", + "userFriendlyMessage": "Option label exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2164,11 +2191,13 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Option value exceeds 63 characters", + "userFriendlyMessage": "Option value exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -2367,6 +2396,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Default value "'OPTION_42'" must be one of the option values", + "userFriendlyMessage": "Default value "'OPTION_42'" must be one of the option values", "value": "'OPTION_42'", }, ], @@ -2433,6 +2463,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should { "code": "INVALID_FIELD_INPUT", "message": "Default value "'UNKNOWN_OPTION'" must be one of the option values", + "userFriendlyMessage": "Default value "'UNKNOWN_OPTION'" must be one of the option values", "value": "'UNKNOWN_OPTION'", }, ], @@ -2499,11 +2530,13 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "invalid", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "invalid" must be one of the option values", + "userFriendlyMessage": "Default value "invalid" must be one of the option values", "value": "invalid", }, ], @@ -2570,6 +2603,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value "'OPTION_424242'" must be one of the option values", + "userFriendlyMessage": "Default value "'OPTION_424242'" must be one of the option values", "value": "'OPTION_424242'", }, ], @@ -2636,6 +2670,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Label must not contain a comma", + "userFriendlyMessage": "Label must not contain a comma", "value": "Option ,1", }, ], @@ -2702,6 +2737,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option id", + "userFriendlyMessage": "Duplicated option id", "value": [ { "color": "green", @@ -2783,6 +2819,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option position", + "userFriendlyMessage": "Duplicated option position", "value": [ { "color": "green", @@ -2864,6 +2901,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -2945,6 +2983,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Duplicated option value", + "userFriendlyMessage": "Duplicated option value", "value": [ { "color": "green", @@ -3093,11 +3132,13 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -3164,6 +3205,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -3298,6 +3340,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -3363,6 +3406,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "not a uuid", }, ], @@ -3429,6 +3473,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"", "value": "Option 1 and some other things, /", }, ], @@ -3562,6 +3607,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": 22222, }, ], @@ -3696,6 +3742,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": 22222, }, ], "flatEntityMinimalInformation": { @@ -3761,11 +3808,12 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is required", - "value": null, + "userFriendlyMessage": "Option id is required", }, { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": null, }, ], @@ -3964,11 +4012,13 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "" must be one of the option values", + "userFriendlyMessage": "Default value "" must be one of the option values", "value": "", }, ], @@ -4035,6 +4085,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "", }, ], @@ -4169,6 +4220,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "code": "INVALID_FIELD_INPUT", "message": "Option value must be a string of at least one character", "userFriendlyMessage": "Option value format not supported", + "value": "", }, ], "flatEntityMinimalInformation": { @@ -4234,11 +4286,13 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value should be as quoted string", + "userFriendlyMessage": "Default value should be as quoted string", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", + "userFriendlyMessage": "Default value "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" must be one of the option values", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4305,6 +4359,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option id is invalid", + "userFriendlyMessage": "Option id is invalid", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4371,6 +4426,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option label exceeds 63 characters", + "userFriendlyMessage": "Option label exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4437,11 +4493,13 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Option value exceeds 63 characters", + "userFriendlyMessage": "Option value exceeds 63 characters", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, { "code": "INVALID_FIELD_INPUT", "message": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", + "userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4640,6 +4698,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail { "code": "INVALID_FIELD_INPUT", "message": "Default value "'OPTION_42'" must be one of the option values", + "userFriendlyMessage": "Default value "'OPTION_42'" must be one of the option values", "value": "'OPTION_42'", }, ], diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap index c60a7bc1409..d1a5bcb4e85 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap @@ -326,6 +326,7 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only { "code": "INVALID_OBJECT_INPUT", "message": "Object label is too short", + "userFriendlyMessage": "Object label is too short", "value": "", }, ], @@ -947,6 +948,7 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu { "code": "INVALID_OBJECT_INPUT", "message": "Object label is too long", + "userFriendlyMessage": "Object label is too long", "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", }, ], @@ -1579,6 +1581,7 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl { "code": "INVALID_OBJECT_INPUT", "message": "Object label is too short", + "userFriendlyMessage": "Object label is too short", "value": "", }, ], @@ -2200,6 +2203,7 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi { "code": "INVALID_OBJECT_INPUT", "message": "Object label is too long", + "userFriendlyMessage": "Object label is too long", "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", }, ], @@ -4106,6 +4110,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt { "code": "INVALID_OBJECT_INPUT", "message": "Name is too long", + "userFriendlyMessage": "Name is too long", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", }, ], @@ -4727,6 +4732,7 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha { "code": "INVALID_OBJECT_INPUT", "message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", + "userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", "value": "μ", }, ], @@ -5348,6 +5354,7 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k { "code": "INVALID_OBJECT_INPUT", "message": "This name is reserved. Use a different name or the system will add "Custom" suffix.", + "userFriendlyMessage": "This name is reserved. Use a different name or the system will add "Custom" suffix.", "value": "users", }, ], @@ -5980,11 +5987,13 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas { "code": "INVALID_OBJECT_INPUT", "message": "Name should be in camelCase", + "userFriendlyMessage": "Name should be in camelCase", "value": "Not_Camel_Case", }, { "code": "INVALID_OBJECT_INPUT", "message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", + "userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", "value": "Not_Camel_Case", }, ], @@ -6666,11 +6675,13 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only { "code": "INVALID_OBJECT_INPUT", "message": "Name should be in camelCase", + "userFriendlyMessage": "Name should be in camelCase", "value": "a a", }, { "code": "INVALID_OBJECT_INPUT", "message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", + "userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", "value": "a a", }, ], @@ -7352,11 +7363,13 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only { "code": "INVALID_OBJECT_INPUT", "message": "Name is too short", + "userFriendlyMessage": "Name is too short", "value": "", }, { "code": "INVALID_OBJECT_INPUT", "message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", + "userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", "value": "", }, ], @@ -8008,6 +8021,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c { "code": "INVALID_OBJECT_INPUT", "message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", + "userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", "value": "μ", }, ], @@ -8659,6 +8673,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved { "code": "INVALID_OBJECT_INPUT", "message": "This name is reserved. Use a different name or the system will add "Custom" suffix.", + "userFriendlyMessage": "This name is reserved. Use a different name or the system will add "Custom" suffix.", "value": "user", }, ], @@ -9351,11 +9366,13 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC { "code": "INVALID_OBJECT_INPUT", "message": "Name should be in camelCase", + "userFriendlyMessage": "Name should be in camelCase", "value": "Not_Camel_Case", }, { "code": "INVALID_OBJECT_INPUT", "message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", + "userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters", "value": "Not_Camel_Case", }, ], diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap index 62b705ab775..3c06f51ec2e 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap @@ -1,5 +1,86 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Object metadata update should fail when labelIdentifier is a UUID field (reserved for system objects) 1`] = ` +[ + { + "extensions": { + "code": "METADATA_VALIDATION_FAILED", + "errors": { + "agent": [], + "cronTrigger": [], + "databaseEventTrigger": [], + "fieldMetadata": [], + "index": [], + "objectMetadata": [ + { + "errors": [ + { + "code": "INVALID_OBJECT_INPUT", + "message": "labelIdentifierFieldMetadataId validation failed: field type uuid is reserved for system object metadata", + "userFriendlyMessage": "Field cannot be used as label identifier", + }, + ], + "flatEntityMinimalInformation": { + "id": Any, + "namePlural": "whatevers", + "nameSingular": "whatever", + }, + "status": "fail", + "type": "update_object", + }, + ], + "role": [], + "roleTarget": [], + "routeTrigger": [], + "serverlessFunction": [], + "view": [], + "viewField": [ + { + "errors": [ + { + "code": "INVALID_VIEW_DATA", + "message": "View field position cannot be lower than label identifier view field position", + "userFriendlyMessage": "View field position cannot be lower than label identifier view field position", + }, + ], + "flatEntityMinimalInformation": { + "fieldMetadataId": Any, + "id": Any, + "viewId": Any, + }, + "status": "fail", + "type": "create_view_field", + }, + ], + "viewFilter": [], + "viewGroup": [], + }, + "message": "Validation failed for 0 object(s) and 0 field(s)", + "summary": { + "invalidAgent": 0, + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, + "invalidFieldMetadata": 0, + "invalidIndex": 0, + "invalidObjectMetadata": 0, + "invalidRole": 0, + "invalidRoleTarget": 0, + "invalidRouteTrigger": 0, + "invalidServerlessFunction": 0, + "invalidView": 0, + "invalidViewField": 0, + "invalidViewFilter": 0, + "invalidViewGroup": 0, + "totalErrors": 0, + }, + "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", + }, + "message": "Multiple validation errors occurred while updating object", + "name": "GraphQLError", + }, +] +`; + exports[`Object metadata update should fail when labelIdentifier is not a TEXT or NAME field 1`] = ` [ { diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-update-one-object-metadata.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-update-one-object-metadata.integration-spec.ts index ebbf8b23e6c..c7c24bf02d5 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-update-one-object-metadata.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/failing-update-one-object-metadata.integration-spec.ts @@ -1,8 +1,10 @@ import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util'; import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util'; import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util'; +import { findManyObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/find-many-object-metadata.util'; import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util'; import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; +import { jestExpectToBeDefined } from 'test/utils/jest-expect-to-be-defined.util.test'; import { eachTestingContextFilter, type EachTestingContext, @@ -14,6 +16,7 @@ import { type UpdateObjectPayload } from 'src/engine/metadata-modules/object-met type TestingRuntimeContext = { objectMetadataId: string; numberFieldMetadataId: string; + uuidFieldMetadataId: string; }; type CreateOneObjectMetadataItemTestingContext = EachTestingContext< @@ -47,6 +50,13 @@ const labelIdentifierFailingTestsUseCase: CreateOneObjectMetadataItemTestingCont labelIdentifierFieldMetadataId: numberFieldMetadataId, }), }, + { + title: + 'when labelIdentifier is a UUID field (reserved for system objects)', + context: ({ uuidFieldMetadataId }) => ({ + labelIdentifierFieldMetadataId: uuidFieldMetadataId, + }), + }, ]; const allTestsUseCases = [...labelIdentifierFailingTestsUseCase]; @@ -54,6 +64,7 @@ const allTestsUseCases = [...labelIdentifierFailingTestsUseCase]; describe('Object metadata update should fail', () => { let objectMetadataId: string; let numberFieldMetadataId: string; + let uuidFieldMetadataId: string; beforeAll(async () => { const { data } = await createOneObjectMetadata({ @@ -82,6 +93,32 @@ describe('Object metadata update should fail', () => { }); numberFieldMetadataId = createOneField.id; + + const { objects } = await findManyObjectMetadata({ + expectToFail: false, + input: { + filter: { isCustom: { is: true } }, + paging: { first: 100 }, + }, + gqlFields: ` + id + fieldsList { + id + type + } + `, + }); + + const createdObject = objects.find((obj) => obj.id === objectMetadataId); + + jestExpectToBeDefined(createdObject); + + const uuidField = createdObject.fieldsList?.find( + (field) => field.type === FieldMetadataType.UUID, + ); + + jestExpectToBeDefined(uuidField); + uuidFieldMetadataId = uuidField.id; }); afterAll(async () => { @@ -106,7 +143,11 @@ describe('Object metadata update should fail', () => { async ({ context }) => { const updatePayload = typeof context === 'function' - ? context({ numberFieldMetadataId, objectMetadataId }) + ? context({ + numberFieldMetadataId, + objectMetadataId, + uuidFieldMetadataId, + }) : context; const { errors } = await updateOneObjectMetadata({ diff --git a/packages/twenty-shared/src/constants/LabelIdentifierFieldMetadataTypes.ts b/packages/twenty-shared/src/constants/LabelIdentifierFieldMetadataTypes.ts index 8bca62a8615..60c1c7a108a 100644 --- a/packages/twenty-shared/src/constants/LabelIdentifierFieldMetadataTypes.ts +++ b/packages/twenty-shared/src/constants/LabelIdentifierFieldMetadataTypes.ts @@ -3,4 +3,5 @@ import { FieldMetadataType } from '@/types'; export const LABEL_IDENTIFIER_FIELD_METADATA_TYPES = [ FieldMetadataType.TEXT, FieldMetadataType.FULL_NAME, + FieldMetadataType.UUID, ];