"use strict";
exports.id = "PackageJsonUpdater";
exports.ids = ["PackageJsonUpdater"];
exports.modules = {

/***/ 254591
/*!**********************************************************!*\
  !*** ./lib-intermediate-esm/logic/PackageJsonUpdater.js ***!
  \**********************************************************/
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   PackageJsonUpdater: () => (/* binding */ PackageJsonUpdater)
/* harmony export */ });
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! semver */ 338064);
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(semver__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @rushstack/terminal */ 367587);
/* harmony import */ var _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _rushstack_node_core_library__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @rushstack/node-core-library */ 277275);
/* harmony import */ var _rushstack_node_core_library__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_rushstack_node_core_library__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _InstallManagerFactory__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./InstallManagerFactory */ 284158);
/* harmony import */ var _versionMismatch_VersionMismatchFinder__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./versionMismatch/VersionMismatchFinder */ 729749);
/* harmony import */ var _PurgeManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./PurgeManager */ 123186);
/* harmony import */ var _utilities_Utilities__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utilities/Utilities */ 591564);
/* harmony import */ var _api_PackageJsonEditor__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../api/PackageJsonEditor */ 519511);
/* harmony import */ var _versionMismatch_VersionMismatchFinderProject__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./versionMismatch/VersionMismatchFinderProject */ 537192);
/* harmony import */ var _RushConstants__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./RushConstants */ 370253);
/* harmony import */ var _installManager_InstallHelpers__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./installManager/InstallHelpers */ 766517);
/* harmony import */ var _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./PackageJsonUpdaterTypes */ 791394);
/* harmony import */ var _cli_actions_AddAction__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../cli/actions/AddAction */ 825331);
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.













/**
 * A helper class for managing the dependencies of various package.json files.
 * @internal
 */
