// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
import * as semver from 'semver';
import { Colorize } from '@rushstack/terminal';
import { RushConstants } from './RushConstants';
/**
 * This constant is the major version of the next LTS node Node.js release. This constant should be updated when
 * a new LTS version is added to Rush's support matrix.
 *
 * LTS schedule: https://nodejs.org/en/about/releases/
 * LTS versions: https://nodejs.org/en/download/releases/
 */
const UPCOMING_NODE_LTS_VERSION = 24;
const nodeVersion = process.versions.node;
const nodeMajorVersion = semver.major(nodeVersion);
/**
 * This class provides useful functions for warning if the current Node.js runtime isn't supported.
 *
 * @internal
 */
export class NodeJsCompatibility {
    /**
     * This reports if the Node.js version is known to have serious incompatibilities.  In that situation, the user
     * should downgrade Rush to an older release that supported their Node.js version.
     */
    static reportAncientIncompatibleVersion() {
        // IMPORTANT: If this test fails, the Rush CLI front-end process will terminate with an error.
        // Only increment it when our code base is known to use newer features (e.g. "async"/"await") that
        // have no hope of working with older Node.js.
        if (semver.satisfies(nodeVersion, '<14.18.0')) {
            // eslint-disable-next-line no-console
            console.error(Colorize.red(`Your version of Node.js (${nodeVersion}) is very old and incompatible with Rush. ` +
                `Please upgrade to the latest Long-Term Support (LTS) version.\n`));
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * Detect whether the Node.js version is "supported" by the Rush maintainers.  We generally
     * only support versions that were "Long Term Support" (LTS) at the time when Rush was published.
     *
     * This is a warning only -- the user is free to ignore it and use Rush anyway.
     */
    static warnAboutCompatibilityIssues(options) {
        // Only show the first warning
        return (NodeJsCompatibility.reportAncientIncompatibleVersion() ||
            NodeJsCompatibility.warnAboutVersionTooNew(options) ||
            NodeJsCompatibility._warnAboutOddNumberedVersion() ||
            NodeJsCompatibility._warnAboutNonLtsVersion(options.rushConfiguration));
    }
    /**
     * Warn about a Node.js version that has not been tested yet with Rush.
     */
    static warnAboutVersionTooNew(options) {
        if (nodeMajorVersion >= UPCOMING_NODE_LTS_VERSION + 1) {
            if (!options.alreadyReportedNodeTooNewError) {
                // We are on a much newer release than we have tested and support
                if (options.isRushLib) {
                    // eslint-disable-next-line no-console
                    console.warn(Colorize.yellow(`Your version of Node.js (${nodeVersion}) has not been tested with this release ` +
                        `of the Rush engine. Please consider upgrading the "rushVersion" setting in ${RushConstants.rushJsonFilename}, ` +
                        `or downgrading Node.js.\n`));
                }
                else {
                    // eslint-disable-next-line no-console
                    console.warn(Colorize.yellow(`Your version of Node.js (${nodeVersion}) has not been tested with this release ` +
                        `of Rush. Please consider installing a newer version of the "@microsoft/rush" ` +
                        `package, or downgrading Node.js.\n`));
                }
            }
            return true;
        }
        else {
            return false;
        }
    }
    static _warnAboutNonLtsVersion(rushConfiguration) {
        if (rushConfiguration && !rushConfiguration.suppressNodeLtsWarning && !NodeJsCompatibility.isLtsVersion) {
            // eslint-disable-next-line no-console
            console.warn(Colorize.yellow(`Your version of Node.js (${nodeVersion}) is not a Long-Term Support (LTS) release. ` +
                'These versions frequently have bugs. Please consider installing a stable release.\n'));
            return true;
        }
        else {
            return false;
        }
    }
    static _warnAboutOddNumberedVersion() {
        if (NodeJsCompatibility.isOddNumberedVersion) {
            // eslint-disable-next-line no-console
            console.warn(Colorize.yellow(`Your version of Node.js (${nodeVersion}) is an odd-numbered release. ` +
                `These releases frequently have bugs. Please consider installing a Long Term Support (LTS) ` +
                `version instead.\n`));
            return true;
        }
        else {
            return false;
        }
    }
    static get isLtsVersion() {
        return !!process.release.lts;
    }
    static get isOddNumberedVersion() {
        return nodeMajorVersion % 2 !== 0;
    }
}
//# sourceMappingURL=NodeJsCompatibility.js.map