"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __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.types = void 0;
const constants_1 = require("@pnpm/constants");
const error_1 = __importDefault(require("@pnpm/error"));
const global_bin_dir_1 = __importDefault(require("@pnpm/global-bin-dir"));
const camelcase_1 = __importDefault(require("camelcase"));
const findBestGlobalPrefixOnWindows_1 = __importDefault(require("./findBestGlobalPrefixOnWindows"));
const getScopeRegistries_1 = __importStar(require("./getScopeRegistries"));
const path = require("path");
const loadNpmConf = require("@zkochan/npm-conf");
const npmTypes = require("@zkochan/npm-conf/lib/types");
const R = require("ramda");
const whichcb = require("which");
const npmDefaults = loadNpmConf.defaults;
function which(cmd) {
    return new Promise((resolve, reject) => {
        whichcb(cmd, (err, resolvedPath) => err ? reject(err) : resolve(resolvedPath));
    });
}
exports.types = Object.assign({
    bail: Boolean,
    'child-concurrency': Number,
    color: ['always', 'auto', 'never'],
    dev: [null, true],
    dir: String,
    'fetching-concurrency': Number,
    filter: [String, Array],
    'frozen-lockfile': Boolean,
    'frozen-shrinkwrap': Boolean,
    'git-checks': Boolean,
    'global-dir': String,
    'global-path': String,
    'global-pnpmfile': String,
    hoist: Boolean,
    'hoist-pattern': Array,
    'ignore-pnpmfile': Boolean,
    'ignore-workspace-root-check': Boolean,
    'link-workspace-packages': [Boolean, 'deep'],
    lockfile: Boolean,
    'lockfile-dir': String,
    'lockfile-directory': String,
    'lockfile-only': Boolean,
    loglevel: ['silent', 'error', 'warn', 'info', 'debug'],
    'modules-dir': String,
    'network-concurrency': Number,
    'npm-path': String,
    offline: Boolean,
    'package-import-method': ['auto', 'hardlink', 'clone', 'copy'],
    pnpmfile: String,
    'prefer-frozen-lockfile': Boolean,
    'prefer-frozen-shrinkwrap': Boolean,
    'prefer-offline': Boolean,
    production: [null, true],
    'public-hoist-pattern': Array,
    'publish-branch': String,
    'recursive-install': Boolean,
    reporter: String,
    'save-peer': Boolean,
    'save-workspace-protocol': Boolean,
    'shamefully-flatten': Boolean,
    'shamefully-hoist': Boolean,
    'shared-workspace-lockfile': Boolean,
    'shared-workspace-shrinkwrap': Boolean,
    'shell-emulator': Boolean,
    'shrinkwrap-directory': String,
    'shrinkwrap-only': Boolean,
    'side-effects-cache': Boolean,
    'side-effects-cache-readonly': Boolean,
    sort: Boolean,
    store: String,
    'store-dir': String,
    stream: Boolean,
    'strict-peer-dependencies': Boolean,
    'use-beta-cli': Boolean,
    'use-running-store-server': Boolean,
    'use-store-server': Boolean,
    'verify-store-integrity': Boolean,
    'virtual-store-dir': String,
    'workspace-concurrency': Number,
    'workspace-packages': [String, Array],
    'workspace-root': Boolean,
}, npmTypes.types);
exports.default = async (opts) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
    const packageManager = (_a = opts.packageManager) !== null && _a !== void 0 ? _a : { name: 'pnpm', version: 'undefined' };
    const cliOptions = (_b = opts.cliOptions) !== null && _b !== void 0 ? _b : {};
    const warnings = new Array();
    if (cliOptions['hoist'] === false) {
        if (cliOptions['shamefully-hoist'] === true) {
            throw new error_1.default('CONFIG_CONFLICT_HOIST', '--shamefully-hoist cannot be used with --no-hoist');
        }
        if (cliOptions['shamefully-flatten'] === true) {
            throw new error_1.default('CONFIG_CONFLICT_HOIST', '--shamefully-flatten cannot be used with --no-hoist');
        }
        if (cliOptions['hoist-pattern']) {
            throw new error_1.default('CONFIG_CONFLICT_HOIST', '--hoist-pattern cannot be used with --no-hoist');
        }
    }
    // This is what npm does as well, overriding process.execPath with the resolved location of Node.
    // The value of process.execPath is changed only for the duration of config initialization.
    // Otherwise, npmConfig.globalPrefix would sometimes have the bad location.
    //
    // TODO: use this workaround only during global installation
    const originalExecPath = process.execPath;
    try {
        const node = await which(process.argv[0]);
        if (node.toUpperCase() !== process.execPath.toUpperCase()) {
            process.execPath = node;
        }
    }
    catch (err) { } // eslint-disable-line:no-empty
    if (cliOptions.dir) {
        cliOptions['prefix'] = cliOptions.dir; // the npm config system still expects `prefix`
    }
    const rcOptionsTypes = { ...exports.types, ...opts.rcOptionsTypes };
    const npmConfig = loadNpmConf(cliOptions, rcOptionsTypes, {
        bail: true,
        color: 'auto',
        'fetch-retries': 2,
        'fetch-retry-factor': 10,
        'fetch-retry-maxtimeout': 60000,
        'fetch-retry-mintimeout': 10000,
        globalconfig: npmDefaults.globalconfig,
        hoist: true,
        'hoist-pattern': ['*'],
        'ignore-workspace-root-check': false,
        'link-workspace-packages': true,
        'package-lock': npmDefaults['package-lock'],
        pending: false,
        'public-hoist-pattern': [
            // Packages like @types/node, @babel/types
            // should be publicly hoisted because TypeScript only searches in the root of node_modules
            '*types*',
            '*eslint*',
        ],
        'recursive-install': true,
        registry: npmDefaults.registry,
        'save-peer': false,
        'save-workspace-protocol': true,
        'shared-workspace-lockfile': true,
        'shared-workspace-shrinkwrap': true,
        'shell-emulator': false,
        shrinkwrap: npmDefaults.shrinkwrap,
        sort: true,
        'strict-peer-dependencies': false,
        'unsafe-perm': npmDefaults['unsafe-perm'],
        'use-beta-cli': false,
        userconfig: npmDefaults.userconfig,
        'virtual-store-dir': 'node_modules/.pnpm',
        'workspace-concurrency': 4,
        'workspace-prefix': opts.workspaceDir,
    });
    delete cliOptions.prefix;
    process.execPath = originalExecPath;
    const pnpmConfig = R.fromPairs([
        ...Object.keys(rcOptionsTypes).map((configKey) => [camelcase_1.default(configKey), npmConfig.get(configKey)]),
        ...Object.entries(cliOptions).filter(([name, value]) => typeof value !== 'undefined').map(([name, value]) => [camelcase_1.default(name), value]),
    ]);
    const cwd = (_c = (cliOptions['dir'] && path.resolve(cliOptions['dir']))) !== null && _c !== void 0 ? _c : npmConfig.localPrefix; // eslint-disable-line
    pnpmConfig.workspaceDir = opts.workspaceDir;
    pnpmConfig.rawLocalConfig = Object.assign.apply(Object, [
        {},
        ...npmConfig.list.slice(3, pnpmConfig.workspaceDir && pnpmConfig.workspaceDir !== cwd ? 5 : 4).reverse(),
        cliOptions,
    ]); // eslint-disable-line @typescript-eslint/no-explicit-any
    pnpmConfig.userAgent = pnpmConfig.rawLocalConfig['user-agent']
        ? pnpmConfig.rawLocalConfig['user-agent']
        : `${packageManager.name}/${packageManager.version} npm/? node/${process.version} ${process.platform} ${process.arch}`;
    pnpmConfig.rawConfig = Object.assign.apply(Object, [
        { registry: 'https://registry.npmjs.org/' },
        ...[...npmConfig.list].reverse(),
        cliOptions,
        { 'user-agent': pnpmConfig.userAgent },
    ]); // eslint-disable-line @typescript-eslint/no-explicit-any
    pnpmConfig.registries = {
        default: getScopeRegistries_1.normalizeRegistry(pnpmConfig.rawConfig.registry),
        ...getScopeRegistries_1.default(pnpmConfig.rawConfig),
    };
    const npmGlobalPrefix = (_e = (_d = pnpmConfig.globalDir) !== null && _d !== void 0 ? _d : pnpmConfig.rawConfig['pnpm-prefix']) !== null && _e !== void 0 ? _e : (process.platform !== 'win32'
        ? npmConfig.globalPrefix
        : findBestGlobalPrefixOnWindows_1.default(npmConfig.globalPrefix, process.env));
    pnpmConfig.npmGlobalBinDir = process.platform === 'win32'
        ? npmGlobalPrefix
        : path.resolve(npmGlobalPrefix, 'bin');
    pnpmConfig.globalDir = pnpmConfig.globalDir ? npmGlobalPrefix : path.join(npmGlobalPrefix, 'pnpm-global');
    pnpmConfig.lockfileDir = (_g = (_f = pnpmConfig.lockfileDir) !== null && _f !== void 0 ? _f : pnpmConfig.lockfileDirectory) !== null && _g !== void 0 ? _g : pnpmConfig.shrinkwrapDirectory;
    pnpmConfig.useLockfile = (() => {
        if (typeof pnpmConfig['lockfile'] === 'boolean')
            return pnpmConfig['lockfile'];
        if (typeof pnpmConfig['packageLock'] === 'boolean')
            return pnpmConfig['packageLock'];
        if (typeof pnpmConfig['shrinkwrap'] === 'boolean')
            return pnpmConfig['shrinkwrap'];
        return false;
    })();
    pnpmConfig.lockfileOnly = typeof pnpmConfig['lockfileOnly'] === 'undefined'
        ? pnpmConfig.shrinkwrapOnly
        : pnpmConfig['lockfileOnly'];
    pnpmConfig.frozenLockfile = typeof pnpmConfig['frozenLockfile'] === 'undefined'
        ? pnpmConfig.frozenShrinkwrap
        : pnpmConfig['frozenLockfile'];
    pnpmConfig.preferFrozenLockfile = typeof pnpmConfig['preferFrozenLockfile'] === 'undefined'
        ? pnpmConfig.preferFrozenShrinkwrap
        : pnpmConfig['preferFrozenLockfile'];
    pnpmConfig.sharedWorkspaceLockfile = typeof pnpmConfig['sharedWorkspaceLockfile'] === 'undefined'
        ? pnpmConfig.sharedWorkspaceShrinkwrap
        : pnpmConfig['sharedWorkspaceLockfile'];
    if (cliOptions['global']) {
        pnpmConfig.save = true;
        pnpmConfig.dir = path.join(pnpmConfig.globalDir, constants_1.LAYOUT_VERSION.toString());
        pnpmConfig.bin = cliOptions['dir']
            ? (process.platform === 'win32'
                ? cliOptions.dir : path.resolve(cliOptions.dir, 'bin'))
            : global_bin_dir_1.default([pnpmConfig.npmGlobalBinDir], { shouldAllowWrite: opts.globalDirShouldAllowWrite === true });
        pnpmConfig.allowNew = true;
        pnpmConfig.ignoreCurrentPrefs = true;
        pnpmConfig.saveProd = true;
        pnpmConfig.saveDev = false;
        pnpmConfig.saveOptional = false;
        if (pnpmConfig.hoistPattern && (pnpmConfig.hoistPattern.length > 1 || pnpmConfig.hoistPattern[0] !== '*')) {
            if (opts.cliOptions['hoist-pattern']) {
                throw new error_1.default('CONFIG_CONFLICT_HOIST_PATTERN_WITH_GLOBAL', 'Configuration conflict. "hoist-pattern" may not be used with "global"');
            }
        }
        if (pnpmConfig.linkWorkspacePackages) {
            if (opts.cliOptions['link-workspace-packages']) {
                throw new error_1.default('CONFIG_CONFLICT_LINK_WORKSPACE_PACKAGES_WITH_GLOBAL', 'Configuration conflict. "link-workspace-packages" may not be used with "global"');
            }
            pnpmConfig.linkWorkspacePackages = false;
        }
        if (pnpmConfig.sharedWorkspaceLockfile) {
            if (opts.cliOptions['shared-workspace-lockfile']) {
                throw new error_1.default('CONFIG_CONFLICT_SHARED_WORKSPACE_LOCKFILE_WITH_GLOBAL', 'Configuration conflict. "shared-workspace-lockfile" may not be used with "global"');
            }
            pnpmConfig.sharedWorkspaceLockfile = false;
        }
        if (pnpmConfig.lockfileDir) {
            if (opts.cliOptions['lockfile-dir']) {
                throw new error_1.default('CONFIG_CONFLICT_LOCKFILE_DIR_WITH_GLOBAL', 'Configuration conflict. "lockfile-dir" may not be used with "global"');
            }
            delete pnpmConfig.lockfileDir;
        }
        if (opts.cliOptions['virtual-store-dir']) {
            throw new error_1.default('CONFIG_CONFLICT_VIRTUAL_STORE_DIR_WITH_GLOBAL', 'Configuration conflict. "virtual-store-dir" may not be used with "global"');
        }
        delete pnpmConfig.virtualStoreDir;
    }
    else {
        pnpmConfig.dir = cwd;
        pnpmConfig.bin = path.join(pnpmConfig.dir, 'node_modules', '.bin');
    }
    if (opts.cliOptions['save-peer']) {
        if (opts.cliOptions['save-prod']) {
            throw new error_1.default('CONFIG_CONFLICT_PEER_CANNOT_BE_PROD_DEP', 'A package cannot be a peer dependency and a prod dependency at the same time');
        }
        if (opts.cliOptions['save-optional']) {
            throw new error_1.default('CONFIG_CONFLICT_PEER_CANNOT_BE_OPTIONAL_DEP', 'A package cannot be a peer dependency and an optional dependency at the same time');
        }
    }
    if (pnpmConfig.sharedWorkspaceLockfile && !pnpmConfig.lockfileDir && pnpmConfig.workspaceDir) {
        pnpmConfig.lockfileDir = pnpmConfig.workspaceDir;
    }
    pnpmConfig.packageManager = packageManager;
    if (pnpmConfig.only === 'prod' || pnpmConfig.only === 'production' || !pnpmConfig.only && pnpmConfig.production) {
        pnpmConfig.production = true;
        pnpmConfig.dev = false;
    }
    else if (pnpmConfig.only === 'dev' || pnpmConfig.only === 'development' || pnpmConfig.dev) {
        pnpmConfig.production = false;
        pnpmConfig.dev = true;
        pnpmConfig.optional = false;
    }
    else {
        pnpmConfig.production = true;
        pnpmConfig.dev = true;
    }
    if (typeof pnpmConfig.filter === 'string') {
        pnpmConfig.filter = pnpmConfig.filter.split(' ');
    }
    if (!pnpmConfig.ignoreScripts && pnpmConfig.workspaceDir) {
        pnpmConfig.extraBinPaths = [path.join(pnpmConfig.workspaceDir, 'node_modules', '.bin')];
    }
    else {
        pnpmConfig.extraBinPaths = [];
    }
    if (pnpmConfig['shamefullyFlatten']) {
        warnings.push('The "shamefully-flatten" setting has been renamed to "shamefully-hoist". Also, in most cases you won\'t need "shamefully-hoist". Since v4, a semistrict node_modules structure is on by default (via hoist-pattern=[*]).');
        pnpmConfig.shamefullyHoist = true;
    }
    if (!pnpmConfig.storeDir && pnpmConfig['store']) {
        warnings.push('The "store" setting has been renamed to "store-dir". Please use the new name.');
        pnpmConfig.storeDir = pnpmConfig['store'];
    }
    if (pnpmConfig['hoist'] === false) {
        delete pnpmConfig.hoistPattern;
    }
    switch (pnpmConfig.shamefullyHoist) {
        case false:
            delete pnpmConfig.publicHoistPattern;
            break;
        case true:
            pnpmConfig.publicHoistPattern = ['*'];
            break;
        default:
            if (!pnpmConfig.publicHoistPattern ||
                (Array.isArray(pnpmConfig.publicHoistPattern) &&
                    pnpmConfig.publicHoistPattern.length === 1 &&
                    pnpmConfig.publicHoistPattern[0] === '')) {
                delete pnpmConfig.publicHoistPattern;
            }
            break;
    }
    if (typeof pnpmConfig['color'] === 'boolean') {
        switch (pnpmConfig['color']) {
            case true:
                pnpmConfig.color = 'always';
                break;
            case false:
                pnpmConfig.color = 'never';
                break;
            default:
                pnpmConfig.color = 'auto';
                break;
        }
    }
    if (!pnpmConfig.httpsProxy) {
        pnpmConfig.httpsProxy = (_h = pnpmConfig.proxy) !== null && _h !== void 0 ? _h : getProcessEnv('https_proxy');
    }
    if (!pnpmConfig.httpProxy) {
        pnpmConfig.httpProxy = (_k = (_j = pnpmConfig.httpsProxy) !== null && _j !== void 0 ? _j : getProcessEnv('http_proxy')) !== null && _k !== void 0 ? _k : getProcessEnv('proxy');
    }
    if (!pnpmConfig.noProxy) {
        pnpmConfig.noProxy = getProcessEnv('no_proxy');
    }
    return { config: pnpmConfig, warnings };
};
function getProcessEnv(env) {
    var _a, _b;
    return (_b = (_a = process.env[env]) !== null && _a !== void 0 ? _a : process.env[env.toUpperCase()]) !== null && _b !== void 0 ? _b : process.env[env.toLowerCase()];
}
//# sourceMappingURL=index.js.map