"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractAllPackageFiles = exports.extractPackageFile = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const global_1 = require("../../../../config/global");
const logger_1 = require("../../../../logger");
const fs_1 = require("../../../../util/fs");
const regex_1 = require("../../../../util/regex");
const npm_1 = require("../../../datasource/npm");
const dependency_1 = require("./common/dependency");
const package_file_1 = require("./common/package-file");
const post_1 = require("./post");
const yarn_1 = require("./yarn");
const yarnrc_1 = require("./yarnrc");
function hasMultipleLockFiles(lockFiles) {
    return Object.values(lockFiles).filter(is_1.default.string).length > 1;
}
async function extractPackageFile(content, packageFile, config) {
    logger_1.logger.trace(`npm.extractPackageFile(${packageFile})`);
    logger_1.logger.trace({ content });
    let packageJson;
    try {
        packageJson = JSON.parse(content);
    }
    catch (err) {
        logger_1.logger.debug({ packageFile }, `Invalid JSON`);
        return null;
    }
    const res = (0, package_file_1.extractPackageJson)(packageJson, packageFile);
    if (!res) {
        return null;
    }
    let workspacesPackages;
    if (is_1.default.array(packageJson.workspaces)) {
        workspacesPackages = packageJson.workspaces;
    }
    else {
        workspacesPackages = packageJson.workspaces?.packages;
    }
    const lockFiles = {
        yarnLock: 'yarn.lock',
        packageLock: 'package-lock.json',
        shrinkwrapJson: 'npm-shrinkwrap.json',
        pnpmShrinkwrap: 'pnpm-lock.yaml',
    };
    for (const [key, val] of Object.entries(lockFiles)) {
        const filePath = (0, fs_1.getSiblingFileName)(packageFile, val);
        if (await (0, fs_1.readLocalFile)(filePath, 'utf8')) {
            lockFiles[key] = filePath;
        }
        else {
            lockFiles[key] = undefined;
        }
    }
    lockFiles.npmLock = lockFiles.packageLock ?? lockFiles.shrinkwrapJson;
    delete lockFiles.packageLock;
    delete lockFiles.shrinkwrapJson;
    if (hasMultipleLockFiles(lockFiles)) {
        logger_1.logger.warn('Updating multiple npm lock files is deprecated and support will be removed in future versions.');
    }
    let npmrc;
    const npmrcFileName = (0, fs_1.getSiblingFileName)(packageFile, '.npmrc');
    let repoNpmrc = await (0, fs_1.readLocalFile)(npmrcFileName, 'utf8');
    if (is_1.default.string(repoNpmrc)) {
        if (is_1.default.string(config.npmrc) && !config.npmrcMerge) {
            logger_1.logger.debug({ npmrcFileName }, 'Repo .npmrc file is ignored due to config.npmrc with config.npmrcMerge=false');
            npmrc = config.npmrc;
        }
        else {
            npmrc = config.npmrc ?? '';
            if (npmrc.length) {
                if (!npmrc.endsWith('\n')) {
                    npmrc += '\n';
                }
            }
            if (repoNpmrc?.includes('package-lock')) {
                logger_1.logger.debug('Stripping package-lock setting from .npmrc');
                repoNpmrc = repoNpmrc.replace((0, regex_1.regEx)(/(^|\n)package-lock.*?(\n|$)/g), '\n');
            }
            if (repoNpmrc.includes('=${') && !global_1.GlobalConfig.get('exposeAllEnv')) {
                logger_1.logger.debug({ npmrcFileName }, 'Stripping .npmrc file of lines with variables');
                repoNpmrc = repoNpmrc
                    .split(regex_1.newlineRegex)
                    .filter((line) => !line.includes('=${'))
                    .join('\n');
            }
            npmrc += repoNpmrc;
        }
    }
    else if (is_1.default.string(config.npmrc)) {
        npmrc = config.npmrc;
    }
    const yarnrcYmlFileName = (0, fs_1.getSiblingFileName)(packageFile, '.yarnrc.yml');
    const yarnZeroInstall = await (0, yarn_1.isZeroInstall)(yarnrcYmlFileName);
    let yarnConfig = null;
    const repoYarnrcYml = await (0, fs_1.readLocalFile)(yarnrcYmlFileName, 'utf8');
    if (is_1.default.string(repoYarnrcYml)) {
        yarnConfig = (0, yarnrc_1.loadConfigFromYarnrcYml)(repoYarnrcYml);
    }
    const legacyYarnrcFileName = (0, fs_1.getSiblingFileName)(packageFile, '.yarnrc');
    const repoLegacyYarnrc = await (0, fs_1.readLocalFile)(legacyYarnrcFileName, 'utf8');
    if (is_1.default.string(repoLegacyYarnrc)) {
        yarnConfig = (0, yarnrc_1.loadConfigFromLegacyYarnrc)(repoLegacyYarnrc);
    }
    if (res.deps.length === 0) {
        logger_1.logger.debug('Package file has no deps');
        if (!(!!res.managerData?.packageJsonName ||
            !!res.packageFileVersion ||
            !!npmrc ||
            workspacesPackages)) {
            logger_1.logger.debug('Skipping file');
            return null;
        }
    }
    let skipInstalls = config.skipInstalls;
    if (skipInstalls === null) {
        const hasFancyRefs = !!res.deps.some((dep) => !!dep.currentValue?.startsWith('file:') ||
            !!dep.currentValue?.startsWith('npm:'));
        if ((hasFancyRefs && !!lockFiles.npmLock) || yarnZeroInstall) {
            // https://github.com/npm/cli/issues/1432
            // Explanation:
            //  - npm install --package-lock-only is buggy for transitive deps in file: and npm: references
            //  - So we set skipInstalls to false if file: or npm: refs are found *and* the user hasn't explicitly set the value already
            //  - Also, do not skip install if Yarn zero-install is used
            logger_1.logger.debug('Automatically setting skipInstalls to false');
            skipInstalls = false;
        }
        else {
            skipInstalls = true;
        }
    }
    const extractedConstraints = (0, dependency_1.getExtractedConstraints)(res.deps);
    if (yarnConfig) {
        for (const dep of res.deps) {
            if (dep.depName) {
                const registryUrlFromYarnConfig = (0, yarnrc_1.resolveRegistryUrl)(dep.depName, yarnConfig);
                if (registryUrlFromYarnConfig && dep.datasource === npm_1.NpmDatasource.id) {
                    dep.registryUrls = [registryUrlFromYarnConfig];
                }
            }
        }
    }
    return {
        ...res,
        npmrc,
        managerData: {
            ...res.managerData,
            ...lockFiles,
            yarnZeroInstall,
            hasPackageManager: is_1.default.nonEmptyStringAndNotWhitespace(packageJson.packageManager),
            workspacesPackages,
        },
        skipInstalls,
        extractedConstraints,
    };
}
exports.extractPackageFile = extractPackageFile;
async function extractAllPackageFiles(config, packageFiles) {
    const npmFiles = [];
    for (const packageFile of packageFiles) {
        const content = await (0, fs_1.readLocalFile)(packageFile, 'utf8');
        // istanbul ignore else
        if (content) {
            const deps = await extractPackageFile(content, packageFile, config);
            if (deps) {
                npmFiles.push({
                    ...deps,
                    packageFile,
                });
            }
        }
        else {
            logger_1.logger.debug({ packageFile }, `No content found`);
        }
    }
    await (0, post_1.postExtract)(npmFiles);
    return npmFiles;
}
exports.extractAllPackageFiles = extractAllPackageFiles;
//# sourceMappingURL=index.js.map