"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const cli_utils_1 = require("@pnpm/cli-utils");
const error_1 = require("@pnpm/error");
const filter_workspace_packages_1 = require("@pnpm/filter-workspace-packages");
const find_workspace_packages_1 = require("@pnpm/find-workspace-packages");
const implementation_1 = require("@pnpm/plugin-commands-rebuild/lib/implementation");
const pnpmfile_1 = require("@pnpm/pnpmfile");
const store_connection_manager_1 = require("@pnpm/store-connection-manager");
const supi_1 = require("supi");
const getPinnedVersion_1 = require("./getPinnedVersion");
const getSaveType_1 = require("./getSaveType");
const recursive_1 = require("./recursive");
const updateToLatestSpecsFromManifest_1 = require("./updateToLatestSpecsFromManifest");
const updateWorkspaceDependencies_1 = require("./updateWorkspaceDependencies");
const OVERWRITE_UPDATE_OPTIONS = {
    allowNew: true,
    update: false,
};
async function handler(opts, params) {
    var _a;
    if (opts.workspace) {
        if (opts.latest) {
            throw new error_1.default('BAD_OPTIONS', 'Cannot use --latest with --workspace simultaneously');
        }
        if (!opts.workspaceDir) {
            throw new error_1.default('WORKSPACE_OPTION_OUTSIDE_WORKSPACE', '--workspace can only be used inside a workspace');
        }
        if (!opts.linkWorkspacePackages && !opts.saveWorkspaceProtocol) {
            if (opts.rawLocalConfig['save-workspace-protocol'] === false) {
                throw new error_1.default('BAD_OPTIONS', `This workspace has link-workspace-packages turned off, \
so dependencies are linked from the workspace only when the workspace protocol is used. \
Either set link-workspace-packages to true or don't use the --no-save-workspace-protocol option \
when running add/update with the --workspace option`);
            }
            else {
                opts.saveWorkspaceProtocol = true;
            }
        }
        opts['preserveWorkspaceProtocol'] = !opts.linkWorkspacePackages;
    }
    const includeDirect = (_a = opts.includeDirect) !== null && _a !== void 0 ? _a : {
        dependencies: true,
        devDependencies: true,
        optionalDependencies: true,
    };
    if (opts.recursive && opts.allProjects && opts.selectedProjectsGraph && opts.workspaceDir) {
        await recursive_1.default(opts.allProjects, params, {
            ...opts,
            selectedProjectsGraph: opts.selectedProjectsGraph,
            workspaceDir: opts.workspaceDir,
        }, opts.update ? 'update' : (params.length === 0 ? 'install' : 'add'));
        return;
    }
    // `pnpm install ""` is going to be just `pnpm install`
    params = params.filter(Boolean);
    const dir = opts.dir || process.cwd();
    let allProjects = opts.allProjects;
    let workspacePackages = undefined;
    if (opts.workspaceDir) {
        allProjects = allProjects !== null && allProjects !== void 0 ? allProjects : await find_workspace_packages_1.default(opts.workspaceDir, opts);
        workspacePackages = find_workspace_packages_1.arrayOfWorkspacePackagesToMap(allProjects);
    }
    const store = await store_connection_manager_1.createOrConnectStoreController(opts);
    const installOpts = {
        ...opts,
        // In case installation is done in a multi-package repository
        // The dependencies should be built first,
        // so ignoring scripts for now
        ignoreScripts: !!workspacePackages || opts.ignoreScripts,
        linkWorkspacePackagesDepth: opts.linkWorkspacePackages === 'deep' ? Infinity : opts.linkWorkspacePackages ? 0 : -1,
        sideEffectsCacheRead: opts.sideEffectsCache || opts.sideEffectsCacheReadonly,
        sideEffectsCacheWrite: opts.sideEffectsCache,
        storeController: store.ctrl,
        storeDir: store.dir,
        workspacePackages,
        forceHoistPattern: typeof opts.rawLocalConfig['hoist-pattern'] !== 'undefined'
            || typeof opts.rawLocalConfig['hoist'] !== 'undefined',
        forcePublicHoistPattern: typeof opts.rawLocalConfig['shamefully-hoist'] !== 'undefined'
            || typeof opts.rawLocalConfig['public-hoist-pattern'] !== 'undefined',
    };
    if (!opts.ignorePnpmfile) {
        installOpts['hooks'] = pnpmfile_1.requireHooks(opts.lockfileDir || dir, opts);
    }
    let { manifest, writeProjectManifest } = await cli_utils_1.tryReadProjectManifest(opts.dir, opts);
    if (manifest === null) {
        if (opts.update) {
            throw new error_1.default('NO_IMPORTER_MANIFEST', 'No package.json found');
        }
        manifest = {};
    }
    const updateMatch = opts.update && params.length ? recursive_1.createMatcher(params) : null;
    if (updateMatch) {
        params = recursive_1.matchDependencies(updateMatch, manifest, includeDirect);
        if (!params.length) {
            throw new error_1.default('NO_PACKAGE_IN_DEPENDENCIES', 'None of the specified packages were found in the dependencies.');
        }
    }
    if (opts.update && opts.latest) {
        if (!params || !params.length) {
            params = updateToLatestSpecsFromManifest_1.default(manifest, includeDirect);
        }
        else {
            params = updateToLatestSpecsFromManifest_1.createLatestSpecs(params, manifest);
        }
    }
    if (opts.workspace) {
        if (!params || !params.length) {
            params = updateWorkspaceDependencies_1.updateToWorkspacePackagesFromManifest(manifest, includeDirect, workspacePackages);
        }
        else {
            params = updateWorkspaceDependencies_1.createWorkspaceSpecs(params, workspacePackages);
        }
    }
    if (!params || !params.length) {
        const updatedManifest = await supi_1.install(manifest, installOpts);
        if (opts.update === true && opts.save !== false) {
            await writeProjectManifest(updatedManifest);
        }
    }
    else {
        const [updatedImporter] = await supi_1.mutateModules([
            {
                allowNew: opts.allowNew,
                binsDir: installOpts.bin,
                dependencySelectors: params,
                manifest,
                mutation: 'installSome',
                peer: opts.savePeer,
                pinnedVersion: getPinnedVersion_1.default(opts),
                rootDir: installOpts.dir,
                targetDependenciesField: getSaveType_1.default(installOpts),
            },
        ], installOpts);
        if (opts.save !== false) {
            await writeProjectManifest(updatedImporter.manifest);
        }
    }
    if (opts.linkWorkspacePackages && opts.workspaceDir) {
        allProjects = allProjects !== null && allProjects !== void 0 ? allProjects : await find_workspace_packages_1.default(opts.workspaceDir, opts);
        const { selectedProjectsGraph } = await filter_workspace_packages_1.filterPkgsBySelectorObjects(allProjects, [
            {
                excludeSelf: true,
                includeDependencies: true,
                parentDir: dir,
            },
        ], {
            workspaceDir: opts.workspaceDir,
        });
        await recursive_1.default(allProjects, [], {
            ...opts,
            ...OVERWRITE_UPDATE_OPTIONS,
            selectedProjectsGraph,
            workspaceDir: opts.workspaceDir,
        }, 'install');
        if (opts.ignoreScripts)
            return;
        await implementation_1.rebuild([
            {
                buildIndex: 0,
                manifest: await cli_utils_1.readProjectManifestOnly(opts.dir, opts),
                rootDir: opts.dir,
            },
        ], {
            ...opts,
            pending: true,
            storeController: store.ctrl,
            storeDir: store.dir,
        });
    }
}
exports.default = handler;
//# sourceMappingURL=installDeps.js.map