"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fakeRegularManifest = exports.handler = exports.help = exports.commandNames = exports.cliOptionsTypes = exports.rcOptionsTypes = void 0;
const cli_utils_1 = require("@pnpm/cli-utils");
const config_1 = require("@pnpm/config");
const error_1 = __importDefault(require("@pnpm/error"));
const exportable_manifest_1 = __importDefault(require("@pnpm/exportable-manifest"));
const lifecycle_1 = __importDefault(require("@pnpm/lifecycle"));
const run_npm_1 = __importDefault(require("@pnpm/run-npm"));
const enquirer_1 = require("enquirer");
const gitChecks_1 = require("./gitChecks");
const recursivePublish_1 = __importDefault(require("./recursivePublish"));
const path = require("path");
const rimraf = require("@zkochan/rimraf");
const cpFile = require("cp-file");
const fg = require("fast-glob");
const fs = require("mz/fs");
const R = require("ramda");
const realpathMissing = require("realpath-missing");
const renderHelp = require("render-help");
const writeJsonFile = require("write-json-file");
function rcOptionsTypes() {
    return R.pick([
        'access',
        'git-checks',
        'ignore-scripts',
        'npm-path',
        'otp',
        'publish-branch',
        'registry',
        'tag',
        'unsafe-perm',
    ], config_1.types);
}
exports.rcOptionsTypes = rcOptionsTypes;
function cliOptionsTypes() {
    return {
        ...rcOptionsTypes(),
        'dry-run': Boolean,
        json: Boolean,
        recursive: Boolean,
    };
}
exports.cliOptionsTypes = cliOptionsTypes;
exports.commandNames = ['publish'];
function help() {
    return renderHelp({
        description: 'Publishes a package to the npm registry.',
        descriptionLists: [
            {
                title: 'Options',
                list: [
                    {
                        description: "Don't check if current branch is your publish branch, clean, and up-to-date",
                        name: '--no-git-checks',
                    },
                    {
                        description: 'Sets branch name to publish. Default is master',
                        name: '--publish-branch',
                    },
                    {
                        description: 'Does everything a publish would do except actually publishing to the registry',
                        name: '--dry-run',
                    },
                    {
                        description: 'Registers the published package with the given tag. By default, the "latest" tag is used.',
                        name: '--tag <tag>',
                    },
                    {
                        description: 'Tells the registry whether this package should be published as public or restricted',
                        name: '--access <public|restricted>',
                    },
                    {
                        description: 'Ignores any publish related lifecycle scripts (prepublishOnly, postpublish, and the like)',
                        name: '--ignore-scripts',
                    },
                ],
            },
        ],
        url: cli_utils_1.docsUrl('publish'),
        usages: ['pnpm publish [<tarball>|<dir>] [--tag <tag>] [--access <public|restricted>] [options]'],
    });
}
exports.help = help;
const GIT_CHECKS_HINT = 'If you want to disable Git checks on publish, set the "git-checks" setting to "false".';
async function handler(opts, params) {
    var _a, _b, _c;
    if (opts.gitChecks !== false && await gitChecks_1.isGitRepo()) {
        if (!(await gitChecks_1.isWorkingTreeClean())) {
            throw new error_1.default('GIT_NOT_UNCLEAN', 'Unclean working tree. Commit or stash changes first.', {
                hint: GIT_CHECKS_HINT,
            });
        }
        const branch = (_a = opts.publishBranch) !== null && _a !== void 0 ? _a : 'master';
        const currentBranch = await gitChecks_1.getCurrentBranch();
        if (currentBranch !== branch) {
            const { confirm } = await enquirer_1.prompt({
                message: `You're on branch "${currentBranch}" but your "publish-branch" is set to "${branch}". \
Do you want to continue?`,
                name: 'confirm',
                type: 'confirm',
            }); // eslint-disable-line @typescript-eslint/no-explicit-any
            if (!confirm) {
                throw new error_1.default('GIT_NOT_CORRECT_BRANCH', `Branch is not on '${branch}'.`, {
                    hint: GIT_CHECKS_HINT,
                });
            }
        }
        if (!(await gitChecks_1.isRemoteHistoryClean())) {
            throw new error_1.default('GIT_NOT_LATEST', 'Remote history differs. Please pull changes.', {
                hint: GIT_CHECKS_HINT,
            });
        }
    }
    if (opts.recursive && opts.selectedProjectsGraph) {
        await recursivePublish_1.default({
            ...opts,
            selectedProjectsGraph: opts.selectedProjectsGraph,
            workspaceDir: (_b = opts.workspaceDir) !== null && _b !== void 0 ? _b : process.cwd(),
        });
        return;
    }
    if (params.length && params[0].endsWith('.tgz')) {
        run_npm_1.default(opts.npmPath, ['publish', ...params]);
        return;
    }
    const dir = params.length && params[0] || process.cwd();
    const _runScriptsIfPresent = runScriptsIfPresent.bind(null, {
        depPath: dir,
        extraBinPaths: opts.extraBinPaths,
        pkgRoot: dir,
        rawConfig: opts.rawConfig,
        rootModulesDir: await realpathMissing(path.join(dir, 'node_modules')),
        stdio: 'inherit',
        unsafePerm: true,
    });
    let _status;
    await fakeRegularManifest({
        dir,
        engineStrict: opts.engineStrict,
        workspaceDir: (_c = opts.workspaceDir) !== null && _c !== void 0 ? _c : dir,
    }, async (publishManifest) => {
        // Unfortunately, we cannot support postpack at the moment
        if (!opts.ignoreScripts) {
            await _runScriptsIfPresent([
                'prepublish',
                'prepare',
                'prepublishOnly',
                'prepack',
            ], publishManifest);
        }
        const { status } = run_npm_1.default(opts.npmPath, ['publish', '--ignore-scripts', ...opts.argv.original.slice(1)]);
        if (!opts.ignoreScripts) {
            await _runScriptsIfPresent([
                'publish',
                'postpublish',
            ], publishManifest);
        }
        _status = status;
    });
    if (_status !== 0) {
        process.exit(_status);
    }
}
exports.handler = handler;
async function runScriptsIfPresent(opts, scriptNames, manifest) {
    var _a;
    for (const scriptName of scriptNames) {
        if (!((_a = manifest.scripts) === null || _a === void 0 ? void 0 : _a[scriptName]))
            continue;
        await lifecycle_1.default(scriptName, manifest, opts);
    }
}
const LICENSE_GLOB = 'LICEN{S,C}E{,.*}';
const findLicenses = fg.bind(fg, [LICENSE_GLOB]);
async function fakeRegularManifest(opts, fn) {
    // If a workspace package has no License of its own,
    // license files from the root of the workspace are used
    const copiedLicenses = opts.dir !== opts.workspaceDir && (await findLicenses({ cwd: opts.dir })).length === 0
        ? await copyLicenses(opts.workspaceDir, opts.dir) : [];
    const { fileName, manifest, writeProjectManifest } = await cli_utils_1.readProjectManifest(opts.dir, opts);
    const publishManifest = await exportable_manifest_1.default(opts.dir, manifest);
    const replaceManifest = fileName !== 'package.json' || !R.equals(manifest, publishManifest);
    if (replaceManifest) {
        await rimraf(path.join(opts.dir, fileName));
        await writeJsonFile(path.join(opts.dir, 'package.json'), publishManifest);
    }
    await fn(publishManifest);
    if (replaceManifest) {
        await rimraf(path.join(opts.dir, 'package.json'));
        await writeProjectManifest(manifest, true);
    }
    await Promise.all(copiedLicenses.map((copiedLicense) => fs.unlink(copiedLicense)));
}
exports.fakeRegularManifest = fakeRegularManifest;
async function copyLicenses(sourceDir, destDir) {
    const licenses = await findLicenses({ cwd: sourceDir });
    if (licenses.length === 0)
        return [];
    const copiedLicenses = [];
    await Promise.all(licenses
        .map((licenseRelPath) => path.join(sourceDir, licenseRelPath))
        .map((licensePath) => {
        const licenseCopyDest = path.join(destDir, path.basename(licensePath));
        copiedLicenses.push(licenseCopyDest);
        return cpFile(licensePath, licenseCopyDest);
    }));
    return copiedLicenses;
}
//# sourceMappingURL=publish.js.map