UNPKG

n8n

Version:

n8n Workflow Automation Tool

661 lines 32 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WorkflowService = void 0; const backend_common_1 = require("@n8n/backend-common"); const config_1 = require("@n8n/config"); const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const typeorm_1 = require("@n8n/typeorm"); const isEqual_1 = __importDefault(require("lodash/isEqual")); const pick_1 = __importDefault(require("lodash/pick")); const n8n_core_1 = require("n8n-core"); const n8n_workflow_1 = require("n8n-workflow"); const uuid_1 = require("uuid"); const workflow_finder_service_1 = require("./workflow-finder.service"); const workflow_history_service_1 = require("./workflow-history/workflow-history.service"); const workflow_sharing_service_1 = require("./workflow-sharing.service"); const active_workflow_manager_1 = require("../active-workflow-manager"); const folder_not_found_error_1 = require("../errors/folder-not-found.error"); const bad_request_error_1 = require("../errors/response-errors/bad-request.error"); const not_found_error_1 = require("../errors/response-errors/not-found.error"); const workflow_validation_error_1 = require("../errors/response-errors/workflow-validation.error"); const workflow_history_version_not_found_error_1 = require("../errors/workflow-history-version-not-found.error"); const event_service_1 = require("../events/event.service"); const external_hooks_1 = require("../external-hooks"); const generic_helpers_1 = require("../generic-helpers"); const node_types_1 = require("../node-types"); const requests_1 = require("../requests"); const ownership_service_1 = require("../services/ownership.service"); const project_service_ee_1 = require("../services/project.service.ee"); const role_service_1 = require("../services/role.service"); const tag_service_1 = require("../services/tag.service"); const WorkflowHelpers = __importStar(require("../workflow-helpers")); const workflow_validation_service_1 = require("./workflow-validation.service"); let WorkflowService = class WorkflowService { constructor(logger, sharedWorkflowRepository, workflowRepository, workflowTagMappingRepository, binaryDataService, ownershipService, tagService, workflowHistoryService, externalHooks, activeWorkflowManager, roleService, workflowSharingService, projectService, executionRepository, eventService, globalConfig, folderRepository, workflowFinderService, workflowPublishHistoryRepository, workflowValidationService, nodeTypes) { this.logger = logger; this.sharedWorkflowRepository = sharedWorkflowRepository; this.workflowRepository = workflowRepository; this.workflowTagMappingRepository = workflowTagMappingRepository; this.binaryDataService = binaryDataService; this.ownershipService = ownershipService; this.tagService = tagService; this.workflowHistoryService = workflowHistoryService; this.externalHooks = externalHooks; this.activeWorkflowManager = activeWorkflowManager; this.roleService = roleService; this.workflowSharingService = workflowSharingService; this.projectService = projectService; this.executionRepository = executionRepository; this.eventService = eventService; this.globalConfig = globalConfig; this.folderRepository = folderRepository; this.workflowFinderService = workflowFinderService; this.workflowPublishHistoryRepository = workflowPublishHistoryRepository; this.workflowValidationService = workflowValidationService; this.nodeTypes = nodeTypes; } async getMany(user, options, includeScopes, includeFolders, onlySharedWithMe, requiredScopes = ['workflow:read']) { let count; let workflows; let workflowsAndFolders = []; let sharedWorkflowIds = []; let isPersonalProject = false; if (options?.filter?.projectId) { const projects = await this.projectService.getProjectRelationsForUser(user); isPersonalProject = !!projects.find((p) => p.project.id === options.filter?.projectId && p.project.type === 'personal'); } if (isPersonalProject) { sharedWorkflowIds = await this.workflowSharingService.getOwnedWorkflowsInPersonalProject(user); } else if (onlySharedWithMe) { sharedWorkflowIds = await this.workflowSharingService.getSharedWithMeIds(user); } else { sharedWorkflowIds = await this.workflowSharingService.getSharedWorkflowIds(user, { scopes: requiredScopes, }); } if (includeFolders) { [workflowsAndFolders, count] = await this.workflowRepository.getWorkflowsAndFoldersWithCount(sharedWorkflowIds, options); workflows = workflowsAndFolders.filter((wf) => wf.resource === 'workflow'); } else { ({ workflows, count } = await this.workflowRepository.getManyAndCount(sharedWorkflowIds, options)); } if ((0, requests_1.hasSharing)(workflows)) { workflows = await this.processSharedWorkflows(workflows, options); } if (includeScopes) { workflows = await this.addUserScopes(workflows, user); } this.cleanupSharedField(workflows); if (includeFolders) { workflows = this.mergeProcessedWorkflows(workflowsAndFolders, workflows); } return { workflows, count, }; } async processSharedWorkflows(workflows, options) { const projectId = options?.filter?.projectId; const shouldAddProjectRelations = typeof projectId === 'string' && projectId !== ''; if (shouldAddProjectRelations) { await this.addSharedRelation(workflows); } return workflows.map((workflow) => this.ownershipService.addOwnedByAndSharedWith(workflow)); } async addSharedRelation(workflows) { const workflowIds = workflows.map((workflow) => workflow.id); const relations = await this.sharedWorkflowRepository.getAllRelationsForWorkflows(workflowIds); workflows.forEach((workflow) => { workflow.shared = relations.filter((relation) => relation.workflowId === workflow.id); }); } async addUserScopes(workflows, user) { const projectRelations = await this.projectService.getProjectRelationsForUser(user); return workflows.map((workflow) => this.roleService.addScopes(workflow, user, projectRelations)); } cleanupSharedField(workflows) { workflows.forEach((workflow) => { delete workflow.shared; }); } mergeProcessedWorkflows(workflowsAndFolders, processedWorkflows) { const workflowMap = new Map(processedWorkflows.map((workflow) => [workflow.id, workflow])); return workflowsAndFolders.map((item) => item.resource === 'workflow' ? (workflowMap.get(item.id) ?? item) : item); } async update(user, workflowUpdateData, workflowId, options = {}) { const { expectedChecksum, tagIds, parentFolderId, forceSave = false, publicApi = false, publishIfActive = false, aiBuilderAssisted = false, autosaved = false, } = options; const workflow = await this.workflowFinderService.findWorkflowForUser(workflowId, user, ['workflow:update'], { includeActiveVersion: true }); if (!workflow) { this.logger.warn('User attempted to update a workflow without permissions', { workflowId, userId: user.id, }); throw new not_found_error_1.NotFoundError('You do not have permission to update this workflow. Ask the owner to share it with you.'); } if (!forceSave && expectedChecksum) { await this._detectConflicts(workflow, expectedChecksum); } const saveNewVersion = ('nodes' in workflowUpdateData && !(0, isEqual_1.default)(workflowUpdateData.nodes, workflow.nodes)) || ('connections' in workflowUpdateData && !(0, isEqual_1.default)(workflowUpdateData.connections, workflow.connections)); if (saveNewVersion) { workflowUpdateData.versionId = (0, uuid_1.v4)(); this.logger.debug(`Updating versionId for workflow ${workflowId} for user ${user.id} after saving`, { previousVersionId: workflow.versionId, newVersionId: workflowUpdateData.versionId, }); workflowUpdateData.nodes = workflowUpdateData.nodes ?? workflow.nodes; workflowUpdateData.connections = workflowUpdateData.connections ?? workflow.connections; } else { workflowUpdateData.versionId = workflow.versionId; } await WorkflowHelpers.replaceInvalidCredentials(workflowUpdateData); WorkflowHelpers.addNodeIds(workflowUpdateData); if (workflowUpdateData.settings && workflow.settings) { workflowUpdateData.settings = { ...workflow.settings, ...workflowUpdateData.settings, }; } const settingsChanged = workflowUpdateData.settings !== undefined && !(0, isEqual_1.default)(workflow.settings, workflowUpdateData.settings); await this.externalHooks.run('workflow.update', [workflowUpdateData]); const workflowSettings = workflowUpdateData.settings ?? {}; const keysAllowingDefault = [ 'timezone', 'saveDataErrorExecution', 'saveDataSuccessExecution', 'saveManualExecutions', 'saveExecutionProgress', ]; for (const key of keysAllowingDefault) { if (workflowSettings[key] === 'DEFAULT') { delete workflowSettings[key]; } } if (workflowSettings.executionTimeout === this.globalConfig.executions.timeout) { delete workflowSettings.executionTimeout; } workflowUpdateData.updatedAt = new Date(); if (workflowUpdateData.name) { await (0, generic_helpers_1.validateEntity)(workflowUpdateData); } const fieldsToUpdate = [ 'name', 'nodes', 'connections', 'meta', 'settings', 'staticData', 'pinData', 'versionId', 'description', 'updatedAt', ]; const updatePayload = (0, pick_1.default)(workflowUpdateData, fieldsToUpdate); if (saveNewVersion) { await this.workflowHistoryService.saveVersion(user, workflowUpdateData, workflowId, autosaved); } const publishCurrent = workflow.activeVersionId && publishIfActive; if (publishCurrent) { updatePayload.active = true; updatePayload.activeVersionId = workflowUpdateData.versionId; } if (parentFolderId) { const project = await this.sharedWorkflowRepository.getWorkflowOwningProject(workflow.id); if (parentFolderId !== n8n_workflow_1.PROJECT_ROOT) { try { await this.folderRepository.findOneOrFailFolderInProject(parentFolderId, project?.id ?? ''); } catch (e) { throw new folder_not_found_error_1.FolderNotFoundError(parentFolderId); } } updatePayload.parentFolder = parentFolderId === n8n_workflow_1.PROJECT_ROOT ? null : { id: parentFolderId }; } await this.workflowRepository.update(workflowId, updatePayload); const tagsDisabled = this.globalConfig.tags.disabled; if (tagIds && !tagsDisabled) { await this.workflowTagMappingRepository.overwriteTaggings(workflowId, tagIds); } const relations = tagsDisabled ? ['activeVersion'] : ['tags', 'activeVersion']; const updatedWorkflow = await this.workflowRepository.findOne({ where: { id: workflowId }, relations, }); if (updatedWorkflow === null) { throw new bad_request_error_1.BadRequestError(`Workflow with ID "${workflowId}" could not be found to be updated.`); } if (updatedWorkflow.tags?.length && tagIds?.length) { updatedWorkflow.tags = this.tagService.sortByRequestOrder(updatedWorkflow.tags, { requestOrder: tagIds, }); } await this.externalHooks.run('workflow.afterUpdate', [updatedWorkflow]); const settingsChangesDetail = this.calculateSettingsChanges(workflow.settings, updatedWorkflow.settings); this.eventService.emit('workflow-saved', { user, workflow: updatedWorkflow, publicApi, previousWorkflow: workflow, aiBuilderAssisted, ...(settingsChangesDetail && { settingsChanged: settingsChangesDetail }), }); if (updatedWorkflow.activeVersionId && (publishCurrent || settingsChanged)) { await this.activateWorkflow(user, workflowId, { versionId: updatedWorkflow.activeVersionId }, publicApi); } return updatedWorkflow; } async _addToActiveWorkflowManager(user, workflowId, workflow, mode, publicApi = false) { let didPublish = false; try { await this.externalHooks.run('workflow.activate', [workflow]); await this.activeWorkflowManager.add(workflowId, mode); didPublish = true; } catch (error) { const rollbackPayload = { active: false, activeVersionId: null, activeVersion: null, }; const previouslyActiveId = workflow.activeVersionId; await this.workflowRepository.update(workflowId, rollbackPayload); workflow.active = rollbackPayload.active; workflow.activeVersionId = rollbackPayload.activeVersionId; workflow.activeVersion = rollbackPayload.activeVersion; if (!workflow.activeVersionId) { this.eventService.emit('workflow-deactivated', { user, workflowId, workflow, publicApi, }); (0, n8n_workflow_1.assert)(previouslyActiveId !== null); await this.workflowPublishHistoryRepository.addRecord({ workflowId, versionId: previouslyActiveId, event: 'deactivated', userId: user.id, }); } let message; if (error instanceof n8n_workflow_1.NodeApiError) message = error.description; message = message ?? error.message; throw new bad_request_error_1.BadRequestError(message); } finally { if (didPublish) { (0, n8n_workflow_1.assert)(workflow.activeVersionId !== null); await this.workflowPublishHistoryRepository.addRecord({ workflowId, versionId: workflow.activeVersionId, event: 'activated', userId: user.id, }); } } } async activateWorkflow(user, workflowId, options, publicApi = false) { const workflow = await this.workflowFinderService.findWorkflowForUser(workflowId, user, ['workflow:publish'], { includeActiveVersion: true }); if (!workflow) { this.logger.warn('User attempted to activate a workflow without permissions', { workflowId, userId: user.id, }); throw new not_found_error_1.NotFoundError('You do not have permission to activate this workflow. Ask the owner to share it with you.'); } const versionIdToActivate = options?.versionId ?? workflow.versionId; const wasActive = workflow.activeVersionId !== null; let versionToActivate; try { versionToActivate = await this.workflowHistoryService.getVersion(user, workflow.id, versionIdToActivate, { includePublishHistory: false, }); } catch (error) { if (error instanceof workflow_history_version_not_found_error_1.WorkflowHistoryVersionNotFoundError) { throw new not_found_error_1.NotFoundError('Version not found'); } throw error; } if (options?.expectedChecksum) { await this._detectConflicts(workflow, options.expectedChecksum); } this._validateNodes(workflowId, versionToActivate.nodes); await this._validateSubWorkflowReferences(workflowId, versionToActivate.nodes); if (wasActive) { await this.activeWorkflowManager.remove(workflowId); } const activationMode = wasActive ? 'update' : 'activate'; await this.workflowRepository.update(workflowId, { activeVersionId: versionIdToActivate, active: true, updatedAt: workflow.updatedAt, }); const workflowForActivation = await this.workflowRepository.findOne({ where: { id: workflowId }, relations: ['activeVersion'], }); if (!workflowForActivation) { throw new not_found_error_1.NotFoundError(`Workflow with ID "${workflowId}" could not be found.`); } this.eventService.emit('workflow-activated', { user, workflowId, workflow: workflowForActivation, publicApi, }); await this._addToActiveWorkflowManager(user, workflowId, workflowForActivation, activationMode, publicApi); if (options?.name !== undefined || options?.description !== undefined) { const updateFields = {}; if (options.name !== undefined) updateFields.name = options.name; if (options.description !== undefined) updateFields.description = options.description; await this.workflowHistoryService.updateVersion(versionIdToActivate, workflowId, updateFields); } const updatedWorkflow = await this.workflowRepository.findOne({ where: { id: workflowId }, relations: { activeVersion: { workflowPublishHistory: true, }, }, }); if (!updatedWorkflow) { throw new not_found_error_1.NotFoundError(`Workflow with ID "${workflowId}" could not be found.`); } return updatedWorkflow; } async deactivateWorkflow(user, workflowId, publicApi = false) { const workflow = await this.workflowFinderService.findWorkflowForUser(workflowId, user, ['workflow:publish'], { includeActiveVersion: true }); if (!workflow) { this.logger.warn('User attempted to deactivate a workflow without permissions', { workflowId, userId: user.id, }); throw new not_found_error_1.NotFoundError('You do not have permission to deactivate this workflow. Ask the owner to share it with you.'); } if (workflow.activeVersionId === null) { return workflow; } await this.activeWorkflowManager.remove(workflowId); await this.workflowRepository.update(workflowId, { active: false, activeVersionId: null, updatedAt: workflow.updatedAt, }); await this.workflowPublishHistoryRepository.addRecord({ workflowId, versionId: workflow.activeVersionId, event: 'deactivated', userId: user.id, }); workflow.active = false; workflow.activeVersionId = null; workflow.activeVersion = null; this.eventService.emit('workflow-deactivated', { user, workflowId, workflow, publicApi, }); return workflow; } async delete(user, workflowId, force = false) { await this.externalHooks.run('workflow.delete', [workflowId]); const workflow = await this.workflowFinderService.findWorkflowForUser(workflowId, user, [ 'workflow:delete', ]); if (!workflow) { return; } if (!workflow.isArchived && !force) { throw new bad_request_error_1.BadRequestError('Workflow must be archived before it can be deleted.'); } if (workflow.active) { await this.activeWorkflowManager.remove(workflowId); } const idsForDeletion = await this.executionRepository .find({ select: ['id'], where: { workflowId }, }) .then((rows) => rows.map(({ id: executionId }) => n8n_core_1.FileLocation.ofExecution(workflowId, executionId))); await this.workflowRepository.delete(workflowId); await this.binaryDataService.deleteMany(idsForDeletion); this.eventService.emit('workflow-deleted', { user, workflowId, publicApi: false }); await this.externalHooks.run('workflow.afterDelete', [workflowId]); return workflow; } async archive(user, workflowId, skipArchived = false) { const workflow = await this.workflowFinderService.findWorkflowForUser(workflowId, user, [ 'workflow:delete', ]); if (!workflow) { return; } if (workflow.isArchived) { if (skipArchived) { return workflow; } throw new bad_request_error_1.BadRequestError('Workflow is already archived.'); } if (workflow.activeVersionId !== null) { await this.activeWorkflowManager.remove(workflowId); await this.workflowPublishHistoryRepository.addRecord({ workflowId, versionId: workflow.activeVersionId, event: 'deactivated', userId: user.id, }); } const versionId = (0, uuid_1.v4)(); workflow.versionId = versionId; workflow.isArchived = true; workflow.active = false; workflow.activeVersionId = null; workflow.activeVersion = null; await this.workflowRepository.update(workflowId, { isArchived: true, active: false, activeVersion: null, versionId, }); await this.workflowHistoryService.saveVersion(user, workflow, workflowId); this.eventService.emit('workflow-archived', { user, workflowId, publicApi: false }); await this.externalHooks.run('workflow.afterArchive', [workflowId]); return workflow; } async unarchive(user, workflowId) { const workflow = await this.workflowFinderService.findWorkflowForUser(workflowId, user, [ 'workflow:delete', ]); if (!workflow) { return; } if (!workflow.isArchived) { throw new bad_request_error_1.BadRequestError('Workflow is not archived.'); } const versionId = (0, uuid_1.v4)(); workflow.versionId = versionId; workflow.isArchived = false; await this.workflowRepository.update(workflowId, { isArchived: false, versionId }); await this.workflowHistoryService.saveVersion(user, workflow, workflowId); this.eventService.emit('workflow-unarchived', { user, workflowId, publicApi: false }); await this.externalHooks.run('workflow.afterUnarchive', [workflowId]); return workflow; } async getWorkflowScopes(user, workflowId) { const userProjectRelations = await this.projectService.getProjectRelationsForUser(user); const shared = await this.sharedWorkflowRepository.find({ where: { projectId: (0, typeorm_1.In)([...new Set(userProjectRelations.map((pr) => pr.projectId))]), workflowId, }, }); return this.roleService.combineResourceScopes('workflow', user, shared, userProjectRelations); } async transferAll(fromProjectId, toProjectId, trx) { trx = trx ?? this.workflowRepository.manager; const allSharedWorkflows = await trx.findBy(db_1.SharedWorkflow, { projectId: (0, typeorm_1.In)([fromProjectId, toProjectId]), }); const sharedWorkflowsOfFromProject = allSharedWorkflows.filter((sw) => sw.projectId === fromProjectId); const ownedWorkflowIds = sharedWorkflowsOfFromProject .filter((sw) => sw.role === 'workflow:owner') .map((sw) => sw.workflowId); await this.sharedWorkflowRepository.makeOwner(ownedWorkflowIds, toProjectId, trx); await this.sharedWorkflowRepository.deleteByIds(ownedWorkflowIds, fromProjectId, trx); const sharedWorkflowIdsOfTransferee = allSharedWorkflows .filter((sw) => sw.projectId === toProjectId) .map((sw) => sw.workflowId); const sharedWorkflowsToTransfer = sharedWorkflowsOfFromProject.filter((sw) => sw.role !== 'workflow:owner' && !sharedWorkflowIdsOfTransferee.includes(sw.workflowId)); await trx.insert(db_1.SharedWorkflow, sharedWorkflowsToTransfer.map((sw) => ({ workflowId: sw.workflowId, projectId: toProjectId, role: sw.role, }))); } async getWorkflowsWithNodesIncluded(user, nodeTypes, includeNodes = false) { const foundWorkflows = await this.workflowRepository.findWorkflowsWithNodeType(nodeTypes, includeNodes); let { workflows } = await this.workflowRepository.getManyAndCount(foundWorkflows.map((w) => w.id)); if ((0, requests_1.hasSharing)(workflows)) { workflows = await this.processSharedWorkflows(workflows); } const withScopes = await this.addUserScopes(workflows, user); this.cleanupSharedField(withScopes); return withScopes.map((workflow) => { const nodes = includeNodes ? (foundWorkflows.find((w) => w.id === workflow.id)?.nodes ?? []) : undefined; return { resourceType: 'workflow', ...workflow, ...(includeNodes ? { nodes } : {}) }; }); } async _detectConflicts(dbWorkflow, expectedChecksum) { const currentChecksum = await (0, n8n_workflow_1.calculateWorkflowChecksum)(dbWorkflow); if (expectedChecksum !== currentChecksum) { throw new bad_request_error_1.BadRequestError('Your most recent changes may be lost, because someone else just updated this workflow. Open this workflow in a new tab to see those new updates.', 100); } } _validateNodes(workflowId, nodes) { const nodesToValidate = nodes.reduce((acc, node) => { acc[node.name] = node; return acc; }, {}); const validation = this.workflowValidationService.validateForActivation(nodesToValidate, this.nodeTypes); if (!validation.isValid) { this.logger.warn('Workflow activation failed validation', { workflowId, error: validation.error, }); throw new workflow_validation_error_1.WorkflowValidationError(validation.error ?? 'Workflow validation failed'); } } calculateSettingsChanges(previousSettings, newSettings) { const changes = {}; const prev = previousSettings ?? {}; const next = newSettings ?? {}; const allKeys = new Set([...Object.keys(prev), ...Object.keys(next)]); for (const key of allKeys) { const prevValue = prev[key]; const nextValue = next[key]; if (!(0, isEqual_1.default)(prevValue, nextValue)) { const from = prevValue ?? null; const to = nextValue ?? null; changes[key] = { from, to }; } } return Object.keys(changes).length > 0 ? changes : undefined; } async _validateSubWorkflowReferences(workflowId, nodes) { const validation = await this.workflowValidationService.validateSubWorkflowReferences(workflowId, nodes); if (!validation.isValid) { this.logger.warn('Workflow activation failed sub-workflow validation', { workflowId, error: validation.error, invalidReferences: validation.invalidReferences, }); throw new workflow_validation_error_1.WorkflowValidationError(validation.error ?? 'Sub-workflow validation failed'); } } }; exports.WorkflowService = WorkflowService; exports.WorkflowService = WorkflowService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [backend_common_1.Logger, db_1.SharedWorkflowRepository, db_1.WorkflowRepository, db_1.WorkflowTagMappingRepository, n8n_core_1.BinaryDataService, ownership_service_1.OwnershipService, tag_service_1.TagService, workflow_history_service_1.WorkflowHistoryService, external_hooks_1.ExternalHooks, active_workflow_manager_1.ActiveWorkflowManager, role_service_1.RoleService, workflow_sharing_service_1.WorkflowSharingService, project_service_ee_1.ProjectService, db_1.ExecutionRepository, event_service_1.EventService, config_1.GlobalConfig, db_1.FolderRepository, workflow_finder_service_1.WorkflowFinderService, db_1.WorkflowPublishHistoryRepository, workflow_validation_service_1.WorkflowValidationService, node_types_1.NodeTypes]) ], WorkflowService); //# sourceMappingURL=workflow.service.js.map