diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 317aadef7de..b4b9d266c26 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -720,6 +720,16 @@ export type CreateApprovedAccessDomainInput = { email: Scalars['String']; }; +export type CreateCronTriggerInput = { + serverlessFunctionId: Scalars['String']; + settings: Scalars['JSON']; +}; + +export type CreateDatabaseEventTriggerInput = { + serverlessFunctionId: Scalars['String']; + settings: Scalars['JSON']; +}; + export type CreateDraftFromWorkflowVersionInput = { /** Workflow ID */ workflowId: Scalars['UUID']; @@ -926,6 +936,19 @@ export type CreateWorkflowVersionStepInput = { workflowVersionId: Scalars['UUID']; }; +export type CronTrigger = { + __typename?: 'CronTrigger'; + createdAt: Scalars['DateTime']; + id: Scalars['UUID']; + serverlessFunctionId: Scalars['String']; + settings: Scalars['JSON']; + updatedAt: Scalars['DateTime']; +}; + +export type CronTriggerIdInput = { + id: Scalars['String']; +}; + export type CursorPaging = { /** Paginate after opaque cursor */ after?: InputMaybe; @@ -946,6 +969,19 @@ export enum DatabaseEventAction { UPDATED = 'UPDATED' } +export type DatabaseEventTrigger = { + __typename?: 'DatabaseEventTrigger'; + createdAt: Scalars['DateTime']; + id: Scalars['UUID']; + serverlessFunctionId: Scalars['String']; + settings: Scalars['JSON']; + updatedAt: Scalars['DateTime']; +}; + +export type DatabaseEventTriggerIdInput = { + id: Scalars['String']; +}; + export type DateFilter = { eq?: InputMaybe; gt?: InputMaybe; @@ -1597,6 +1633,8 @@ export type Mutation = { createObjectEvent: Analytics; createOneAgent: Agent; createOneAppToken: AppToken; + createOneCronTrigger: CronTrigger; + createOneDatabaseEventTrigger: DatabaseEventTrigger; createOneField: Field; createOneObject: Object; createOneRemoteServer: RemoteServer; @@ -1623,6 +1661,8 @@ export type Mutation = { deleteEmailingDomain: Scalars['Boolean']; deleteFile: File; deleteOneAgent: Agent; + deleteOneCronTrigger: CronTrigger; + deleteOneDatabaseEventTrigger: DatabaseEventTrigger; deleteOneField: Field; deleteOneObject: Object; deleteOneRemoteServer: RemoteServer; @@ -1704,6 +1744,8 @@ export type Mutation = { updateDatabaseConfigVariable: Scalars['Boolean']; updateLabPublicFeatureFlag: FeatureFlagDto; updateOneAgent: Agent; + updateOneCronTrigger: CronTrigger; + updateOneDatabaseEventTrigger: DatabaseEventTrigger; updateOneField: Field; updateOneObject: Object; updateOneRemoteServer: RemoteServer; @@ -1877,6 +1919,16 @@ export type MutationCreateOneAppTokenArgs = { }; +export type MutationCreateOneCronTriggerArgs = { + input: CreateCronTriggerInput; +}; + + +export type MutationCreateOneDatabaseEventTriggerArgs = { + input: CreateDatabaseEventTriggerInput; +}; + + export type MutationCreateOneFieldArgs = { input: CreateOneFieldMetadataInput; }; @@ -2002,6 +2054,16 @@ export type MutationDeleteOneAgentArgs = { }; +export type MutationDeleteOneCronTriggerArgs = { + input: CronTriggerIdInput; +}; + + +export type MutationDeleteOneDatabaseEventTriggerArgs = { + input: DatabaseEventTriggerIdInput; +}; + + export type MutationDeleteOneFieldArgs = { input: DeleteOneFieldInput; }; @@ -2398,6 +2460,16 @@ export type MutationUpdateOneAgentArgs = { }; +export type MutationUpdateOneCronTriggerArgs = { + input: UpdateCronTriggerInput; +}; + + +export type MutationUpdateOneDatabaseEventTriggerArgs = { + input: UpdateDatabaseEventTriggerInput; +}; + + export type MutationUpdateOneFieldArgs = { input: UpdateOneFieldMetadataInput; }; @@ -2873,10 +2945,14 @@ export type Query = { findAgentHandoffs: Array; findDistantTablesWithStatus: Array; findManyAgents: Array; + findManyCronTriggers: Array; + findManyDatabaseEventTriggers: Array; findManyPublicDomains: Array; findManyRemoteServersByType: Array; findManyServerlessFunctions: Array; findOneAgent: Agent; + findOneCronTrigger: CronTrigger; + findOneDatabaseEventTrigger: DatabaseEventTrigger; findOneRemoteServerById: RemoteServer; findOneServerlessFunction: ServerlessFunction; findWorkspaceFromInviteHash: Workspace; @@ -3007,6 +3083,16 @@ export type QueryFindOneAgentArgs = { }; +export type QueryFindOneCronTriggerArgs = { + input: CronTriggerIdInput; +}; + + +export type QueryFindOneDatabaseEventTriggerArgs = { + input: DatabaseEventTriggerIdInput; +}; + + export type QueryFindOneRemoteServerByIdArgs = { input: RemoteServerIdInput; }; @@ -3712,6 +3798,16 @@ export type UpdateApiKeyDto = { revokedAt?: InputMaybe; }; +export type UpdateCronTriggerInput = { + id: Scalars['String']; + settings: Scalars['JSON']; +}; + +export type UpdateDatabaseEventTriggerInput = { + id: Scalars['String']; + settings: Scalars['JSON']; +}; + export type UpdateFieldInput = { defaultValue?: InputMaybe; description?: InputMaybe; diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index e1b57d8d2ac..81cb945d478 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -890,6 +890,15 @@ export type CreateWorkflowVersionStepInput = { workflowVersionId: Scalars['UUID']; }; +export type CronTrigger = { + __typename?: 'CronTrigger'; + createdAt: Scalars['DateTime']; + id: Scalars['UUID']; + serverlessFunctionId: Scalars['String']; + settings: Scalars['JSON']; + updatedAt: Scalars['DateTime']; +}; + export type CursorPaging = { /** Paginate after opaque cursor */ after?: InputMaybe; @@ -910,6 +919,15 @@ export enum DatabaseEventAction { UPDATED = 'UPDATED' } +export type DatabaseEventTrigger = { + __typename?: 'DatabaseEventTrigger'; + createdAt: Scalars['DateTime']; + id: Scalars['UUID']; + serverlessFunctionId: Scalars['String']; + settings: Scalars['JSON']; + updatedAt: Scalars['DateTime']; +}; + export type DateFilter = { eq?: InputMaybe; gt?: InputMaybe; diff --git a/packages/twenty-server/src/database/commands/cron-register-all.command.ts b/packages/twenty-server/src/database/commands/cron-register-all.command.ts index d409fe1a755..88ef5bdddee 100644 --- a/packages/twenty-server/src/database/commands/cron-register-all.command.ts +++ b/packages/twenty-server/src/database/commands/cron-register-all.command.ts @@ -3,7 +3,9 @@ import { Logger } from '@nestjs/common'; import { Command, CommandRunner } from 'nest-commander'; import { CleanupOrphanedFilesCronCommand } from 'src/engine/core-modules/file/crons/commands/cleanup-orphaned-files.cron.command'; -import { CronTriggerCronCommand } from 'src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command'; +import { CheckPublicDomainsValidRecordsCronCommand } from 'src/engine/core-modules/public-domain/crons/commands/check-public-domains-valid-records.cron.command'; +import { CheckCustomDomainValidRecordsCronCommand } from 'src/engine/core-modules/workspace/crons/commands/check-custom-domain-valid-records.cron.command'; +import { CronTriggerCronCommand } from 'src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command'; import { CleanOnboardingWorkspacesCronCommand } from 'src/engine/workspace-manager/workspace-cleaner/commands/clean-onboarding-workspaces.cron.command'; import { CleanSuspendedWorkspacesCronCommand } from 'src/engine/workspace-manager/workspace-cleaner/commands/clean-suspended-workspaces.cron.command'; import { CalendarEventListFetchCronCommand } from 'src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-event-list-fetch.cron.command'; @@ -16,8 +18,6 @@ import { WorkflowCleanWorkflowRunsCronCommand } from 'src/modules/workflow/workf import { WorkflowHandleStaledRunsCronCommand } from 'src/modules/workflow/workflow-runner/workflow-run-queue/cron/command/workflow-handle-staled-runs.cron.command'; import { WorkflowRunEnqueueCronCommand } from 'src/modules/workflow/workflow-runner/workflow-run-queue/cron/command/workflow-run-enqueue.cron.command'; import { WorkflowCronTriggerCronCommand } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/commands/workflow-cron-trigger.cron.command'; -import { CheckCustomDomainValidRecordsCronCommand } from 'src/engine/core-modules/workspace/crons/commands/check-custom-domain-valid-records.cron.command'; -import { CheckPublicDomainsValidRecordsCronCommand } from 'src/engine/core-modules/public-domain/crons/commands/check-public-domains-valid-records.cron.command'; @Command({ name: 'cron:register:all', 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 16968661104..b2603765713 100644 --- a/packages/twenty-server/src/database/commands/database-command.module.ts +++ b/packages/twenty-server/src/database/commands/database-command.module.ts @@ -9,11 +9,14 @@ import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { FileModule } from 'src/engine/core-modules/file/file.module'; +import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public-domain.module'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; +import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; +import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module'; import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; -import { TriggerModule } from 'src/engine/metadata-modules/trigger/trigger.module'; import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; import { DevSeederModule } from 'src/engine/workspace-manager/dev-seeder/dev-seeder.module'; import { WorkspaceCleanerModule } from 'src/engine/workspace-manager/workspace-cleaner/workspace-cleaner.module'; @@ -22,8 +25,6 @@ import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar- 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'; import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/automated-trigger/automated-trigger.module'; -import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; -import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public-domain.module'; @Module({ imports: [ @@ -46,7 +47,8 @@ import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public WorkspaceCacheStorageModule, ApiKeyModule, FeatureFlagModule, - TriggerModule, + CronTriggerModule, + DatabaseEventTriggerModule, WorkspaceCleanerModule, PublicDomainModule, ], diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts index 8417e507423..188e9ac028b 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts @@ -10,17 +10,17 @@ import { type ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/ty import { type ObjectRecordNonDestructiveEvent } from 'src/engine/core-modules/event-emitter/types/object-record-non-destructive-event'; import { type ObjectRecordRestoreEvent } from 'src/engine/core-modules/event-emitter/types/object-record-restore.event'; import { type ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event'; +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 { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; -import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; -import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job'; import { CallWebhookJobsJob } from 'src/engine/core-modules/webhook/jobs/call-webhook-jobs.job'; import { type ObjectRecordEventForWebhook } from 'src/engine/core-modules/webhook/types/object-record-event-for-webhook.type'; -import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job'; +import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job'; import { SubscriptionsService } from 'src/engine/subscriptions/subscriptions.service'; -import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; +import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; +import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job'; @Injectable() export class EntityEventsToDbListener { diff --git a/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts b/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts index 61f50bf24e1..ed0be7d99e2 100644 --- a/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts +++ b/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts @@ -6,4 +6,6 @@ export const ALL_FLAT_ENTITY_MAPS_PROPERTIES = [ 'flatViewMaps', 'flatIndexMaps', 'flatServerlessFunctionMaps', + 'flatDatabaseEventTriggerMaps', + 'flatCronTriggerMaps', ] as const satisfies (keyof AllFlatEntityMaps)[]; diff --git a/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts b/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts index 933206acbcf..3913d816ee3 100644 --- a/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts +++ b/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts @@ -10,4 +10,6 @@ export const EMPTY_ALL_FLAT_ENTITY_MAPS = { flatViewFieldMaps: EMPTY_FLAT_ENTITY_MAPS, flatViewMaps: EMPTY_FLAT_ENTITY_MAPS, flatServerlessFunctionMaps: EMPTY_FLAT_ENTITY_MAPS, + flatCronTriggerMaps: EMPTY_FLAT_ENTITY_MAPS, + flatDatabaseEventTriggerMaps: EMPTY_FLAT_ENTITY_MAPS, } as const satisfies AllFlatEntityMaps; diff --git a/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts b/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts index a7e327f38a0..0ea00ca9245 100644 --- a/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts +++ b/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts @@ -1,5 +1,7 @@ import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type'; import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type'; +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; +import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; @@ -11,4 +13,6 @@ export type AllFlatEntitiesByMetadataEngineName = { viewField: FlatViewField; index: FlatIndexMetadata; serverlessFunction: FlatServerlessFunction; + cronTrigger: FlatCronTrigger; + databaseEventTrigger: FlatDatabaseEventTrigger; }; diff --git a/packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts b/packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts index 8c4783ddadd..9bd4c5cd423 100644 --- a/packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts @@ -14,11 +14,15 @@ import { EmailModule } from 'src/engine/core-modules/email/email.module'; import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module'; import { UserVarsModule } from 'src/engine/core-modules/user/user-vars/user-vars.module'; import { UserModule } from 'src/engine/core-modules/user/user.module'; +import { WebhookJobModule } from 'src/engine/core-modules/webhook/jobs/webhook-job.module'; import { HandleWorkspaceMemberDeletedJob } from 'src/engine/core-modules/workspace/handle-workspace-member-deleted.job'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; +import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; +import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; +import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module'; import { SubscriptionsModule } from 'src/engine/subscriptions/subscriptions.module'; import { CleanOnboardingWorkspacesJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-onboarding-workspaces.job'; import { CleanSuspendedWorkspacesJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-suspended-workspaces.job'; @@ -31,10 +35,7 @@ import { FavoriteModule } from 'src/modules/favorite/favorite.module'; import { MessagingModule } from 'src/modules/messaging/messaging.module'; import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module'; import { TimelineActivityModule } from 'src/modules/timeline/timeline-activity.module'; -import { WebhookJobModule } from 'src/engine/core-modules/webhook/jobs/webhook-job.module'; import { WorkflowModule } from 'src/modules/workflow/workflow.module'; -import { TriggerModule } from 'src/engine/metadata-modules/trigger/trigger.module'; -import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module'; @Module({ imports: [ @@ -62,7 +63,8 @@ import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless WorkspaceCleanerModule, SubscriptionsModule, AuditJobModule, - TriggerModule, + CronTriggerModule, + DatabaseEventTriggerModule, ServerlessFunctionModule, ], providers: [ diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-editable-properties.constant.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-editable-properties.constant.ts new file mode 100644 index 00000000000..09b0c8c1ff4 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-editable-properties.constant.ts @@ -0,0 +1,5 @@ +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; + +export const FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES = [ + 'settings', +] as const satisfies (keyof FlatCronTrigger)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-properties-to-compare.constant.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-properties-to-compare.constant.ts new file mode 100644 index 00000000000..de954e34f41 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-properties-to-compare.constant.ts @@ -0,0 +1,6 @@ +import { FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-editable-properties.constant'; +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; + +export const FLAT_CRON_TRIGGER_PROPERTIES_TO_COMPARE = [ + ...FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES, +] as const satisfies (keyof FlatCronTrigger)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/cron-trigger.module.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/cron-trigger.module.ts new file mode 100644 index 00000000000..a9a39de3ad0 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/cron-trigger.module.ts @@ -0,0 +1,33 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.module'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { CronTriggerCronCommand } from 'src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command'; +import { CronTriggerCronJob } from 'src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job'; +import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { CronTriggerResolver } from 'src/engine/metadata-modules/cron-trigger/resolvers/cron-trigger.resolver'; +import { CronTriggerV2Service } from 'src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service'; +import { WorkspaceFlatCronTriggerMapCacheService } from 'src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service'; +import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Workspace, CronTrigger]), + WorkspaceManyOrAllFlatEntityMapsCacheModule, + WorkspaceMigrationV2Module, + ], + providers: [ + CronTriggerCronJob, + CronTriggerCronCommand, + CronTriggerResolver, + CronTriggerV2Service, + WorkspaceFlatCronTriggerMapCacheService, + ], + exports: [ + CronTriggerCronCommand, + CronTriggerV2Service, + WorkspaceFlatCronTriggerMapCacheService, + ], +}) +export class CronTriggerModule {} diff --git a/packages/twenty-server/src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command.ts similarity index 92% rename from packages/twenty-server/src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command.ts rename to packages/twenty-server/src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command.ts index 85c2ff59d04..e162a2a2280 100644 --- a/packages/twenty-server/src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command.ts +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command.ts @@ -6,7 +6,7 @@ import { MessageQueueService } from 'src/engine/core-modules/message-queue/servi import { CRON_TRIGGER_CRON_PATTERN, CronTriggerCronJob, -} from 'src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job'; +} from 'src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job'; @Command({ name: 'cron:trigger:start-cron-trigger', description: diff --git a/packages/twenty-server/src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job.ts similarity index 96% rename from packages/twenty-server/src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job.ts rename to packages/twenty-server/src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job.ts index 2fd4109a258..b45c0d26cbe 100644 --- a/packages/twenty-server/src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job.ts +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job.ts @@ -10,7 +10,7 @@ import { Process } from 'src/engine/core-modules/message-queue/decorators/proces import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; -import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity'; +import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { ServerlessFunctionTriggerJob, diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input.ts new file mode 100644 index 00000000000..c6883ff4eda --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input.ts @@ -0,0 +1,19 @@ +import { Field, InputType } from '@nestjs/graphql'; + +import { IsNotEmpty, IsObject, IsUUID } from 'class-validator'; +import GraphQLJSON from 'graphql-type-json'; + +import { CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; + +@InputType() +export class CreateCronTriggerInput { + @IsObject() + @IsNotEmpty() + @Field(() => GraphQLJSON) + settings: CronTriggerSettings; + + @IsUUID() + @IsNotEmpty() + @Field() + serverlessFunctionId: string; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input.ts new file mode 100644 index 00000000000..67400d80e5e --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input.ts @@ -0,0 +1,11 @@ +import { Field, InputType } from '@nestjs/graphql'; + +import { IsNotEmpty, IsUUID } from 'class-validator'; + +@InputType() +export class CronTriggerIdInput { + @IsUUID() + @IsNotEmpty() + @Field(() => String) + id: string; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/cron-trigger.dto.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/cron-trigger.dto.ts new file mode 100644 index 00000000000..83d56215db2 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/cron-trigger.dto.ts @@ -0,0 +1,35 @@ +import { Field, HideField, ObjectType } from '@nestjs/graphql'; + +import { IDField } from '@ptc-org/nestjs-query-graphql'; +import { IsDateString, IsNotEmpty, IsObject, IsUUID } from 'class-validator'; +import GraphQLJSON from 'graphql-type-json'; + +import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; +import { CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; + +@ObjectType('CronTrigger') +export class CronTriggerDTO { + @IsUUID() + @IsNotEmpty() + @IDField(() => UUIDScalarType) + id: string; + + @IsObject() + @Field(() => GraphQLJSON) + settings: CronTriggerSettings; + + @HideField() + workspaceId: string; + + @IsUUID() + @Field() + serverlessFunctionId: string; + + @IsDateString() + @Field() + createdAt: Date; + + @IsDateString() + @Field() + updatedAt: Date; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input.ts new file mode 100644 index 00000000000..f5fa5850582 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input.ts @@ -0,0 +1,19 @@ +import { Field, InputType } from '@nestjs/graphql'; + +import { IsNotEmpty, IsObject, IsUUID } from 'class-validator'; +import GraphQLJSON from 'graphql-type-json'; + +import { CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; + +@InputType() +export class UpdateCronTriggerInput { + @IsUUID() + @IsNotEmpty() + @Field(() => String) + id: string; + + @IsObject() + @IsNotEmpty() + @Field(() => GraphQLJSON) + settings: CronTriggerSettings; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/trigger/entities/cron-trigger.entity.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity.ts similarity index 76% rename from packages/twenty-server/src/engine/metadata-modules/trigger/entities/cron-trigger.entity.ts rename to packages/twenty-server/src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity.ts index 3f3bbbf92ed..c157a70b8b5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/trigger/entities/cron-trigger.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity.ts @@ -2,22 +2,27 @@ import { Column, CreateDateColumn, Entity, + Index, JoinColumn, ManyToOne, PrimaryGeneratedColumn, - UpdateDateColumn, Relation, - Index, + UpdateDateColumn, } from 'typeorm'; import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface'; +import { CronTriggerEntityRelationProperties } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; export type CronTriggerSettings = { pattern: string; }; +export const CRON_TRIGGER_ENTITY_RELATION_PROPERTIES = [ + 'serverlessFunction', +] as const satisfies readonly CronTriggerEntityRelationProperties[]; + @Entity({ name: 'cronTrigger', schema: 'core' }) @Index('IDX_CRON_TRIGGER_WORKSPACE_ID', ['workspaceId']) export class CronTrigger extends SyncableEntity { @@ -35,6 +40,9 @@ export class CronTrigger extends SyncableEntity { @JoinColumn({ name: 'serverlessFunctionId' }) serverlessFunction: Relation; + @Column({ nullable: true, type: 'uuid' }) + serverlessFunctionId: string | null; + @Column({ nullable: false, type: 'uuid' }) workspaceId: string; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception.ts new file mode 100644 index 00000000000..c8588c31f53 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception.ts @@ -0,0 +1,12 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class CronTriggerException extends CustomException { + constructor(message: string, code: CronTriggerExceptionCode) { + super(message, code); + } +} + +export enum CronTriggerExceptionCode { + CRON_TRIGGER_NOT_FOUND = 'CRON_TRIGGER_NOT_FOUND', + CRON_TRIGGER_ALREADY_EXIST = 'CRON_TRIGGER_ALREADY_EXIST', +} diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/resolvers/cron-trigger.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/resolvers/cron-trigger.resolver.ts new file mode 100644 index 00000000000..4ab22f16f1a --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/resolvers/cron-trigger.resolver.ts @@ -0,0 +1,99 @@ +import { UseFilters, UseGuards, UsePipes } from '@nestjs/common'; +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; + +import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter'; +import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input'; +import { CronTriggerIdInput } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input'; +import { CronTriggerDTO } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger.dto'; +import { UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input'; +import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { CronTriggerV2Service } from 'src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service'; +import { cronTriggerGraphQLApiExceptionHandler } from 'src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.util'; + +@UseGuards(WorkspaceAuthGuard) +@Resolver() +@UsePipes(ResolverValidationPipe) +@UseFilters(PreventNestToAutoLogGraphqlErrorsFilter) +export class CronTriggerResolver { + constructor( + private readonly cronTriggerV2Service: CronTriggerV2Service, + @InjectRepository(CronTrigger) + private readonly cronTriggerRepository: Repository, + ) {} + + @Query(() => CronTriggerDTO) + async findOneCronTrigger( + @Args('input') { id }: CronTriggerIdInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.cronTriggerRepository.findOneOrFail({ + where: { + id, + workspaceId, + }, + }); + } catch (error) { + cronTriggerGraphQLApiExceptionHandler(error); + } + } + + @Query(() => [CronTriggerDTO]) + async findManyCronTriggers(@AuthWorkspace() { id: workspaceId }: Workspace) { + try { + return await this.cronTriggerRepository.find({ + where: { workspaceId }, + }); + } catch (error) { + cronTriggerGraphQLApiExceptionHandler(error); + } + } + + @Mutation(() => CronTriggerDTO) + async deleteOneCronTrigger( + @Args('input') input: CronTriggerIdInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.cronTriggerV2Service.destroyOne({ + destroyCronTriggerInput: input, + workspaceId, + }); + } catch (error) { + cronTriggerGraphQLApiExceptionHandler(error); + } + } + + @Mutation(() => CronTriggerDTO) + async updateOneCronTrigger( + @Args('input') + input: UpdateCronTriggerInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.cronTriggerV2Service.updateOne(input, workspaceId); + } catch (error) { + cronTriggerGraphQLApiExceptionHandler(error); + } + } + + @Mutation(() => CronTriggerDTO) + async createOneCronTrigger( + @Args('input') + input: CreateCronTriggerInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.cronTriggerV2Service.createOne(input, workspaceId); + } catch (error) { + cronTriggerGraphQLApiExceptionHandler(error); + } + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service.ts new file mode 100644 index 00000000000..049a7b975c3 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service.ts @@ -0,0 +1,222 @@ +import { Injectable } from '@nestjs/common'; + +import { isDefined } from 'twenty-shared/utils'; + +import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service.'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input'; +import { CronTriggerIdInput } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input'; +import { UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input'; +import { + CronTriggerException, + CronTriggerExceptionCode, +} from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception'; +import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; +import { fromCreateCronTriggerInputToFlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/utils/from-create-cron-trigger-input-to-flat-cron-trigger.util'; +import { fromUpdateCronTriggerInputToFlatCronTriggerToUpdateOrThrow } from 'src/engine/metadata-modules/cron-trigger/utils/from-update-cron-trigger-input-to-flat-cron-trigger-to-update-or-throw.util'; +import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2'; +import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service'; + +@Injectable() +export class CronTriggerV2Service { + constructor( + private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, + private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService, + ) {} + + async createOne( + cronTriggerInput: CreateCronTriggerInput, + workspaceId: string, + ) { + const flatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatCronTriggerMaps'], + }, + ); + + const existingFlatCronTriggerMaps = flatEntityMaps.flatCronTriggerMaps; + + const flatCronTriggerToCreate = fromCreateCronTriggerInputToFlatCronTrigger( + { + createCronTriggerInput: cronTriggerInput, + workspaceId, + }, + ); + + const toFlatCronTriggerMaps = addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatCronTriggerToCreate, + flatEntityMaps: existingFlatCronTriggerMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + workspaceId, + fromToAllFlatEntityMaps: { + flatCronTriggerMaps: { + from: existingFlatCronTriggerMaps, + to: toFlatCronTriggerMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while creating cron trigger', + ); + } + + const { flatCronTriggerMaps: recomputedExistingFlatCronTriggerMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatCronTriggerMaps'], + }, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: flatCronTriggerToCreate.id, + flatEntityMaps: recomputedExistingFlatCronTriggerMaps, + }); + } + + async updateOne( + cronTriggerInput: UpdateCronTriggerInput, + workspaceId: string, + ) { + const flatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatCronTriggerMaps'], + }, + ); + + const existingFlatCronTriggerMaps = flatEntityMaps.flatCronTriggerMaps; + + const optimisticallyUpdatedFlatCronTrigger = + fromUpdateCronTriggerInputToFlatCronTriggerToUpdateOrThrow({ + flatCronTriggerMaps: existingFlatCronTriggerMaps, + updateCronTriggerInput: cronTriggerInput, + }); + + const fromFlatCronTriggerMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds: [optimisticallyUpdatedFlatCronTrigger.id], + flatEntityMaps: existingFlatCronTriggerMaps, + }); + const toFlatCronTriggerMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: optimisticallyUpdatedFlatCronTrigger, + flatEntityMaps: fromFlatCronTriggerMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + workspaceId, + fromToAllFlatEntityMaps: { + flatCronTriggerMaps: { + from: existingFlatCronTriggerMaps, + to: toFlatCronTriggerMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while updating cron trigger', + ); + } + + const { flatCronTriggerMaps: recomputedExistingFlatCronTriggerMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatCronTriggerMaps'], + }, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: optimisticallyUpdatedFlatCronTrigger.id, + flatEntityMaps: recomputedExistingFlatCronTriggerMaps, + }); + } + + async destroyOne({ + destroyCronTriggerInput, + workspaceId, + }: { + destroyCronTriggerInput: CronTriggerIdInput; + workspaceId: string; + }): Promise { + const { flatCronTriggerMaps: existingFlatCronTriggerMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatCronTriggerMaps'], + }, + ); + + const existingFlatCronTrigger = + existingFlatCronTriggerMaps.byId[destroyCronTriggerInput.id]; + + if (!isDefined(existingFlatCronTrigger)) { + throw new CronTriggerException( + 'Cron trigger to destroy not found', + CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND, + ); + } + + const fromFlatCronTriggerMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds: [existingFlatCronTrigger.id], + flatEntityMaps: existingFlatCronTriggerMaps, + }); + const toFlatCronTriggerMaps = deleteFlatEntityFromFlatEntityMapsOrThrow({ + flatEntityMaps: fromFlatCronTriggerMaps, + entityToDeleteId: existingFlatCronTrigger.id, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatCronTriggerMaps: { + from: fromFlatCronTriggerMaps, + to: toFlatCronTriggerMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: true, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while destroying cron trigger', + ); + } + + return existingFlatCronTrigger; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service.ts new file mode 100644 index 00000000000..b4785da3f94 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/services/workspace-flat-cron-trigger-map-cache.service.ts @@ -0,0 +1,69 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { removePropertiesFromRecord } from 'twenty-shared/utils'; +import { Repository } from 'typeorm'; + +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; +import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { + CRON_TRIGGER_ENTITY_RELATION_PROPERTIES, + CronTrigger, +} from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; +import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; +import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; + +@Injectable() +@WorkspaceFlatMapCache('flatCronTriggerMaps') +export class WorkspaceFlatCronTriggerMapCacheService extends WorkspaceFlatMapCacheService< + FlatEntityMaps +> { + constructor( + @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) + cacheStorageService: CacheStorageService, + @InjectRepository(CronTrigger) + private readonly cronTriggerRepository: Repository, + ) { + super(cacheStorageService); + } + + protected async computeFlatMap({ + workspaceId, + }: { + workspaceId: string; + }): Promise> { + const cronTriggers = await this.cronTriggerRepository.find({ + where: { + workspaceId, + }, + }); + + const flatCronTriggerMaps = cronTriggers.reduce< + FlatEntityMaps + >((flatEntityMaps, cronTrigger) => { + const flatCronTrigger = { + ...removePropertiesFromRecord(cronTrigger, [ + ...CRON_TRIGGER_ENTITY_RELATION_PROPERTIES, + ]), + universalIdentifier: cronTrigger.universalIdentifier ?? cronTrigger.id, + } satisfies FlatCronTrigger; + + return { + byId: { + ...flatEntityMaps.byId, + [flatCronTrigger.id]: flatCronTrigger, + }, + idByUniversalIdentifier: { + ...flatEntityMaps.idByUniversalIdentifier, + [flatCronTrigger.universalIdentifier]: flatCronTrigger.id, + }, + }; + }, EMPTY_FLAT_ENTITY_MAPS); + + return flatCronTriggerMaps; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger-properties-to-compare.type.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger-properties-to-compare.type.ts new file mode 100644 index 00000000000..0dc240210f8 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger-properties-to-compare.type.ts @@ -0,0 +1,6 @@ +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; + +export type FlatCronTriggerPropertiesToCompare = keyof Pick< + FlatCronTrigger, + 'settings' +>; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type.ts new file mode 100644 index 00000000000..d5c7c71694c --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type.ts @@ -0,0 +1,17 @@ +import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { type CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type'; + +export type CronTriggerEntityRelationProperties = + ExtractRecordTypeOrmRelationProperties< + CronTrigger, + ServerlessFunctionEntity | Workspace + >; + +export type FlatCronTrigger = Omit< + CronTrigger, + CronTriggerEntityRelationProperties +> & { + universalIdentifier: string; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/compare-two-flat-cron-trigger.util.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/compare-two-flat-cron-trigger.util.ts new file mode 100644 index 00000000000..b85fccfd931 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/compare-two-flat-cron-trigger.util.ts @@ -0,0 +1,69 @@ +import diff from 'microdiff'; +import { type FromTo } from 'twenty-shared/types'; +import { parseJson } from 'twenty-shared/utils'; + +import { FLAT_CRON_TRIGGER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-properties-to-compare.constant'; +import { type CronTriggerSettings } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { type FlatCronTriggerPropertiesToCompare } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger-properties-to-compare.type'; +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; +import { type UpdateCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type'; +import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util'; + +type GetWorkspaceMigrationUpdateCronTriggerActionArgs = FromTo< + FlatCronTrigger, + 'FlatCronTrigger' +>; + +export const compareTwoFlatCronTrigger = ({ + fromFlatCronTrigger, + toFlatCronTrigger, +}: GetWorkspaceMigrationUpdateCronTriggerActionArgs) => { + const transformMetadataForComparisonParameters = { + shouldIgnoreProperty: (property: string) => + !FLAT_CRON_TRIGGER_PROPERTIES_TO_COMPARE.includes( + property as FlatCronTriggerPropertiesToCompare, + ), + propertiesToStringify: ['settings'] as const, + }; + const fromCompare = transformMetadataForComparison( + fromFlatCronTrigger, + transformMetadataForComparisonParameters, + ); + const toCompare = transformMetadataForComparison( + toFlatCronTrigger, + transformMetadataForComparisonParameters, + ); + + const flatCronTriggerDifferences = diff(fromCompare, toCompare); + + return flatCronTriggerDifferences.flatMap< + UpdateCronTriggerAction['updates'][number] + >((difference) => { + switch (difference.type) { + case 'CHANGE': { + const { oldValue, path, value } = difference; + const property = path[0] as FlatCronTriggerPropertiesToCompare; + + if (property === 'settings') { + return { + from: parseJson(oldValue) as CronTriggerSettings, + to: parseJson(value) as CronTriggerSettings, + property, + }; + } + + return { + from: oldValue, + to: value, + property, + }; + } + case 'CREATE': + case 'REMOVE': + default: { + // Should never occurs, we should only provide null never undefined and so on + return []; + } + } + }); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.util.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.util.ts new file mode 100644 index 00000000000..083c3ed37c1 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.util.ts @@ -0,0 +1,23 @@ +import { + ConflictError, + NotFoundError, +} from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; +import { + CronTriggerException, + CronTriggerExceptionCode, +} from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception'; + +export const cronTriggerGraphQLApiExceptionHandler = (error: Error): void => { + if (error instanceof CronTriggerException) { + switch (error.code) { + case CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND: + throw new NotFoundError('Cron trigger not found'); + case CronTriggerExceptionCode.CRON_TRIGGER_ALREADY_EXIST: + throw new ConflictError('Cron trigger already exists'); + default: + throw error; + } + } + + throw error; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.utils.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.utils.ts new file mode 100644 index 00000000000..96fdd0a7f8b --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/cron-trigger-graphql-api-exception-handler.utils.ts @@ -0,0 +1,9 @@ +import { CronTriggerException } from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception'; + +export const cronTriggerGraphqlApiExceptionHandler = (error: Error) => { + if (error instanceof CronTriggerException) { + throw error; + } + + throw error; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/from-create-cron-trigger-input-to-flat-cron-trigger.util.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/from-create-cron-trigger-input-to-flat-cron-trigger.util.ts new file mode 100644 index 00000000000..b0ff3e5c513 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/from-create-cron-trigger-input-to-flat-cron-trigger.util.ts @@ -0,0 +1,24 @@ +import { v4 as uuidv4 } from 'uuid'; + +import { type CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input'; +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; + +export const fromCreateCronTriggerInputToFlatCronTrigger = ({ + createCronTriggerInput, + workspaceId, +}: { + createCronTriggerInput: CreateCronTriggerInput; + workspaceId: string; +}): FlatCronTrigger => { + const now = new Date(); + + return { + id: uuidv4(), + universalIdentifier: uuidv4(), + settings: createCronTriggerInput.settings, + serverlessFunctionId: createCronTriggerInput.serverlessFunctionId, + workspaceId, + createdAt: now, + updatedAt: now, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/from-update-cron-trigger-input-to-flat-cron-trigger-to-update-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/from-update-cron-trigger-input-to-flat-cron-trigger-to-update-or-throw.util.ts new file mode 100644 index 00000000000..c4519255d29 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/cron-trigger/utils/from-update-cron-trigger-input-to-flat-cron-trigger-to-update-or-throw.util.ts @@ -0,0 +1,31 @@ +import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { type UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input'; +import { + CronTriggerException, + CronTriggerExceptionCode, +} from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception'; +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; + +export const fromUpdateCronTriggerInputToFlatCronTriggerToUpdateOrThrow = ({ + flatCronTriggerMaps, + updateCronTriggerInput, +}: { + flatCronTriggerMaps: FlatEntityMaps; + updateCronTriggerInput: UpdateCronTriggerInput; +}): FlatCronTrigger => { + const existingFlatCronTrigger = + flatCronTriggerMaps.byId[updateCronTriggerInput.id]; + + if (!existingFlatCronTrigger) { + throw new CronTriggerException( + 'Cron trigger not found', + CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND, + ); + } + + return { + ...existingFlatCronTrigger, + settings: updateCronTriggerInput.settings, + updatedAt: new Date(), + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-editable-properties.constant.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-editable-properties.constant.ts new file mode 100644 index 00000000000..674a61ea152 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-editable-properties.constant.ts @@ -0,0 +1,5 @@ +import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; + +export const FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES = [ + 'settings', +] as const satisfies (keyof FlatDatabaseEventTrigger)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-properties-to-compare.constant.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-properties-to-compare.constant.ts new file mode 100644 index 00000000000..12a3a57f8ab --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-properties-to-compare.constant.ts @@ -0,0 +1,6 @@ +import { FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-editable-properties.constant'; +import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; + +export const FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE = [ + ...FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES, +] as const satisfies (keyof FlatDatabaseEventTrigger)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/database-event-trigger.module.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/database-event-trigger.module.ts new file mode 100644 index 00000000000..4bbd2e85008 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/database-event-trigger.module.ts @@ -0,0 +1,27 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.module'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job'; +import { DatabaseEventTriggerResolver } from 'src/engine/metadata-modules/database-event-trigger/resolvers/database-event-trigger.resolver'; +import { DatabaseEventTriggerV2Service } from 'src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service'; +import { WorkspaceFlatDatabaseEventTriggerMapCacheService } from 'src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service'; +import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Workspace, DatabaseEventTrigger]), + WorkspaceManyOrAllFlatEntityMapsCacheModule, + WorkspaceMigrationV2Module, + ], + providers: [ + CallDatabaseEventTriggerJobsJob, + DatabaseEventTriggerV2Service, + DatabaseEventTriggerResolver, + WorkspaceFlatDatabaseEventTriggerMapCacheService, + ], + exports: [DatabaseEventTriggerV2Service], +}) +export class DatabaseEventTriggerModule {} diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input.ts new file mode 100644 index 00000000000..021bc9717e5 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input.ts @@ -0,0 +1,19 @@ +import { Field, InputType } from '@nestjs/graphql'; + +import { IsNotEmpty, IsObject, IsUUID } from 'class-validator'; +import GraphQLJSON from 'graphql-type-json'; + +import { DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; + +@InputType() +export class CreateDatabaseEventTriggerInput { + @IsObject() + @IsNotEmpty() + @Field(() => GraphQLJSON) + settings: DatabaseEventTriggerSettings; + + @IsUUID() + @IsNotEmpty() + @Field() + serverlessFunctionId: string; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input.ts new file mode 100644 index 00000000000..e3fb3641c90 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input.ts @@ -0,0 +1,11 @@ +import { Field, InputType } from '@nestjs/graphql'; + +import { IsNotEmpty, IsUUID } from 'class-validator'; + +@InputType() +export class DatabaseEventTriggerIdInput { + @IsUUID() + @IsNotEmpty() + @Field() + id: string; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger.dto.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger.dto.ts new file mode 100644 index 00000000000..c294025af93 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger.dto.ts @@ -0,0 +1,35 @@ +import { Field, HideField, ObjectType } from '@nestjs/graphql'; + +import { IDField } from '@ptc-org/nestjs-query-graphql'; +import { IsDateString, IsNotEmpty, IsObject, IsUUID } from 'class-validator'; +import GraphQLJSON from 'graphql-type-json'; + +import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; +import { DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; + +@ObjectType('DatabaseEventTrigger') +export class DatabaseEventTriggerDTO { + @IsUUID() + @IsNotEmpty() + @IDField(() => UUIDScalarType) + id: string; + + @IsObject() + @Field(() => GraphQLJSON) + settings: DatabaseEventTriggerSettings; + + @HideField() + workspaceId: string; + + @IsUUID() + @Field() + serverlessFunctionId: string; + + @IsDateString() + @Field() + createdAt: Date; + + @IsDateString() + @Field() + updatedAt: Date; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input.ts new file mode 100644 index 00000000000..186924d258d --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input.ts @@ -0,0 +1,19 @@ +import { Field, InputType } from '@nestjs/graphql'; + +import { IsNotEmpty, IsObject, IsUUID } from 'class-validator'; +import GraphQLJSON from 'graphql-type-json'; + +import { DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; + +@InputType() +export class UpdateDatabaseEventTriggerInput { + @IsUUID() + @IsNotEmpty() + @Field() + id: string; + + @IsObject() + @IsNotEmpty() + @Field(() => GraphQLJSON) + settings: DatabaseEventTriggerSettings; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/trigger/entities/database-event-trigger.entity.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity.ts similarity index 67% rename from packages/twenty-server/src/engine/metadata-modules/trigger/entities/database-event-trigger.entity.ts rename to packages/twenty-server/src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity.ts index 7727dd5e529..d5e6f2648df 100644 --- a/packages/twenty-server/src/engine/metadata-modules/trigger/entities/database-event-trigger.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity.ts @@ -2,25 +2,33 @@ import { Column, CreateDateColumn, Entity, + Index, JoinColumn, ManyToOne, PrimaryGeneratedColumn, - UpdateDateColumn, Relation, - Index, + UpdateDateColumn, } from 'typeorm'; import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface'; +import { DatabaseEventTriggerEntityRelationProperties } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; export type DatabaseEventTriggerSettings = { eventName: string; }; -@Entity({ name: 'databaseEventTrigger', schema: 'core' }) +export const DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES = [ + 'serverlessFunction', +] as const satisfies readonly DatabaseEventTriggerEntityRelationProperties[]; + +@Entity('databaseEventTrigger') @Index('IDX_DATABASE_EVENT_TRIGGER_WORKSPACE_ID', ['workspaceId']) -export class DatabaseEventTrigger extends SyncableEntity { +export class DatabaseEventTrigger + extends SyncableEntity + implements Required +{ @PrimaryGeneratedColumn('uuid') id: string; @@ -35,6 +43,9 @@ export class DatabaseEventTrigger extends SyncableEntity { @JoinColumn({ name: 'serverlessFunctionId' }) serverlessFunction: Relation; + @Column({ nullable: true, type: 'uuid' }) + serverlessFunctionId: string | null; + @Column({ nullable: false, type: 'uuid' }) workspaceId: string; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception.ts new file mode 100644 index 00000000000..c4123b41433 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception.ts @@ -0,0 +1,12 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class DatabaseEventTriggerException extends CustomException { + constructor(message: string, code: DatabaseEventTriggerExceptionCode) { + super(message, code); + } +} + +export enum DatabaseEventTriggerExceptionCode { + DATABASE_EVENT_TRIGGER_NOT_FOUND = 'DATABASE_EVENT_TRIGGER_NOT_FOUND', + DATABASE_EVENT_TRIGGER_ALREADY_EXIST = 'DATABASE_EVENT_TRIGGER_ALREADY_EXIST', +} diff --git a/packages/twenty-server/src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job.ts similarity index 97% rename from packages/twenty-server/src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job.ts rename to packages/twenty-server/src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job.ts index 64b2f9c3a79..3c90ccab7db 100644 --- a/packages/twenty-server/src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job.ts +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job.ts @@ -2,18 +2,18 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; +import type { ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/types/object-record-event.event'; +import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; -import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; -import type { ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/types/object-record-event.event'; -import { DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity'; +import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; import { ServerlessFunctionTriggerJob, ServerlessFunctionTriggerJobData, } from 'src/engine/metadata-modules/serverless-function/jobs/serverless-function-trigger.job'; -import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; -import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; @Processor(MessageQueue.triggerQueue) export class CallDatabaseEventTriggerJobsJob { diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/resolvers/database-event-trigger.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/resolvers/database-event-trigger.resolver.ts new file mode 100644 index 00000000000..acda16875b5 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/resolvers/database-event-trigger.resolver.ts @@ -0,0 +1,107 @@ +import { UseFilters, UseGuards, UsePipes } from '@nestjs/common'; +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; + +import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter'; +import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input'; +import { DatabaseEventTriggerIdInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input'; +import { DatabaseEventTriggerDTO } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger.dto'; +import { UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input'; +import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { DatabaseEventTriggerV2Service } from 'src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service'; +import { databaseEventTriggerGraphQLApiExceptionHandler } from 'src/engine/metadata-modules/database-event-trigger/utils/database-event-trigger-graphql-api-exception-handler.utils'; + +@UseGuards(WorkspaceAuthGuard) +@Resolver() +@UsePipes(ResolverValidationPipe) +@UseFilters(PreventNestToAutoLogGraphqlErrorsFilter) +export class DatabaseEventTriggerResolver { + constructor( + private readonly databaseEventTriggerV2Service: DatabaseEventTriggerV2Service, + @InjectRepository(DatabaseEventTrigger) + private readonly databaseEventTriggerRepository: Repository, + ) {} + + @Query(() => DatabaseEventTriggerDTO) + async findOneDatabaseEventTrigger( + @Args('input') { id }: DatabaseEventTriggerIdInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.databaseEventTriggerRepository.findOneOrFail({ + where: { + id, + workspaceId, + }, + }); + } catch (error) { + databaseEventTriggerGraphQLApiExceptionHandler(error); + } + } + + @Query(() => [DatabaseEventTriggerDTO]) + async findManyDatabaseEventTriggers( + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.databaseEventTriggerRepository.find({ + where: { workspaceId }, + }); + } catch (error) { + databaseEventTriggerGraphQLApiExceptionHandler(error); + } + } + + @Mutation(() => DatabaseEventTriggerDTO) + async deleteOneDatabaseEventTrigger( + @Args('input') input: DatabaseEventTriggerIdInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.databaseEventTriggerV2Service.destroyOne({ + destroyDatabaseEventTriggerInput: input, + workspaceId, + }); + } catch (error) { + databaseEventTriggerGraphQLApiExceptionHandler(error); + } + } + + @Mutation(() => DatabaseEventTriggerDTO) + async updateOneDatabaseEventTrigger( + @Args('input') + input: UpdateDatabaseEventTriggerInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.databaseEventTriggerV2Service.updateOne( + input, + workspaceId, + ); + } catch (error) { + databaseEventTriggerGraphQLApiExceptionHandler(error); + } + } + + @Mutation(() => DatabaseEventTriggerDTO) + async createOneDatabaseEventTrigger( + @Args('input') + input: CreateDatabaseEventTriggerInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ) { + try { + return await this.databaseEventTriggerV2Service.createOne( + input, + workspaceId, + ); + } catch (error) { + databaseEventTriggerGraphQLApiExceptionHandler(error); + } + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service.ts new file mode 100644 index 00000000000..df442b94f14 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/database-event-trigger-v2.service.ts @@ -0,0 +1,239 @@ +import { Injectable } from '@nestjs/common'; + +import { isDefined } from 'twenty-shared/utils'; + +import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service.'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input'; +import { DatabaseEventTriggerIdInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input'; +import { UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input'; +import { + DatabaseEventTriggerException, + DatabaseEventTriggerExceptionCode, +} from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception'; +import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; +import { fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/utils/from-create-database-event-trigger-input-to-flat-database-event-trigger.util'; +import { fromUpdateDatabaseEventTriggerInputToFlatDatabaseEventTriggerToUpdateOrThrow } from 'src/engine/metadata-modules/database-event-trigger/utils/from-update-database-event-trigger-input-to-flat-database-event-trigger-to-update-or-throw.util'; +import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2'; +import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service'; + +@Injectable() +export class DatabaseEventTriggerV2Service { + constructor( + private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, + private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService, + ) {} + + async createOne( + databaseEventTriggerInput: CreateDatabaseEventTriggerInput, + workspaceId: string, + ) { + const flatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatDatabaseEventTriggerMaps'], + }, + ); + + const existingFlatDatabaseEventTriggerMaps = + flatEntityMaps.flatDatabaseEventTriggerMaps; + + const flatDatabaseEventTriggerToCreate = + fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger({ + createDatabaseEventTriggerInput: databaseEventTriggerInput, + workspaceId, + }); + + const toFlatDatabaseEventTriggerMaps = addFlatEntityToFlatEntityMapsOrThrow( + { + flatEntity: flatDatabaseEventTriggerToCreate, + flatEntityMaps: existingFlatDatabaseEventTriggerMaps, + }, + ); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + workspaceId, + fromToAllFlatEntityMaps: { + flatDatabaseEventTriggerMaps: { + from: existingFlatDatabaseEventTriggerMaps, + to: toFlatDatabaseEventTriggerMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while creating database event trigger', + ); + } + + const { + flatDatabaseEventTriggerMaps: + recomputedExistingFlatDatabaseEventTriggerMaps, + } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatDatabaseEventTriggerMaps'], + }, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: flatDatabaseEventTriggerToCreate.id, + flatEntityMaps: recomputedExistingFlatDatabaseEventTriggerMaps, + }); + } + + async updateOne( + databaseEventTriggerInput: UpdateDatabaseEventTriggerInput, + workspaceId: string, + ) { + const flatEntityMaps = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatDatabaseEventTriggerMaps'], + }, + ); + + const existingFlatDatabaseEventTriggerMaps = + flatEntityMaps.flatDatabaseEventTriggerMaps; + + const optimisticallyUpdatedFlatDatabaseEventTrigger = + fromUpdateDatabaseEventTriggerInputToFlatDatabaseEventTriggerToUpdateOrThrow( + { + flatDatabaseEventTriggerMaps: existingFlatDatabaseEventTriggerMaps, + updateDatabaseEventTriggerInput: databaseEventTriggerInput, + }, + ); + + const fromFlatDatabaseEventTriggerMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds: [optimisticallyUpdatedFlatDatabaseEventTrigger.id], + flatEntityMaps: existingFlatDatabaseEventTriggerMaps, + }); + const toFlatDatabaseEventTriggerMaps = + replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: optimisticallyUpdatedFlatDatabaseEventTrigger, + flatEntityMaps: fromFlatDatabaseEventTriggerMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + workspaceId, + fromToAllFlatEntityMaps: { + flatDatabaseEventTriggerMaps: { + from: existingFlatDatabaseEventTriggerMaps, + to: toFlatDatabaseEventTriggerMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while updating database event trigger', + ); + } + + const { + flatDatabaseEventTriggerMaps: + recomputedExistingFlatDatabaseEventTriggerMaps, + } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatDatabaseEventTriggerMaps'], + }, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: optimisticallyUpdatedFlatDatabaseEventTrigger.id, + flatEntityMaps: recomputedExistingFlatDatabaseEventTriggerMaps, + }); + } + + async destroyOne({ + destroyDatabaseEventTriggerInput, + workspaceId, + }: { + destroyDatabaseEventTriggerInput: DatabaseEventTriggerIdInput; + workspaceId: string; + }): Promise { + const { + flatDatabaseEventTriggerMaps: existingFlatDatabaseEventTriggerMaps, + } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatEntities: ['flatDatabaseEventTriggerMaps'], + }, + ); + + const existingFlatDatabaseEventTrigger = + existingFlatDatabaseEventTriggerMaps.byId[ + destroyDatabaseEventTriggerInput.id + ]; + + if (!isDefined(existingFlatDatabaseEventTrigger)) { + throw new DatabaseEventTriggerException( + 'Database event trigger to destroy not found', + DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND, + ); + } + + const fromFlatDatabaseEventTriggerMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds: [existingFlatDatabaseEventTrigger.id], + flatEntityMaps: existingFlatDatabaseEventTriggerMaps, + }); + const toFlatDatabaseEventTriggerMaps = + deleteFlatEntityFromFlatEntityMapsOrThrow({ + flatEntityMaps: fromFlatDatabaseEventTriggerMaps, + entityToDeleteId: existingFlatDatabaseEventTrigger.id, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatDatabaseEventTriggerMaps: { + from: fromFlatDatabaseEventTriggerMaps, + to: toFlatDatabaseEventTriggerMaps, + }, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: true, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while destroying database event trigger', + ); + } + + return existingFlatDatabaseEventTrigger; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service.ts new file mode 100644 index 00000000000..6f4f1a001fe --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/services/workspace-flat-database-event-trigger-map-cache.service.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { removePropertiesFromRecord } from 'twenty-shared/utils'; +import { Repository } from 'typeorm'; + +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; +import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { + DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES, + DatabaseEventTrigger, +} from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; +import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; +import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; + +@Injectable() +@WorkspaceFlatMapCache('flatDatabaseEventTriggerMaps') +export class WorkspaceFlatDatabaseEventTriggerMapCacheService extends WorkspaceFlatMapCacheService< + FlatEntityMaps +> { + constructor( + @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) + cacheStorageService: CacheStorageService, + @InjectRepository(DatabaseEventTrigger) + private readonly databaseEventTriggerRepository: Repository, + ) { + super(cacheStorageService); + } + + protected async computeFlatMap({ + workspaceId, + }: { + workspaceId: string; + }): Promise> { + const databaseEventTriggers = + await this.databaseEventTriggerRepository.find({ + where: { + workspaceId, + }, + }); + + const flatDatabaseEventTriggerMaps = databaseEventTriggers.reduce< + FlatEntityMaps + >((flatEntityMaps, databaseEventTrigger) => { + const flatDatabaseEventTrigger = { + ...removePropertiesFromRecord(databaseEventTrigger, [ + ...DATABASE_EVENT_TRIGGER_ENTITY_RELATION_PROPERTIES, + ]), + universalIdentifier: databaseEventTrigger.universalIdentifier ?? '', + } satisfies FlatDatabaseEventTrigger; + + return { + byId: { + ...flatEntityMaps.byId, + [flatDatabaseEventTrigger.id]: flatDatabaseEventTrigger, + }, + idByUniversalIdentifier: { + ...flatEntityMaps.idByUniversalIdentifier, + [flatDatabaseEventTrigger.universalIdentifier]: + flatDatabaseEventTrigger.id, + }, + }; + }, EMPTY_FLAT_ENTITY_MAPS); + + return flatDatabaseEventTriggerMaps; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger-properties-to-compare.type.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger-properties-to-compare.type.ts new file mode 100644 index 00000000000..1fc47d31398 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger-properties-to-compare.type.ts @@ -0,0 +1,4 @@ +import { type FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-properties-to-compare.constant'; + +export type FlatDatabaseEventTriggerPropertiesToCompare = + (typeof FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE)[number]; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type.ts new file mode 100644 index 00000000000..a2413cc5ec6 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type.ts @@ -0,0 +1,17 @@ +import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { type DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; +import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type'; + +export type DatabaseEventTriggerEntityRelationProperties = + ExtractRecordTypeOrmRelationProperties< + DatabaseEventTrigger, + ServerlessFunctionEntity | Workspace + >; + +export type FlatDatabaseEventTrigger = Omit< + DatabaseEventTrigger, + DatabaseEventTriggerEntityRelationProperties +> & { + universalIdentifier: string; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/compare-two-flat-database-event-trigger.util.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/compare-two-flat-database-event-trigger.util.ts new file mode 100644 index 00000000000..9f16f5fd5f5 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/compare-two-flat-database-event-trigger.util.ts @@ -0,0 +1,69 @@ +import diff from 'microdiff'; +import { type FromTo } from 'twenty-shared/types'; +import { parseJson } from 'twenty-shared/utils'; + +import { FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-properties-to-compare.constant'; +import { type DatabaseEventTriggerSettings } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { type FlatDatabaseEventTriggerPropertiesToCompare } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger-properties-to-compare.type'; +import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; +import { type UpdateDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type'; +import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util'; + +type GetWorkspaceMigrationUpdateDatabaseEventTriggerActionArgs = FromTo< + FlatDatabaseEventTrigger, + 'FlatDatabaseEventTrigger' +>; + +export const compareTwoFlatDatabaseEventTrigger = ({ + fromFlatDatabaseEventTrigger, + toFlatDatabaseEventTrigger, +}: GetWorkspaceMigrationUpdateDatabaseEventTriggerActionArgs) => { + const transformMetadataForComparisonParameters = { + shouldIgnoreProperty: (property: string) => + !FLAT_DATABASE_EVENT_TRIGGER_PROPERTIES_TO_COMPARE.includes( + property as FlatDatabaseEventTriggerPropertiesToCompare, + ), + propertiesToStringify: ['settings'] as const, + }; + const fromCompare = transformMetadataForComparison( + fromFlatDatabaseEventTrigger, + transformMetadataForComparisonParameters, + ); + const toCompare = transformMetadataForComparison( + toFlatDatabaseEventTrigger, + transformMetadataForComparisonParameters, + ); + + const flatDatabaseEventTriggerDifferences = diff(fromCompare, toCompare); + + return flatDatabaseEventTriggerDifferences.flatMap< + UpdateDatabaseEventTriggerAction['updates'][number] + >((difference) => { + switch (difference.type) { + case 'CHANGE': { + const { oldValue, path, value } = difference; + const property = path[0] as FlatDatabaseEventTriggerPropertiesToCompare; + + if (property === 'settings') { + return { + from: parseJson(oldValue) as DatabaseEventTriggerSettings, + to: parseJson(value) as DatabaseEventTriggerSettings, + property, + }; + } + + return { + from: oldValue, + to: value, + property, + }; + } + case 'CREATE': + case 'REMOVE': + default: { + // Should never occurs, we should only provide null never undefined and so on + return []; + } + } + }); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/database-event-trigger-graphql-api-exception-handler.utils.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/database-event-trigger-graphql-api-exception-handler.utils.ts new file mode 100644 index 00000000000..069f0727205 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/database-event-trigger-graphql-api-exception-handler.utils.ts @@ -0,0 +1,25 @@ +import { + ConflictError, + NotFoundError, +} from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; +import { + DatabaseEventTriggerException, + DatabaseEventTriggerExceptionCode, +} from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception'; + +export const databaseEventTriggerGraphQLApiExceptionHandler = ( + error: Error, +): void => { + if (error instanceof DatabaseEventTriggerException) { + switch (error.code) { + case DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND: + throw new NotFoundError('Database event trigger not found'); + case DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_ALREADY_EXIST: + throw new ConflictError('Database event trigger already exists'); + default: + throw error; + } + } + + throw error; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/from-create-database-event-trigger-input-to-flat-database-event-trigger.util.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/from-create-database-event-trigger-input-to-flat-database-event-trigger.util.ts new file mode 100644 index 00000000000..c964be8186d --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/from-create-database-event-trigger-input-to-flat-database-event-trigger.util.ts @@ -0,0 +1,24 @@ +import { v4 as uuidV4 } from 'uuid'; + +import { type CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input'; +import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; + +export const fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger = ({ + createDatabaseEventTriggerInput, + workspaceId, +}: { + createDatabaseEventTriggerInput: CreateDatabaseEventTriggerInput; + workspaceId: string; +}): FlatDatabaseEventTrigger => { + const now = new Date(); + + return { + id: uuidV4(), + universalIdentifier: uuidV4(), + settings: createDatabaseEventTriggerInput.settings, + serverlessFunctionId: createDatabaseEventTriggerInput.serverlessFunctionId, + workspaceId, + createdAt: now, + updatedAt: now, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/from-update-database-event-trigger-input-to-flat-database-event-trigger-to-update-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/from-update-database-event-trigger-input-to-flat-database-event-trigger-to-update-or-throw.util.ts new file mode 100644 index 00000000000..6ee92f6ae4b --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/database-event-trigger/utils/from-update-database-event-trigger-input-to-flat-database-event-trigger-to-update-or-throw.util.ts @@ -0,0 +1,32 @@ +import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { type UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input'; +import { + DatabaseEventTriggerException, + DatabaseEventTriggerExceptionCode, +} from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception'; +import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; + +export const fromUpdateDatabaseEventTriggerInputToFlatDatabaseEventTriggerToUpdateOrThrow = + ({ + flatDatabaseEventTriggerMaps, + updateDatabaseEventTriggerInput, + }: { + flatDatabaseEventTriggerMaps: FlatEntityMaps; + updateDatabaseEventTriggerInput: UpdateDatabaseEventTriggerInput; + }): FlatDatabaseEventTrigger => { + const existingFlatDatabaseEventTrigger = + flatDatabaseEventTriggerMaps.byId[updateDatabaseEventTriggerInput.id]; + + if (!existingFlatDatabaseEventTrigger) { + throw new DatabaseEventTriggerException( + 'Database event trigger not found', + DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND, + ); + } + + return { + ...existingFlatDatabaseEventTrigger, + settings: updateDatabaseEventTriggerInput.settings, + updatedAt: new Date(), + }; + }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts index 0a2fd8cec83..b92fcbe34ea 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts @@ -35,6 +35,8 @@ export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilatio }, ], serverlessFunction: [], + databaseEventTrigger: [], + cronTrigger: [], }, status: 'fail', }, diff --git a/packages/twenty-server/src/engine/metadata-modules/metadata-engine.module.ts b/packages/twenty-server/src/engine/metadata-modules/metadata-engine.module.ts index b614ccf1f3b..19a1557d1b2 100644 --- a/packages/twenty-server/src/engine/metadata-modules/metadata-engine.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/metadata-engine.module.ts @@ -1,17 +1,19 @@ import { Module } from '@nestjs/common'; import { AgentModule } from 'src/engine/metadata-modules/agent/agent.module'; +import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; +import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module'; import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module'; import { RemoteServerModule } from 'src/engine/metadata-modules/remote-server/remote-server.module'; import { RoleModule } from 'src/engine/metadata-modules/role/role.module'; +import { RouteModule } from 'src/engine/metadata-modules/route/route.module'; import { SearchFieldMetadataModule } from 'src/engine/metadata-modules/search-field-metadata/search-field-metadata.module'; import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module'; import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; -import { RouteModule } from 'src/engine/metadata-modules/route/route.module'; @Module({ imports: [ @@ -27,6 +29,8 @@ import { RouteModule } from 'src/engine/metadata-modules/route/route.module'; RoleModule, PermissionsModule, RouteModule, + CronTriggerModule, + DatabaseEventTriggerModule, ], providers: [], exports: [ diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts index b5b150aa7fd..56859a5c89d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.entity.ts @@ -12,10 +12,10 @@ import { import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface'; +import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; import { Route } from 'src/engine/metadata-modules/route/route.entity'; import { ServerlessFunctionEntityRelationProperties } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; -import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity'; -import { DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity'; import { InputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/input-schema.type'; const DEFAULT_SERVERLESS_TIMEOUT_SECONDS = 300; // 5 minutes diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts index 18e2924eff7..b5a2a0a4e31 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type.ts @@ -1,8 +1,8 @@ import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { type CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { type DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; import { type Route } from 'src/engine/metadata-modules/route/route.entity'; import { type ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity'; -import { type CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity'; -import { type DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity'; import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type'; export type ServerlessFunctionEntityRelationProperties = diff --git a/packages/twenty-server/src/engine/metadata-modules/trigger/trigger.module.ts b/packages/twenty-server/src/engine/metadata-modules/trigger/trigger.module.ts deleted file mode 100644 index f8ae2e4bad4..00000000000 --- a/packages/twenty-server/src/engine/metadata-modules/trigger/trigger.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { CronTriggerCronCommand } from 'src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command'; -import { CronTriggerCronJob } from 'src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity'; -import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job'; -import { DatabaseEventTrigger } from 'src/engine/metadata-modules/trigger/entities/database-event-trigger.entity'; - -@Module({ - imports: [ - TypeOrmModule.forFeature([Workspace, CronTrigger, DatabaseEventTrigger]), - ], - providers: [ - CronTriggerCronJob, - CronTriggerCronCommand, - CallDatabaseEventTriggerJobsJob, - ], - exports: [CronTriggerCronCommand], -}) -export class TriggerModule {} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts index 11cfc3456d8..0e716bc8cc9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts @@ -16,4 +16,6 @@ export const EMPTY_ORCHESTRATOR_ACTIONS_REPORT = { viewField: emptyCreatedDeletedUpdated, fieldMetadata: emptyCreatedDeletedUpdated, serverlessFunction: emptyCreatedDeletedUpdated, + databaseEventTrigger: emptyCreatedDeletedUpdated, + cronTrigger: emptyCreatedDeletedUpdated, } as const satisfies OrchestratorActionsReport; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts index 881e66dab0d..d99d1ea7556 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts @@ -11,6 +11,8 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = ( invalidViewField: 0, invalidIndex: 0, invalidServerlessFunction: 0, + invalidDatabaseEventTrigger: 0, + invalidCronTrigger: 0, totalErrors: 0, }, errors: { @@ -19,6 +21,8 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = ( view: [], viewField: [], serverlessFunction: [], + databaseEventTrigger: [], + cronTrigger: [], }, }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts index c9e670cc066..818235e3570 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts @@ -11,6 +11,8 @@ import { WorkspaceMigrationOrchestratorFailedResult, WorkspaceMigrationOrchestratorSuccessfulResult, } from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type'; +import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service'; +import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service'; import { WorkspaceMigrationV2IndexActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service'; import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service'; import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service'; @@ -29,6 +31,8 @@ export class WorkspaceMigrationBuildOrchestratorService { private readonly workspaceMigrationV2ViewActionsBuilderService: WorkspaceMigrationV2ViewActionsBuilderService, private readonly workspaceMigrationV2ViewFieldActionsBuilderService: WorkspaceMigrationV2ViewFieldActionsBuilderService, private readonly workspaceMigrationV2ServerlessFunctionActionsBuilderService: WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, + private readonly workspaceMigrationV2DatabaseEventTriggerActionsBuilderService: WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService, + private readonly workspaceMigrationV2CronTriggerActionsBuilderService: WorkspaceMigrationV2CronTriggerActionsBuilderService, ) {} private setupOptimisticCache({ @@ -80,6 +84,8 @@ export class WorkspaceMigrationBuildOrchestratorService { viewField: [], index: [], serverlessFunction: [], + databaseEventTrigger: [], + cronTrigger: [], }; const optimisticAllFlatEntityMaps = this.setupOptimisticCache({ @@ -92,6 +98,8 @@ export class WorkspaceMigrationBuildOrchestratorService { flatViewMaps, flatIndexMaps, flatServerlessFunctionMaps, + flatDatabaseEventTriggerMaps, + flatCronTriggerMaps, } = fromToAllFlatEntityMaps; if (isDefined(flatObjectMetadataMaps)) { @@ -222,6 +230,59 @@ export class WorkspaceMigrationBuildOrchestratorService { } } + if (isDefined(flatDatabaseEventTriggerMaps)) { + const { + from: fromFlatDatabaseEventTriggerMaps, + to: toFlatDatabaseEventTriggerMaps, + } = flatDatabaseEventTriggerMaps; + + const databaseEventTriggerResult = + await this.workspaceMigrationV2DatabaseEventTriggerActionsBuilderService.validateAndBuild( + { + from: fromFlatDatabaseEventTriggerMaps, + to: toFlatDatabaseEventTriggerMaps, + buildOptions, + dependencyOptimisticFlatEntityMaps: {} as AllFlatEntityMaps, + }, + ); + + optimisticAllFlatEntityMaps.flatDatabaseEventTriggerMaps = + databaseEventTriggerResult.optimisticFlatEntityMaps; + + if (databaseEventTriggerResult.status === 'fail') { + orchestratorFailureReport.databaseEventTrigger.push( + ...databaseEventTriggerResult.errors, + ); + } else { + orchestratorActionsReport.databaseEventTrigger = + databaseEventTriggerResult.actions; + } + } + + if (isDefined(flatCronTriggerMaps)) { + const { from: fromFlatCronTriggerMaps, to: toFlatCronTriggerMaps } = + flatCronTriggerMaps; + + const cronTriggerResult = + await this.workspaceMigrationV2CronTriggerActionsBuilderService.validateAndBuild( + { + from: fromFlatCronTriggerMaps, + to: toFlatCronTriggerMaps, + buildOptions, + dependencyOptimisticFlatEntityMaps: {} as AllFlatEntityMaps, + }, + ); + + optimisticAllFlatEntityMaps.flatCronTriggerMaps = + cronTriggerResult.optimisticFlatEntityMaps; + + if (cronTriggerResult.status === 'fail') { + orchestratorFailureReport.cronTrigger.push(...cronTriggerResult.errors); + } else { + orchestratorActionsReport.cronTrigger = cronTriggerResult.actions; + } + } + const allErrors = Object.values(orchestratorFailureReport); if (allErrors.some((report) => report.length > 0)) { @@ -266,6 +327,18 @@ export class WorkspaceMigrationBuildOrchestratorService { ...orchestratorActionsReport.serverlessFunction.created, ...orchestratorActionsReport.serverlessFunction.updated, /// + + // Database event triggers + ...orchestratorActionsReport.databaseEventTrigger.deleted, + ...orchestratorActionsReport.databaseEventTrigger.created, + ...orchestratorActionsReport.databaseEventTrigger.updated, + /// + + // Cron triggers + ...orchestratorActionsReport.cronTrigger.deleted, + ...orchestratorActionsReport.cronTrigger.created, + ...orchestratorActionsReport.cronTrigger.updated, + /// ], workspaceId, }, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service.ts new file mode 100644 index 00000000000..f3e5179114f --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service.ts @@ -0,0 +1,154 @@ +import { Injectable } from '@nestjs/common'; + +import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; +import { compareTwoFlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/utils/compare-two-flat-cron-trigger.util'; +import { + FlatEntityUpdateValidationArgs, + FlatEntityValidationArgs, + FlatEntityValidationReturnType, + WorkspaceEntityMigrationBuilderV2Service, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; +import { + UpdateCronTriggerAction, + WorkspaceMigrationCronTriggerActionV2, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type'; +import { + CronTriggerRelatedFlatEntityMaps, + FlatCronTriggerValidatorService, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service'; + +@Injectable() +export class WorkspaceMigrationV2CronTriggerActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service< + FlatCronTrigger, + WorkspaceMigrationCronTriggerActionV2, + CronTriggerRelatedFlatEntityMaps +> { + constructor( + private readonly flatCronTriggerValidatorService: FlatCronTriggerValidatorService, + ) { + super(); + } + + protected async validateFlatEntityCreation({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatCronTriggerToValidate, + optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps, + }: FlatEntityValidationArgs< + FlatCronTrigger, + CronTriggerRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationCronTriggerActionV2, + FlatCronTrigger + > + > { + const validationResult = + await this.flatCronTriggerValidatorService.validateFlatCronTriggerCreation( + { + flatCronTriggerToValidate, + optimisticFlatCronTriggerMaps, + dependencyOptimisticFlatEntityMaps, + }, + ); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + return { + status: 'success', + action: { + type: 'create_cron_trigger', + cronTrigger: flatCronTriggerToValidate, + }, + }; + } + + protected async validateFlatEntityDeletion({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatCronTriggerToValidate, + optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps, + }: FlatEntityValidationArgs< + FlatCronTrigger, + CronTriggerRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationCronTriggerActionV2, + FlatCronTrigger + > + > { + const validationResult = + this.flatCronTriggerValidatorService.validateFlatCronTriggerDeletion({ + flatCronTriggerToValidate, + optimisticFlatCronTriggerMaps, + dependencyOptimisticFlatEntityMaps, + }); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + return { + status: 'success', + action: { + type: 'delete_cron_trigger', + cronTriggerId: flatCronTriggerToValidate.id, + }, + }; + } + + protected async validateFlatEntityUpdate({ + dependencyOptimisticFlatEntityMaps, + flatEntityUpdate: { from: fromFlatCronTrigger, to: toFlatCronTrigger }, + optimisticFlatEntityMaps: optimisticFlatCronTriggerMaps, + }: FlatEntityUpdateValidationArgs< + FlatCronTrigger, + CronTriggerRelatedFlatEntityMaps + >): Promise< + | FlatEntityValidationReturnType< + WorkspaceMigrationCronTriggerActionV2, + FlatCronTrigger + > + | undefined + > { + const cronTriggerUpdatedProperties = compareTwoFlatCronTrigger({ + fromFlatCronTrigger, + toFlatCronTrigger, + }); + + if (cronTriggerUpdatedProperties.length === 0) { + return undefined; + } + + const validationResult = + this.flatCronTriggerValidatorService.validateFlatCronTriggerUpdate({ + flatCronTriggerToValidate: toFlatCronTrigger, + optimisticFlatCronTriggerMaps, + dependencyOptimisticFlatEntityMaps, + }); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + const updateCronTriggerAction: UpdateCronTriggerAction = { + type: 'update_cron_trigger', + cronTriggerId: toFlatCronTrigger.id, + updates: cronTriggerUpdatedProperties, + }; + + return { + status: 'success', + action: updateCronTriggerAction, + }; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service.ts new file mode 100644 index 00000000000..c07d8d52988 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service.ts @@ -0,0 +1,162 @@ +import { Injectable } from '@nestjs/common'; + +import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; +import { compareTwoFlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/utils/compare-two-flat-database-event-trigger.util'; +import { + FlatEntityUpdateValidationArgs, + FlatEntityValidationArgs, + FlatEntityValidationReturnType, + WorkspaceEntityMigrationBuilderV2Service, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; +import { + UpdateDatabaseEventTriggerAction, + WorkspaceMigrationDatabaseEventTriggerActionV2, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type'; +import { + DatabaseEventTriggerRelatedFlatEntityMaps, + FlatDatabaseEventTriggerValidatorService, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service'; + +@Injectable() +export class WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service< + FlatDatabaseEventTrigger, + WorkspaceMigrationDatabaseEventTriggerActionV2, + DatabaseEventTriggerRelatedFlatEntityMaps +> { + constructor( + private readonly flatDatabaseEventTriggerValidatorService: FlatDatabaseEventTriggerValidatorService, + ) { + super(); + } + + protected async validateFlatEntityCreation({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatDatabaseEventTriggerToValidate, + optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps, + }: FlatEntityValidationArgs< + FlatDatabaseEventTrigger, + DatabaseEventTriggerRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationDatabaseEventTriggerActionV2, + FlatDatabaseEventTrigger + > + > { + const validationResult = + await this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerCreation( + { + flatDatabaseEventTriggerToValidate, + optimisticFlatDatabaseEventTriggerMaps, + dependencyOptimisticFlatEntityMaps, + }, + ); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + return { + status: 'success', + action: { + type: 'create_database_event_trigger', + databaseEventTrigger: flatDatabaseEventTriggerToValidate, + }, + }; + } + + protected async validateFlatEntityDeletion({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatDatabaseEventTriggerToValidate, + optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps, + }: FlatEntityValidationArgs< + FlatDatabaseEventTrigger, + DatabaseEventTriggerRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationDatabaseEventTriggerActionV2, + FlatDatabaseEventTrigger + > + > { + const validationResult = + this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerDeletion( + { + flatDatabaseEventTriggerToValidate, + optimisticFlatDatabaseEventTriggerMaps, + dependencyOptimisticFlatEntityMaps, + }, + ); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + return { + status: 'success', + action: { + type: 'delete_database_event_trigger', + databaseEventTriggerId: flatDatabaseEventTriggerToValidate.id, + }, + }; + } + + protected async validateFlatEntityUpdate({ + dependencyOptimisticFlatEntityMaps, + flatEntityUpdate: { + from: fromFlatDatabaseEventTrigger, + to: toFlatDatabaseEventTrigger, + }, + optimisticFlatEntityMaps: optimisticFlatDatabaseEventTriggerMaps, + }: FlatEntityUpdateValidationArgs< + FlatDatabaseEventTrigger, + DatabaseEventTriggerRelatedFlatEntityMaps + >): Promise< + | FlatEntityValidationReturnType< + WorkspaceMigrationDatabaseEventTriggerActionV2, + FlatDatabaseEventTrigger + > + | undefined + > { + const databaseEventTriggerUpdatedProperties = + compareTwoFlatDatabaseEventTrigger({ + fromFlatDatabaseEventTrigger, + toFlatDatabaseEventTrigger, + }); + + if (databaseEventTriggerUpdatedProperties.length === 0) { + return undefined; + } + + const validationResult = + this.flatDatabaseEventTriggerValidatorService.validateFlatDatabaseEventTriggerUpdate( + { + flatDatabaseEventTriggerToValidate: toFlatDatabaseEventTrigger, + optimisticFlatDatabaseEventTriggerMaps, + dependencyOptimisticFlatEntityMaps, + }, + ); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + const updateDatabaseEventTriggerAction: UpdateDatabaseEventTriggerAction = { + type: 'update_database_event_trigger', + databaseEventTriggerId: toFlatDatabaseEventTrigger.id, + updates: databaseEventTriggerUpdatedProperties, + }; + + return { + status: 'success', + action: updateDatabaseEventTriggerAction, + }; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts index 4ec9516e99c..31197057a77 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts @@ -1,3 +1,5 @@ +import { type WorkspaceMigrationCronTriggerActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type'; +import { type WorkspaceMigrationDatabaseEventTriggerActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type'; import { type WorkspaceMigrationFieldActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-field-action-v2'; import { type WorkspaceMigrationIndexActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-index-action-v2'; import { type WorkspaceMigrationObjectActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-object-action-v2'; @@ -11,7 +13,9 @@ export type WorkspaceMigrationActionV2 = | WorkspaceMigrationIndexActionV2 | WorkspaceMigrationViewActionV2 | WorkspaceMigrationViewFieldActionV2 - | WorkspaceMigrationServerlessFunctionActionV2; + | WorkspaceMigrationServerlessFunctionActionV2 + | WorkspaceMigrationDatabaseEventTriggerActionV2 + | WorkspaceMigrationCronTriggerActionV2; export type WorkspaceMigrationActionTypeV2 = WorkspaceMigrationActionV2['type']; export type ExtractAction = Extract< diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type.ts new file mode 100644 index 00000000000..ffeed771d95 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type.ts @@ -0,0 +1,31 @@ +import { type FlatCronTriggerPropertiesToCompare } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger-properties-to-compare.type'; +import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; +import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type'; + +export type CreateCronTriggerAction = { + type: 'create_cron_trigger'; + cronTrigger: FlatCronTrigger; +}; + +export type UpdateCronTriggerAction = { + type: 'update_cron_trigger'; + cronTriggerId: string; + updates: Array< + { + [P in FlatCronTriggerPropertiesToCompare]: PropertyUpdate< + FlatCronTrigger, + P + >; + }[FlatCronTriggerPropertiesToCompare] + >; +}; + +export type DeleteCronTriggerAction = { + type: 'delete_cron_trigger'; + cronTriggerId: string; +}; + +export type WorkspaceMigrationCronTriggerActionV2 = + | CreateCronTriggerAction + | UpdateCronTriggerAction + | DeleteCronTriggerAction; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type.ts new file mode 100644 index 00000000000..3cfdd0dcc31 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type.ts @@ -0,0 +1,31 @@ +import { type FlatDatabaseEventTriggerPropertiesToCompare } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger-properties-to-compare.type'; +import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; +import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type'; + +export type CreateDatabaseEventTriggerAction = { + type: 'create_database_event_trigger'; + databaseEventTrigger: FlatDatabaseEventTrigger; +}; + +export type UpdateDatabaseEventTriggerAction = { + type: 'update_database_event_trigger'; + databaseEventTriggerId: string; + updates: Array< + { + [P in FlatDatabaseEventTriggerPropertiesToCompare]: PropertyUpdate< + FlatDatabaseEventTrigger, + P + >; + }[FlatDatabaseEventTriggerPropertiesToCompare] + >; +}; + +export type DeleteDatabaseEventTriggerAction = { + type: 'delete_database_event_trigger'; + databaseEventTriggerId: string; +}; + +export type WorkspaceMigrationDatabaseEventTriggerActionV2 = + | CreateDatabaseEventTriggerAction + | UpdateDatabaseEventTriggerAction + | DeleteDatabaseEventTriggerAction; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service.ts new file mode 100644 index 00000000000..d4a71fcf99a --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service.ts @@ -0,0 +1,107 @@ +import { Injectable } from '@nestjs/common'; + +import { t } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { CronTriggerExceptionCode } from 'src/engine/metadata-modules/cron-trigger/exceptions/cron-trigger.exception'; +import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type'; +import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; + +export type CronTriggerRelatedFlatEntityMaps = Pick< + AllFlatEntityMaps, + 'flatCronTriggerMaps' +>; + +type CronTriggerValidationArgs = { + flatCronTriggerToValidate: FlatCronTrigger; + optimisticFlatCronTriggerMaps: FlatEntityMaps; + dependencyOptimisticFlatEntityMaps: CronTriggerRelatedFlatEntityMaps; +}; +// TODO: validate settings integrity +@Injectable() +export class FlatCronTriggerValidatorService { + constructor() {} + + public validateFlatCronTriggerUpdate({ + flatCronTriggerToValidate: updatedFlatCronTrigger, + optimisticFlatCronTriggerMaps, + }: CronTriggerValidationArgs): FailedFlatEntityValidation { + const errors = []; + + const existingFlatCronTrigger = + optimisticFlatCronTriggerMaps.byId[updatedFlatCronTrigger.id]; + + if (!isDefined(existingFlatCronTrigger)) { + errors.push({ + code: CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND, + message: t`Cron trigger not found`, + userFriendlyMessage: t`Cron trigger not found`, + }); + } + + return { + type: 'update_cron_trigger', + errors, + flatEntityMinimalInformation: { + id: updatedFlatCronTrigger.id, + }, + }; + } + + public validateFlatCronTriggerDeletion({ + flatCronTriggerToValidate: { id: cronTriggerIdToDelete }, + optimisticFlatCronTriggerMaps, + }: CronTriggerValidationArgs): FailedFlatEntityValidation { + const errors = []; + + const existingFlatCronTrigger = + optimisticFlatCronTriggerMaps.byId[cronTriggerIdToDelete]; + + if (!isDefined(existingFlatCronTrigger)) { + errors.push({ + code: CronTriggerExceptionCode.CRON_TRIGGER_NOT_FOUND, + message: t`Cron trigger not found`, + userFriendlyMessage: t`Cron trigger not found`, + }); + } + + return { + type: 'delete_cron_trigger', + errors, + flatEntityMinimalInformation: { + id: cronTriggerIdToDelete, + }, + }; + } + + public async validateFlatCronTriggerCreation({ + flatCronTriggerToValidate, + optimisticFlatCronTriggerMaps, + }: CronTriggerValidationArgs): Promise< + FailedFlatEntityValidation + > { + const errors = []; + + if ( + isDefined( + optimisticFlatCronTriggerMaps.byId[flatCronTriggerToValidate.id], + ) + ) { + errors.push({ + code: CronTriggerExceptionCode.CRON_TRIGGER_ALREADY_EXIST, + message: t`Cron trigger with same id already exists`, + userFriendlyMessage: t`Cron trigger already exists`, + }); + } + + return { + type: 'create_cron_trigger', + errors, + flatEntityMinimalInformation: { + id: flatCronTriggerToValidate.id, + }, + }; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service.ts new file mode 100644 index 00000000000..de9791e318a --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service.ts @@ -0,0 +1,113 @@ +import { Injectable } from '@nestjs/common'; + +import { t } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { DatabaseEventTriggerExceptionCode } from 'src/engine/metadata-modules/database-event-trigger/exceptions/database-event-trigger.exception'; +import { FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type'; +import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; + +export type DatabaseEventTriggerRelatedFlatEntityMaps = Pick< + AllFlatEntityMaps, + 'flatDatabaseEventTriggerMaps' +>; + +type DatabaseEventTriggerValidationArgs = { + flatDatabaseEventTriggerToValidate: FlatDatabaseEventTrigger; + optimisticFlatDatabaseEventTriggerMaps: FlatEntityMaps; + dependencyOptimisticFlatEntityMaps: DatabaseEventTriggerRelatedFlatEntityMaps; +}; +// TODO: validate settings integrity +@Injectable() +export class FlatDatabaseEventTriggerValidatorService { + constructor() {} + + public validateFlatDatabaseEventTriggerUpdate({ + flatDatabaseEventTriggerToValidate: updatedFlatDatabaseEventTrigger, + optimisticFlatDatabaseEventTriggerMaps, + }: DatabaseEventTriggerValidationArgs): FailedFlatEntityValidation { + const errors = []; + + const existingFlatDatabaseEventTrigger = + optimisticFlatDatabaseEventTriggerMaps.byId[ + updatedFlatDatabaseEventTrigger.id + ]; + + if (!isDefined(existingFlatDatabaseEventTrigger)) { + errors.push({ + code: DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND, + message: t`Database event trigger not found`, + userFriendlyMessage: t`Database event trigger not found`, + }); + } + + return { + type: 'update_database_event_trigger', + errors, + flatEntityMinimalInformation: { + id: updatedFlatDatabaseEventTrigger.id, + }, + }; + } + + public validateFlatDatabaseEventTriggerDeletion({ + flatDatabaseEventTriggerToValidate: { id: databaseEventTriggerIdToDelete }, + optimisticFlatDatabaseEventTriggerMaps, + }: DatabaseEventTriggerValidationArgs): FailedFlatEntityValidation { + const errors = []; + + const existingFlatDatabaseEventTrigger = + optimisticFlatDatabaseEventTriggerMaps.byId[ + databaseEventTriggerIdToDelete + ]; + + if (!isDefined(existingFlatDatabaseEventTrigger)) { + errors.push({ + code: DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_NOT_FOUND, + message: t`Database event trigger not found`, + userFriendlyMessage: t`Database event trigger not found`, + }); + } + + return { + type: 'delete_database_event_trigger', + errors, + flatEntityMinimalInformation: { + id: databaseEventTriggerIdToDelete, + }, + }; + } + + public async validateFlatDatabaseEventTriggerCreation({ + flatDatabaseEventTriggerToValidate, + optimisticFlatDatabaseEventTriggerMaps, + }: DatabaseEventTriggerValidationArgs): Promise< + FailedFlatEntityValidation + > { + const errors = []; + + if ( + isDefined( + optimisticFlatDatabaseEventTriggerMaps.byId[ + flatDatabaseEventTriggerToValidate.id + ], + ) + ) { + errors.push({ + code: DatabaseEventTriggerExceptionCode.DATABASE_EVENT_TRIGGER_ALREADY_EXIST, + message: t`Database event trigger with same id already exists`, + userFriendlyMessage: t`Database event trigger already exists`, + }); + } + + return { + type: 'create_database_event_trigger', + errors, + flatEntityMinimalInformation: { + id: flatDatabaseEventTriggerToValidate.id, + }, + }; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts index 13edd2f5e1e..dd8681d31e2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts @@ -4,6 +4,8 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature- import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service'; import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service'; +import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service'; +import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service'; import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/services/workspace-migration-v2-field-actions-builder.service'; import { WorkspaceMigrationV2IndexActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/index/workspace-migration-v2-index-actions-builder.service'; import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/services/workspace-migration-v2-object-actions-builder.service'; @@ -11,6 +13,8 @@ import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service'; import { WorkspaceMigrationV2ViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service'; import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service'; +import { FlatCronTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service'; +import { FlatDatabaseEventTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service'; import { FlatServerlessFunctionValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service'; import { FlatViewFieldValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service'; import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service'; @@ -29,9 +33,13 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace- WorkspaceMigrationV2ViewFieldActionsBuilderService, WorkspaceMigrationV2IndexActionsBuilderService, WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, + WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService, + WorkspaceMigrationV2CronTriggerActionsBuilderService, FlatViewValidatorService, FlatViewFieldValidatorService, FlatServerlessFunctionValidatorService, + FlatDatabaseEventTriggerValidatorService, + FlatCronTriggerValidatorService, ], exports: [ WorkspaceMigrationBuilderV2Service, @@ -39,6 +47,8 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace- WorkspaceMigrationV2IndexActionsBuilderService, WorkspaceMigrationV2ViewFieldActionsBuilderService, WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, + WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService, + WorkspaceMigrationV2CronTriggerActionsBuilderService, ], }) export class WorkspaceMigrationBuilderV2Module {} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/create-cron-trigger-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/create-cron-trigger-action-handler.service.ts new file mode 100644 index 00000000000..4602871c9cc --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/create-cron-trigger-action-handler.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { CreateCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; + +@Injectable() +export class CreateCronTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'create_cron_trigger', +) { + constructor() { + super(); + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { cronTrigger } = action; + + const cronTriggerRepository = + queryRunner.manager.getRepository(CronTrigger); + + await cronTriggerRepository.insert({ + ...cronTrigger, + workspaceId, + }); + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/delete-cron-trigger-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/delete-cron-trigger-action-handler.service.ts new file mode 100644 index 00000000000..3ed663360f1 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/delete-cron-trigger-action-handler.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { DeleteCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; + +@Injectable() +export class DeleteCronTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'delete_cron_trigger', +) { + constructor() { + super(); + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { cronTriggerId } = action; + + const cronTriggerRepository = + queryRunner.manager.getRepository(CronTrigger); + + await cronTriggerRepository.delete({ + id: cronTriggerId, + workspaceId, + }); + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/update-cron-trigger-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/update-cron-trigger-action-handler.service.ts new file mode 100644 index 00000000000..f720d2db09b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/update-cron-trigger-action-handler.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { CronTrigger } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity'; +import { UpdateCronTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-cron-trigger-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; +import { fromWorkspaceMigrationUpdateActionToPartialEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util'; + +@Injectable() +export class UpdateCronTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'update_cron_trigger', +) { + constructor() { + super(); + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner } = context; + const { cronTriggerId } = action; + + const cronTriggerRepository = + queryRunner.manager.getRepository(CronTrigger); + + await cronTriggerRepository.update( + cronTriggerId, + fromWorkspaceMigrationUpdateActionToPartialEntity(action), + ); + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/create-database-event-trigger-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/create-database-event-trigger-action-handler.service.ts new file mode 100644 index 00000000000..cc21ad5adea --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/create-database-event-trigger-action-handler.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { CreateDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; + +@Injectable() +export class CreateDatabaseEventTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'create_database_event_trigger', +) { + constructor() { + super(); + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { databaseEventTrigger } = action; + + const databaseEventTriggerRepository = + queryRunner.manager.getRepository( + DatabaseEventTrigger, + ); + + await databaseEventTriggerRepository.insert({ + ...databaseEventTrigger, + workspaceId, + }); + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/delete-database-event-trigger-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/delete-database-event-trigger-action-handler.service.ts new file mode 100644 index 00000000000..a385b3c7242 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/delete-database-event-trigger-action-handler.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { DeleteDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; + +@Injectable() +export class DeleteDatabaseEventTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'delete_database_event_trigger', +) { + constructor() { + super(); + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { databaseEventTriggerId } = action; + + const databaseEventTriggerRepository = + queryRunner.manager.getRepository( + DatabaseEventTrigger, + ); + + await databaseEventTriggerRepository.delete({ + id: databaseEventTriggerId, + workspaceId, + }); + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/update-database-event-trigger-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/update-database-event-trigger-action-handler.service.ts new file mode 100644 index 00000000000..9ebb9eb7e16 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/update-database-event-trigger-action-handler.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@nestjs/common'; + +import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { DatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity'; +import { UpdateDatabaseEventTriggerAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-database-event-trigger-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; +import { fromWorkspaceMigrationUpdateActionToPartialEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util'; + +@Injectable() +export class UpdateDatabaseEventTriggerActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'update_database_event_trigger', +) { + constructor() { + super(); + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner } = context; + const { databaseEventTriggerId } = action; + + const databaseEventTriggerRepository = + queryRunner.manager.getRepository( + DatabaseEventTrigger, + ); + + await databaseEventTriggerRepository.update( + databaseEventTriggerId, + fromWorkspaceMigrationUpdateActionToPartialEntity(action), + ); + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts index 03124d77c84..2f66809c7ac 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts @@ -1,6 +1,12 @@ import { Module } from '@nestjs/common'; import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.module'; +import { CreateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/create-cron-trigger-action-handler.service'; +import { DeleteCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/delete-cron-trigger-action-handler.service'; +import { UpdateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/update-cron-trigger-action-handler.service'; +import { CreateDatabaseEventTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/create-database-event-trigger-action-handler.service'; +import { DeleteDatabaseEventTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/delete-database-event-trigger-action-handler.service'; +import { UpdateDatabaseEventTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/database-event-trigger/services/update-database-event-trigger-action-handler.service'; import { CreateFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/create-field-action-handler.service'; import { DeleteFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/delete-field-action-handler.service'; import { UpdateFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/update-field-action-handler.service'; @@ -44,6 +50,14 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor CreateServerlessFunctionActionHandlerService, DeleteServerlessFunctionActionHandlerService, UpdateServerlessFunctionActionHandlerService, + + CreateDatabaseEventTriggerActionHandlerService, + DeleteDatabaseEventTriggerActionHandlerService, + UpdateDatabaseEventTriggerActionHandlerService, + + CreateCronTriggerActionHandlerService, + DeleteCronTriggerActionHandlerService, + UpdateCronTriggerActionHandlerService, ], }) export class WorkspaceSchemaMigrationRunnerActionHandlersModule {} diff --git a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap index f2d279f14c0..db2d90e586c 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap @@ -5,6 +5,8 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [], "serverlessFunction": [], @@ -30,6 +32,8 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -49,6 +53,8 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [], "serverlessFunction": [], @@ -74,6 +80,8 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap index 46a13318386..fa29d0fcfd9 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap @@ -5,6 +5,8 @@ exports[`createOne FieldMetadataService name/label sync should return an error w "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -30,6 +32,8 @@ exports[`createOne FieldMetadataService name/label sync should return an error w }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap index 0ddca359d25..2328f11fb38 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap @@ -6,6 +6,8 @@ exports[`updateOne failing update should not update a field name if it is not sy "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -30,6 +32,8 @@ exports[`updateOne failing update should not update a field name if it is not sy }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -51,6 +55,8 @@ exports[`updateOne failing update should throw if the field name is not availabl "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -81,6 +87,8 @@ exports[`updateOne failing update should throw if the field name is not availabl }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, 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 e3d0e38bbbe..4bbf1d3ee0c 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 @@ -6,6 +6,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -31,6 +33,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -52,6 +56,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -77,6 +83,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -98,6 +106,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -122,6 +132,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -143,6 +155,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -182,6 +196,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -203,6 +219,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -242,6 +260,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -263,6 +283,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -302,6 +324,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -323,6 +347,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -362,6 +388,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -383,6 +411,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -407,6 +437,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -428,6 +460,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -453,6 +487,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -474,6 +510,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -503,6 +541,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -524,6 +564,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -548,6 +590,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -569,6 +613,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -594,6 +640,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -615,6 +663,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -639,6 +689,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -660,6 +712,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -699,6 +753,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -720,6 +776,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -744,6 +802,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -765,6 +825,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -789,6 +851,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -810,6 +874,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -835,6 +901,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -856,6 +924,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -881,6 +951,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -902,6 +974,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -926,6 +1000,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -947,6 +1023,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -972,6 +1050,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -993,6 +1073,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1017,6 +1099,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1038,6 +1122,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1067,6 +1153,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1088,6 +1176,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1112,6 +1202,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1133,6 +1225,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1158,6 +1252,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1179,6 +1275,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1203,6 +1301,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1224,6 +1324,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1253,6 +1355,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1274,6 +1378,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1298,6 +1404,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1319,6 +1427,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1344,6 +1454,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1365,6 +1477,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1389,6 +1503,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1410,6 +1526,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1439,6 +1557,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1460,6 +1580,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1484,6 +1606,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1505,6 +1629,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1529,6 +1655,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1550,6 +1678,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1579,6 +1709,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1600,6 +1732,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1624,6 +1758,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1645,6 +1781,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1669,6 +1807,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1690,6 +1830,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1715,6 +1857,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1736,6 +1880,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1760,6 +1906,8 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1781,6 +1929,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1810,6 +1960,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1831,6 +1983,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1855,6 +2009,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1876,6 +2032,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1900,6 +2058,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1921,6 +2081,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1960,6 +2122,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1981,6 +2145,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2020,6 +2186,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2041,6 +2209,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2080,6 +2250,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2101,6 +2273,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2140,6 +2314,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2161,6 +2337,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2186,6 +2364,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2207,6 +2387,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2236,6 +2418,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2257,6 +2441,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2281,6 +2467,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2302,6 +2490,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2327,6 +2517,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2348,6 +2540,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2372,6 +2566,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2393,6 +2589,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2417,6 +2615,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2438,6 +2638,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2462,6 +2664,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2483,6 +2687,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2508,6 +2714,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2529,6 +2737,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2553,6 +2763,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2574,6 +2786,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2599,6 +2813,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2620,6 +2836,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2644,6 +2862,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2665,6 +2885,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2694,6 +2916,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2715,6 +2939,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2739,6 +2965,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2760,6 +2988,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2785,6 +3015,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2806,6 +3038,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2830,6 +3064,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2851,6 +3087,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2880,6 +3118,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2901,6 +3141,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2925,6 +3167,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2946,6 +3190,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2971,6 +3217,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2992,6 +3240,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3016,6 +3266,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3037,6 +3289,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3066,6 +3320,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3087,6 +3343,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3111,6 +3369,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3132,6 +3392,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3156,6 +3418,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3177,6 +3441,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3206,6 +3472,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3227,6 +3495,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3251,6 +3521,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3272,6 +3544,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3296,6 +3570,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3317,6 +3593,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3342,6 +3620,8 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, 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 186f6864042..d3a36ebd62d 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 @@ -6,6 +6,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -31,6 +33,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -52,6 +56,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -77,6 +83,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -98,6 +106,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -122,6 +132,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -143,6 +155,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -182,6 +196,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -203,6 +219,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -242,6 +260,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -263,6 +283,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -302,6 +324,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -323,6 +347,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -362,6 +388,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -383,6 +411,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -407,6 +437,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -428,6 +460,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -453,6 +487,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -474,6 +510,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -503,6 +541,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -524,6 +564,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -548,6 +590,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -569,6 +613,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -594,6 +640,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -615,6 +663,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -639,6 +689,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -660,6 +712,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -699,6 +753,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -720,6 +776,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -744,6 +802,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -765,6 +825,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -789,6 +851,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -810,6 +874,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -835,6 +901,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -856,6 +924,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -881,6 +951,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -902,6 +974,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -926,6 +1000,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -947,6 +1023,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -972,6 +1050,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -993,6 +1073,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1017,6 +1099,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1038,6 +1122,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1067,6 +1153,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1088,6 +1176,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1112,6 +1202,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1133,6 +1225,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1157,6 +1251,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1178,6 +1274,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1207,6 +1305,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1228,6 +1328,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1252,6 +1354,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1273,6 +1377,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1298,6 +1404,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1319,6 +1427,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1343,6 +1453,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1364,6 +1476,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1393,6 +1507,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1414,6 +1530,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1438,6 +1556,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1459,6 +1579,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1483,6 +1605,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1504,6 +1628,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1533,6 +1659,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1554,6 +1682,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1578,6 +1708,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1599,6 +1731,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1623,6 +1757,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1644,6 +1780,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1668,6 +1806,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1689,6 +1829,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1713,6 +1855,8 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1734,6 +1878,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1763,6 +1909,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1784,6 +1932,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1808,6 +1958,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1829,6 +1981,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1853,6 +2007,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1874,6 +2030,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1913,6 +2071,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1934,6 +2094,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1973,6 +2135,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1994,6 +2158,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2033,6 +2199,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2054,6 +2222,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2093,6 +2263,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2114,6 +2286,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2139,6 +2313,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2160,6 +2336,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2189,6 +2367,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2210,6 +2390,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2234,6 +2416,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2255,6 +2439,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2280,6 +2466,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2301,6 +2489,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2325,6 +2515,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2346,6 +2538,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2370,6 +2564,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2391,6 +2587,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2415,6 +2613,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2436,6 +2636,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2461,6 +2663,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2482,6 +2686,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2506,6 +2712,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2527,6 +2735,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2552,6 +2762,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2573,6 +2785,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2597,6 +2811,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2618,6 +2834,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2647,6 +2865,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2668,6 +2888,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2692,6 +2914,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2713,6 +2937,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2737,6 +2963,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2758,6 +2986,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2787,6 +3017,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2808,6 +3040,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2832,6 +3066,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2853,6 +3089,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2878,6 +3116,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2899,6 +3139,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2923,6 +3165,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2944,6 +3188,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -2973,6 +3219,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2994,6 +3242,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3018,6 +3268,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3039,6 +3291,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3063,6 +3317,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3084,6 +3340,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3113,6 +3371,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3134,6 +3394,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3158,6 +3420,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3179,6 +3443,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3203,6 +3469,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3224,6 +3492,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -3248,6 +3518,8 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap index 467ada0cadc..ced2508fbde 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap @@ -5,6 +5,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -77,6 +79,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -96,6 +100,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -121,6 +127,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -140,6 +148,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -160,6 +170,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -179,6 +191,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -199,6 +213,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -218,6 +234,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -265,6 +283,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -284,6 +304,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -325,6 +347,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -344,6 +368,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -385,6 +411,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -404,6 +432,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -451,6 +481,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -470,6 +502,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -498,6 +532,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -517,6 +553,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -545,6 +583,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -564,6 +604,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -591,6 +633,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -610,6 +654,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -630,6 +676,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -649,6 +697,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -669,6 +719,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -688,6 +740,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -708,6 +762,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -727,6 +783,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -750,6 +808,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -769,6 +829,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -790,6 +852,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -809,6 +873,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -829,6 +895,8 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap index 781041ef555..f70090c476f 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap @@ -6,6 +6,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -31,6 +33,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -52,6 +56,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -77,6 +83,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -98,6 +106,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -129,6 +139,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -150,6 +162,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -175,6 +189,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -196,6 +212,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -227,6 +245,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -248,6 +268,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -274,6 +296,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -295,6 +319,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -321,6 +347,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -342,6 +370,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -367,6 +397,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -388,6 +420,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -429,6 +463,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -450,6 +486,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -476,6 +514,8 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -497,6 +537,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -538,6 +580,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -559,6 +603,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -600,6 +646,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -621,6 +669,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -668,6 +718,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -689,6 +741,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -730,6 +784,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -751,6 +807,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -798,6 +856,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -819,6 +879,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -845,6 +907,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -866,6 +930,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -892,6 +958,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -913,6 +981,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -938,6 +1008,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -959,6 +1031,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -984,6 +1058,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1005,6 +1081,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -1031,6 +1109,8 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap index abb68e0e15f..990849b6f74 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap @@ -6,6 +6,8 @@ exports[`Field metadata relation update should fail relation when name is change "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -45,6 +47,8 @@ exports[`Field metadata relation update should fail relation when name is change }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -66,6 +70,8 @@ exports[`Field metadata relation update should fail relation when name is not in "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -129,6 +135,8 @@ exports[`Field metadata relation update should fail relation when name is not in }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, 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 96e7c153b15..818390a48e3 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 @@ -5,6 +5,8 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -297,6 +299,8 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -316,6 +320,8 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -608,6 +614,8 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -627,6 +635,8 @@ exports[`Object metadata creation should fail v2 when labelPlural is empty 1`] = "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -919,6 +929,8 @@ exports[`Object metadata creation should fail v2 when labelPlural is empty 1`] = }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -938,6 +950,8 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -1230,6 +1244,8 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1249,6 +1265,8 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -1541,6 +1559,8 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1560,6 +1580,8 @@ exports[`Object metadata creation should fail v2 when labelSingular is empty 1`] "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -1852,6 +1874,8 @@ exports[`Object metadata creation should fail v2 when labelSingular is empty 1`] }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -1871,6 +1895,8 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] = "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -2164,6 +2190,8 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] = }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2183,6 +2211,8 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -2476,6 +2506,8 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2495,6 +2527,8 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -2867,6 +2901,8 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -2886,6 +2922,8 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -3178,6 +3216,8 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3197,6 +3237,8 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -3489,6 +3531,8 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3508,6 +3552,8 @@ exports[`Object metadata creation should fail v2 when namePlural is an empty str "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -3805,6 +3851,8 @@ exports[`Object metadata creation should fail v2 when namePlural is an empty str }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -3824,6 +3872,8 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -4121,6 +4171,8 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -4140,6 +4192,8 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -4547,6 +4601,8 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -4566,6 +4622,8 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -4973,6 +5031,8 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -4992,6 +5052,8 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -5364,6 +5426,8 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -5383,6 +5447,8 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -5755,6 +5821,8 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -5774,6 +5842,8 @@ exports[`Object metadata creation should fail v2 when nameSingular is an empty s "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -6181,6 +6251,8 @@ exports[`Object metadata creation should fail v2 when nameSingular is an empty s }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -6200,6 +6272,8 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -6607,6 +6681,8 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -6626,6 +6702,8 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] = "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -6919,6 +6997,8 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] = }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -6938,6 +7018,8 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [ { "errors": [ @@ -7231,6 +7313,8 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, 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 d1d55af5205..c5c2e95c2a0 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 @@ -6,6 +6,8 @@ exports[`Object metadata update should fail when labelIdentifier is not a TEXT o "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -31,6 +33,8 @@ exports[`Object metadata update should fail when labelIdentifier is not a TEXT o }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -52,6 +56,8 @@ exports[`Object metadata update should fail when labelIdentifier is not a known "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -77,6 +83,8 @@ exports[`Object metadata update should fail when labelIdentifier is not a known }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0, @@ -114,6 +122,8 @@ exports[`Object metadata update should fail when labelIdentifier is null 1`] = ` "extensions": { "code": "BAD_USER_INPUT", "errors": { + "cronTrigger": [], + "databaseEventTrigger": [], "index": [], "objectMetadata": [ { @@ -138,6 +148,8 @@ exports[`Object metadata update should fail when labelIdentifier is null 1`] = ` }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { + "invalidCronTrigger": 0, + "invalidDatabaseEventTrigger": 0, "invalidIndex": 0, "invalidObjectMetadata": 0, "invalidServerlessFunction": 0,