"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isNpmExecErrorWithStdout = isNpmExecErrorWithStdout;
exports.executeNpmCommand = executeNpmCommand;
exports.verifyIntegrity = verifyIntegrity;
exports.checkIfVersionExistsOrThrow = checkIfVersionExistsOrThrow;
const constants_1 = require("../../constants");
const axios_1 = __importDefault(require("axios"));
const n8n_workflow_1 = require("n8n-workflow");
const node_child_process_1 = require("node:child_process");
const node_util_1 = require("node:util");
const asyncExecFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
const REQUEST_TIMEOUT = 30000;
const NPM_ERROR_PATTERNS = {
    PACKAGE_NOT_FOUND: [constants_1.NPM_COMMAND_TOKENS.NPM_PACKAGE_NOT_FOUND_ERROR],
    NO_VERSION_AVAILABLE: [constants_1.NPM_COMMAND_TOKENS.NPM_NO_VERSION_AVAILABLE],
    PACKAGE_VERSION_NOT_FOUND: [constants_1.NPM_COMMAND_TOKENS.NPM_PACKAGE_VERSION_NOT_FOUND_ERROR],
    DISK_NO_SPACE: [constants_1.NPM_COMMAND_TOKENS.NPM_DISK_NO_SPACE],
    DISK_INSUFFICIENT_SPACE: [constants_1.NPM_COMMAND_TOKENS.NPM_DISK_INSUFFICIENT_SPACE],
};
function isDnsError(error) {
    const message = error instanceof Error ? error.message : String(error);
    return message.includes('getaddrinfo') || message.includes('ENOTFOUND');
}
function isNpmExecErrorWithStdout(error) {
    return typeof error === 'object' && error !== null && 'code' in error && 'stdout' in error;
}
function isNpmError(error) {
    const message = error instanceof Error ? error.message : String(error);
    return (message.includes('npm ERR!') ||
        message.includes('E404') ||
        message.includes('404 Not Found') ||
        message.includes('ENOTFOUND'));
}
function sanitizeRegistryUrl(registryUrl) {
    return registryUrl.replace(/\/+$/, '');
}
function matchesErrorPattern(message, patterns) {
    return patterns.some((pattern) => message.includes(pattern));
}
async function executeNpmCommand(args, options = {}) {
    const { cwd, doNotHandleError } = options;
    try {
        const { stdout } = await asyncExecFile('npm', args, cwd ? { cwd } : undefined);
        return typeof stdout === 'string' ? stdout : stdout.toString();
    }
    catch (error) {
        if (doNotHandleError) {
            throw error;
        }
        const errorMessage = error instanceof Error ? error.message : String(error);
        n8n_workflow_1.LoggerProxy.warn('Failed to execute npm command', { errorMessage });
        if (matchesErrorPattern(errorMessage, NPM_ERROR_PATTERNS.PACKAGE_NOT_FOUND)) {
            throw new n8n_workflow_1.UnexpectedError(constants_1.RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND);
        }
        if (matchesErrorPattern(errorMessage, NPM_ERROR_PATTERNS.NO_VERSION_AVAILABLE)) {
            throw new n8n_workflow_1.UnexpectedError(constants_1.RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND);
        }
        if (matchesErrorPattern(errorMessage, NPM_ERROR_PATTERNS.PACKAGE_VERSION_NOT_FOUND)) {
            throw new n8n_workflow_1.UnexpectedError(constants_1.RESPONSE_ERROR_MESSAGES.PACKAGE_VERSION_NOT_FOUND);
        }
        if (matchesErrorPattern(errorMessage, NPM_ERROR_PATTERNS.DISK_NO_SPACE) ||
            matchesErrorPattern(errorMessage, NPM_ERROR_PATTERNS.DISK_INSUFFICIENT_SPACE)) {
            throw new n8n_workflow_1.UnexpectedError(constants_1.RESPONSE_ERROR_MESSAGES.DISK_IS_FULL);
        }
        if (isDnsError(error)) {
            throw new n8n_workflow_1.UnexpectedError('Network error: Unable to reach npm registry. Please check your internet connection.');
        }
        throw new n8n_workflow_1.UnexpectedError('Failed to execute npm command', { cause: error });
    }
}
async function verifyIntegrity(packageName, version, registryUrl, expectedIntegrity) {
    const url = `${sanitizeRegistryUrl(registryUrl)}/${encodeURIComponent(packageName)}`;
    try {
        const metadata = await axios_1.default.get(`${url}/${version}`, {
            timeout: REQUEST_TIMEOUT,
        });
        const integrity = metadata?.data?.dist?.integrity;
        if (integrity !== expectedIntegrity) {
            throw new n8n_workflow_1.UnexpectedError('Checksum verification failed. Package integrity does not match. Try restarting n8n and attempting the installation again.');
        }
        return;
    }
    catch (error) {
        try {
            const stdout = await executeNpmCommand([
                'view',
                `${packageName}@${version}`,
                'dist.integrity',
                `--registry=${sanitizeRegistryUrl(registryUrl)}`,
                '--json',
            ], { doNotHandleError: true });
            const integrity = (0, n8n_workflow_1.jsonParse)(stdout);
            if (integrity !== expectedIntegrity) {
                throw new n8n_workflow_1.UnexpectedError('Checksum verification failed. Package integrity does not match. Try restarting n8n and attempting the installation again.');
            }
            return;
        }
        catch (cliError) {
            if (isDnsError(cliError) || isNpmError(cliError)) {
                throw new n8n_workflow_1.UnexpectedError('Checksum verification failed. Please check your network connection and try again.');
            }
            throw new n8n_workflow_1.UnexpectedError('Checksum verification failed. Try restarting n8n and attempting the installation again.');
        }
    }
}
async function checkIfVersionExistsOrThrow(packageName, version, registryUrl) {
    const url = `${sanitizeRegistryUrl(registryUrl)}/${encodeURIComponent(packageName)}`;
    try {
        await axios_1.default.get(`${url}/${version}`, { timeout: REQUEST_TIMEOUT });
        return true;
    }
    catch (error) {
        try {
            const stdout = await executeNpmCommand([
                'view',
                `${packageName}@${version}`,
                'version',
                `--registry=${sanitizeRegistryUrl(registryUrl)}`,
                '--json',
            ], { doNotHandleError: true });
            const versionInfo = (0, n8n_workflow_1.jsonParse)(stdout);
            if (versionInfo === version) {
                return true;
            }
            throw new n8n_workflow_1.UnexpectedError('Failed to check package version existence');
        }
        catch (cliError) {
            const message = cliError instanceof Error ? cliError.message : String(cliError);
            if (message.includes('E404') || message.includes('404 Not Found')) {
                throw new n8n_workflow_1.UnexpectedError('Package version does not exist');
            }
            if (isDnsError(cliError) || isNpmError(cliError)) {
                throw new n8n_workflow_1.UnexpectedError('The community nodes service is temporarily unreachable. Please try again later.');
            }
            throw new n8n_workflow_1.UnexpectedError('Failed to check package version existence');
        }
    }
}
//# sourceMappingURL=npm-utils.js.map