UNPKG

n8n

Version:

n8n Workflow Automation Tool

272 lines 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validatePinDataSize = validatePinDataSize; exports.getDataLastExecutedNodeData = getDataLastExecutedNodeData; exports.addNodeIds = addNodeIds; exports.resolveNodeWebhookIds = resolveNodeWebhookIds; exports.validateWorkflowStructure = validateWorkflowStructure; exports.removeDefaultValues = removeDefaultValues; exports.replaceInvalidCredentials = replaceInvalidCredentials; exports.getVariables = getVariables; exports.shouldRestartParentExecution = shouldRestartParentExecution; exports.updateParentExecutionWithChildResults = updateParentExecutionWithChildResults; exports.getActiveVersionUpdateValue = getActiveVersionUpdateValue; exports.preserveInputOverride = preserveInputOverride; const api_types_1 = require("@n8n/api-types"); const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); const uuid_1 = require("uuid"); const bad_request_error_1 = require("./errors/response-errors/bad-request.error"); const variables_service_ee_1 = require("./environments.ee/variables/variables.service.ee"); const ownership_service_1 = require("./services/ownership.service"); function validatePinDataSize(workflow) { if (!workflow.pinData) return; const pinDataStr = JSON.stringify(workflow.pinData); const pinDataSize = Buffer.byteLength(pinDataStr, 'utf8'); if (pinDataSize > api_types_1.MAX_PINNED_DATA_SIZE) { throw new bad_request_error_1.BadRequestError(`Pinned data exceeds the maximum allowed size of ${api_types_1.MAX_PINNED_DATA_SIZE / (1024 * 1024)} MB`); } const { pinData: _, ...workflowWithoutPinData } = workflow; const workflowSize = Buffer.byteLength(JSON.stringify(workflowWithoutPinData), 'utf8') + pinDataSize; const limit = api_types_1.MAX_WORKFLOW_SIZE - api_types_1.MAX_EXPECTED_REQUEST_SIZE; if (workflowSize > limit) { const limitMB = Math.floor(limit / (1024 * 1024)); throw new bad_request_error_1.BadRequestError(`Workflow with pinned data exceeds the maximum allowed size of ${limitMB} MB`); } } function getDataLastExecutedNodeData(inputData) { const { runData, pinData = {} } = inputData.data.resultData; const { lastNodeExecuted } = inputData.data.resultData; if (lastNodeExecuted === undefined) { return undefined; } if (runData[lastNodeExecuted] === undefined) { return undefined; } const lastNodeRunData = runData[lastNodeExecuted][runData[lastNodeExecuted].length - 1]; let lastNodePinData = pinData[lastNodeExecuted]; if (lastNodePinData && inputData.mode === 'manual') { if (!Array.isArray(lastNodePinData)) lastNodePinData = [lastNodePinData]; const itemsPerRun = lastNodePinData.map((item, index) => { return { json: item, pairedItem: { item: index } }; }); return { startTime: 0, executionIndex: 0, executionTime: 0, data: { main: [itemsPerRun] }, source: lastNodeRunData.source, }; } return lastNodeRunData; } function addNodeIds(workflow) { const { nodes } = workflow; if (!nodes) return; nodes.forEach((node) => { if (!node.id) { node.id = (0, uuid_1.v4)(); } }); } function resolveNodeWebhookIds(workflow, nodeTypes) { const { nodes } = workflow; if (!nodes) return; for (const node of nodes) { try { const nodeType = nodeTypes.getByNameAndVersion(node.type, node.typeVersion); (0, n8n_workflow_1.resolveNodeWebhookId)(node, nodeType.description); } catch { } } } function validateWorkflowStructure(workflow) { const result = (0, n8n_workflow_1.safeParseWorkflowStructure)(workflow); if (result.success) return; const details = result.issues .map(({ path, message, code }) => { const formattedPath = Array.isArray(path) ? (0, n8n_workflow_1.formatWorkflowStructureIssuePath)(path) : 'workflow'; return `${formattedPath} (${code}): ${message}`; }) .join('; '); throw new bad_request_error_1.BadRequestError(`Workflow structure is invalid. ${details}`); } function removeDefaultValues(settings, defaultExecutionTimeout) { const cleanedSettings = { ...settings }; const keysAllowingDefault = [ 'errorWorkflow', 'timezone', 'saveDataErrorExecution', 'saveDataSuccessExecution', 'saveManualExecutions', 'saveExecutionProgress', ]; for (const key of keysAllowingDefault) { if (cleanedSettings[key] === 'DEFAULT') { delete cleanedSettings[key]; } } if (cleanedSettings.executionTimeout === defaultExecutionTimeout) { delete cleanedSettings.executionTimeout; } if (!cleanedSettings.credentialResolverId) { delete cleanedSettings.credentialResolverId; } return cleanedSettings; } async function replaceInvalidCredentials(workflow, projectId) { const { nodes } = workflow; if (!nodes) return workflow; const credentialsByName = {}; const credentialsById = {}; for (const node of nodes) { if (!node.credentials || node.disabled) { continue; } const allNodeCredentials = Object.entries(node.credentials); for (const [nodeCredentialType, nodeCredentials] of allNodeCredentials) { if (nodeCredentials === null || nodeCredentials === undefined) { continue; } if (nodeCredentials.__aiGatewayManaged) continue; if (typeof nodeCredentials === 'string' || nodeCredentials.id === null) { const name = typeof nodeCredentials === 'string' ? nodeCredentials : nodeCredentials.name; if (!credentialsByName[nodeCredentialType]) { credentialsByName[nodeCredentialType] = {}; } if (credentialsByName[nodeCredentialType][name] === undefined) { const credentials = await di_1.Container.get(db_1.CredentialsRepository).findByNameAndTypeInProject(name, nodeCredentialType, projectId); if (credentials?.length === 1) { credentialsByName[nodeCredentialType][name] = { id: credentials[0].id, name: credentials[0].name, }; node.credentials[nodeCredentialType] = credentialsByName[nodeCredentialType][name]; continue; } credentialsByName[nodeCredentialType][name] = { id: null, name, }; } else { node.credentials[nodeCredentialType] = credentialsByName[nodeCredentialType][name]; } continue; } if (!credentialsById[nodeCredentialType]) { credentialsById[nodeCredentialType] = {}; } if (credentialsById[nodeCredentialType][nodeCredentials.id] === undefined) { const credentials = await di_1.Container.get(db_1.CredentialsRepository).findOneBy({ id: nodeCredentials.id, type: nodeCredentialType, }); if (credentials) { credentialsById[nodeCredentialType][nodeCredentials.id] = { id: credentials.id, name: credentials.name, }; node.credentials[nodeCredentialType] = credentialsById[nodeCredentialType][nodeCredentials.id]; continue; } const credsByName = await di_1.Container.get(db_1.CredentialsRepository).findByNameAndTypeInProject(nodeCredentials.name, nodeCredentialType, projectId); if (credsByName?.length === 1) { credentialsById[nodeCredentialType][credsByName[0].id] = { id: credsByName[0].id, name: credsByName[0].name, }; node.credentials[nodeCredentialType] = credentialsById[nodeCredentialType][credsByName[0].id]; continue; } credentialsById[nodeCredentialType][nodeCredentials.id] = nodeCredentials; continue; } node.credentials[nodeCredentialType] = credentialsById[nodeCredentialType][nodeCredentials.id]; } } return workflow; } async function getVariables(workflowId, projectId) { const [variables, project] = await Promise.all([ di_1.Container.get(variables_service_ee_1.VariablesService).getAllCached(), workflowId && !projectId ? di_1.Container.get(ownership_service_1.OwnershipService).getWorkflowProjectCached(workflowId) : null, ]); const projectIdToUse = projectId ?? project?.id; return Object.freeze(variables.reduce((acc, curr) => { if (!curr.project) { acc[curr.key] = curr.value; } else if (projectIdToUse && curr.project.id === projectIdToUse) { acc[curr.key] = curr.value; } return acc; }, {})); } function shouldRestartParentExecution(parentExecution) { if (parentExecution === undefined) { return false; } if (parentExecution.shouldResume === undefined) { return true; } return parentExecution.shouldResume; } async function updateParentExecutionWithChildResults(executionRepository, parentExecutionId, subworkflowResults) { const lastExecutedNodeData = getDataLastExecutedNodeData(subworkflowResults); if (!lastExecutedNodeData?.data) return; const parent = await executionRepository.findSingleExecution(parentExecutionId, { includeData: true, unflattenData: true, }); if (parent?.status !== 'waiting') { return; } const parentWithSubWorkflowResults = { data: { ...parent.data } }; const nodeExecutionStack = parentWithSubWorkflowResults.data.executionData?.nodeExecutionStack; if (!nodeExecutionStack || nodeExecutionStack?.length === 0) { return; } nodeExecutionStack[0].data = lastExecutedNodeData.data; await executionRepository.updateExistingExecution(parentExecutionId, parentWithSubWorkflowResults); } function getActiveVersionUpdateValue(dbWorkflow, updatedVersion, updatedActive) { if (updatedActive) { return updatedVersion; } if (updatedActive === false) { return null; } return dbWorkflow.activeVersionId ? updatedVersion : null; } function preserveInputOverride(runDataArray) { const entryToPop = runDataArray.pop(); const preservedInputOverride = entryToPop.inputOverride; if (preservedInputOverride) { runDataArray.push({ startTime: 0, executionTime: 0, executionIndex: 0, source: entryToPop.source, inputOverride: preservedInputOverride, }); } } //# sourceMappingURL=workflow-helpers.js.map