UNPKG

n8n

Version:

n8n Workflow Automation Tool

137 lines 7.41 kB
"use strict"; const backend_common_1 = require("@n8n/backend-common"); const constants_1 = require("@n8n/constants"); const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const n8n_core_1 = require("n8n-core"); const n8n_workflow_1 = require("n8n-workflow"); const conflict_error_1 = require("../../../../errors/response-errors/conflict.error"); const forbidden_error_1 = require("../../../../errors/response-errors/forbidden.error"); const not_found_error_1 = require("../../../../errors/response-errors/not-found.error"); const payment_required_error_1 = require("../../../../errors/response-errors/payment-required.error"); const test_runner_service_ee_1 = require("../../../../evaluation.ee/test-runner/test-runner.service.ee"); const workflow_finder_service_1 = require("../../../../workflows/workflow-finder.service"); const evaluations_mapper_1 = require("./evaluations.mapper"); const global_middleware_1 = require("../../shared/middlewares/global.middleware"); const pagination_service_1 = require("../../shared/services/pagination.service"); function assertEvaluationsEnabled() { if (di_1.Container.get(backend_common_1.LicenseState).getMaxWorkflowsWithEvaluations() === 0) { throw new forbidden_error_1.ForbiddenError('Evaluations are not available on your plan'); } } async function assertEvaluationQuotaAvailable(workflowId) { const limit = di_1.Container.get(backend_common_1.LicenseState).getMaxWorkflowsWithEvaluations(); if (limit === constants_1.UNLIMITED_LICENSE_QUOTA) return; const alreadyCounts = (await di_1.Container.get(db_1.TestRunRepository).countByWorkflowId(workflowId)) > 0; if (alreadyCounts) return; const used = await di_1.Container.get(db_1.WorkflowRepository).getWorkflowsWithEvaluationCount(); if (used >= limit) { throw new payment_required_error_1.PaymentRequiredError(`Evaluation quota exceeded: ${used}/${limit} workflows already have evaluations`); } } const evaluationsHandlers = { getTestRuns: [ (0, global_middleware_1.publicApiScope)('testRun:list'), (0, global_middleware_1.projectScope)('workflow:read', 'workflow'), global_middleware_1.validCursor, async (req, res) => { const { id: workflowId } = req.params; const { offset = 0, limit = 100, status } = req.query; const testRunRepository = di_1.Container.get(db_1.TestRunRepository); const [testRuns, count] = await Promise.all([ testRunRepository.getMany(workflowId, { skip: offset, take: limit }, status), testRunRepository.countByWorkflowId(workflowId, status), ]); return res.json({ data: testRuns.map(evaluations_mapper_1.toTestRunSummaryDto), nextCursor: (0, pagination_service_1.encodeNextCursor)({ offset, limit, numberOfTotalRecords: count }), }); }, ], getTestRun: [ (0, global_middleware_1.publicApiScope)('testRun:read'), (0, global_middleware_1.projectScope)('workflow:read', 'workflow'), async (req, res) => { const { id: workflowId, runId } = req.params; const summary = await di_1.Container.get(db_1.TestRunRepository).getTestRunSummaryByWorkflowId(runId, workflowId); if (!summary) throw new not_found_error_1.NotFoundError('Test run not found'); return res.json((0, evaluations_mapper_1.toTestRunSummaryDto)({ ...summary, testCaseCount: summary.testCaseExecutions?.length ?? 0, })); }, ], getTestCases: [ (0, global_middleware_1.publicApiScope)('testRun:read'), (0, global_middleware_1.projectScope)('workflow:read', 'workflow'), global_middleware_1.validCursor, async (req, res) => { const { id: workflowId, runId } = req.params; const { offset = 0, limit = 100 } = req.query; if (!(await di_1.Container.get(db_1.TestRunRepository).existsInWorkflow(runId, workflowId))) { throw new not_found_error_1.NotFoundError('Test run not found'); } const testCaseExecutionRepository = di_1.Container.get(db_1.TestCaseExecutionRepository); const [testCases, count] = await Promise.all([ testCaseExecutionRepository.getManyByTestRunId(runId, { skip: offset, take: limit }), testCaseExecutionRepository.countByTestRunId(runId), ]); return res.json({ data: testCases.map(evaluations_mapper_1.toTestCaseExecutionDto), nextCursor: (0, pagination_service_1.encodeNextCursor)({ offset, limit, numberOfTotalRecords: count }), }); }, ], createTestRun: [ (0, global_middleware_1.publicApiScope)('testRun:create'), (0, global_middleware_1.projectScope)('workflow:execute', 'workflow'), async (req, res) => { const { id: workflowId } = req.params; const testRunnerService = di_1.Container.get(test_runner_service_ee_1.TestRunnerService); assertEvaluationsEnabled(); const workflow = await di_1.Container.get(workflow_finder_service_1.WorkflowFinderService).findWorkflowForUser(workflowId, req.user, ['workflow:execute']); if (!workflow) throw new not_found_error_1.NotFoundError('Workflow not found'); const hasTrigger = workflow.nodes.some((node) => node.type === n8n_workflow_1.EVALUATION_TRIGGER_NODE_TYPE); if (!hasTrigger) { throw new conflict_error_1.ConflictError('Workflow has no evaluation trigger'); } await assertEvaluationQuotaAvailable(workflowId); const { testRun, finished } = await testRunnerService.startTestRun(req.user, workflowId, 1, { via: 'public-api', }); void finished.catch((error) => di_1.Container.get(n8n_core_1.ErrorReporter).error(error)); const body = { id: testRun.id, status: testRun.status, createdAt: testRun.createdAt.toISOString(), }; return res.status(201).json(body); }, ], cancelTestRun: [ (0, global_middleware_1.publicApiScope)('testRun:cancel'), (0, global_middleware_1.projectScope)('workflow:execute', 'workflow'), async (req, res) => { const { id: workflowId, runId } = req.params; assertEvaluationsEnabled(); const testRunnerService = di_1.Container.get(test_runner_service_ee_1.TestRunnerService); const testRun = await di_1.Container.get(db_1.TestRunRepository).findOne({ where: { id: runId, workflow: { id: workflowId } }, }); if (!testRun) throw new not_found_error_1.NotFoundError('Test run not found'); if (testRunnerService.canBeCancelled(testRun)) { throw new conflict_error_1.ConflictError(`The test run "${runId}" cannot be cancelled`); } await testRunnerService.cancelTestRun(runId); const body = { id: runId, status: 'cancelled' }; return res.status(202).json(body); }, ], }; module.exports = evaluationsHandlers; //# sourceMappingURL=evaluations.handler.js.map