"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("@pnpm/constants");
const core_loggers_1 = require("@pnpm/core-loggers");
const lockfile_file_1 = require("@pnpm/lockfile-file");
const logger_1 = require("@pnpm/logger");
const modules_cleaner_1 = require("@pnpm/modules-cleaner");
const modules_yaml_1 = require("@pnpm/modules-yaml");
const prune_lockfile_1 = require("@pnpm/prune-lockfile");
const shamefully_flatten_1 = require("@pnpm/shamefully-flatten");
const utils_1 = require("@pnpm/utils");
const dp = require("dependency-path");
const path = require("path");
const getContext_1 = require("../getContext");
const lock_1 = require("../lock");
const lockfilesEqual_1 = require("../lockfilesEqual");
const extendUninstallOptions_1 = require("./extendUninstallOptions");
const removeDeps_1 = require("./removeDeps");
async function uninstall(pkgsToUninstall, maybeOpts) {
    const reporter = maybeOpts && maybeOpts.reporter;
    if (reporter) {
        logger_1.streamParser.on('data', reporter);
    }
    const opts = await extendUninstallOptions_1.default(maybeOpts);
    if (opts.lock) {
        await lock_1.default(opts.prefix, _uninstall, {
            locks: opts.locks,
            prefix: opts.prefix,
            stale: opts.lockStaleDuration,
            storeController: opts.storeController,
        });
    }
    else {
        await _uninstall();
    }
    if (reporter) {
        logger_1.streamParser.removeListener('data', reporter);
    }
    async function _uninstall() {
        const ctx = await getContext_1.getContextForSingleImporter(opts);
        if (!ctx.pkg) {
            throw new Error('No package.json found - cannot uninstall');
        }
        return uninstallInContext(pkgsToUninstall, ctx, opts);
    }
}
exports.default = uninstall;
async function uninstallInContext(pkgsToUninstall, ctx, opts) {
    const makePartialCurrentLockfile = !lockfilesEqual_1.default(ctx.currentLockfile, ctx.wantedLockfile);
    const pkgJsonPath = path.join(ctx.prefix, 'package.json');
    const saveType = utils_1.getSaveType(opts);
    const pkg = await removeDeps_1.default(pkgJsonPath, pkgsToUninstall, { prefix: opts.prefix, saveType });
    const newLockfile = prune_lockfile_1.pruneLockfile(ctx.wantedLockfile, pkg, ctx.importerId, {
        defaultRegistry: ctx.registries.default,
        warn: (message) => logger_1.default.warn({ message, prefix: ctx.prefix }),
    });
    const removedPkgIds = await modules_cleaner_1.prune({
        importers: [
            {
                bin: opts.bin,
                hoistedAliases: ctx.hoistedAliases,
                id: ctx.importerId,
                modulesDir: ctx.modulesDir,
                prefix: ctx.prefix,
                removePackages: pkgsToUninstall,
                shamefullyFlatten: opts.shamefullyFlatten,
            },
        ],
        lockfileDirectory: opts.lockfileDirectory,
        newLockfile,
        oldLockfile: ctx.currentLockfile,
        registries: ctx.registries,
        storeController: opts.storeController,
        virtualStoreDir: ctx.virtualStoreDir,
    });
    ctx.pendingBuilds = ctx.pendingBuilds.filter((pkgId) => !removedPkgIds.has(dp.resolve(ctx.registries, pkgId)));
    await opts.storeController.close();
    const currentLockfile = makePartialCurrentLockfile
        ? prune_lockfile_1.pruneLockfile(ctx.currentLockfile, pkg, ctx.importerId, { defaultRegistry: ctx.registries.default })
        : newLockfile;
    const lockfileOpts = { forceSharedFormat: opts.forceSharedLockfile };
    if (opts.useLockfile) {
        await lockfile_file_1.writeLockfiles(ctx.lockfileDirectory, newLockfile, currentLockfile, lockfileOpts);
    }
    else {
        await lockfile_file_1.writeCurrentLockfile(ctx.lockfileDirectory, currentLockfile, lockfileOpts);
    }
    if (opts.shamefullyFlatten) {
        ctx.hoistedAliases = await shamefully_flatten_1.shamefullyFlattenByLockfile(currentLockfile, ctx.importerId, {
            getIndependentPackageLocation: opts.independentLeaves
                ? async (packageId, packageName) => {
                    const { directory } = await opts.storeController.getPackageLocation(packageId, packageName, {
                        lockfileDirectory: ctx.lockfileDirectory,
                        targetEngine: opts.sideEffectsCacheRead && constants_1.ENGINE_NAME || undefined,
                    });
                    return directory;
                }
                : undefined,
            lockfileDirectory: opts.lockfileDirectory,
            modulesDir: ctx.modulesDir,
            registries: ctx.registries,
            virtualStoreDir: ctx.virtualStoreDir,
        }) || {};
    }
    await modules_yaml_1.write(ctx.virtualStoreDir, Object.assign({}, ctx.modulesFile, { importers: Object.assign({}, ctx.modulesFile && ctx.modulesFile.importers, { [ctx.importerId]: {
                hoistedAliases: ctx.hoistedAliases,
                shamefullyFlatten: opts.shamefullyFlatten,
            } }), included: ctx.include, independentLeaves: opts.independentLeaves, layoutVersion: constants_1.LAYOUT_VERSION, packageManager: `${opts.packageManager.name}@${opts.packageManager.version}`, pendingBuilds: ctx.pendingBuilds, registries: ctx.registries, skipped: Array.from(ctx.skipped).filter((pkgId) => !removedPkgIds.has(pkgId)), store: ctx.storePath }));
    core_loggers_1.summaryLogger.debug({ prefix: opts.prefix });
}
exports.uninstallInContext = uninstallInContext;
//# sourceMappingURL=index.js.map