From 446e026e0a1a4a210408e46d4c8a3c589465ce09 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Mon, 29 Jul 2024 18:48:35 +0200 Subject: [PATCH 1/3] Add enable workflow trigger endpoint --- .../workspace-query-runner.exception.ts | 2 +- .../engine/core-modules/core-engine.module.ts | 18 ++-- ...gger-graphql-api-exception-handler.util.ts | 23 +++++ .../workflow/workflow-trigger.exception.ts | 14 +++ .../workflow/workflow-trigger.module.ts | 9 ++ .../workflow/workflow-trigger.resolver.ts | 31 ++++++ .../workflow/workflow-trigger.service.ts | 99 +++++++++++++++++++ .../constants/standard-field-ids.ts | 6 ++ .../constants/standard-object-ids.ts | 1 + .../standard-objects/index.ts | 2 + ...orkflow-event-listener.workspace-entity.ts | 57 +++++++++++ .../workflow-version.workspace-entity.ts | 14 +++ .../workflow.workspace-entity.ts | 13 +++ 13 files changed, 280 insertions(+), 9 deletions(-) create mode 100644 packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.exception.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts create mode 100644 packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.service.ts create mode 100644 packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception.ts index e750eec1f4a8..f734e667d1d9 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception.ts @@ -8,7 +8,7 @@ export class WorkspaceQueryRunnerException extends CustomException { } export enum WorkspaceQueryRunnerExceptionCode { - INVALID_QUERY_INPUT = 'INVALID_FIELD_INPUT', + INVALID_QUERY_INPUT = 'INVALID_QUERY_INPUT', DATA_NOT_FOUND = 'DATA_NOT_FOUND', QUERY_TIMEOUT = 'QUERY_TIMEOUT', QUERY_VIOLATES_UNIQUE_CONSTRAINT = 'QUERY_VIOLATES_UNIQUE_CONSTRAINT', diff --git a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts index a8c98201c189..91d7c3e20f30 100644 --- a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts +++ b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts @@ -1,21 +1,22 @@ import { Module } from '@nestjs/common'; -import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; -import { UserModule } from 'src/engine/core-modules/user/user.module'; +import { AISQLQueryModule } from 'src/engine/core-modules/ai-sql-query/ai-sql-query.module'; import { AppTokenModule } from 'src/engine/core-modules/app-token/app-token.module'; import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; -import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { OpenApiModule } from 'src/engine/core-modules/open-api/open-api.module'; -import { TimelineMessagingModule } from 'src/engine/core-modules/messaging/timeline-messaging.module'; -import { TimelineCalendarEventModule } from 'src/engine/core-modules/calendar/timeline-calendar-event.module'; import { BillingModule } from 'src/engine/core-modules/billing/billing.module'; +import { TimelineCalendarEventModule } from 'src/engine/core-modules/calendar/timeline-calendar-event.module'; +import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { HealthModule } from 'src/engine/core-modules/health/health.module'; -import { AISQLQueryModule } from 'src/engine/core-modules/ai-sql-query/ai-sql-query.module'; +import { TimelineMessagingModule } from 'src/engine/core-modules/messaging/timeline-messaging.module'; +import { OpenApiModule } from 'src/engine/core-modules/open-api/open-api.module'; import { PostgresCredentialsModule } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.module'; +import { UserModule } from 'src/engine/core-modules/user/user.module'; +import { WorkflowTriggerModule } from 'src/engine/core-modules/workflow/workflow-trigger.module'; +import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; +import { AnalyticsModule } from './analytics/analytics.module'; import { ClientConfigModule } from './client-config/client-config.module'; import { FileModule } from './file/file.module'; -import { AnalyticsModule } from './analytics/analytics.module'; @Module({ imports: [ @@ -34,6 +35,7 @@ import { AnalyticsModule } from './analytics/analytics.module'; WorkspaceModule, AISQLQueryModule, PostgresCredentialsModule, + WorkflowTriggerModule, ], exports: [ AnalyticsModule, diff --git a/packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts b/packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts new file mode 100644 index 000000000000..09af12eada87 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts @@ -0,0 +1,23 @@ +import { + InternalServerError, + UserInputError, +} from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; +import { + WorkflowTriggerException, + WorkflowTriggerExceptionCode, +} from 'src/engine/core-modules/workflow/workflow-trigger.exception'; + +export const workflowTriggerGraphqlApiExceptionHandler = (error: Error) => { + if (error instanceof WorkflowTriggerException) { + switch (error.code) { + case WorkflowTriggerExceptionCode.INVALID_INPUT: + throw new UserInputError(error.message); + case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_TRIGGER: + case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION: + default: + throw new InternalServerError(error.message); + } + } + + throw error; +}; diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.exception.ts b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.exception.ts new file mode 100644 index 000000000000..d153e827d00a --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.exception.ts @@ -0,0 +1,14 @@ +import { CustomException } from 'src/utils/custom-exception'; + +export class WorkflowTriggerException extends CustomException { + code: WorkflowTriggerExceptionCode; + constructor(message: string, code: WorkflowTriggerExceptionCode) { + super(message, code); + } +} + +export enum WorkflowTriggerExceptionCode { + INVALID_INPUT = 'INVALID_INPUT', + INVALID_WORKFLOW_TRIGGER = 'INVALID_WORKFLOW_TRIGGER', + INVALID_WORKFLOW_VERSION = 'INVALID_WORKFLOW_VERSION', +} diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts new file mode 100644 index 000000000000..66db4e7756cf --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; + +import { WorkflowTriggerResolver } from 'src/engine/core-modules/workflow/workflow-trigger.resolver'; +import { WorkflowTriggerService } from 'src/engine/core-modules/workflow/workflow-trigger.service'; + +@Module({ + providers: [WorkflowTriggerService, WorkflowTriggerResolver], +}) +export class WorkflowTriggerModule {} diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts new file mode 100644 index 000000000000..29501cba2682 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts @@ -0,0 +1,31 @@ +import { UseGuards } from '@nestjs/common'; +import { Args, Mutation, Resolver } from '@nestjs/graphql'; + +import { workflowTriggerGraphqlApiExceptionHandler } from 'src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util'; +import { WorkflowTriggerService } from 'src/engine/core-modules/workflow/workflow-trigger.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; + +@UseGuards(JwtAuthGuard) +@Resolver() +export class WorkflowTriggerResolver { + constructor( + private readonly workflowTriggerService: WorkflowTriggerService, + ) {} + + @Mutation(() => Boolean) + async enableWorkflowTrigger( + @AuthWorkspace() { id: workspaceId }: Workspace, + @Args('workflowVersionId') workflowVersionId: string, + ) { + try { + return await this.workflowTriggerService.enableWorkflowTrigger( + workspaceId, + workflowVersionId, + ); + } catch (error) { + workflowTriggerGraphqlApiExceptionHandler(error); + } + } +} diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.service.ts b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.service.ts new file mode 100644 index 000000000000..c2f2f2f8c26f --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.service.ts @@ -0,0 +1,99 @@ +import { Injectable } from '@nestjs/common'; + +import { + WorkflowTriggerException, + WorkflowTriggerExceptionCode, +} from 'src/engine/core-modules/workflow/workflow-trigger.exception'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity'; +import { + WorkflowInternalEventTrigger, + WorkflowVersionTrigger, + WorkflowVersionTriggerType, + WorkflowVersionWorkspaceEntity, +} from 'src/modules/workflow/standard-objects/workflow-version.workspace-entity'; + +@Injectable() +export class WorkflowTriggerService { + constructor( + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) {} + + async enableWorkflowTrigger(workspaceId: string, workflowVersionId: string) { + const workflowVersionRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'workflowVersion', + ); + + const workflowVersion = await workflowVersionRepository.findOne({ + where: { + id: workflowVersionId, + }, + }); + + if (!workflowVersion) { + throw new WorkflowTriggerException( + 'Workflow version not found', + WorkflowTriggerExceptionCode.INVALID_INPUT, + ); + } + + const trigger = + workflowVersion.trigger as unknown as WorkflowVersionTrigger; + + if (!trigger || !trigger?.type) { + throw new WorkflowTriggerException( + 'Workflow version does not contains trigger', + WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION, + ); + } + + switch (trigger.type) { + case WorkflowVersionTriggerType.INTERNAL_EVENT: + await this.executeInternalEventTrigger( + workspaceId, + workflowVersion.workflowId, + trigger, + ); + break; + default: + break; + } + + return true; + } + + private async executeInternalEventTrigger( + workspaceId: string, + workflowId: string, + trigger: WorkflowInternalEventTrigger, + ) { + const eventName = trigger?.settings?.eventName; + + if (!eventName) { + throw new WorkflowTriggerException( + 'No event name provided in internal event trigger', + WorkflowTriggerExceptionCode.INVALID_WORKFLOW_TRIGGER, + ); + } + + const workflowEventListenerRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'workflowEventListener', + ); + + await workflowEventListenerRepository.delete({ + workflowId, + eventName, + }); + + const workflowEventListener = await workflowEventListenerRepository.create({ + workflowId, + eventName, + }); + + await workflowEventListenerRepository.save(workflowEventListener); + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts index af6e7dd975c4..907f8da7a948 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts @@ -327,10 +327,16 @@ export const WEBHOOK_STANDARD_FIELD_IDS = { operation: '20202020-15b7-458e-bf30-74770a54410c', }; +export const WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS = { + eventName: '20202020-7318-4cf8-a6ac-2de75e3fd97d', + workflow: '20202020-4082-4641-8569-dc08d5365002', +}; + export const WORKFLOW_STANDARD_FIELD_IDS = { name: '20202020-b3d3-478f-acc0-5d901e725b20', publishedVersionId: '20202020-326a-4fba-8639-3456c0a169e8', versions: '20202020-9432-416e-8f3c-27ee3153d099', + eventListeners: '20202020-0229-4c66-832e-035c67579a38', position: '20202020-39b0-4d8c-8c5f-33c2326deb5f', favorites: '20202020-c554-4c41-be7a-cf9cd4b0d512', activityTargets: '20202020-9d65-445a-899d-1c6f1cf3a9ab', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts index 100f4aa3b3f3..4e927c3cd5ed 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts @@ -35,6 +35,7 @@ export const STANDARD_OBJECT_IDS = { view: '20202020-722e-4739-8e2c-0c372d661f49', webhook: '20202020-be4d-4e08-811d-0fffcd13ffd4', workflow: '20202020-62be-406c-b9ca-8caa50d51392', + workflowEventListener: '20202020-92aa-462f-965c-a785b00e9989', workflowVersion: '20202020-d65d-4ab9-9344-d77bfb376a3d', workspaceMember: '20202020-2632-4659-9540-567498166593', }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts index f8e4d410a347..87d8813b2caa 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts @@ -26,6 +26,7 @@ import { ViewFilterWorkspaceEntity } from 'src/modules/view/standard-objects/vie import { ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity'; import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; import { WebhookWorkspaceEntity } from 'src/modules/webhook/standard-objects/webhook.workspace-entity'; +import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity'; import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-version.workspace-entity'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -56,6 +57,7 @@ export const standardObjectMetadataDefinitions = [ ViewWorkspaceEntity, WebhookWorkspaceEntity, WorkflowWorkspaceEntity, + WorkflowEventListenerWorkspaceEntity, WorkflowVersionWorkspaceEntity, WorkspaceMemberWorkspaceEntity, MessageThreadWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts new file mode 100644 index 000000000000..8fb3a8d40057 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts @@ -0,0 +1,57 @@ +import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; + +import { FeatureFlagKeys } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; + +@WorkspaceEntity({ + standardId: STANDARD_OBJECT_IDS.workflowEventListener, + namePlural: 'workflowEventListeners', + labelSingular: 'WorkflowEventListener', + labelPlural: 'WorkflowEventListeners', + description: 'A workflow event listener', + icon: 'IconPhoneCheck', + labelIdentifierStandardId: + WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS.eventName, +}) +@WorkspaceGate({ + featureFlag: FeatureFlagKeys.IsWorkflowEnabled, +}) +@WorkspaceIsSystem() +export class WorkflowEventListenerWorkspaceEntity extends BaseWorkspaceEntity { + @WorkspaceField({ + standardId: WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS.eventName, + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'The workflow event listener name', + icon: 'IconPhoneCheck', + }) + eventName: string; + + // Relations + @WorkspaceRelation({ + standardId: WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS.workflow, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Workflow', + description: 'WorkflowEventListener workflow', + icon: 'IconSettingsAutomation', + inverseSideTarget: () => WorkflowWorkspaceEntity, + inverseSideFieldKey: 'eventListeners', + }) + @WorkspaceIsNullable() + workflow: Relation; + + @WorkspaceJoinColumn('workflow') + workflowId: string; +} diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts index 7c09304f3bd2..3173f6f2b63d 100644 --- a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts @@ -15,6 +15,20 @@ import { WORKFLOW_VERSION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manage import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; +export enum WorkflowVersionTriggerType { + INTERNAL_EVENT = 'INTERNAL_EVENT', +} + +export type WorkflowInternalEventTrigger = { + type: WorkflowVersionTriggerType.INTERNAL_EVENT; + settings: { + eventName: string; + triggerName: string; + }; +}; + +export type WorkflowVersionTrigger = WorkflowInternalEventTrigger; + @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.workflowVersion, namePlural: 'workflowVersions', diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow.workspace-entity.ts index 37f35a15fd5b..d09cdd1f3e0a 100644 --- a/packages/twenty-server/src/modules/workflow/standard-objects/workflow.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow.workspace-entity.ts @@ -19,6 +19,7 @@ import { ActivityTargetWorkspaceEntity } from 'src/modules/activity/standard-obj import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; +import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity'; import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-version.workspace-entity'; @WorkspaceEntity({ @@ -77,6 +78,18 @@ export class WorkflowWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceIsNullable() versions: Relation; + @WorkspaceRelation({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.eventListeners, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Event Listeners', + description: 'Workflow event listeners linked to the workflow.', + icon: 'IconVersions', + inverseSideTarget: () => WorkflowEventListenerWorkspaceEntity, + onDelete: RelationOnDeleteAction.SET_NULL, + }) + @WorkspaceIsNullable() + eventListeners: Relation; + @WorkspaceRelation({ standardId: WORKFLOW_STANDARD_FIELD_IDS.activityTargets, type: RelationMetadataType.ONE_TO_MANY, From 98c83787d4a33f189931d8a892d42eb371bac7f2 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Tue, 30 Jul 2024 12:14:12 +0200 Subject: [PATCH 2/3] Rename event and move into separated module --- ...gger-graphql-api-exception-handler.util.ts | 2 +- .../workflow/workflow-trigger.module.ts | 2 +- .../workflow/workflow-trigger.resolver.ts | 2 +- ...orkflow-event-listener.workspace-entity.ts | 1 - .../workflow-trigger.exception.ts | 0 .../workflow-trigger.service.ts | 25 +++++++++---------- .../workflow-version.workspace-entity.ts | 10 ++++---- 7 files changed, 20 insertions(+), 22 deletions(-) rename packages/twenty-server/src/{engine/core-modules/workflow => modules/workflow/standard-objects/workflow-trigger}/workflow-trigger.exception.ts (100%) rename packages/twenty-server/src/{engine/core-modules/workflow => modules/workflow/standard-objects/workflow-trigger}/workflow-trigger.service.ts (82%) diff --git a/packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts b/packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts index 09af12eada87..be71dca48505 100644 --- a/packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts +++ b/packages/twenty-server/src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util.ts @@ -5,7 +5,7 @@ import { import { WorkflowTriggerException, WorkflowTriggerExceptionCode, -} from 'src/engine/core-modules/workflow/workflow-trigger.exception'; +} from 'src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.exception'; export const workflowTriggerGraphqlApiExceptionHandler = (error: Error) => { if (error instanceof WorkflowTriggerException) { diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts index 66db4e7756cf..a71459f9e1bc 100644 --- a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts +++ b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; import { WorkflowTriggerResolver } from 'src/engine/core-modules/workflow/workflow-trigger.resolver'; -import { WorkflowTriggerService } from 'src/engine/core-modules/workflow/workflow-trigger.service'; +import { WorkflowTriggerService } from 'src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service'; @Module({ providers: [WorkflowTriggerService, WorkflowTriggerResolver], diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts index 29501cba2682..b589bb1aec45 100644 --- a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.resolver.ts @@ -2,10 +2,10 @@ import { UseGuards } from '@nestjs/common'; import { Args, Mutation, Resolver } from '@nestjs/graphql'; import { workflowTriggerGraphqlApiExceptionHandler } from 'src/engine/core-modules/workflow/utils/workflow-trigger-graphql-api-exception-handler.util'; -import { WorkflowTriggerService } from 'src/engine/core-modules/workflow/workflow-trigger.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkflowTriggerService } from 'src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service'; @UseGuards(JwtAuthGuard) @Resolver() diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts index 8fb3a8d40057..2cf07c5f354c 100644 --- a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity.ts @@ -21,7 +21,6 @@ import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/w labelSingular: 'WorkflowEventListener', labelPlural: 'WorkflowEventListeners', description: 'A workflow event listener', - icon: 'IconPhoneCheck', labelIdentifierStandardId: WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS.eventName, }) diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.exception.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.exception.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.exception.ts rename to packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.exception.ts diff --git a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.service.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service.ts similarity index 82% rename from packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.service.ts rename to packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service.ts index c2f2f2f8c26f..380017fed8d5 100644 --- a/packages/twenty-server/src/engine/core-modules/workflow/workflow-trigger.service.ts +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service.ts @@ -1,15 +1,15 @@ import { Injectable } from '@nestjs/common'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity'; import { WorkflowTriggerException, WorkflowTriggerExceptionCode, -} from 'src/engine/core-modules/workflow/workflow-trigger.exception'; -import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; -import { WorkflowEventListenerWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-event-listener.workspace-entity'; +} from 'src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.exception'; import { - WorkflowInternalEventTrigger, - WorkflowVersionTrigger, - WorkflowVersionTriggerType, + WorkflowDatabaseEventTrigger, + WorkflowTrigger, + WorkflowTriggerType, WorkflowVersionWorkspaceEntity, } from 'src/modules/workflow/standard-objects/workflow-version.workspace-entity'; @@ -39,8 +39,7 @@ export class WorkflowTriggerService { ); } - const trigger = - workflowVersion.trigger as unknown as WorkflowVersionTrigger; + const trigger = workflowVersion.trigger as unknown as WorkflowTrigger; if (!trigger || !trigger?.type) { throw new WorkflowTriggerException( @@ -50,8 +49,8 @@ export class WorkflowTriggerService { } switch (trigger.type) { - case WorkflowVersionTriggerType.INTERNAL_EVENT: - await this.executeInternalEventTrigger( + case WorkflowTriggerType.DATABASE_EVENT: + await this.upsertWorkflowEventListener( workspaceId, workflowVersion.workflowId, trigger, @@ -64,16 +63,16 @@ export class WorkflowTriggerService { return true; } - private async executeInternalEventTrigger( + private async upsertWorkflowEventListener( workspaceId: string, workflowId: string, - trigger: WorkflowInternalEventTrigger, + trigger: WorkflowDatabaseEventTrigger, ) { const eventName = trigger?.settings?.eventName; if (!eventName) { throw new WorkflowTriggerException( - 'No event name provided in internal event trigger', + 'No event name provided in database event trigger', WorkflowTriggerExceptionCode.INVALID_WORKFLOW_TRIGGER, ); } diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts index 3173f6f2b63d..27191682432f 100644 --- a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts @@ -15,19 +15,19 @@ import { WORKFLOW_VERSION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manage import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; -export enum WorkflowVersionTriggerType { - INTERNAL_EVENT = 'INTERNAL_EVENT', +export enum WorkflowTriggerType { + DATABASE_EVENT = 'DATABASE_EVENT', } -export type WorkflowInternalEventTrigger = { - type: WorkflowVersionTriggerType.INTERNAL_EVENT; +export type WorkflowDatabaseEventTrigger = { + type: WorkflowTriggerType.DATABASE_EVENT; settings: { eventName: string; triggerName: string; }; }; -export type WorkflowVersionTrigger = WorkflowInternalEventTrigger; +export type WorkflowTrigger = WorkflowDatabaseEventTrigger; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.workflowVersion, From 3c3c333ea66a129a75d19e103cf867ab04953611 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Tue, 30 Jul 2024 13:56:59 +0200 Subject: [PATCH 3/3] Comment on upsert --- .../workflow-trigger/workflow-trigger.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service.ts index 380017fed8d5..7ce804088f40 100644 --- a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service.ts +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-trigger/workflow-trigger.service.ts @@ -83,6 +83,7 @@ export class WorkflowTriggerService { 'workflowEventListener', ); + // TODO: Use upsert when available for workspace entities await workflowEventListenerRepository.delete({ workflowId, eventName,