"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handler = exports.help = exports.completion = exports.commandNames = exports.shorthands = exports.cliOptionsTypes = exports.rcOptionsTypes = void 0;
const cli_utils_1 = require("@pnpm/cli-utils");
const common_cli_options_help_1 = require("@pnpm/common-cli-options-help");
const config_1 = require("@pnpm/config");
const outdated_1 = require("@pnpm/outdated");
const chalk = require("chalk");
const enquirer_1 = require("enquirer");
const R = require("ramda");
const renderHelp = require("render-help");
const installDeps_1 = require("../installDeps");
const getUpdateChoices_1 = require("./getUpdateChoices");
function rcOptionsTypes() {
    return R.pick([
        'depth',
        'dev',
        'engine-strict',
        'force',
        'global-dir',
        'global-pnpmfile',
        'global',
        'ignore-pnpmfile',
        'ignore-scripts',
        'lockfile-dir',
        'lockfile-directory',
        'lockfile-only',
        'lockfile',
        'network-concurrency',
        'npmPath',
        'offline',
        'only',
        'optional',
        'package-import-method',
        'pnpmfile',
        'prefer-offline',
        'production',
        'registry',
        'reporter',
        'save',
        'save-exact',
        'shamefully-flatten',
        'shamefully-hoist',
        'shared-workspace-lockfile',
        'side-effects-cache-readonly',
        'side-effects-cache',
        'store',
        'store-dir',
        'unsafe-perm',
        'use-running-store-server',
    ], config_1.types);
}
exports.rcOptionsTypes = rcOptionsTypes;
function cliOptionsTypes() {
    return {
        ...rcOptionsTypes(),
        interactive: Boolean,
        latest: Boolean,
        recursive: Boolean,
        workspace: Boolean,
    };
}
exports.cliOptionsTypes = cliOptionsTypes;
exports.shorthands = {
    'D': '--dev',
    'P': '--production',
};
exports.commandNames = ['update', 'up', 'upgrade'];
exports.completion = (cliOpts) => {
    return cli_utils_1.readDepNameCompletions(cliOpts.dir);
};
function help() {
    return renderHelp({
        aliases: ['up', 'upgrade'],
        description: 'Updates packages to their latest version based on the specified range. You can use "*" in package name to update all packages with the same pattern.',
        descriptionLists: [
            {
                title: 'Options',
                list: [
                    {
                        description: `Update in every package found in subdirectories \
or every workspace package, when executed inside a workspace. \
For options that may be used with \`-r\`, see "pnpm help recursive"`,
                        name: '--recursive',
                        shortAlias: '-r',
                    },
                    {
                        description: 'Update globally installed packages',
                        name: '--global',
                        shortAlias: '-g',
                    },
                    {
                        description: 'How deep should levels of dependencies be inspected. 0 is default, which means top-level dependencies',
                        name: '--depth <number>',
                    },
                    {
                        description: 'Ignore version ranges in package.json',
                        name: '--latest',
                        shortAlias: '-L',
                    },
                    {
                        description: 'Update packages only in "dependencies" and "optionalDependencies"',
                        name: '--prod',
                        shortAlias: '-P',
                    },
                    {
                        description: 'Update packages only in "devDependencies"',
                        name: '--dev',
                        shortAlias: '-D',
                    },
                    {
                        description: `Don't update packages in "optionalDependencies"`,
                        name: '--no-optional',
                    },
                    {
                        description: `Tries to link all packages from the workspace. \
Versions are updated to match the versions of packages inside the workspace. \
If specific packages are updated, the command will fail if any of the updated \
dependencies is not found inside the workspace`,
                        name: '--workspace',
                    },
                    {
                        description: 'Show outdated dependencies and select which ones to update',
                        name: '--interactive',
                        shortAlias: '-i',
                    },
                    common_cli_options_help_1.OPTIONS.globalDir,
                    ...common_cli_options_help_1.UNIVERSAL_OPTIONS,
                ],
            },
            common_cli_options_help_1.FILTERING,
        ],
        url: cli_utils_1.docsUrl('update'),
        usages: ['pnpm update [-g] [<pkg>...]'],
    });
}
exports.help = help;
async function handler(opts, params = []) {
    if (opts.interactive) {
        return interactiveUpdate(params, opts);
    }
    return update(params, opts);
}
exports.handler = handler;
async function interactiveUpdate(input, opts) {
    const include = {
        dependencies: opts.production !== false,
        devDependencies: opts.dev !== false,
        optionalDependencies: opts.optional !== false,
    };
    const projects = opts.selectedProjectsGraph
        ? Object.values(opts.selectedProjectsGraph).map((wsPkg) => wsPkg.package)
        : [
            {
                dir: opts.dir,
                manifest: await cli_utils_1.readProjectManifestOnly(opts.dir, opts),
            },
        ];
    const outdatedPkgsOfProjects = await outdated_1.outdatedDepsOfProjects(projects, input, {
        ...opts,
        compatible: opts.latest !== true,
        include,
    });
    const choices = getUpdateChoices_1.default(R.unnest(outdatedPkgsOfProjects));
    if (choices.length === 0) {
        if (opts.latest) {
            return 'All of your dependencies are already up-to-date';
        }
        return 'All of your dependencies are already up-to-date inside the specified ranges. Use the --latest option to update the ranges in package.json';
    }
    const { updateDependencies } = await enquirer_1.prompt({
        choices,
        footer: '\nEnter to start updating. Ctrl-c to cancel.',
        indicator(state, choice) {
            return ` ${choice.enabled ? '●' : '○'}`;
        },
        message: `Choose which packages to update ` +
            `(Press ${chalk.cyan('<space>')} to select, ` +
            `${chalk.cyan('<a>')} to toggle all, ` +
            `${chalk.cyan('<i>')} to invert selection)`,
        name: 'updateDependencies',
        pointer: '❯',
        styles: {
            dark: chalk.white,
            em: chalk.bgBlack.whiteBright,
            success: chalk.white,
        },
        type: 'multiselect',
        validate(value) {
            if (value.length === 0) {
                return 'You must choose at least one package.';
            }
            return true;
        },
        // For Vim users (related: https://github.com/enquirer/enquirer/pull/163)
        j() { return this.down(); },
        k() { return this.up(); },
    }); // tslint:disable-line:no-any
    return update(updateDependencies, opts);
}
async function update(dependencies, opts) {
    const includeDirect = {
        dependencies: opts.production !== false,
        devDependencies: opts.dev !== false,
        optionalDependencies: opts.optional !== false,
    };
    return installDeps_1.default({
        ...opts,
        allowNew: false,
        includeDirect,
        update: true,
        updatePackageManifest: opts.save !== false,
    }, dependencies);
}
//# sourceMappingURL=index.js.map