feat(workflow) - Add validation layer (#21422)
Add workflow validation framework and consolidate output schema types/search logic into twenty-shared This PR introduces a comprehensive workflow validation system that catches configuration errors at build-time, and consolidates the fragmented output-schema type definitions and variable-search logic from the front-end into twenty-shared **Workflow validation** — A new system that checks workflows for errors before activation: graph connectivity (unreachable steps, dangling references), step parameter schemas (via Zod), variable references (typos, wrong step order), and workspace metadata (non-existent objects). Returns structured errors/warnings with "did you mean?" suggestions. Runs automatically after create_complete_workflow and update_workflow_version_step, and is also available as a standalone validate_workflow tool. **Output schema consolidation** — Moves all output schema types and the variable-search logic from scattered front-end files into twenty-shared, replacing ~800 lines of duplicated per-schema-type code with a single unified searchVariableInOutputSchema dispatcher. To do : - validation on CODE and AGENT step --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1
-1
@@ -31,7 +31,7 @@ import {
|
||||
WorkflowStatus,
|
||||
type WorkflowWorkspaceEntity,
|
||||
} from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
WorkflowTriggerException,
|
||||
WorkflowTriggerExceptionCode,
|
||||
|
||||
+2
-4
@@ -1,8 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { computeWorkflowVersionStepChanges } from 'src/modules/workflow/workflow-builder/utils/compute-workflow-version-step-updates.util';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import {
|
||||
type WorkflowTrigger,
|
||||
WorkflowTriggerType,
|
||||
|
||||
+6
-1
@@ -1,11 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
|
||||
import { WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service';
|
||||
|
||||
@Module({
|
||||
imports: [WorkflowCommonModule, FeatureFlagModule],
|
||||
imports: [
|
||||
WorkflowCommonModule,
|
||||
FeatureFlagModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
],
|
||||
providers: [WorkflowSchemaWorkspaceService],
|
||||
exports: [WorkflowSchemaWorkspaceService],
|
||||
})
|
||||
|
||||
+4
-4
@@ -10,10 +10,12 @@ import {
|
||||
navigateOutputSchemaProperty,
|
||||
SingleRecordAvailability,
|
||||
TRIGGER_STEP_ID,
|
||||
WorkflowActionType,
|
||||
} from 'twenty-shared/workflow';
|
||||
|
||||
import { type DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { checkStringIsDatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/utils/check-string-is-database-event-action';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { generateFakeValue } from 'src/engine/utils/generate-fake-value';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { DEFAULT_ITERATOR_CURRENT_ITEM } from 'src/modules/workflow/workflow-builder/workflow-schema/constants/default-iterator-current-item.const';
|
||||
@@ -29,10 +31,7 @@ import { generateFakeObjectRecord } from 'src/modules/workflow/workflow-builder/
|
||||
import { generateFakeObjectRecordEvent } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record-event';
|
||||
import { inferArrayItemSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/infer-array-item-schema';
|
||||
import { type FormFieldMetadata } from 'src/modules/workflow/workflow-executor/workflow-actions/form/types/workflow-form-action-settings.type';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import {
|
||||
WorkflowTrigger,
|
||||
WorkflowTriggerType,
|
||||
@@ -42,6 +41,7 @@ import {
|
||||
export class WorkflowSchemaWorkspaceService {
|
||||
constructor(
|
||||
private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
) {}
|
||||
|
||||
async computeStepOutputSchema({
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { type WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { type WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service';
|
||||
import {
|
||||
type WorkflowAiAgentAction,
|
||||
type WorkflowFindRecordsAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowValidationWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-validation/workflow-validation.workspace-service';
|
||||
|
||||
const WORKSPACE_ID = 'workspace-id';
|
||||
|
||||
const ERROR_HANDLING_OPTIONS = {
|
||||
retryOnFailure: { value: false },
|
||||
continueOnFailure: { value: false },
|
||||
};
|
||||
|
||||
const buildService = (objectIdByNameSingular: Record<string, string> = {}) => {
|
||||
const workflowCommonWorkspaceService = {
|
||||
getWorkflowVersionOrFail: jest.fn(),
|
||||
getFlatEntityMaps: jest.fn().mockResolvedValue({ objectIdByNameSingular }),
|
||||
} as unknown as jest.Mocked<WorkflowCommonWorkspaceService>;
|
||||
|
||||
const workflowSchemaWorkspaceService = {
|
||||
computeStepOutputSchema: jest.fn().mockResolvedValue(undefined),
|
||||
} as unknown as jest.Mocked<WorkflowSchemaWorkspaceService>;
|
||||
|
||||
return new WorkflowValidationWorkspaceService(
|
||||
workflowCommonWorkspaceService,
|
||||
workflowSchemaWorkspaceService,
|
||||
);
|
||||
};
|
||||
|
||||
const buildAiAgentStep = (input: {
|
||||
agentId?: string;
|
||||
prompt?: string;
|
||||
}): WorkflowAiAgentAction => ({
|
||||
id: 'ai-agent-step',
|
||||
name: 'AI Agent',
|
||||
type: WorkflowActionType.AI_AGENT,
|
||||
valid: true,
|
||||
settings: {
|
||||
input,
|
||||
outputSchema: {
|
||||
result: { isLeaf: true, type: 'string', label: 'result', value: '' },
|
||||
},
|
||||
errorHandlingOptions: ERROR_HANDLING_OPTIONS,
|
||||
},
|
||||
});
|
||||
|
||||
const buildFindRecordsStep = (
|
||||
objectName: string,
|
||||
): WorkflowFindRecordsAction => ({
|
||||
id: 'find-records-step',
|
||||
name: 'Find Records',
|
||||
type: WorkflowActionType.FIND_RECORDS,
|
||||
valid: true,
|
||||
settings: {
|
||||
input: { objectName },
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: ERROR_HANDLING_OPTIONS,
|
||||
},
|
||||
});
|
||||
|
||||
describe('WorkflowValidationWorkspaceService', () => {
|
||||
it('should flag an AI Agent step that has no agent selected', async () => {
|
||||
const service = buildService();
|
||||
|
||||
const result = await service.validateWorkflowDefinition({
|
||||
workspaceId: WORKSPACE_ID,
|
||||
trigger: null,
|
||||
steps: [buildAiAgentStep({})],
|
||||
});
|
||||
|
||||
expect(result.errors.map((issue) => issue.code)).toContain(
|
||||
'AI_AGENT_MISSING_AGENT',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not flag an AI Agent step that has an agent selected', async () => {
|
||||
const service = buildService();
|
||||
|
||||
const result = await service.validateWorkflowDefinition({
|
||||
workspaceId: WORKSPACE_ID,
|
||||
trigger: null,
|
||||
steps: [buildAiAgentStep({ agentId: 'agent-1' })],
|
||||
});
|
||||
|
||||
expect(result.errors.map((issue) => issue.code)).not.toContain(
|
||||
'AI_AGENT_MISSING_AGENT',
|
||||
);
|
||||
});
|
||||
|
||||
it('should flag a record step targeting an object that does not exist in the workspace', async () => {
|
||||
const service = buildService({});
|
||||
|
||||
const result = await service.validateWorkflowDefinition({
|
||||
workspaceId: WORKSPACE_ID,
|
||||
trigger: null,
|
||||
steps: [buildFindRecordsStep('ghost')],
|
||||
});
|
||||
|
||||
expect(
|
||||
result.errors.some((issue) =>
|
||||
issue.message.includes('does not exist in this workspace'),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should not flag a record step targeting an existing object', async () => {
|
||||
const service = buildService({ person: 'object-id-1' });
|
||||
|
||||
const result = await service.validateWorkflowDefinition({
|
||||
workspaceId: WORKSPACE_ID,
|
||||
trigger: null,
|
||||
steps: [buildFindRecordsStep('person')],
|
||||
});
|
||||
|
||||
expect(
|
||||
result.errors.some((issue) =>
|
||||
issue.message.includes('does not exist in this workspace'),
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
|
||||
import { WorkflowSchemaModule } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.module';
|
||||
|
||||
import { WorkflowValidationWorkspaceService } from './workflow-validation.workspace-service';
|
||||
|
||||
@Module({
|
||||
imports: [WorkflowCommonModule, WorkflowSchemaModule],
|
||||
providers: [WorkflowValidationWorkspaceService],
|
||||
exports: [WorkflowValidationWorkspaceService],
|
||||
})
|
||||
export class WorkflowValidationModule {}
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isNonEmptyString, isObject, isString } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
validateWorkflowStructure,
|
||||
type WorkflowValidationIssue,
|
||||
type WorkflowValidationResult,
|
||||
WorkflowActionType,
|
||||
} from 'twenty-shared/workflow';
|
||||
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
type WorkflowAiAgentAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
|
||||
const RECORD_CRUD_ACTION_TYPES = new Set<WorkflowActionType>([
|
||||
WorkflowActionType.CREATE_RECORD,
|
||||
WorkflowActionType.UPDATE_RECORD,
|
||||
WorkflowActionType.DELETE_RECORD,
|
||||
WorkflowActionType.UPSERT_RECORD,
|
||||
WorkflowActionType.FIND_RECORDS,
|
||||
]);
|
||||
|
||||
@Injectable()
|
||||
export class WorkflowValidationWorkspaceService {
|
||||
constructor(
|
||||
private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService,
|
||||
private readonly workflowSchemaWorkspaceService: WorkflowSchemaWorkspaceService,
|
||||
) {}
|
||||
|
||||
async validateWorkflowVersion({
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
workflowVersionId: string;
|
||||
}): Promise<WorkflowValidationResult> {
|
||||
const workflowVersion =
|
||||
await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail({
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
});
|
||||
|
||||
return this.validateWorkflowDefinition({
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
trigger: workflowVersion.trigger,
|
||||
steps: workflowVersion.steps,
|
||||
});
|
||||
}
|
||||
|
||||
async validateWorkflowDefinition({
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
trigger,
|
||||
steps,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
workflowVersionId?: string;
|
||||
trigger: WorkflowTrigger | null;
|
||||
steps: WorkflowAction[] | null;
|
||||
}): Promise<WorkflowValidationResult> {
|
||||
const { trigger: enrichedTrigger, steps: enrichedSteps } =
|
||||
await this.enrichOutputSchemas({
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
trigger,
|
||||
steps,
|
||||
});
|
||||
|
||||
const staticResult = validateWorkflowStructure({
|
||||
trigger: enrichedTrigger,
|
||||
steps: enrichedSteps,
|
||||
});
|
||||
|
||||
const semanticIssues = this.validateStepTypeRequirements({
|
||||
steps: enrichedSteps ?? [],
|
||||
});
|
||||
|
||||
const metadataIssues = await this.validateWorkspaceMetadata({
|
||||
workspaceId,
|
||||
steps: enrichedSteps ?? [],
|
||||
});
|
||||
|
||||
return mergeValidationResults(staticResult, [
|
||||
...semanticIssues,
|
||||
...metadataIssues,
|
||||
]);
|
||||
}
|
||||
|
||||
private async enrichOutputSchemas({
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
trigger,
|
||||
steps,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
workflowVersionId?: string;
|
||||
trigger: WorkflowTrigger | null;
|
||||
steps: WorkflowAction[] | null;
|
||||
}): Promise<{
|
||||
trigger: WorkflowTrigger | null;
|
||||
steps: WorkflowAction[] | null;
|
||||
}> {
|
||||
const enrichedTrigger = isDefined(trigger)
|
||||
? await this.withComputedOutputSchema({
|
||||
step: trigger,
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
})
|
||||
: trigger;
|
||||
|
||||
const enrichedSteps = isDefined(steps)
|
||||
? await Promise.all(
|
||||
steps.map((step) =>
|
||||
this.withComputedOutputSchema({
|
||||
step,
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
}),
|
||||
),
|
||||
)
|
||||
: steps;
|
||||
|
||||
return { trigger: enrichedTrigger, steps: enrichedSteps };
|
||||
}
|
||||
|
||||
private async withComputedOutputSchema<
|
||||
TStep extends WorkflowTrigger | WorkflowAction,
|
||||
>({
|
||||
step,
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
}: {
|
||||
step: TStep;
|
||||
workspaceId: string;
|
||||
workflowVersionId?: string;
|
||||
}): Promise<TStep> {
|
||||
try {
|
||||
const computedSchema =
|
||||
await this.workflowSchemaWorkspaceService.computeStepOutputSchema({
|
||||
step,
|
||||
workspaceId,
|
||||
workflowVersionId,
|
||||
});
|
||||
|
||||
if (
|
||||
!isDefined(computedSchema) ||
|
||||
Object.keys(computedSchema).length === 0
|
||||
) {
|
||||
return step;
|
||||
}
|
||||
|
||||
return {
|
||||
...step,
|
||||
settings: { ...step.settings, outputSchema: computedSchema },
|
||||
};
|
||||
} catch {
|
||||
// Output schema enrichment is best-effort: if it cannot be computed,
|
||||
// validation still runs against the step's existing settings rather
|
||||
// than failing the whole validation.
|
||||
return step;
|
||||
}
|
||||
}
|
||||
|
||||
private validateStepTypeRequirements({
|
||||
steps,
|
||||
}: {
|
||||
steps: WorkflowAction[];
|
||||
}): WorkflowValidationIssue[] {
|
||||
const issues: WorkflowValidationIssue[] = [];
|
||||
|
||||
for (const step of steps) {
|
||||
switch (step.type) {
|
||||
case WorkflowActionType.AI_AGENT:
|
||||
issues.push(...this.validateAiAgentStep(step));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
private validateAiAgentStep(
|
||||
step: WorkflowAiAgentAction,
|
||||
): WorkflowValidationIssue[] {
|
||||
const issues: WorkflowValidationIssue[] = [];
|
||||
|
||||
if (!isNonEmptyString(step.settings?.input?.agentId)) {
|
||||
issues.push({
|
||||
severity: 'error',
|
||||
code: 'AI_AGENT_MISSING_AGENT',
|
||||
message: `AI Agent step "${step.name ?? step.id}" has no agent selected.`,
|
||||
stepId: step.id,
|
||||
});
|
||||
}
|
||||
|
||||
const outputSchema = step.settings?.outputSchema;
|
||||
const hasOutputSchema =
|
||||
isDefined(outputSchema) && Object.keys(outputSchema).length > 0;
|
||||
|
||||
if (!hasOutputSchema) {
|
||||
issues.push({
|
||||
severity: 'warning',
|
||||
code: 'AI_AGENT_MISSING_OUTPUT_VARIABLE',
|
||||
message: `AI Agent step "${step.name ?? step.id}" has no output variable defined. Downstream steps won't be able to reference its result.`,
|
||||
stepId: step.id,
|
||||
});
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
private async validateWorkspaceMetadata({
|
||||
workspaceId,
|
||||
steps,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
steps: WorkflowAction[];
|
||||
}): Promise<WorkflowValidationIssue[]> {
|
||||
const recordSteps = steps.filter((step) =>
|
||||
RECORD_CRUD_ACTION_TYPES.has(step.type),
|
||||
);
|
||||
|
||||
if (recordSteps.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { objectIdByNameSingular } =
|
||||
await this.workflowCommonWorkspaceService.getFlatEntityMaps(workspaceId);
|
||||
|
||||
const issues: WorkflowValidationIssue[] = [];
|
||||
|
||||
for (const step of recordSteps) {
|
||||
const input = step.settings.input;
|
||||
const objectName =
|
||||
isObject(input) && 'objectName' in input ? input.objectName : undefined;
|
||||
|
||||
if (!isString(objectName)) {
|
||||
issues.push({
|
||||
severity: 'error',
|
||||
code: 'INVALID_STEP_PARAMS',
|
||||
message: `Step "${step.name ?? step.id}" has an invalid object name.`,
|
||||
stepId: step.id,
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isDefined(objectIdByNameSingular[objectName])) {
|
||||
issues.push({
|
||||
severity: 'error',
|
||||
code: 'INVALID_STEP_PARAMS',
|
||||
message: `Step "${step.name ?? step.id}" targets object "${objectName}" which does not exist in this workspace.`,
|
||||
stepId: step.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
}
|
||||
|
||||
const mergeValidationResults = (
|
||||
baseResult: WorkflowValidationResult,
|
||||
additionalIssues: WorkflowValidationIssue[],
|
||||
): WorkflowValidationResult => {
|
||||
const errors = [
|
||||
...baseResult.errors,
|
||||
...additionalIssues.filter((issue) => issue.severity === 'error'),
|
||||
];
|
||||
const warnings = [
|
||||
...baseResult.warnings,
|
||||
...additionalIssues.filter((issue) => issue.severity === 'warning'),
|
||||
];
|
||||
|
||||
return {
|
||||
valid: errors.length === 0,
|
||||
errors,
|
||||
warnings,
|
||||
};
|
||||
};
|
||||
+2
-5
@@ -1,16 +1,13 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
import { type WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkflowVersionEdgeWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-edge/workflow-version-edge.workspace-service';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowTriggerType } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
|
||||
type MockWorkspaceRepository = Partial<
|
||||
|
||||
+2
-5
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { type WorkflowVersionStepChangesDTO } from 'src/engine/core-modules/workflow/dtos/workflow-version-step-changes.dto';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
@@ -16,10 +16,7 @@ import { assertWorkflowVersionIsDraft } from 'src/modules/workflow/common/utils/
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { computeWorkflowVersionStepChanges } from 'src/modules/workflow/workflow-builder/utils/compute-workflow-version-step-updates.util';
|
||||
import { WorkflowStepConnectionOptions } from 'src/modules/workflow/workflow-builder/workflow-version-step/types/WorkflowStepCreationOptions';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
|
||||
@Injectable()
|
||||
|
||||
+2
-4
@@ -1,6 +1,7 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { SEED_WORKFLOW_ACTION_TRIGGER_SETTINGS } from 'twenty-shared/logic-function';
|
||||
|
||||
import { AiAgentRoleService } from 'src/engine/metadata-modules/ai/ai-agent-role/ai-agent-role.service';
|
||||
@@ -17,10 +18,7 @@ import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/works
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { CodeStepBuildService } from 'src/modules/workflow/workflow-builder/workflow-version-step/code-step/services/code-step-build.service';
|
||||
import { WorkflowVersionStepOperationsWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
const mockWorkspaceId = 'workspace-id';
|
||||
|
||||
|
||||
+2
-5
@@ -1,6 +1,6 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
@@ -13,10 +13,7 @@ import { WorkflowVersionStepHelpersWorkspaceService } from 'src/modules/workflow
|
||||
import { WorkflowVersionStepOperationsWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service';
|
||||
import { WorkflowVersionStepUpdateWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-update.workspace-service';
|
||||
import { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.workspace-service';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowTriggerType } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
|
||||
jest.mock(
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import {
|
||||
extractCodeStepLogicFunctionIdsFromWorkflowSteps,
|
||||
type NonCodeStepForLogicFunctionIdExtraction,
|
||||
} from 'src/modules/workflow/workflow-builder/workflow-version-step/code-step/utils/extract-code-step-logic-function-ids-from-workflow-steps.util';
|
||||
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
const buildCodeStep = (
|
||||
logicFunctionId: string,
|
||||
|
||||
+1
-1
@@ -4,11 +4,11 @@ import {
|
||||
WorkflowVersionStepException,
|
||||
WorkflowVersionStepExceptionCode,
|
||||
} from 'src/modules/workflow/common/exceptions/workflow-version-step.exception';
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { type WorkflowCodeActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/code/types/workflow-code-action-input.type';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
type WorkflowCodeAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
export type CodeStepForLogicFunctionIdExtraction = Pick<
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { type WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
type WorkflowIteratorStepConnectionOptions = {
|
||||
connectedStepType: WorkflowActionType.ITERATOR;
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { insertStep } from 'src/modules/workflow/workflow-builder/workflow-version-step/utils/insert-step';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
type WorkflowIteratorAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import {
|
||||
type WorkflowTrigger,
|
||||
|
||||
+2
-5
@@ -2,13 +2,10 @@
|
||||
// @ts-nocheck
|
||||
// Disabled type checking due to tsgo performance issue with deep spread operations
|
||||
// See: https://github.com/microsoft/typescript-go/issues/2551
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { removeStep } from 'src/modules/workflow/workflow-builder/workflow-version-step/utils/remove-step';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import {
|
||||
type WorkflowTrigger,
|
||||
WorkflowTriggerType,
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import {
|
||||
WorkflowVersionStepException,
|
||||
@@ -7,10 +7,7 @@ import {
|
||||
} from 'src/modules/workflow/common/exceptions/workflow-version-step.exception';
|
||||
import { type WorkflowStepConnectionOptions } from 'src/modules/workflow/workflow-builder/workflow-version-step/types/WorkflowStepCreationOptions';
|
||||
import { type WorkflowIteratorActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/iterator/types/workflow-iterator-action-settings.type';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
|
||||
export const insertStep = ({
|
||||
|
||||
+1
-1
@@ -3,13 +3,13 @@ import {
|
||||
IF_ELSE_BRANCH_POSITION_OFFSETS,
|
||||
TRIGGER_STEP_ID,
|
||||
type StepIfElseBranch,
|
||||
WorkflowActionType,
|
||||
} from 'twenty-shared/workflow';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { isWorkflowEmptyAction } from 'src/modules/workflow/workflow-executor/workflow-actions/empty/guards/is-workflow-empty-action.guard';
|
||||
import { isWorkflowIfElseAction } from 'src/modules/workflow/workflow-executor/workflow-actions/if-else/guards/is-workflow-if-else-action.guard';
|
||||
import {
|
||||
WorkflowActionType,
|
||||
type WorkflowAction,
|
||||
type WorkflowIteratorAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
+1
-1
@@ -12,6 +12,7 @@ import {
|
||||
IF_ELSE_BRANCH_POSITION_OFFSETS,
|
||||
getFunctionInputFromInputSchema,
|
||||
type StepIfElseBranch,
|
||||
WorkflowActionType,
|
||||
} from 'twenty-shared/workflow';
|
||||
import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
@@ -44,7 +45,6 @@ import { type OutputSchema } from 'src/modules/workflow/workflow-builder/workflo
|
||||
import { CodeStepBuildService } from 'src/modules/workflow/workflow-builder/workflow-version-step/code-step/services/code-step-build.service';
|
||||
import { type BaseWorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type';
|
||||
import {
|
||||
WorkflowActionType,
|
||||
type WorkflowAction,
|
||||
type WorkflowEmptyAction,
|
||||
type WorkflowFormAction,
|
||||
|
||||
+2
-5
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { WithLock } from 'src/engine/core-modules/cache-lock/with-lock.decorator';
|
||||
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
|
||||
@@ -25,10 +25,7 @@ import { assertWorkflowVersionIsDraft } from 'src/modules/workflow/common/utils/
|
||||
import { assertWorkflowVersionTriggerIsDefined } from 'src/modules/workflow/common/utils/assert-workflow-version-trigger-is-defined.util';
|
||||
import { WorkflowVersionStepOperationsWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service';
|
||||
import { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.workspace-service';
|
||||
import {
|
||||
WorkflowActionType,
|
||||
type WorkflowAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
@Injectable()
|
||||
export class WorkflowVersionWorkspaceService {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import { DeleteRecordWorkflowAction } from 'src/modules/workflow/workflow-execut
|
||||
import { FindRecordsWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action';
|
||||
import { UpdateRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action';
|
||||
import { UpsertRecordWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/upsert-record.workflow-action';
|
||||
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
@Injectable()
|
||||
export class WorkflowActionFactory {
|
||||
|
||||
+2
-5
@@ -1,10 +1,7 @@
|
||||
import { StepStatus } from 'twenty-shared/workflow';
|
||||
import { StepStatus, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { shouldExecuteChildStep } from 'src/modules/workflow/workflow-executor/utils/should-execute-child-step.util';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
describe('shouldExecuteChildStep', () => {
|
||||
const parentSteps = [
|
||||
|
||||
+2
-5
@@ -1,4 +1,4 @@
|
||||
import { StepStatus } from 'twenty-shared/workflow';
|
||||
import { StepStatus, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { WorkflowRunStatus } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
|
||||
import {
|
||||
@@ -6,10 +6,7 @@ import {
|
||||
createMockIfElseStep,
|
||||
} from 'src/modules/workflow/workflow-executor/utils/create-mock-workflow-steps.util';
|
||||
import { shouldExecuteStep } from 'src/modules/workflow/workflow-executor/utils/should-execute-step.util';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
describe('shouldExecuteStep', () => {
|
||||
const steps = [
|
||||
|
||||
+4
-2
@@ -1,10 +1,12 @@
|
||||
import { type StepIfElseBranch } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type StepIfElseBranch,
|
||||
WorkflowActionType,
|
||||
} from 'twenty-shared/workflow';
|
||||
|
||||
import { type WorkflowCodeActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/code/types/workflow-code-action-settings.type';
|
||||
import { type WorkflowIfElseActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/if-else/types/workflow-if-else-action-settings.type';
|
||||
import { type WorkflowIteratorActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/iterator/types/workflow-iterator-action-settings.type';
|
||||
import {
|
||||
WorkflowActionType,
|
||||
type WorkflowCodeAction,
|
||||
type WorkflowIfElseAction,
|
||||
type WorkflowIteratorAction,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowAiAgentAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowCodeAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowDelayAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+2
-4
@@ -1,7 +1,5 @@
|
||||
import {
|
||||
WorkflowActionType,
|
||||
type WorkflowAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
export const isWorkflowEmptyAction = (
|
||||
action: WorkflowAction,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowFilterAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowFormAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+2
-4
@@ -1,12 +1,10 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { HttpTool } from 'src/engine/core-modules/tool/tools/http-tool/http-tool';
|
||||
import { HttpRequestWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/http-request/http-request.workflow-action';
|
||||
import { type WorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowRunStepLogWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run-step-log.workspace-service';
|
||||
|
||||
const baseSettings: WorkflowActionSettings = {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowHttpRequestAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowIfElseAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+2
-5
@@ -1,15 +1,12 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { StepStatus } from 'twenty-shared/workflow';
|
||||
import { StepStatus, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { WorkflowStepExecutorException } from 'src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception';
|
||||
import { IteratorWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/iterator/iterator.workflow-action';
|
||||
import { type WorkflowIteratorActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/iterator/types/workflow-iterator-action-settings.type';
|
||||
import { type WorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service';
|
||||
|
||||
describe('IteratorWorkflowAction', () => {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowIteratorAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+2
-4
@@ -1,7 +1,5 @@
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
export const isWorkflowLogicFunctionAction = (
|
||||
action: WorkflowAction,
|
||||
|
||||
+2
-4
@@ -1,12 +1,10 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { DraftEmailTool } from 'src/engine/core-modules/tool/tools/email-tool/draft-email-tool';
|
||||
import { DraftEmailWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/mail-sender/draft-email.workflow-action';
|
||||
import { type WorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowRunStepLogWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run-step-log.workspace-service';
|
||||
|
||||
jest.mock(
|
||||
|
||||
+2
-4
@@ -1,12 +1,10 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { SendEmailTool } from 'src/engine/core-modules/tool/tools/email-tool/send-email-tool';
|
||||
import { SendEmailWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/mail-sender/send-email.workflow-action';
|
||||
import { type WorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowRunStepLogWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run-step-log.workspace-service';
|
||||
|
||||
jest.mock(
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowDraftEmailAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowSendEmailAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowDeleteRecordAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowFindRecordsAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowUpdateRecordAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
type WorkflowUpsertRecordAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
|
||||
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
export enum WorkflowActionType {
|
||||
CODE = 'CODE',
|
||||
LOGIC_FUNCTION = 'LOGIC_FUNCTION',
|
||||
SEND_EMAIL = 'SEND_EMAIL',
|
||||
DRAFT_EMAIL = 'DRAFT_EMAIL',
|
||||
CREATE_RECORD = 'CREATE_RECORD',
|
||||
UPDATE_RECORD = 'UPDATE_RECORD',
|
||||
DELETE_RECORD = 'DELETE_RECORD',
|
||||
UPSERT_RECORD = 'UPSERT_RECORD',
|
||||
FIND_RECORDS = 'FIND_RECORDS',
|
||||
FORM = 'FORM',
|
||||
FILTER = 'FILTER',
|
||||
IF_ELSE = 'IF_ELSE',
|
||||
HTTP_REQUEST = 'HTTP_REQUEST',
|
||||
AI_AGENT = 'AI_AGENT',
|
||||
ITERATOR = 'ITERATOR',
|
||||
EMPTY = 'EMPTY',
|
||||
DELAY = 'DELAY',
|
||||
}
|
||||
+2
-6
@@ -1,3 +1,5 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
|
||||
import { type WorkflowAiAgentActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/ai-agent/types/workflow-ai-agent-action-settings.type';
|
||||
import { type WorkflowCodeActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/code/types/workflow-code-action-settings.type';
|
||||
import { type WorkflowDelayActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/delay/types/workflow-delay-action-settings.type';
|
||||
@@ -17,12 +19,6 @@ import {
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-settings.type';
|
||||
import { type WorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type';
|
||||
|
||||
// Import the enum from its dedicated file to avoid circular dependencies
|
||||
import { WorkflowActionType } from './workflow-action-type.enum';
|
||||
|
||||
// Re-export for consumers
|
||||
export { WorkflowActionType };
|
||||
|
||||
type BaseWorkflowAction = {
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
+6
-5
@@ -1,6 +1,10 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { getWorkflowRunContext, StepStatus } from 'twenty-shared/workflow';
|
||||
import {
|
||||
getWorkflowRunContext,
|
||||
StepStatus,
|
||||
WorkflowActionType,
|
||||
} from 'twenty-shared/workflow';
|
||||
|
||||
import { BillingUsageService } from 'src/engine/core-modules/billing/services/billing-usage.service';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
@@ -17,10 +21,7 @@ import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/fa
|
||||
import { shouldExecuteStep } from 'src/modules/workflow/workflow-executor/utils/should-execute-step.util';
|
||||
import { shouldFailSafely } from 'src/modules/workflow/workflow-executor/utils/should-fail-safely.util';
|
||||
import { shouldSkipStepExecution } from 'src/modules/workflow/workflow-executor/utils/should-skip-step-execution.util';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service';
|
||||
import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service';
|
||||
|
||||
|
||||
+6
@@ -8,6 +8,7 @@ import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadat
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
|
||||
import { WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service';
|
||||
import { WorkflowValidationWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-validation/workflow-validation.workspace-service';
|
||||
import { WorkflowVersionEdgeWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-edge/workflow-version-edge.workspace-service';
|
||||
import { WorkflowVersionStepHelpersWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-helpers.workspace-service';
|
||||
import { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.workspace-service';
|
||||
@@ -27,6 +28,7 @@ import { createUpdateLogicFunctionSourceTool } from 'src/modules/workflow/workfl
|
||||
import { createUpdateWorkflowVersionPositionsTool } from 'src/modules/workflow/workflow-tools/tools/update-workflow-version-positions.tool';
|
||||
import { createUpdateWorkflowVersionStepTool } from 'src/modules/workflow/workflow-tools/tools/update-workflow-version-step.tool';
|
||||
import { createUpdateWorkflowVersionTriggerTool } from 'src/modules/workflow/workflow-tools/tools/update-workflow-version-trigger.tool';
|
||||
import { createValidateWorkflowTool } from 'src/modules/workflow/workflow-tools/tools/validate-workflow.tool';
|
||||
import { type WorkflowToolDependencies } from 'src/modules/workflow/workflow-tools/types/workflow-tool-dependencies.type';
|
||||
import { WorkflowTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service';
|
||||
|
||||
@@ -41,6 +43,7 @@ export class WorkflowToolWorkspaceService {
|
||||
workflowVersionService: WorkflowVersionWorkspaceService,
|
||||
workflowTriggerService: WorkflowTriggerWorkspaceService,
|
||||
workflowSchemaService: WorkflowSchemaWorkspaceService,
|
||||
workflowValidationService: WorkflowValidationWorkspaceService,
|
||||
globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
recordPositionService: RecordPositionService,
|
||||
logicFunctionFromSourceService: LogicFunctionFromSourceService,
|
||||
@@ -53,6 +56,7 @@ export class WorkflowToolWorkspaceService {
|
||||
workflowVersionService,
|
||||
workflowTriggerService,
|
||||
workflowSchemaService,
|
||||
workflowValidationService,
|
||||
globalWorkspaceOrmManager,
|
||||
recordPositionService,
|
||||
logicFunctionFromSourceService,
|
||||
@@ -124,6 +128,7 @@ export class WorkflowToolWorkspaceService {
|
||||
this.deps,
|
||||
context,
|
||||
);
|
||||
const validateWorkflow = createValidateWorkflowTool(this.deps, context);
|
||||
|
||||
return {
|
||||
[createCompleteWorkflow.name]: createCompleteWorkflow,
|
||||
@@ -141,6 +146,7 @@ export class WorkflowToolWorkspaceService {
|
||||
[getWorkflowCurrentVersion.name]: getWorkflowCurrentVersion,
|
||||
[updateLogicFunctionSource.name]: updateLogicFunctionSource,
|
||||
[listLogicFunctionTools.name]: listLogicFunctionTools,
|
||||
[validateWorkflow.name]: validateWorkflow,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -7,12 +7,12 @@ import { z } from 'zod';
|
||||
|
||||
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
import { WorkflowVersionStatus } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
|
||||
import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import {
|
||||
WorkflowVersionStepException,
|
||||
WorkflowVersionStepExceptionCode,
|
||||
} from 'src/modules/workflow/common/exceptions/workflow-version-step.exception';
|
||||
import { WorkflowVersionStatus } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
|
||||
import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import {
|
||||
type WorkflowToolContext,
|
||||
@@ -70,6 +70,7 @@ type CreateCompleteWorkflowToolDeps = Pick<
|
||||
| 'workflowTriggerService'
|
||||
| 'globalWorkspaceOrmManager'
|
||||
| 'recordPositionService'
|
||||
| 'workflowValidationService'
|
||||
>;
|
||||
|
||||
type CreateCompleteWorkflowToolContext = WorkflowToolContext & {
|
||||
@@ -182,6 +183,13 @@ This is the most efficient way for AI to create workflows as it handles all the
|
||||
});
|
||||
}
|
||||
|
||||
const validation =
|
||||
await deps.workflowValidationService.validateWorkflowDefinition({
|
||||
workspaceId: context.workspaceId,
|
||||
trigger: parameters.trigger,
|
||||
steps: parameters.steps,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `Workflow "${parameters.name}" created successfully with ${parameters.steps.length} steps`,
|
||||
@@ -191,6 +199,7 @@ This is the most efficient way for AI to create workflows as it handles all the
|
||||
name: parameters.name,
|
||||
trigger: parameters.trigger,
|
||||
steps: parameters.steps,
|
||||
validation,
|
||||
},
|
||||
recordReferences: [
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-type.enum';
|
||||
import {
|
||||
type WorkflowToolContext,
|
||||
type WorkflowToolDependencies,
|
||||
|
||||
+2
-3
@@ -1,10 +1,9 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
|
||||
import { TRIGGER_STEP_ID, WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { CreateWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/create-workflow-version-step.input';
|
||||
import { type WorkflowVersionStepChangesDTO } from 'src/engine/core-modules/workflow/dtos/workflow-version-step-changes.dto';
|
||||
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-type.enum';
|
||||
import {
|
||||
type WorkflowToolContext,
|
||||
type WorkflowToolDependencies,
|
||||
@@ -85,7 +84,7 @@ const enrichResultWithNextStep = ({
|
||||
return {
|
||||
...result,
|
||||
nextStep:
|
||||
'This CODE step was created with a default placeholder function. You MUST now call update_logic_function_source with the logicFunctionId from this step to define the actual code.',
|
||||
'This CODE step was created with a default placeholder function. You MUST now call update_logic_function_source with the logicFunctionId from this step to define the actual code. IMPORTANT: Also provide outputSchema (an example return value, e.g. { datePlus7: "2026-06-16" }) so downstream steps can reference this step\'s output variables via {{stepId.fieldName}}.',
|
||||
};
|
||||
default:
|
||||
return result;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-type.enum';
|
||||
import {
|
||||
type WorkflowToolContext,
|
||||
type WorkflowToolDependencies,
|
||||
|
||||
+25
-2
@@ -18,7 +18,10 @@ const updateWorkflowVersionStepSchema = z.object({
|
||||
});
|
||||
|
||||
export const createUpdateWorkflowVersionStepTool = (
|
||||
deps: Pick<WorkflowToolDependencies, 'workflowVersionStepService'>,
|
||||
deps: Pick<
|
||||
WorkflowToolDependencies,
|
||||
'workflowVersionStepService' | 'workflowValidationService'
|
||||
>,
|
||||
context: WorkflowToolContext,
|
||||
) => ({
|
||||
name: 'update_workflow_version_step' as const,
|
||||
@@ -26,8 +29,10 @@ export const createUpdateWorkflowVersionStepTool = (
|
||||
'Update an existing step in a workflow version. This modifies the step configuration.',
|
||||
inputSchema: updateWorkflowVersionStepSchema,
|
||||
execute: async (parameters: UpdateWorkflowVersionStepInput) => {
|
||||
let result;
|
||||
|
||||
try {
|
||||
return await deps.workflowVersionStepService.updateWorkflowVersionStep({
|
||||
result = await deps.workflowVersionStepService.updateWorkflowVersionStep({
|
||||
workspaceId: context.workspaceId,
|
||||
workflowVersionId: parameters.workflowVersionId,
|
||||
step: parameters.step,
|
||||
@@ -39,5 +44,23 @@ export const createUpdateWorkflowVersionStepTool = (
|
||||
message: `Failed to update workflow version step: ${error.message}`,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const validation =
|
||||
await deps.workflowValidationService.validateWorkflowVersion({
|
||||
workspaceId: context.workspaceId,
|
||||
workflowVersionId: parameters.workflowVersionId,
|
||||
});
|
||||
return {
|
||||
...result,
|
||||
validation,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
...result,
|
||||
validationError: error.message,
|
||||
message: `Step updated successfully, but validation could not be computed: ${error.message}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { type WorkflowValidationWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-validation/workflow-validation.workspace-service';
|
||||
import { type WorkflowToolContext } from 'src/modules/workflow/workflow-tools/types/workflow-tool-dependencies.type';
|
||||
|
||||
const validateWorkflowSchema = z.object({
|
||||
workflowVersionId: z
|
||||
.string()
|
||||
.uuid()
|
||||
.describe('The UUID of the workflow version to validate'),
|
||||
});
|
||||
|
||||
type ValidateWorkflowInput = z.infer<typeof validateWorkflowSchema>;
|
||||
|
||||
export const createValidateWorkflowTool = (
|
||||
deps: {
|
||||
workflowValidationService: WorkflowValidationWorkspaceService;
|
||||
},
|
||||
context: WorkflowToolContext,
|
||||
) => ({
|
||||
name: 'validate_workflow' as const,
|
||||
description:
|
||||
'Validate a workflow version for correctness. Checks graph topology (connections, reachability, branches, loops), per-step configuration, references to other objects, and variable references between steps. Returns a list of errors and warnings to fix. Does not block or modify the workflow.',
|
||||
inputSchema: validateWorkflowSchema,
|
||||
execute: async (parameters: ValidateWorkflowInput) => {
|
||||
try {
|
||||
const result =
|
||||
await deps.workflowValidationService.validateWorkflowVersion({
|
||||
workspaceId: context.workspaceId,
|
||||
workflowVersionId: parameters.workflowVersionId,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
valid: result.valid,
|
||||
errors: result.errors,
|
||||
warnings: result.warnings,
|
||||
message: result.valid
|
||||
? 'The workflow is valid.'
|
||||
: `The workflow has ${result.errors.length} error(s) that should be fixed.`,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
message: `Failed to validate workflow: ${error.message}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
+2
@@ -3,6 +3,7 @@ import type { LogicFunctionFromSourceService } from 'src/engine/metadata-modules
|
||||
import type { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import type { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import type { WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service';
|
||||
import type { WorkflowValidationWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-validation/workflow-validation.workspace-service';
|
||||
import type { WorkflowVersionEdgeWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-edge/workflow-version-edge.workspace-service';
|
||||
import type { WorkflowVersionStepHelpersWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-helpers.workspace-service';
|
||||
import type { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.workspace-service';
|
||||
@@ -16,6 +17,7 @@ export type WorkflowToolDependencies = {
|
||||
workflowVersionService: WorkflowVersionWorkspaceService;
|
||||
workflowTriggerService: WorkflowTriggerWorkspaceService;
|
||||
workflowSchemaService: WorkflowSchemaWorkspaceService;
|
||||
workflowValidationService: WorkflowValidationWorkspaceService;
|
||||
globalWorkspaceOrmManager: GlobalWorkspaceOrmManager;
|
||||
recordPositionService: RecordPositionService;
|
||||
logicFunctionFromSourceService: LogicFunctionFromSourceService;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { WORKFLOW_TOOL_SERVICE_TOKEN } from 'src/engine/core-modules/tool-provid
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { LogicFunctionModule } from 'src/engine/metadata-modules/logic-function/logic-function.module';
|
||||
import { WorkflowSchemaModule } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.module';
|
||||
import { WorkflowValidationModule } from 'src/modules/workflow/workflow-builder/workflow-validation/workflow-validation.module';
|
||||
import { WorkflowVersionEdgeModule } from 'src/modules/workflow/workflow-builder/workflow-version-edge/workflow-version-edge.module';
|
||||
import { WorkflowVersionStepModule } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.module';
|
||||
import { WorkflowVersionModule } from 'src/modules/workflow/workflow-builder/workflow-version/workflow-version.module';
|
||||
@@ -22,6 +23,7 @@ import { WorkflowToolWorkspaceService } from './services/workflow-tool.workspace
|
||||
WorkflowVersionModule,
|
||||
WorkflowTriggerModule,
|
||||
WorkflowSchemaModule,
|
||||
WorkflowValidationModule,
|
||||
RecordPositionModule,
|
||||
LogicFunctionModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
|
||||
+2
-4
@@ -4,11 +4,9 @@ import {
|
||||
WorkflowVersionStatus,
|
||||
type WorkflowVersionWorkspaceEntity,
|
||||
} from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
|
||||
import { WorkflowActionType } from 'twenty-shared/workflow';
|
||||
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import {
|
||||
type WorkflowAction,
|
||||
WorkflowActionType,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import {
|
||||
WorkflowTriggerException,
|
||||
WorkflowTriggerExceptionCode,
|
||||
|
||||
Reference in New Issue
Block a user