"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validatePinDataSize = validatePinDataSize;
exports.getDataLastExecutedNodeData = getDataLastExecutedNodeData;
exports.addNodeIds = addNodeIds;
exports.resolveNodeWebhookIds = resolveNodeWebhookIds;
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 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