"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.handler = exports.help = exports.commandNames = exports.completion = exports.cliOptionsTypes = exports.rcOptionsTypes = exports.shorthands = exports.PARALLEL_OPTION_HELP = exports.IF_PRESENT_OPTION_HELP = exports.IF_PRESENT_OPTION = 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 error_1 = __importDefault(require("@pnpm/error"));
const lifecycle_1 = __importDefault(require("@pnpm/lifecycle"));
const runRecursive_1 = __importDefault(require("./runRecursive"));
const path = require("path");
const R = require("ramda");
const realpathMissing = require("realpath-missing");
const renderHelp = require("render-help");
exports.IF_PRESENT_OPTION = {
    'if-present': Boolean,
};
exports.IF_PRESENT_OPTION_HELP = {
    description: 'Avoid exiting with a non-zero exit code when the script is undefined',
    name: '--if-present',
};
exports.PARALLEL_OPTION_HELP = {
    description: 'Completely disregard concurrency and topological sorting, \
running a given script immediately in all matching packages \
with prefixed streaming output. This is the preferred flag \
for long-running processes such as watch run over many packages.',
    name: '--parallel',
};
exports.shorthands = {
    parallel: [
        '--workspace-concurrency=Infinity',
        '--no-sort',
        '--stream',
        '--recursive',
    ],
};
function rcOptionsTypes() {
    return {
        ...R.pick([
            'npm-path',
        ], config_1.types),
    };
}
exports.rcOptionsTypes = rcOptionsTypes;
function cliOptionsTypes() {
    return {
        ...R.pick([
            'bail',
            'sort',
            'unsafe-perm',
            'workspace-concurrency',
        ], config_1.types),
        ...exports.IF_PRESENT_OPTION,
        recursive: Boolean,
    };
}
exports.cliOptionsTypes = cliOptionsTypes;
exports.completion = async (cliOpts, params) => {
    var _a, _b;
    if (params.length > 0) {
        return [];
    }
    const manifest = await cli_utils_1.readProjectManifestOnly((_a = cliOpts.dir) !== null && _a !== void 0 ? _a : process.cwd(), cliOpts);
    return Object.keys((_b = manifest.scripts) !== null && _b !== void 0 ? _b : {}).map((name) => ({ name }));
};
exports.commandNames = ['run', 'run-script'];
function help() {
    return renderHelp({
        aliases: ['run-script'],
        description: 'Runs a defined package script.',
        descriptionLists: [
            {
                title: 'Options',
                list: [
                    {
                        description: 'Run the defined package script 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',
                    },
                    exports.IF_PRESENT_OPTION_HELP,
                    exports.PARALLEL_OPTION_HELP,
                    ...common_cli_options_help_1.UNIVERSAL_OPTIONS,
                ],
            },
            common_cli_options_help_1.FILTERING,
        ],
        url: cli_utils_1.docsUrl('run'),
        usages: ['pnpm run <command> [-- <args>...]'],
    });
}
exports.help = help;
async function handler(opts, params) {
    var _a, _b, _c, _d;
    let dir;
    const [scriptName, ...passedThruArgs] = params;
    if (opts.recursive) {
        if (scriptName || Object.keys(opts.selectedProjectsGraph).length > 1) {
            await runRecursive_1.default(params, opts);
            return;
        }
        dir = Object.keys(opts.selectedProjectsGraph)[0];
    }
    else {
        dir = opts.dir;
    }
    const manifest = await cli_utils_1.readProjectManifestOnly(dir, opts);
    if (!scriptName) {
        const rootManifest = opts.workspaceDir ? (await cli_utils_1.tryReadProjectManifest(opts.workspaceDir, opts)).manifest : undefined;
        return printProjectCommands(manifest, rootManifest !== null && rootManifest !== void 0 ? rootManifest : undefined);
    }
    if (scriptName !== 'start' && !((_a = manifest.scripts) === null || _a === void 0 ? void 0 : _a[scriptName])) {
        if (opts.ifPresent)
            return;
        if (opts.workspaceDir) {
            const { manifest: rootManifest } = await cli_utils_1.tryReadProjectManifest(opts.workspaceDir, opts);
            if ((_b = rootManifest === null || rootManifest === void 0 ? void 0 : rootManifest.scripts) === null || _b === void 0 ? void 0 : _b[scriptName]) {
                throw new error_1.default('NO_SCRIPT', `Missing script: ${scriptName}`, {
                    hint: `But ${scriptName} is present in the root of the workspace,
so you may run "pnpm -w ${scriptName}"`,
                });
            }
        }
        throw new error_1.default('NO_SCRIPT', `Missing script: ${scriptName}`);
    }
    const lifecycleOpts = {
        depPath: dir,
        extraBinPaths: opts.extraBinPaths,
        pkgRoot: dir,
        rawConfig: opts.rawConfig,
        rootModulesDir: await realpathMissing(path.join(dir, 'node_modules')),
        silent: opts.reporter === 'silent',
        shellEmulator: opts.shellEmulator,
        stdio: 'inherit',
        unsafePerm: true,
    };
    if ((_c = manifest.scripts) === null || _c === void 0 ? void 0 : _c[`pre${scriptName}`]) {
        await lifecycle_1.default(`pre${scriptName}`, manifest, lifecycleOpts);
    }
    await lifecycle_1.default(scriptName, manifest, { ...lifecycleOpts, args: passedThruArgs });
    if ((_d = manifest.scripts) === null || _d === void 0 ? void 0 : _d[`post${scriptName}`]) {
        await lifecycle_1.default(`post${scriptName}`, manifest, lifecycleOpts);
    }
    return undefined;
}
exports.handler = handler;
const ALL_LIFECYCLE_SCRIPTS = new Set([
    'prepublish',
    'prepare',
    'prepublishOnly',
    'prepack',
    'postpack',
    'publish',
    'postpublish',
    'preinstall',
    'install',
    'postinstall',
    'preuninstall',
    'uninstall',
    'postuninstall',
    'preversion',
    'version',
    'postversion',
    'pretest',
    'test',
    'posttest',
    'prestop',
    'stop',
    'poststop',
    'prestart',
    'start',
    'poststart',
    'prerestart',
    'restart',
    'postrestart',
    'preshrinkwrap',
    'shrinkwrap',
    'postshrinkwrap',
]);
function printProjectCommands(manifest, rootManifest) {
    var _a;
    const lifecycleScripts = [];
    const otherScripts = [];
    for (const [scriptName, script] of Object.entries((_a = manifest.scripts) !== null && _a !== void 0 ? _a : {})) {
        if (ALL_LIFECYCLE_SCRIPTS.has(scriptName)) {
            lifecycleScripts.push([scriptName, script]);
        }
        else {
            otherScripts.push([scriptName, script]);
        }
    }
    if (lifecycleScripts.length === 0 && otherScripts.length === 0) {
        return 'There are no scripts specified.';
    }
    let output = '';
    if (lifecycleScripts.length > 0) {
        output += `Lifecycle scripts:\n${renderCommands(lifecycleScripts)}`;
    }
    if (otherScripts.length > 0) {
        if (output !== '')
            output += '\n\n';
        output += `Commands available via "pnpm run":\n${renderCommands(otherScripts)}`;
    }
    if (!(rootManifest === null || rootManifest === void 0 ? void 0 : rootManifest.scripts)) {
        return output;
    }
    const rootScripts = Object.entries(rootManifest.scripts);
    if (!rootScripts.length) {
        return output;
    }
    if (output !== '')
        output += '\n\n';
    output += `Commands of the root workspace project (to run them, use "pnpm -w run"):
${renderCommands(rootScripts)}`;
    return output;
}
function renderCommands(commands) {
    return commands.map(([scriptName, script]) => `  ${scriptName}\n    ${script}`).join('\n');
}
//# sourceMappingURL=run.js.map