"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AddAction = exports.MAKE_CONSISTENT_FLAG_NAME = void 0;
const semver = __importStar(require("semver"));
const BaseAddAndRemoveAction_1 = require("./BaseAddAndRemoveAction");
const DependencySpecifier_1 = require("../../logic/DependencySpecifier");
const PackageJsonUpdaterTypes_1 = require("../../logic/PackageJsonUpdaterTypes");
const Variants_1 = require("../../api/Variants");
const ADD_ACTION_NAME = 'add';
exports.MAKE_CONSISTENT_FLAG_NAME = '--make-consistent';
const EXACT_FLAG_NAME = '--exact';
const CARET_FLAG_NAME = '--caret';
class AddAction extends BaseAddAndRemoveAction_1.BaseAddAndRemoveAction {
    constructor(parser) {
        const documentation = [
            'Adds specified package(s) to the dependencies of the current project (as determined by the current working directory)' +
                ' and then runs "rush update". If no version is specified, a version will be automatically detected (typically' +
                ' either the latest version or a version that won\'t break the "ensureConsistentVersions" policy). If a version' +
                ' range (or a workspace range) is specified, the latest version in the range will be used. The version will be' +
                ` automatically prepended with a tilde, unless the "${EXACT_FLAG_NAME}" or "${CARET_FLAG_NAME}" flags are used.` +
                ` The "${exports.MAKE_CONSISTENT_FLAG_NAME}" flag can be used to update all packages with the dependency.`
        ].join('\n');
        super({
            actionName: ADD_ACTION_NAME,
            summary: 'Adds one or more dependencies to the package.json and runs rush update.',
            documentation,
            safeForSimultaneousRushProcesses: false,
            parser,
            allFlagDescription: 'If specified, the dependency will be added to all projects.',
            packageNameListParameterDescription: 'The name of the package which should be added as a dependency.' +
                ' A SemVer version specifier can be appended after an "@" sign.  WARNING: Symbol characters' +
                " are usually interpreted by your shell, so it's recommended to use quotes." +
                ` For example, write "rush add ${BaseAddAndRemoveAction_1.PACKAGE_PARAMETER_NAME} "example@^1.2.3"" instead of "rush add ${BaseAddAndRemoveAction_1.PACKAGE_PARAMETER_NAME} example@^1.2.3".` +
                ` To add multiple packages, write "rush add ${BaseAddAndRemoveAction_1.PACKAGE_PARAMETER_NAME} foo ${BaseAddAndRemoveAction_1.PACKAGE_PARAMETER_NAME} bar".`
        });
        this._exactFlag = this.defineFlagParameter({
            parameterLongName: EXACT_FLAG_NAME,
            description: 'If specified, the SemVer specifier added to the' +
                ' package.json will be an exact version (e.g. without tilde or caret).'
        });
        this._caretFlag = this.defineFlagParameter({
            parameterLongName: CARET_FLAG_NAME,
            description: 'If specified, the SemVer specifier added to the' +
                ' package.json will be a prepended with a "caret" specifier ("^").'
        });
        this._devDependencyFlag = this.defineFlagParameter({
            parameterLongName: '--dev',
            description: 'If specified, the package will be added to the "devDependencies" section of the package.json'
        });
        this._peerDependencyFlag = this.defineFlagParameter({
            parameterLongName: '--peer',
            description: 'If specified, the package will be added to the "peerDependencies" section of the package.json'
        });
        this._makeConsistentFlag = this.defineFlagParameter({
            parameterLongName: exports.MAKE_CONSISTENT_FLAG_NAME,
            parameterShortName: '-m',
            description: 'If specified, other packages with this dependency will have their package.json' +
                ' files updated to use the same version of the dependency.'
        });
    }
    async getUpdateOptionsAsync() {
        const projects = super.getProjects();
        if (this._caretFlag.value && this._exactFlag.value) {
            throw new Error(`Only one of "${this._caretFlag.longName}" and "${this._exactFlag.longName}" should be specified`);
        }
        const packagesToAdd = [];
        for (const specifiedPackageName of this.specifiedPackageNameList) {
            /**
             * Name & Version
             */
            let packageName = specifiedPackageName;
            let version = undefined;
            const parts = packageName.split('@');
            if (parts[0] === '') {
                // this is a scoped package
                packageName = '@' + parts[1];
                version = parts[2];
            }
            else {
                packageName = parts[0];
                version = parts[1];
            }
            if (!this.rushConfiguration.packageNameParser.isValidName(packageName)) {
                throw new Error(`The package name "${packageName}" is not valid.`);
            }
            if (version && version !== 'latest') {
                const specifier = new DependencySpecifier_1.DependencySpecifier(packageName, version);
                if (!semver.validRange(specifier.versionSpecifier) && !semver.valid(specifier.versionSpecifier)) {
                    throw new Error(`The SemVer specifier "${version}" is not valid.`);
                }
            }
            /**
             * RangeStyle
             */
            let rangeStyle;
            if (version && version !== 'latest') {
                if (this._exactFlag.value || this._caretFlag.value) {
                    throw new Error(`The "${this._caretFlag.longName}" and "${this._exactFlag.longName}" flags may not be specified if a ` +
                        `version is provided in the ${this._packageNameListParameter.longName} specifier. In this case "${version}" was provided.`);
                }
                rangeStyle = PackageJsonUpdaterTypes_1.SemVerStyle.Passthrough;
            }
            else {
                rangeStyle = this._caretFlag.value
                    ? PackageJsonUpdaterTypes_1.SemVerStyle.Caret
                    : this._exactFlag.value
                        ? PackageJsonUpdaterTypes_1.SemVerStyle.Exact
                        : PackageJsonUpdaterTypes_1.SemVerStyle.Tilde;
            }
            packagesToAdd.push({ packageName, version, rangeStyle });
        }
        const variant = await (0, Variants_1.getVariantAsync)(this._variantParameter, this.rushConfiguration, true);
        return {
            projects,
            packagesToUpdate: packagesToAdd,
            devDependency: this._devDependencyFlag.value,
            peerDependency: this._peerDependencyFlag.value,
            updateOtherPackages: this._makeConsistentFlag.value,
            skipUpdate: this._skipUpdateFlag.value,
            debugInstall: this.parser.isDebug,
            actionName: this.actionName,
            variant
        };
    }
}
exports.AddAction = AddAction;
//# sourceMappingURL=AddAction.js.map