"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 __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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleFormRedirectionCase = void 0;
exports.handleHostedChatResponse = handleHostedChatResponse;
exports.getWorkflowWebhooks = getWorkflowWebhooks;
exports.autoDetectResponseMode = autoDetectResponseMode;
exports.setupResponseNodePromise = setupResponseNodePromise;
exports.prepareExecutionData = prepareExecutionData;
exports.executeWebhook = executeWebhook;
exports._privateGetWebhookErrorMessage = _privateGetWebhookErrorMessage;
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 n8n_core_1 = require("n8n-core");
const n8n_workflow_1 = require("n8n-workflow");
const promises_1 = require("stream/promises");
const webhook_service_1 = require("./webhook.service");
const webhook_response_headers_1 = require("./webhook-response-headers");
const active_executions_1 = require("../active-executions");
const auth_service_1 = require("../auth/auth.service");
const constants_1 = require("../constants");
const event_service_1 = require("../events/event.service");
const internal_server_error_1 = require("../errors/response-errors/internal-server.error");
const not_found_error_1 = require("../errors/response-errors/not-found.error");
const unprocessable_error_1 = require("../errors/response-errors/unprocessable.error");
const middlewares_1 = require("../middlewares");
const ownership_service_1 = require("../services/ownership.service");
const workflow_statistics_service_1 = require("../services/workflow-statistics.service");
const wait_tracker_1 = require("../wait-tracker");
const webhook_execution_context_1 = require("../webhooks/webhook-execution-context");
const webhook_form_data_1 = require("../webhooks/webhook-form-data");
const webhook_last_node_response_extractor_1 = require("../webhooks/webhook-last-node-response-extractor");
const webhook_on_received_response_extractor_1 = require("../webhooks/webhook-on-received-response-extractor");
const webhook_response_1 = require("../webhooks/webhook-response");
const WorkflowExecuteAdditionalData = __importStar(require("../workflow-execute-additional-data"));
const WorkflowHelpers = __importStar(require("../workflow-helpers"));
const workflow_runner_1 = require("../workflow-runner");
const merge_1 = __importDefault(require("lodash/merge"));
function isMcpToolCall(value) {
    return (typeof value === 'object' &&
        value !== null &&
        'toolName' in value &&
        typeof value.toolName === 'string' &&
        'arguments' in value &&
        typeof value.arguments === 'object');
}
function isMcpListToolsRelay(value) {
    return (typeof value === 'object' &&
        value !== null &&
        'sessionId' in value &&
        typeof value.sessionId === 'string' &&
        'messageId' in value &&
        typeof value.messageId === 'string' &&
        'marker' in value);
}
function handleHostedChatResponse(res, responseMode, didSendResponse, executionId, resumeToken) {
    if (responseMode === 'hostedChat' && !didSendResponse) {
        res.send({ executionStarted: true, executionId, resumeToken });
        process.nextTick(() => res.end());
        return true;
    }
    return didSendResponse;
}
function getWorkflowWebhooks(workflow, additionalData, destinationNode, ignoreRestartWebhooks = false) {
    const returnData = [];
    let parentNodes;
    if (destinationNode !== undefined) {
        parentNodes = workflow.getParentNodes(destinationNode.nodeName);
        if (destinationNode.mode === 'inclusive') {
            parentNodes.push(destinationNode.nodeName);
        }
    }
    for (const node of Object.values(workflow.nodes)) {
        if (parentNodes !== undefined && !parentNodes.includes(node.name)) {
            continue;
        }
        returnData.push.apply(returnData, di_1.Container.get(webhook_service_1.WebhookService).getNodeWebhooks(workflow, node, additionalData, ignoreRestartWebhooks));
    }
    return returnData;
}
const getChatResponseMode = (workflowStartNode, method) => {
    const parameters = workflowStartNode.parameters;
    if (workflowStartNode.type !== n8n_workflow_1.CHAT_TRIGGER_NODE_TYPE)
        return undefined;
    if (method === 'GET')
        return 'onReceived';
    if (method === 'POST' && parameters.options?.responseMode === 'responseNodes') {
        return 'hostedChat';
    }
    return undefined;
};
function autoDetectResponseMode(workflowStartNode, workflow, method) {
    if (workflowStartNode.type === n8n_workflow_1.FORM_TRIGGER_NODE_TYPE && method === 'POST') {
        const connectedNodes = workflow.getChildNodes(workflowStartNode.name);
        for (const nodeName of connectedNodes) {
            const node = workflow.nodes[nodeName];
            if (node.type === n8n_workflow_1.WAIT_NODE_TYPE && node.parameters.resume !== 'form') {
                continue;
            }
            if ([n8n_workflow_1.FORM_NODE_TYPE, n8n_workflow_1.WAIT_NODE_TYPE].includes(node.type) && !node.disabled) {
                return 'formPage';
            }
        }
    }
    const chatResponseMode = getChatResponseMode(workflowStartNode, method);
    if (chatResponseMode)
        return chatResponseMode;
    if (workflowStartNode.type === n8n_workflow_1.FORM_NODE_TYPE && method === 'POST') {
        const connectedNodes = workflow.getChildNodes(workflowStartNode.name);
        for (const nodeName of connectedNodes) {
            const node = workflow.nodes[nodeName];
            if (node.type === n8n_workflow_1.FORM_NODE_TYPE && !node.disabled) {
                return 'formPage';
            }
        }
    }
    if (workflowStartNode.type === n8n_workflow_1.WAIT_NODE_TYPE && workflowStartNode.parameters.resume !== 'form') {
        return undefined;
    }
    if (workflowStartNode.type === n8n_workflow_1.FORM_NODE_TYPE &&
        workflowStartNode.parameters.operation === 'completion') {
        return 'onReceived';
    }
    if ([n8n_workflow_1.FORM_NODE_TYPE, n8n_workflow_1.WAIT_NODE_TYPE].includes(workflowStartNode.type) && method === 'POST') {
        const connectedNodes = workflow.getChildNodes(workflowStartNode.name);
        for (const nodeName of connectedNodes) {
            const node = workflow.nodes[nodeName];
            if (node.type === n8n_workflow_1.WAIT_NODE_TYPE && node.parameters.resume !== 'form') {
                continue;
            }
            if ([n8n_workflow_1.FORM_NODE_TYPE, n8n_workflow_1.WAIT_NODE_TYPE].includes(node.type) && !node.disabled) {
                return 'responseNode';
            }
        }
    }
    return undefined;
}
const handleFormRedirectionCase = (data, workflowStartNode) => {
    if (workflowStartNode.type === n8n_workflow_1.WAIT_NODE_TYPE && workflowStartNode.parameters.resume !== 'form') {
        return data;
    }
    if ([n8n_workflow_1.FORM_NODE_TYPE, n8n_workflow_1.FORM_TRIGGER_NODE_TYPE, n8n_workflow_1.WAIT_NODE_TYPE].includes(workflowStartNode.type) &&
        data?.headers?.location &&
        String(data?.responseCode).startsWith('3')) {
        const locationUrl = String(data?.headers?.location);
        let validatedUrl;
        try {
            validatedUrl = (0, n8n_workflow_1.tryToParseUrl)(locationUrl);
        }
        catch {
        }
        data.responseCode = 200;
        if (validatedUrl) {
            data.data = {
                redirectURL: validatedUrl,
            };
        }
        delete data.headers.location;
    }
    return data;
};
exports.handleFormRedirectionCase = handleFormRedirectionCase;
const { formDataFileSizeMax } = di_1.Container.get(config_1.GlobalConfig).endpoints;
const parseFormData = (0, webhook_form_data_1.createMultiFormDataParser)(formDataFileSizeMax);
function setupResponseNodePromise(responsePromise, res, responseCallback, workflowStartNode, executionId, workflow) {
    void responsePromise.promise
        .then(async (response) => {
        const binaryData = response.body?.binaryData;
        if (binaryData?.id) {
            webhook_response_headers_1.WebhookResponseHeaders.fromObject(response.headers).applyToResponse(res);
            const stream = await di_1.Container.get(n8n_core_1.BinaryDataService).getAsStream(binaryData.id);
            stream.pipe(res, { end: false });
            await (0, promises_1.finished)(stream);
            responseCallback(null, { noWebhookResponse: true });
        }
        else if (Buffer.isBuffer(response.body)) {
            webhook_response_headers_1.WebhookResponseHeaders.fromObject(response.headers).applyToResponse(res);
            res.end(response.body);
            responseCallback(null, { noWebhookResponse: true });
        }
        else {
            let data = {
                data: response.body,
                headers: response.headers,
                responseCode: response.statusCode,
            };
            data = (0, exports.handleFormRedirectionCase)(data, workflowStartNode);
            responseCallback(null, data);
        }
        process.nextTick(() => res.end());
    })
        .catch(async (error) => {
        di_1.Container.get(n8n_core_1.ErrorReporter).error(error);
        di_1.Container.get(backend_common_1.Logger).error(`Error with Webhook-Response for execution "${executionId}": "${error.message}"`, { executionId, workflowId: workflow.id });
        responseCallback(error, {});
    });
}
function prepareExecutionData(executionMode, workflowStartNode, webhookResultData, runExecutionData, runExecutionDataMerge = {}, destinationNode, executionId, workflowData) {
    const nodeExecutionStack = [
        {
            node: workflowStartNode,
            data: {
                main: webhookResultData.workflowData ?? [],
            },
            source: null,
        },
    ];
    if ([n8n_workflow_1.MICROSOFT_AGENT365_TRIGGER_NODE_TYPE, n8n_workflow_1.CHAT_TRIGGER_NODE_TYPE].includes(workflowStartNode.type) &&
        runExecutionData?.executionData?.nodeExecutionStack) {
        (0, merge_1.default)(runExecutionData.executionData.nodeExecutionStack, nodeExecutionStack);
    }
    runExecutionData ??= (0, n8n_workflow_1.createRunExecutionData)({
        executionData: {
            nodeExecutionStack,
        },
    });
    if (destinationNode && runExecutionData.startData) {
        runExecutionData.startData.destinationNode = destinationNode;
    }
    if (executionId !== undefined) {
        runExecutionData.executionData.nodeExecutionStack[0].data.main =
            webhookResultData.workflowData ?? [];
    }
    if (Object.keys(runExecutionDataMerge).length !== 0) {
        Object.assign(runExecutionData, runExecutionDataMerge);
    }
    let pinData;
    const usePinData = ['manual', 'evaluation'].includes(executionMode);
    if (usePinData) {
        pinData = workflowData?.pinData;
        runExecutionData.resultData.pinData = pinData;
    }
    return { runExecutionData, pinData };
}
async function executeWebhook(workflow, webhookData, workflowData, workflowStartNode, executionMode, pushRef, runExecutionData, executionId, req, res, responseCallback, destinationNode) {
    const nodeType = workflow.nodeTypes.getByNameAndVersion(workflowStartNode.type, workflowStartNode.typeVersion);
    const additionalKeys = {
        $executionId: executionId,
    };
    const context = new webhook_execution_context_1.WebhookExecutionContext(workflow, workflowStartNode, webhookData, executionMode, additionalKeys);
    let project = undefined;
    try {
        project = await di_1.Container.get(ownership_service_1.OwnershipService).getWorkflowProjectCached(workflowData.id);
    }
    catch (error) {
        throw new not_found_error_1.NotFoundError('Cannot find workflow');
    }
    const additionalData = await WorkflowExecuteAdditionalData.getBase({
        projectId: project?.id,
    });
    if (executionId) {
        additionalData.executionId = executionId;
    }
    const { responseMode, responseCode, responseData, checkAllMainOutputs, responsePropertyName, responseContentType, responseBinaryPropertyName, } = evaluateResponseOptions(workflowStartNode, workflow, req, webhookData, executionMode, additionalKeys);
    if (!['onReceived', 'lastNode', 'responseNode', 'formPage', 'streaming', 'hostedChat'].includes(responseMode)) {
        const errorMessage = `The response mode '${responseMode}' is not valid!`;
        responseCallback(new n8n_workflow_1.UnexpectedError(errorMessage), {});
        throw new internal_server_error_1.InternalServerError(errorMessage);
    }
    additionalData.httpRequest = req;
    additionalData.httpResponse = res;
    const authService = di_1.Container.get(auth_service_1.AuthService);
    additionalData.validateCookieAuth = async (token) => {
        await authService.validateCookieToken(token);
    };
    let didSendResponse = false;
    let runExecutionDataMerge = {};
    try {
        let webhookResultData;
        await parseRequestBody(req, workflowStartNode, workflow, executionMode, additionalKeys);
        if ([
            constants_1.MCP_TRIGGER_NODE_TYPE,
            n8n_workflow_1.MICROSOFT_AGENT365_TRIGGER_NODE_TYPE,
            n8n_workflow_1.CHAT_TRIGGER_NODE_TYPE,
        ].includes(workflowStartNode.type)) {
            const nodeExecutionStack = [];
            nodeExecutionStack.push({
                node: workflowStartNode,
                data: {
                    main: [],
                },
                source: null,
            });
            runExecutionData =
                runExecutionData ??
                    (0, n8n_workflow_1.createRunExecutionData)({
                        executionData: {
                            nodeExecutionStack,
                        },
                    });
        }
        try {
            webhookResultData = await di_1.Container.get(webhook_service_1.WebhookService).runWebhook(workflow, webhookData, workflowStartNode, additionalData, executionMode, runExecutionData ?? null);
            di_1.Container.get(workflow_statistics_service_1.WorkflowStatisticsService).emit('nodeFetchedData', {
                workflowId: workflow.id,
                node: workflowStartNode,
            });
        }
        catch (err) {
            const webhookType = ['formTrigger', 'form'].includes(nodeType.description.name)
                ? 'Form'
                : 'Webhook';
            const errorMessage = _privateGetWebhookErrorMessage(err, webhookType);
            di_1.Container.get(n8n_core_1.ErrorReporter).error(err, {
                extra: {
                    nodeName: workflowStartNode.name,
                    nodeType: workflowStartNode.type,
                    nodeVersion: workflowStartNode.typeVersion,
                    workflowId: workflow.id,
                },
            });
            responseCallback(new n8n_workflow_1.UnexpectedError(errorMessage), {});
            didSendResponse = true;
            runExecutionDataMerge = {
                resultData: {
                    runData: {},
                    lastNodeExecuted: workflowStartNode.name,
                    error: {
                        ...err,
                        message: err.message,
                        stack: err.stack,
                    },
                },
            };
            webhookResultData = {
                noWebhookResponse: true,
                workflowData: [[{ json: {} }]],
            };
        }
        const responseHeaders = evaluateResponseHeaders(context);
        if (!res.headersSent && responseHeaders) {
            responseHeaders.applyToResponse(res);
        }
        if (webhookResultData.noWebhookResponse === true && !didSendResponse) {
            responseCallback(null, {
                noWebhookResponse: true,
            });
            didSendResponse = true;
        }
        if (webhookResultData.workflowData === undefined) {
            if (webhookResultData.webhookResponse !== undefined) {
                if (!didSendResponse) {
                    responseCallback(null, {
                        data: webhookResultData.webhookResponse,
                        responseCode,
                    });
                    didSendResponse = true;
                }
            }
            else {
                if (!didSendResponse) {
                    responseCallback(null, {
                        data: {
                            message: 'Webhook call received',
                        },
                        responseCode,
                    });
                    didSendResponse = true;
                }
            }
            return;
        }
        const shouldDeferOnReceivedResponse = responseMode === 'onReceived' && !didSendResponse;
        const { runExecutionData: preparedRunExecutionData, pinData } = prepareExecutionData(executionMode, workflowStartNode, webhookResultData, runExecutionData, runExecutionDataMerge, destinationNode, executionId, workflowData);
        runExecutionData = preparedRunExecutionData;
        const runData = {
            executionMode,
            executionData: runExecutionData,
            pushRef,
            workflowData,
            pinData,
            projectId: project?.id,
            projectName: project?.name,
        };
        if (!runData.pushRef) {
            runData.pushRef = runExecutionData.pushRef;
        }
        const executionsConfig = di_1.Container.get(config_1.ExecutionsConfig);
        if (workflowStartNode.type === constants_1.MCP_TRIGGER_NODE_TYPE && executionsConfig.mode === 'queue') {
            const querySessionId = req.query?.sessionId;
            const headerSessionId = req.headers['mcp-session-id'];
            const mcpSessionId = typeof querySessionId === 'string'
                ? querySessionId
                : typeof headerSessionId === 'string'
                    ? headerSessionId
                    : '';
            const firstItem = webhookResultData.workflowData?.[0]?.[0];
            const mcpMessageId = (firstItem && 'json' in firstItem && typeof firstItem.json?.mcpMessageId === 'string'
                ? firstItem.json.mcpMessageId
                : null) ?? `mcp-trigger-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
            runData.isMcpExecution = true;
            runData.mcpType = 'trigger';
            runData.mcpSessionId = mcpSessionId;
            runData.mcpMessageId = mcpMessageId;
            const mcpToolCallValue = firstItem && 'json' in firstItem ? firstItem.json?.mcpToolCall : null;
            if (isMcpToolCall(mcpToolCallValue)) {
                runData.mcpToolCall = mcpToolCallValue;
            }
            const mcpListToolsRelayValue = firstItem && 'json' in firstItem ? firstItem.json?.mcpListToolsRelay : null;
            if (isMcpListToolsRelay(mcpListToolsRelayValue)) {
                const { Publisher } = await Promise.resolve().then(() => __importStar(require('../scaling/pubsub/publisher.service')));
                const publisher = di_1.Container.get(Publisher);
                await publisher.publishMcpRelay({
                    sessionId: mcpListToolsRelayValue.sessionId,
                    messageId: mcpListToolsRelayValue.messageId,
                    response: mcpListToolsRelayValue.marker,
                });
                return undefined;
            }
        }
        let responsePromise;
        if (responseMode === 'responseNode') {
            responsePromise = (0, n8n_workflow_1.createDeferredPromise)();
            setupResponseNodePromise(responsePromise, res, responseCallback, workflowStartNode, executionId, workflow);
        }
        if (responseMode === 'streaming') {
            di_1.Container.get(backend_common_1.Logger).debug(`Execution of workflow "${workflow.name}" from with ID ${executionId} is set to streaming`, { executionId });
            runData.httpResponse = res;
            runData.streamingEnabled = true;
            didSendResponse = true;
        }
        executionId = await di_1.Container.get(workflow_runner_1.WorkflowRunner).run(runData, true, !didSendResponse && !shouldDeferOnReceivedResponse, executionId, responsePromise);
        di_1.Container.get(active_executions_1.ActiveExecutions).setResponseMode(executionId, responseMode);
        if (shouldDeferOnReceivedResponse) {
            additionalKeys.$executionId = executionId;
            additionalKeys.$execution = {
                id: executionId,
                mode: executionMode === 'manual' ? 'test' : 'production',
                resumeUrl: `${additionalData.webhookWaitingBaseUrl}/${executionId}`,
                resumeFormUrl: `${additionalData.formWaitingBaseUrl}/${executionId}`,
            };
            const evaluatedResponseData = context.evaluateComplexWebhookDescriptionExpression('responseData', undefined, 'firstEntryJson');
            const responseBody = (0, webhook_on_received_response_extractor_1.extractWebhookOnReceivedResponse)(evaluatedResponseData, webhookResultData);
            const webhookResponse = (0, webhook_response_1.createStaticResponse)(responseBody, responseCode, responseHeaders);
            responseCallback(null, webhookResponse);
            didSendResponse = true;
        }
        di_1.Container.get(event_service_1.EventService).emit('workflow-executed', {
            workflowId: workflowData.id,
            workflowName: workflowData.name,
            executionId,
            source: 'webhook',
        });
        if (responseMode === 'formPage' && !didSendResponse) {
            const formUrl = new URL(`${additionalData.formWaitingBaseUrl}/${executionId}`);
            if (runExecutionData.resumeToken) {
                formUrl.searchParams.set(n8n_core_1.WAITING_TOKEN_QUERY_PARAM, runExecutionData.resumeToken);
            }
            res.send({ formWaitingUrl: formUrl.toString() });
            process.nextTick(() => res.end());
            didSendResponse = true;
        }
        didSendResponse = handleHostedChatResponse(res, responseMode, didSendResponse, executionId, runExecutionData?.resumeToken);
        di_1.Container.get(backend_common_1.Logger).debug(`Started execution of workflow "${workflow.name}" from webhook with execution ID ${executionId}`, { executionId });
        const activeExecutions = di_1.Container.get(active_executions_1.ActiveExecutions);
        const executePromise = activeExecutions.getPostExecutePromise(executionId);
        const { parentExecution } = runExecutionData;
        if (WorkflowHelpers.shouldRestartParentExecution(parentExecution)) {
            const executionRepository = di_1.Container.get(db_1.ExecutionRepository);
            void executePromise
                .then(async (subworkflowResults) => {
                if (!subworkflowResults)
                    return;
                if (subworkflowResults.status === 'waiting')
                    return;
                await WorkflowHelpers.updateParentExecutionWithChildResults(executionRepository, parentExecution.executionId, subworkflowResults);
                return subworkflowResults;
            })
                .then((subworkflowResults) => {
                if (!subworkflowResults)
                    return;
                if (subworkflowResults.status === 'waiting')
                    return;
                const waitTracker = di_1.Container.get(wait_tracker_1.WaitTracker);
                void waitTracker.startExecution(parentExecution.executionId);
            });
        }
        if (!didSendResponse) {
            executePromise
                .then(async (runData) => {
                if (runData === undefined) {
                    if (!didSendResponse) {
                        responseCallback(null, {
                            data: {
                                message: 'Workflow executed successfully but no data was returned',
                            },
                            responseCode,
                        });
                        didSendResponse = true;
                    }
                    return undefined;
                }
                if (pinData) {
                    runData.data.resultData.pinData = pinData;
                }
                const lastNodeTaskData = WorkflowHelpers.getDataLastExecutedNodeData(runData);
                if (runData.data.resultData.error || lastNodeTaskData?.error !== undefined) {
                    if (!didSendResponse) {
                        responseCallback(null, {
                            data: {
                                message: 'Error in workflow',
                            },
                            responseCode: 500,
                        });
                    }
                    didSendResponse = true;
                    return runData;
                }
                if (responseMode === 'responseNode' && responsePromise) {
                    await Promise.allSettled([responsePromise.promise]);
                    return undefined;
                }
                if (lastNodeTaskData === undefined) {
                    if (!didSendResponse) {
                        responseCallback(null, {
                            data: {
                                message: 'Workflow executed successfully but the last node did not return any data',
                            },
                            responseCode,
                        });
                    }
                    didSendResponse = true;
                    return runData;
                }
                if (didSendResponse) {
                    return runData;
                }
                const result = await (0, webhook_last_node_response_extractor_1.extractWebhookLastNodeResponse)(responseData, lastNodeTaskData, checkAllMainOutputs, { responsePropertyName, responseContentType, responseBinaryPropertyName });
                if (!result.ok) {
                    responseCallback(result.error, {});
                    didSendResponse = true;
                    return runData;
                }
                const response = result.result;
                if (response.contentType) {
                    responseHeaders.set('content-type', response.contentType);
                }
                responseCallback(null, response.type === 'static'
                    ? (0, webhook_response_1.createStaticResponse)(response.body, responseCode, responseHeaders)
                    : (0, webhook_response_1.createStreamResponse)(response.stream, responseCode, responseHeaders));
                didSendResponse = true;
                return runData;
            })
                .catch((e) => {
                if (!didSendResponse) {
                    responseCallback(new n8n_workflow_1.OperationalError('There was a problem executing the workflow', {
                        cause: e,
                    }), {});
                }
                const internalServerError = new internal_server_error_1.InternalServerError(e.message, e);
                if (e instanceof n8n_workflow_1.ExecutionCancelledError)
                    internalServerError.level = 'warning';
                throw internalServerError;
            });
        }
        return executionId;
    }
    catch (e) {
        const error = e instanceof unprocessable_error_1.UnprocessableRequestError
            ? e
            : new n8n_workflow_1.OperationalError('There was a problem executing the workflow', {
                cause: e,
            });
        if (didSendResponse)
            throw error;
        responseCallback(error, {});
        return;
    }
}
function evaluateResponseOptions(workflowStartNode, workflow, req, webhookData, executionMode, additionalKeys) {
    const responseMode = autoDetectResponseMode(workflowStartNode, workflow, req.method) ??
        workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseMode, executionMode, additionalKeys, undefined, 'onReceived');
    const responseCode = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseCode, executionMode, additionalKeys, undefined, 200);
    const responseData = workflow.expression.getComplexParameterValue(workflowStartNode, webhookData.webhookDescription.responseData, executionMode, additionalKeys, undefined, 'firstEntryJson');
    const checkAllMainOutputs = workflowStartNode.type === n8n_workflow_1.CHAT_TRIGGER_NODE_TYPE;
    const responsePropertyName = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responsePropertyName, executionMode, additionalKeys);
    const responseContentType = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseContentType, executionMode, additionalKeys);
    const responseBinaryPropertyName = workflow.expression.getSimpleParameterValue(workflowStartNode, webhookData.webhookDescription.responseBinaryPropertyName, executionMode, additionalKeys, undefined, 'data');
    return {
        responseMode,
        responseCode,
        responseData,
        checkAllMainOutputs,
        responsePropertyName,
        responseContentType,
        responseBinaryPropertyName,
    };
}
async function parseRequestBody(req, workflowStartNode, workflow, executionMode, additionalKeys) {
    let binaryData;
    const nodeVersion = workflowStartNode.typeVersion;
    if (nodeVersion === 1) {
        binaryData = workflow.expression.getSimpleParameterValue(workflowStartNode, '={{$parameter["options"]["binaryData"]}}', executionMode, additionalKeys, undefined, false);
    }
    if (binaryData) {
        return;
    }
    const { contentType } = req;
    if (contentType === 'multipart/form-data') {
        req.body = await parseFormData(req);
    }
    else {
        if (nodeVersion > 1) {
            if (contentType?.startsWith('application/json') ||
                contentType?.startsWith('text/plain') ||
                contentType?.startsWith('application/x-www-form-urlencoded') ||
                contentType?.endsWith('/xml') ||
                contentType?.endsWith('+xml')) {
                await (0, middlewares_1.parseBody)(req);
            }
        }
        else {
            await (0, middlewares_1.parseBody)(req);
        }
    }
}
function evaluateResponseHeaders(context) {
    const headers = new webhook_response_headers_1.WebhookResponseHeaders();
    if (context.webhookData.webhookDescription.responseHeaders === undefined) {
        return headers;
    }
    const evaluatedHeaders = context.evaluateComplexWebhookDescriptionExpression('responseHeaders');
    if (evaluatedHeaders) {
        headers.addFromNodeHeaders(evaluatedHeaders);
    }
    return headers;
}
function _privateGetWebhookErrorMessage(err, webhookType) {
    if (err instanceof n8n_workflow_1.NodeOperationError && err.type === 'manual-form-test') {
        return err.message;
    }
    if (err instanceof n8n_workflow_1.WorkflowConfigurationError) {
        return err.message;
    }
    return `Workflow ${webhookType} Error: Workflow could not be started!`;
}
//# sourceMappingURL=webhook-helpers.js.map