class PackageJsonUpdater {
    constructor(terminal, rushConfiguration, rushGlobalFolder) {
        this._terminal = terminal;
        this._rushConfiguration = rushConfiguration;
        this._rushGlobalFolder = rushGlobalFolder;
    }
    /**
     * Upgrade dependencies to a particular project, or across specified projects. This is the core business logic for
     * "rush upgrade-interactive".
     */
    async doRushUpgradeAsync(options) {
        const { projects, packagesToAdd, updateOtherPackages, skipUpdate, debugInstall, variant } = options;
        const { DependencyAnalyzer } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ./DependencyAnalyzer */ 699335));
        const dependencyAnalyzer = DependencyAnalyzer.forRushConfiguration(this._rushConfiguration);
        const { allVersionsByPackageName, implicitlyPreferredVersionByPackageName, commonVersionsConfiguration } = dependencyAnalyzer.getAnalysis(undefined, variant, false);
        const dependenciesToUpdate = {};
        const devDependenciesToUpdate = {};
        const peerDependenciesToUpdate = {};
        for (const { moduleName, latest: latestVersion, packageJson, devDependency } of packagesToAdd) {
            const inferredRangeStyle = this._cheaplyDetectSemVerRangeStyle(packageJson);
            const implicitlyPreferredVersion = implicitlyPreferredVersionByPackageName.get(moduleName);
            const explicitlyPreferredVersion = commonVersionsConfiguration.preferredVersions.get(moduleName);
            const version = await this._getNormalizedVersionSpecAsync(projects, moduleName, latestVersion, implicitlyPreferredVersion, explicitlyPreferredVersion, inferredRangeStyle, commonVersionsConfiguration.ensureConsistentVersions);
            if (devDependency) {
                devDependenciesToUpdate[moduleName] = version;
            }
            else {
                dependenciesToUpdate[moduleName] = version;
            }
            this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green(`Updating projects to use `) + moduleName + '@' + _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(version));
            this._terminal.writeLine();
            const existingSpecifiedVersions = allVersionsByPackageName.get(moduleName);
            if (existingSpecifiedVersions &&
                !existingSpecifiedVersions.has(version) &&
                commonVersionsConfiguration.ensureConsistentVersions &&
                !updateOtherPackages) {
                // There are existing versions, and the version we're going to use is not one of them, and this repo
                // requires consistent versions, and we aren't going to update other packages, so we can't proceed.
                const existingVersionList = Array.from(existingSpecifiedVersions).join(', ');
                throw new Error(`Adding '${moduleName}@${version}' ` +
                    `causes mismatched dependencies. Use the "--make-consistent" flag to update other packages to use ` +
                    `this version, or try specify one of the existing versions (${existingVersionList}).`);
            }
        }
        const allPackageUpdates = new Map();
        const allDependenciesToUpdate = [
            ...Object.entries(dependenciesToUpdate),
            ...Object.entries(devDependenciesToUpdate),
            ...Object.entries(peerDependenciesToUpdate)
        ];
        for (const project of projects) {
            const mismatchFinderProject = new _versionMismatch_VersionMismatchFinderProject__WEBPACK_IMPORTED_MODULE_8__.VersionMismatchFinderProject(project);
            const currentProjectDepUpdate = {
                project: mismatchFinderProject,
                dependenciesToAddOrUpdateOrRemove: dependenciesToUpdate,
                dependencyType: _api_PackageJsonEditor__WEBPACK_IMPORTED_MODULE_7__.DependencyType.Regular
            };
            const currentProjectDevDepUpdate = {
                project: mismatchFinderProject,
                dependenciesToAddOrUpdateOrRemove: devDependenciesToUpdate,
                dependencyType: _api_PackageJsonEditor__WEBPACK_IMPORTED_MODULE_7__.DependencyType.Dev
            };
            allPackageUpdates.set(mismatchFinderProject.filePath, mismatchFinderProject);
            this.updateProject(currentProjectDepUpdate);
            this.updateProject(currentProjectDevDepUpdate);
        }
        if (updateOtherPackages) {
            const mismatchFinder = _versionMismatch_VersionMismatchFinder__WEBPACK_IMPORTED_MODULE_4__.VersionMismatchFinder.getMismatches(this._rushConfiguration, options);
            for (const update of this._getUpdates(mismatchFinder, allDependenciesToUpdate)) {
                this.updateProject(update);
                allPackageUpdates.set(update.project.filePath, update.project);
            }
        }
        await _rushstack_node_core_library__WEBPACK_IMPORTED_MODULE_2__.Async.forEachAsync(allPackageUpdates, async ([filePath, project]) => {
            const modified = await project.saveIfModifiedAsync();
            if (modified) {
                this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green('Wrote ') + filePath);
            }
        }, { concurrency: 10 });
        if (!skipUpdate) {
            if (this._rushConfiguration.subspacesFeatureEnabled) {
                const subspaceSet = this._rushConfiguration.getSubspacesForProjects(options.projects);
                for (const subspace of subspaceSet) {
                    await this._doUpdateAsync(debugInstall, subspace, variant);
                }
            }
            else {
                await this._doUpdateAsync(debugInstall, this._rushConfiguration.defaultSubspace, variant);
            }
        }
    }
    async doRushUpdateAsync(options) {
        let allPackageUpdates = [];
        if (options.actionName === 'add') {
            allPackageUpdates = await this._doRushAddAsync(options);
        }
        else if (options.actionName === 'remove') {
            allPackageUpdates = await this._doRushRemoveAsync(options);
        }
        else {
            throw new Error('only accept "rush add" or "rush remove"');
        }
        const { skipUpdate, debugInstall, variant } = options;
        await _rushstack_node_core_library__WEBPACK_IMPORTED_MODULE_2__.Async.forEachAsync(allPackageUpdates, async ({ project }) => {
            const modified = await project.saveIfModifiedAsync();
            if (modified) {
                this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green('Wrote'), project.filePath);
            }
        }, { concurrency: 10 });
        if (!skipUpdate) {
            if (this._rushConfiguration.subspacesFeatureEnabled) {
                const subspaceSet = this._rushConfiguration.getSubspacesForProjects(options.projects);
                for (const subspace of subspaceSet) {
                    await this._doUpdateAsync(debugInstall, subspace, variant);
                }
            }
            else {
                await this._doUpdateAsync(debugInstall, this._rushConfiguration.defaultSubspace, variant);
            }
        }
    }
    async _doUpdateAsync(debugInstall, subspace, variant) {
        this._terminal.writeLine();
        this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green('Running "rush update"'));
        this._terminal.writeLine();
        const purgeManager = new _PurgeManager__WEBPACK_IMPORTED_MODULE_5__.PurgeManager(this._rushConfiguration, this._rushGlobalFolder);
        const installManagerOptions = {
            debug: debugInstall,
            allowShrinkwrapUpdates: true,
            bypassPolicy: false,
            noLink: false,
            fullUpgrade: false,
            recheckShrinkwrap: false,
            networkConcurrency: undefined,
            offline: false,
            collectLogFile: false,
            variant,
            maxInstallAttempts: _RushConstants__WEBPACK_IMPORTED_MODULE_9__.RushConstants.defaultMaxInstallAttempts,
            pnpmFilterArgumentValues: [],
            selectedProjects: new Set(this._rushConfiguration.projects),
            checkOnly: false,
            subspace: subspace,
            terminal: this._terminal
        };
        const installManager = await _InstallManagerFactory__WEBPACK_IMPORTED_MODULE_3__.InstallManagerFactory.getInstallManagerAsync(this._rushConfiguration, this._rushGlobalFolder, purgeManager, installManagerOptions);
        try {
            await installManager.doInstallAsync();
        }
        finally {
            await purgeManager.startDeleteAllAsync();
        }
    }
    /**
     * Adds a dependency to a particular project. The core business logic for "rush add".
     */
    async _doRushAddAsync(options) {
        const { projects } = options;
        const { DependencyAnalyzer } = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ./DependencyAnalyzer */ 699335));
        const dependencyAnalyzer = DependencyAnalyzer.forRushConfiguration(this._rushConfiguration);
        const allPackageUpdates = [];
        const subspaceSet = this._rushConfiguration.getSubspacesForProjects(projects);
        for (const subspace of subspaceSet) {
            // Projects for this subspace
            allPackageUpdates.push(...(await this._updateProjectsAsync(subspace, dependencyAnalyzer, options)));
        }
        return allPackageUpdates;
    }
    async _updateProjectsAsync(subspace, dependencyAnalyzer, options) {
        const { projects, packagesToUpdate, devDependency, peerDependency, updateOtherPackages, variant } = options;
        // Get projects for this subspace
        const subspaceProjects = projects.filter((project) => project.subspace === subspace);
        const { allVersionsByPackageName, implicitlyPreferredVersionByPackageName, commonVersionsConfiguration } = dependencyAnalyzer.getAnalysis(subspace, variant, options.actionName === 'add');
        this._terminal.writeLine();
        const dependenciesToAddOrUpdate = {};
        for (const { packageName, version: initialVersion, rangeStyle } of packagesToUpdate) {
            const implicitlyPreferredVersion = implicitlyPreferredVersionByPackageName.get(packageName);
            const explicitlyPreferredVersion = commonVersionsConfiguration.preferredVersions.get(packageName);
            const version = await this._getNormalizedVersionSpecAsync(subspaceProjects, packageName, initialVersion, implicitlyPreferredVersion, explicitlyPreferredVersion, rangeStyle, commonVersionsConfiguration.ensureConsistentVersions);
            dependenciesToAddOrUpdate[packageName] = version;
            this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green('Updating projects to use '), `${packageName}@`, _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(version));
            this._terminal.writeLine();
            const existingSpecifiedVersions = allVersionsByPackageName.get(packageName);
            if (existingSpecifiedVersions &&
                !existingSpecifiedVersions.has(version) &&
                commonVersionsConfiguration.ensureConsistentVersions &&
                !updateOtherPackages) {
                // There are existing versions, and the version we're going to use is not one of them, and this repo
                // requires consistent versions, and we aren't going to update other packages, so we can't proceed.
                const existingVersionList = Array.from(existingSpecifiedVersions).join(', ');
                throw new Error(`Adding '${packageName}@${version}' ` +
                    `causes mismatched dependencies. Use the "${_cli_actions_AddAction__WEBPACK_IMPORTED_MODULE_12__.MAKE_CONSISTENT_FLAG_NAME}" flag to update other packages to use ` +
                    `this version, or try specify one of the existing versions (${existingVersionList}).`);
            }
        }
        const allPackageUpdates = [];
        for (const project of subspaceProjects) {
            const currentProjectUpdate = {
                project: new _versionMismatch_VersionMismatchFinderProject__WEBPACK_IMPORTED_MODULE_8__.VersionMismatchFinderProject(project),
                dependenciesToAddOrUpdateOrRemove: dependenciesToAddOrUpdate,
                dependencyType: devDependency ? _api_PackageJsonEditor__WEBPACK_IMPORTED_MODULE_7__.DependencyType.Dev : peerDependency ? _api_PackageJsonEditor__WEBPACK_IMPORTED_MODULE_7__.DependencyType.Peer : undefined
            };
            this.updateProject(currentProjectUpdate);
            let otherPackageUpdates = [];
            // we need to do a mismatch check
            if (updateOtherPackages) {
                const mismatchFinder = _versionMismatch_VersionMismatchFinder__WEBPACK_IMPORTED_MODULE_4__.VersionMismatchFinder.getMismatches(this._rushConfiguration, {
                    subspace,
                    variant
                });
                otherPackageUpdates = this._getUpdates(mismatchFinder, Object.entries(dependenciesToAddOrUpdate));
            }
            this.updateProjects(otherPackageUpdates);
            allPackageUpdates.push(currentProjectUpdate, ...otherPackageUpdates);
        }
        return allPackageUpdates;
    }
    _getUpdates(mismatchFinder, dependenciesToUpdate) {
        const result = [];
        const { mismatches } = mismatchFinder;
        for (const [packageName, version] of dependenciesToUpdate) {
            const projectsByVersion = mismatches.get(packageName);
            if (projectsByVersion) {
                for (const consumers of projectsByVersion.values()) {
                    for (const consumer of consumers) {
                        result.push({
                            project: consumer,
                            dependenciesToAddOrUpdateOrRemove: {
                                [packageName]: version
                            }
                        });
                    }
                }
            }
        }
        return result;
    }
    /**
     * Remove a dependency from a particular project. The core business logic for "rush remove".
     */
    async _doRushRemoveAsync(options) {
        const { projects, packagesToUpdate } = options;
        this._terminal.writeLine();
        const dependenciesToRemove = {};
        const allPackageUpdates = [];
        for (const project of projects) {
            for (const { packageName } of packagesToUpdate) {
                dependenciesToRemove[packageName] = '';
            }
            const currentProjectUpdate = {
                project: new _versionMismatch_VersionMismatchFinderProject__WEBPACK_IMPORTED_MODULE_8__.VersionMismatchFinderProject(project),
                dependenciesToAddOrUpdateOrRemove: dependenciesToRemove
            };
            this.removePackageFromProject(currentProjectUpdate);
            allPackageUpdates.push(currentProjectUpdate);
        }
        return allPackageUpdates;
    }
    /**
     * Updates several projects' package.json files
     */
    updateProjects(projectUpdates) {
        for (const update of projectUpdates) {
            this.updateProject(update);
        }
    }
    /**
     * Updates a single project's package.json file
     */
    updateProject(options) {
        let { dependencyType } = options;
        const { project, dependenciesToAddOrUpdateOrRemove } = options;
        for (const [packageName, newVersion] of Object.entries(dependenciesToAddOrUpdateOrRemove)) {
            const oldDependency = project.tryGetDependency(packageName);
            const oldDevDependency = project.tryGetDevDependency(packageName);
            const oldDependencyType = oldDevDependency
                ? oldDevDependency.dependencyType
                : oldDependency
                    ? oldDependency.dependencyType
                    : undefined;
            dependencyType = dependencyType || oldDependencyType || _api_PackageJsonEditor__WEBPACK_IMPORTED_MODULE_7__.DependencyType.Regular;
            project.addOrUpdateDependency(packageName, newVersion, dependencyType);
        }
    }
    removePackageFromProject(options) {
        const { project, dependenciesToAddOrUpdateOrRemove } = options;
        for (const packageName of Object.keys(dependenciesToAddOrUpdateOrRemove)) {
            const packageJsonDependencies = [
                project.tryGetDependency(packageName),
                project.tryGetDevDependency(packageName)
            ];
            for (const packageJsonDependency of packageJsonDependencies) {
                if (!packageJsonDependency) {
                    continue;
                }
                project.removeDependency(packageName, packageJsonDependency.dependencyType);
            }
        }
    }
    /**
     * Selects an appropriate version number for a particular package, given an optional initial SemVer spec.
     * If ensureConsistentVersions, tries to pick a version that will be consistent.
     * Otherwise, will choose the latest semver matching the initialSpec and append the proper range style.
     * @param projects - the projects which will have their package.json's updated
     * @param packageName - the name of the package to be used
     * @param initialSpec - a semver pattern that should be used to find the latest version matching the spec
     * @param implicitlyPreferredVersion - the implicitly preferred (aka common/primary) version of the package in use
     * @param rangeStyle - if this version is selected by querying registry, then this range specifier is prepended to
     *   the selected version.
     */
    async _getNormalizedVersionSpecAsync(projects, packageName, initialSpec, implicitlyPreferredVersion, explicitlyPreferredVersion, rangeStyle, ensureConsistentVersions) {
        this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.gray(`Determining new version for dependency: ${packageName}`));
        if (initialSpec) {
            this._terminal.writeLine(`Specified version selector: ${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(initialSpec)}`);
        }
        else {
            this._terminal.writeLine(`No version selector was specified, so the version will be determined automatically.`);
        }
        this._terminal.writeLine();
        // if ensureConsistentVersions => reuse the pinned version
        // else, query the registry and use the latest that satisfies semver spec
        if (initialSpec) {
            if (initialSpec === implicitlyPreferredVersion) {
                this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green('Assigning "') +
                    _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(initialSpec) +
                    _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green(`" for "${packageName}" because it matches what other projects are using in this repo.`));
                return initialSpec;
            }
            if (initialSpec === explicitlyPreferredVersion) {
                this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green('Assigning "') +
                    _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(initialSpec) +
                    _rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.green(`" for "${packageName}" because it is the preferred version listed in ${_RushConstants__WEBPACK_IMPORTED_MODULE_9__.RushConstants.commonVersionsFilename}.`));
                return initialSpec;
            }
        }
        if (ensureConsistentVersions && !initialSpec) {
            if (implicitlyPreferredVersion) {
                this._terminal.writeLine(`Assigning the version "${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(implicitlyPreferredVersion)}" for "${packageName}" ` +
                    'because it is already used by other projects in this repo.');
                return implicitlyPreferredVersion;
            }
            if (explicitlyPreferredVersion) {
                this._terminal.writeLine(`Assigning the version "${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(explicitlyPreferredVersion)}" for "${packageName}" ` +
                    `because it is the preferred version listed in ${_RushConstants__WEBPACK_IMPORTED_MODULE_9__.RushConstants.commonVersionsFilename}.`);
                return explicitlyPreferredVersion;
            }
        }
        await _installManager_InstallHelpers__WEBPACK_IMPORTED_MODULE_10__.InstallHelpers.ensureLocalPackageManagerAsync(this._rushConfiguration, this._rushGlobalFolder, _RushConstants__WEBPACK_IMPORTED_MODULE_9__.RushConstants.defaultMaxInstallAttempts);
        const useWorkspaces = !!(this._rushConfiguration.pnpmOptions && this._rushConfiguration.pnpmOptions.useWorkspaces);
        const workspacePrefix = 'workspace:';
        // Trim 'workspace:' notation from the spec, since we're going to be tweaking the range
        if (useWorkspaces && initialSpec && initialSpec.startsWith(workspacePrefix)) {
            initialSpec = initialSpec.substring(workspacePrefix.length).trim();
        }
        // determine if the package is a project in the local repository and if the version exists
        const localProject = this._tryGetLocalProject(packageName, projects);
        let selectedVersion;
        let selectedVersionPrefix = '';
        if (initialSpec && initialSpec !== 'latest') {
            this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.gray('Finding versions that satisfy the selector: ') + initialSpec);
            this._terminal.writeLine();
            if (localProject !== undefined) {
                const version = localProject.packageJson.version;
                if (semver__WEBPACK_IMPORTED_MODULE_0__.satisfies(version, initialSpec)) {
                    // For workspaces, assume that specifying the exact version means you always want to consume
                    // the local project. Otherwise, use the exact local package version
                    if (useWorkspaces) {
                        selectedVersion = initialSpec === version ? '*' : initialSpec;
                        selectedVersionPrefix = workspacePrefix;
                    }
                    else {
                        selectedVersion = version;
                    }
                }
                else {
                    throw new Error(`The dependency being added ("${packageName}") is a project in the local Rush repository, ` +
                        `but the version specifier provided (${initialSpec}) does not match the local project's version ` +
                        `(${version}). Correct the version specifier, omit a version specifier, or include "${packageName}" as a ` +
                        `cyclicDependencyProject if it is intended for "${packageName}" to come from an external feed and not ` +
                        'from the local Rush repository.');
                }
            }
            else {
                this._terminal.writeLine(`Querying registry for all versions of "${packageName}"...`);
                let args;
                if (this._rushConfiguration.packageManager === 'yarn') {
                    args = ['info', packageName, 'versions', '--json'];
                }
                else {
                    args = ['view', packageName, 'versions', '--json'];
                }
                const allVersions = await _utilities_Utilities__WEBPACK_IMPORTED_MODULE_6__.Utilities.executeCommandAndCaptureOutputAsync({
                    command: this._rushConfiguration.packageManagerToolFilename,
                    args,
                    workingDirectory: this._rushConfiguration.commonTempFolder
                });
                let versionList;
                if (this._rushConfiguration.packageManager === 'yarn') {
                    versionList = JSON.parse(allVersions).data;
                }
                else {
                    versionList = JSON.parse(allVersions);
                }
                this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.gray(`Found ${versionList.length} available versions.`));
                for (const version of versionList) {
                    if (semver__WEBPACK_IMPORTED_MODULE_0__.satisfies(version, initialSpec)) {
                        selectedVersion = initialSpec;
                        this._terminal.writeLine(`Found a version that satisfies ${initialSpec}: ${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(version)}`);
                        break;
                    }
                }
                if (!selectedVersion) {
                    throw new Error(`Unable to find a version of "${packageName}" that satisfies` +
                        ` the version specifier "${initialSpec}"`);
                }
            }
        }
        else {
            if (localProject !== undefined) {
                // For workspaces, assume that no specified version range means you always want to consume
                // the local project. Otherwise, use the exact local package version
                if (useWorkspaces) {
                    selectedVersion = '*';
                    selectedVersionPrefix = workspacePrefix;
                }
                else {
                    selectedVersion = localProject.packageJson.version;
                }
            }
            else {
                if (!this._rushConfiguration.ensureConsistentVersions) {
                    this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.gray(`The "ensureConsistentVersions" policy is NOT active, so we will assign the latest version.`));
                    this._terminal.writeLine();
                }
                this._terminal.writeLine(`Querying NPM registry for latest version of "${packageName}"...`);
                let args;
                if (this._rushConfiguration.packageManager === 'yarn') {
                    args = ['info', packageName, 'dist-tags.latest', '--silent'];
                }
                else {
                    args = ['view', `${packageName}@latest`, 'version'];
                }
                selectedVersion = (await _utilities_Utilities__WEBPACK_IMPORTED_MODULE_6__.Utilities.executeCommandAndCaptureOutputAsync({
                    command: this._rushConfiguration.packageManagerToolFilename,
                    args,
                    workingDirectory: this._rushConfiguration.commonTempFolder
                })).trim();
            }
            this._terminal.writeLine();
            this._terminal.writeLine(`Found latest version: ${_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.cyan(selectedVersion)}`);
        }
        this._terminal.writeLine();
        let reasonForModification = '';
        if (selectedVersion !== '*') {
            switch (rangeStyle) {
                case _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__.SemVerStyle.Caret: {
                    selectedVersionPrefix += '^';
                    reasonForModification = ' because the "--caret" flag was specified';
                    break;
                }
                case _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__.SemVerStyle.Exact: {
                    reasonForModification = ' because the "--exact" flag was specified';
                    break;
                }
                case _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__.SemVerStyle.Tilde: {
                    selectedVersionPrefix += '~';
                    break;
                }
                case _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__.SemVerStyle.Passthrough: {
                    break;
                }
                default: {
                    throw new Error(`Unexpected SemVerStyle ${rangeStyle}.`);
                }
            }
        }
        const normalizedVersion = selectedVersionPrefix + selectedVersion;
        this._terminal.writeLine(_rushstack_terminal__WEBPACK_IMPORTED_MODULE_1__.Colorize.gray(`Assigning version "${normalizedVersion}" for "${packageName}"${reasonForModification}.`));
        return normalizedVersion;
    }
    _collectAllDownstreamDependencies(project) {
        const allProjectDownstreamDependencies = new Set();
        const collectDependencies = (rushProject) => {
            for (const downstreamDependencyProject of rushProject.downstreamDependencyProjects) {
                const foundProject = this._rushConfiguration.projectsByName.get(downstreamDependencyProject);
                if (!foundProject) {
                    continue;
                }
                if (foundProject.decoupledLocalDependencies.has(rushProject.packageName)) {
                    continue;
                }
                if (!allProjectDownstreamDependencies.has(foundProject)) {
                    allProjectDownstreamDependencies.add(foundProject);
                    collectDependencies(foundProject);
                }
            }
        };
        collectDependencies(project);
        return allProjectDownstreamDependencies;
    }
    /**
     * Given a package name, this function returns a {@see RushConfigurationProject} if the package is a project
     * in the local Rush repo and is not marked as cyclic for any of the projects.
     *
     * @remarks
     * This function throws an error if adding the discovered local project as a dependency
     * would create a dependency cycle, or if it would be added to multiple projects.
     */
    _tryGetLocalProject(packageName, projects) {
        const foundProject = this._rushConfiguration.projectsByName.get(packageName);
        if (foundProject === undefined) {
            return undefined;
        }
        if (projects.length > 1) {
            throw new Error(`"rush add" does not support adding a local project as a dependency to multiple projects at once.`);
        }
        const project = projects[0];
        if (project.decoupledLocalDependencies.has(foundProject.packageName)) {
            return undefined;
        }
        // Are we attempting to add this project to itself?
        if (project === foundProject) {
            throw new Error('Unable to add a project as a dependency of itself unless the dependency is listed as a cyclic dependency ' +
                `in ${_RushConstants__WEBPACK_IMPORTED_MODULE_9__.RushConstants.rushJsonFilename}. This command attempted to add "${foundProject.packageName}" ` +
                `as a dependency of itself.`);
        }
        // Are we attempting to create a cycle?
        const downstreamDependencies = this._collectAllDownstreamDependencies(project);
        if (downstreamDependencies.has(foundProject)) {
            throw new Error(`Adding "${foundProject.packageName}" as a direct or indirect dependency of ` +
                `"${project.packageName}" would create a dependency cycle.`);
        }
        return foundProject;
    }
    _cheaplyDetectSemVerRangeStyle(version) {
        // create a swtich statement to detect the first character of the version string and determine the range style
        // TODO: This is a temporary solution until we have a better way to detect more complext range styles
        // TODO: Should we handle/care about peerDependencies?
        switch (version[0]) {
            case '~':
                return _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__.SemVerStyle.Tilde;
            case '^':
                return _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__.SemVerStyle.Caret;
            default:
                this._terminal.writeLine(`No SemVer range detected for version: ${version}. The exact version will be set in package.json.`);
                return _PackageJsonUpdaterTypes__WEBPACK_IMPORTED_MODULE_11__.SemVerStyle.Exact;
        }
    }
    _normalizeDepsToUpgrade(deps) {
        return deps.map((dep) => {
            return {
                packageName: dep.moduleName,
                version: dep.latest,
                rangeStyle: this._cheaplyDetectSemVerRangeStyle(dep.packageJson)
            };
        });
    }
}
//# sourceMappingURL=PackageJsonUpdater.js.map

/***/ }

};
;
//# sourceMappingURL=PackageJsonUpdater.js.map