// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
import * as path from 'node:path';
import { InternalError, PackageJsonLookup } from '@rushstack/node-core-library';
import '../utilities/SetRushLibPath';
import { RushCommandLineParser } from '../cli/RushCommandLineParser';
import { RushStartupBanner } from '../cli/RushStartupBanner';
import { RushXCommandLine } from '../cli/RushXCommandLine';
import { CommandLineMigrationAdvisor } from '../cli/CommandLineMigrationAdvisor';
import { EnvironmentVariableNames } from './EnvironmentConfiguration';
import { RushPnpmCommandLine } from '../cli/RushPnpmCommandLine';
import { measureAsyncFn } from '../utilities/performance';
/**
 * General operations for the Rush engine.
 *
 * @public
 */
export class Rush {
    /**
     * This API is used by the `@microsoft/rush` front end to launch the "rush" command-line.
     * Third-party tools should not use this API.  Instead, they should execute the "rush" binary
     * and start a new Node.js process.
     *
     * @remarks
     * Earlier versions of the rush frontend used a different API contract. In the old contract,
     * the second argument was the `isManaged` value of the {@link ILaunchOptions} object.
     *
     * Even though this API isn't documented, it is still supported for legacy compatibility.
     */
    static launch(launcherVersion, options) {
        options = Rush._normalizeLaunchOptions(options);
        if (!RushCommandLineParser.shouldRestrictConsoleOutput()) {
            RushStartupBanner.logBanner(Rush.version, options.isManaged);
        }
        if (!CommandLineMigrationAdvisor.checkArgv(process.argv)) {
            // The migration advisor recognized an obsolete command-line
            process.exitCode = 1;
            return;
        }
        Rush._assignRushInvokedFolder();
        const parser = new RushCommandLineParser({
            alreadyReportedNodeTooNewError: options.alreadyReportedNodeTooNewError,
            builtInPluginConfigurations: options.builtInPluginConfigurations
        });
        // CommandLineParser.executeAsync() should never reject the promise
        // eslint-disable-next-line no-console
        measureAsyncFn('rush:parser:executeAsync', () => parser.executeAsync()).catch(console.error);
    }
    /**
     * This API is used by the `@microsoft/rush` front end to launch the "rushx" command-line.
     * Third-party tools should not use this API.  Instead, they should execute the "rushx" binary
     * and start a new Node.js process.
     */
    static launchRushX(launcherVersion, options) {
        options = Rush._normalizeLaunchOptions(options);
        Rush._assignRushInvokedFolder();
        // eslint-disable-next-line no-console
        RushXCommandLine.launchRushXAsync(launcherVersion, options).catch(console.error); // CommandLineParser.executeAsync() should never reject the promise
    }
    /**
     * This API is used by the `@microsoft/rush` front end to launch the "rush-pnpm" command-line.
     * Third-party tools should not use this API.  Instead, they should execute the "rush-pnpm" binary
     * and start a new Node.js process.
     */
    static launchRushPnpm(launcherVersion, options) {
        Rush._assignRushInvokedFolder();
        RushPnpmCommandLine.launch(launcherVersion, { ...options });
    }
    /**
     * The currently executing version of the "rush-lib" library.
     * This is the same as the Rush tool version for that release.
     */
    static get version() {
        return this._rushLibPackageJson.version;
    }
    /**
     * @internal
     */
    static get _rushLibPackageJson() {
        Rush._ensureOwnPackageJsonIsLoaded();
        return Rush.__rushLibPackageJson;
    }
    static get _rushLibPackageFolder() {
        Rush._ensureOwnPackageJsonIsLoaded();
        return Rush.__rushLibPackageFolder;
    }
    static _ensureOwnPackageJsonIsLoaded() {
        if (!Rush.__rushLibPackageJson) {
            const packageJsonFilePath = PackageJsonLookup.instance.tryGetPackageJsonFilePathFor(__dirname);
            if (!packageJsonFilePath) {
                throw new InternalError('Unable to locate the package.json file for this module');
            }
            Rush.__rushLibPackageFolder = path.dirname(packageJsonFilePath);
            Rush.__rushLibPackageJson = PackageJsonLookup.instance.loadPackageJson(packageJsonFilePath);
        }
    }
    /**
     * Assign the `RUSH_INVOKED_FOLDER` environment variable during startup.  This is only applied when
     * Rush is invoked via the CLI, not via the `@microsoft/rush-lib` automation API.
     *
     * @remarks
     * Modifying the parent process's environment is not a good design.  The better design is (1) to consolidate
     * Rush's code paths that invoke scripts, and (2) to pass down the invoked folder with each code path,
     * so that it can finally be applied in a centralized helper like `Utilities._createEnvironmentForRushCommand()`.
     * The natural time to do that refactoring is when we rework `Utilities.executeCommand()` to use
     * `Executable.spawn()` or rushell.
     */
    static _assignRushInvokedFolder() {
        process.env[EnvironmentVariableNames.RUSH_INVOKED_FOLDER] = process.cwd();
    }
    /**
     * This function normalizes legacy options to the current {@link ILaunchOptions} object.
     */
    static _normalizeLaunchOptions(arg) {
        return typeof arg === 'boolean'
            ? { isManaged: arg } // In older versions of Rush, this the `launch` functions took a boolean arg for "isManaged"
            : arg;
    }
}
Rush.__rushLibPackageJson = undefined;
Rush.__rushLibPackageFolder = undefined;
//# sourceMappingURL=Rush.js.map