"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Text = exports.capitalise = exports.itemList = void 0;
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const terminal_link_1 = tslib_1.__importDefault(require("terminal-link"));
const case_1 = require("case");
const log_symbols_1 = tslib_1.__importDefault(require("./log-symbols"));
const log_color_1 = require("./log-color");
const graphql_types_1 = require("../graphql/graphql-types");
const cli_details_1 = require("../shared/cli-details");
const environment_1 = require("../shared/environment");
const manifest_1 = require("@forge/manifest");
const ctrlC = 'Press Ctrl+C to cancel.';
const encryptedValue = '****';
const greenTick = `${chalk_1.default.bold(chalk_1.default.green('✔'))}`;
const buildTerminalLink = (text) => (0, terminal_link_1.default)(chalk_1.default.bold(text), text, { fallback: () => chalk_1.default.underline.bold(text) });
const go = (link) => buildTerminalLink(`https://go.atlassian.com/${link}`);
const gettingStartedDACLink = go('dac/platform/forge/getting-started/#log-in-with-an-atlassian-api-token');
const command = (...args) => chalk_1.default.bold(args.join(' '));
const forge = (...args) => command('forge', ...args);
const autoSpaceSentences = (...sentences) => sentences
    .filter((sentence) => sentence.length > 0)
    .join(' ');
function itemList(items, indent) {
    return items.map((item) => `${indent ?? ' '}- ${item}`).join(`\n${indent ?? ''}`);
}
exports.itemList = itemList;
const fatalError = (message) => chalk_1.default.bold(chalk_1.default.red(message));
const keytarAccessErrorBase = (message) => `Keytar error detected: ${message}`;
const capitalise = (word) => word.charAt(0).toUpperCase() + word.slice(1);
exports.capitalise = capitalise;
const getLintMessage = (line, column, message, level, colourFunction, reference) => `${chalk_1.default.dim(`${line}:${column}`.padEnd(7))} ${colourFunction(level.padEnd(8))} ${message}  ${chalk_1.default.dim(reference)}\n`;
const checkLintTotalPlurals = (numErrors, numWarnings, numFixableErrors, numFixableWarnings) => ({
    pluralCheckedErrors: `${numErrors} ${numErrors === 1 ? 'error' : 'errors'}`,
    pluralCheckedWarnings: `${numWarnings} ${numWarnings === 1 ? 'warning' : 'warnings'}`,
    pluralCheckedTotal: `${numErrors + numWarnings} ${numErrors + numWarnings === 1 ? 'issue' : 'issues'}`,
    pluralCheckedFixableErrors: `${numFixableErrors} ${numFixableErrors === 1 ? 'error' : 'errors'}`,
    pluralCheckedFixableWarnings: `${numFixableWarnings} ${numFixableWarnings === 1 ? 'warning' : 'warnings'}`
});
const platformKeytarRecommendations = () => {
    switch (process.platform) {
        case 'darwin':
            return 'Ensure you enable access to the macOS keychain when prompted.';
        case 'linux':
            return `Ensure you have ${chalk_1.default.bold('libsecret')} installed.`;
        default:
            return '';
    }
};
exports.Text = {
    buildTerminalLink,
    go,
    error: {
        noKeytar: autoSpaceSentences(`The CLI couldn't securely store your login credentials in a local keychain.`, platformKeytarRecommendations(), `If a local keychain is not available, use environment variables before trying again. See ${gettingStartedDACLink} for more.`),
        noTokenStored: `Not logged in. If a local keychain is available, run ${forge('login')}, otherwise set environment variables before trying again. See ${gettingStartedDACLink} for more.`,
        keytarAccessError: {
            other: (message) => keytarAccessErrorBase(message),
            mac: (message) => keytarAccessErrorBase(message) +
                `\nSomething went wrong while accessing Keychain Access. Try locking and unlocking the login keychain.`,
            linux: (message) => keytarAccessErrorBase(message) + `\nSomething went wrong while accessing Secret Service API.`,
            windows: (message) => keytarAccessErrorBase(message) + `\nSomething went wrong while accessing Credentials Vault.`
        },
        outdatedCLIVersion: (installed, latest) => `Warning: Your version of Forge CLI is out of date. We recommend you update to the latest version to get the latest features and bug fixes.` +
            `\nRun ${command('npm', 'install', '-g', `${cli_details_1.FORGE_CLI_PACKAGE}@latest`)} to update from version ${chalk_1.default.bold(installed)} to ${chalk_1.default.bold(latest)}.` +
            `\n`,
        outdatedNodeVersion: (compatibleNodeVersion, currentNodeVersion) => fatalError(`Unsupported Node.js version. The CLI requires Node.js ${compatibleNodeVersion}, but you're using Node.js ${currentNodeVersion}.`),
        missingProductNameValue: 'Parameter requires an Atlassian app name. Rerun the command with a valid Atlassian app name.',
        invalidContext: (validContexts) => `Invalid Atlassian app. Rerun ${chalk_1.default.bold('forge install')} with ${validContexts.length > 0
            ? `one of the following valid Atlassian apps: ${validContexts.join(', ')}`
            : 'a valid Atlassian app'}.`,
        missingSiteUrlValue: 'Site parameter requires a site URL. Rerun the command with a valid site URL.',
        invalidSite: 'The site you entered is not an Atlassian site. Rerun the command with the URL to an Atlassian site to install the app.',
        invalidWorkspace: 'The workspace you entered is not a valid workspace. Rerun the command with the URL to a valid workspace to install the app.',
        invalidInstallationContext: 'Could not find an installation for the provided Atlassian app',
        invalidTokenInKeytar: `Your API token is no longer valid. Run ${forge('login')} to reset your login credentials.`,
        invalidTokenInEnv: (instructionsUrl, emailVar, tokenVar) => `The API token on your machine is no longer valid.` +
            `\n    1) Get a new API token: ${instructionsUrl}` +
            `\n    2) Set your email and the token to ${emailVar} and ${tokenVar} environment variables.`,
        promptInputRequired: 'Your response is needed to continue.',
        noExecutableFile: "Couldn't find the main executable file",
        resourceDefinitionMissing: (resourceKeys) => `The following resources are declared but are improperly defined in the manifest.yml file:${itemList(resourceKeys)}`,
        resourceDirectoryMissing: (resourceKey, directory) => `Resource ${resourceKey} at: ${directory} not found`,
        resourceDirectoryEmpty: (resourceKey, directory) => `Resource ${resourceKey} at: ${directory} is an empty directory`,
        templateFetchFailed: (message) => `Failed to fetch templates, try running the command again: ${message}`,
        handlerFormat: (handler) => `Function handler "${handler}" must be in format <module>.<function>, example: index.run`,
        licenseOverrideErrors: {
            prodSupport: 'License is not supported in production environments',
            invalid: 'Invalid license value. Supported values are active, inactive, and trial',
            empty: '--license argument requires a value. Supported values are active, inactive, and trial'
        },
        licenseModesOverrideErrors: {
            prodEnvNotSupported: '--license-modes and --users-with-access options are not supported in production environments',
            empty: '--license-modes option list is empty. Provide a space-separated list of license mode. Supported values are user-access. \nFor example: install --license-modes user-access --users-with-access aaid1',
            invalid: 'Invalid --license-modes option value. Supported values are user-access'
        },
        userWithAccessOverrideErrors: {
            prodEnvNotSupported: '--license-modes and --users-with-access options are not supported in production environments',
            empty: '--users-with-access option list is empty. Provide a space-separated list of Atlassian Account IDs(aaid). \nFor example: install --license-modes user-access --users-with-access aaid1 aaid2',
            countSize: (maxSizeOfUsersWithAccess) => `User limit exceeded. The --users-with-access option allows a maximum of ${maxSizeOfUsersWithAccess} users.`
        },
        multipleMatchingInstallations: 'Multiple matching installations found for the provided Atlassian app when only one was expected',
        partialInstallation: (failedProductInstallations) => `Failed to install into the following Atlassian apps: ${failedProductInstallations.join(', ')}. Run ${chalk_1.default.bold('forge install')} again to reattempt this installation.`,
        invalidServicePort: (serviceKey) => `Invalid tunnel port value for service ${serviceKey}. The 'tunnel:port' must be an integer between 1024 and 49152. Update your manifest.yml and try again.`,
        environmentIsNotDefined: (envKey) => `Environment with name ${envKey} not defined. Create this environment with ${chalk_1.default.bold(`forge environments create -e ${envKey}`)} before proceeding.`
    },
    warning: {
        plaintextCredentialsFound: (url) => `Your credentials were stored in plaintext by a previous version of the Forge CLI. For additional security, revoke your existing API token by visting this URL ${buildTerminalLink(url)}.`,
        plaintextCredentialsMigrated: 'The credentials found in plaintext have been migrated to your local keychain.',
        plaintextCredentialsNotMigrated: autoSpaceSentences(`The CLI couldn't securely store your login credentials in a local keychain.`, platformKeytarRecommendations(), `If a local keychain is not available, use environment variables instead. See ${gettingStartedDACLink} for more information.`),
        unsupportedNodeVersion: (_userNodeVersion, supportedNodeVersions) => log_color_1.LogColor.warn(`Warning: Forge CLI supports Node.js ${supportedNodeVersions}.` +
            `\nUnsupported Node.js versions are not guaranteed to work correctly.\n`),
        deprecation: {
            uikit: (modules) => {
                return `${chalk_1.default.bold('Warning')}: Your app is currently using deprecated UI Kit 1 modules: ${modules.join(', ')}. ${chalk_1.default.bold('UI Kit 1')} has been deprecated on February 28, 2025. Please refer to the ${(0, terminal_link_1.default)('documentation', 'https://developer.atlassian.com/platform/forge/ui-kit/upgrade-to-ui-kit-latest/#upgrade-from-ui-kit-1-to-ui-kit-latest-version')} to upgrade your modules.`;
            }
        }
    },
    maxSizeOfUsersWithAccess: 10,
    installationContext: {
        overviewProduct: 'Select an Atlassian app or platform tool.\n',
        promptProduct: 'Select an Atlassian app or platform tool:',
        promptOptionalProducts: 'Select other Atlassian apps:',
        overviewSite: '\nEnter your site. For example, your-domain.atlassian.net\n',
        overviewWorkspace: '\nEnter your workspace. For example, bitbucket.org/your-workspace\n',
        promptSite: 'Enter the site URL:',
        promptWorkspace: 'Enter the workspace URL:'
    },
    upgradeContext: {
        overview: `To upgrade your app to use the latest scopes, select it from the list.\n${ctrlC}`,
        promptInstallation: 'Select the site or workspace to upgrade:'
    },
    optionSite: 'site URL (example.atlassian.net)',
    optionProduct: (supportedProducts) => `Atlassian app (${supportedProducts.join(', ')})`,
    optionVerbose: 'enable verbose mode',
    optionJson: 'output results in JSON format',
    invalidCmd: (command) => `’${command}’ is not a Forge command.`,
    invalidCmdHelp: `Run ${forge('--help')} to see the full list of available commands.`,
    rerunningWithVerbose: 'Rerunning the command with --verbose may give more details.',
    ctrlC,
    graphQL: {
        request: (url, query, variables) => `▶️  GraphQL ${url}\nQuery: ${query}\nVariables: ${variables}`,
        response: (result, requestId) => `◀️  GraphQL\nRequest ID: ${requestId || 'unknown'}\nResult: ${result}`,
        error: 'Server error',
        outdatedClientVersion: `Your version of Forge CLI is no longer supported.` +
            `\nRun ${command('npm', 'uninstall', '-g', cli_details_1.FORGE_CLI_PACKAGE)} followed by ${command('npm', 'install', '-g', cli_details_1.FORGE_CLI_PACKAGE)} to update to the latest version.` +
            `\n`
    },
    hostedResources: {
        error: (errorMessage) => `Failed to deploy hosted resources. ${errorMessage}`,
        missingEntrypoint: `Missing index.html for custom UI resource. Make sure the file paths for resources in the manifest.yml file are correct and contain an index.html file.`,
        missingEntrypointWithResourceDetails: (resourceKey, directory) => `Missing index.html file for ${resourceKey}. Make sure the resource directory (${directory}) is correct and contains an index.html file.`,
        malformedEntrypoint: `Invalid index.html file. Make sure the index.html file has the <html> root element.`,
        malformedEntrypointWithKey: (resourceKey) => `Invalid index.html file for ${resourceKey}. Make sure the index.html file has the <html> root element.`,
        lambdaTimeout: 'Reduce the number or size of the files you’re uploading to avoid a timeout.'
    },
    bundle: {
        detectedChanges: 'Reloading code...',
        errors: (errors) => `Bundling failed: ${errors.join(', ')}`,
        failed: 'Bundling failed.',
        finished: 'Bundling succeeded.',
        warnings: (warnings) => `Bundling warnings: ${warnings.join(', ')}`
    },
    config: {
        missing: `Your app details are missing from the manifest.yml file. Register your app by running ${forge('register')}.`,
        invalid: `Invalid app details in the manifest.yml file. Register your app by running ${forge('register')}.`,
        manifest: {
            invalid: 'Command failed due to validation error.',
            error: (errorMessage, additionalInfo) => `Manifest validation failed: ${errorMessage}` +
                (additionalInfo ? '\nAdditional information: ' + additionalInfo : '')
        }
    },
    autocomplete: {
        cmd: {
            desc: 'configures autocomplete for the Forge CLI'
        },
        confirmInstalling: "This appends a line to your shell's config file. Would you like to continue?",
        installing: 'Installing autocomplete. Restart your shell when installation is completed.',
        uninstalling: 'Uninstalling autocomplete.',
        postinstall: `\n${chalk_1.default.cyan('ℹ')} To install autocompletion for Forge, run ${forge('autocomplete', 'install')}.\n`,
        error: {
            badArg: (arg) => `${arg ? `Invalid argument detected: "${arg}"` : 'Missing argument'}. Expected: "install" or "uninstall".`,
            unsupportedShell: 'Unsupported shell detected. Autocomplete functionality is only available on bash, fish, and zsh shells.',
            unsupportedNodeVersion: 'Your NodeJS version does not support Forge autocompletion. You must upgrade to NodeJS LTS version 12.7.0 or later.'
        }
    },
    login: {
        cmd: 'log in to your Atlassian account',
        optionEmail: 'specify the email to use',
        optionToken: 'specify the API token to use',
        introText: 'Log in to your Atlassian account',
        promptEmail: 'Enter your email:',
        url: (link) => `Next, enter your Atlassian API token. If you don't have a token, visit this URL to create one:\n${buildTerminalLink(link)}`,
        promptToken: 'Enter your Atlassian API token:',
        checking: 'Logging you in...',
        nextStep: `Now try ${forge('create')} to start a new app.`,
        success: (name) => `Logged in as ${name}.`,
        error: "We couldn't log you in with those credentials. Check your email address and token before rerunning the command.",
        scopedToken: {
            error: `Forge CLI currently does not support API tokens with scopes. To use CLI, create an API token without scopes by selecting ${chalk_1.default.bold('Create API token')}. Support for scoped API tokens will be included in a future release.`
        }
    },
    logout: {
        cmd: 'log out of your Atlassian account',
        loggedOut: `${greenTick} Logged out.`
    },
    whoami: {
        cmd: 'display the account information of the logged in user',
        success: {
            containerToken: (ciTokenKey) => `Logged in with CI Token ${ciTokenKey}`,
            personalCredentials: (email, name, accountId) => `Logged in as ${name} (${email})\nAccount ID: ${accountId}`
        },
        error: {
            personalCredentialsEnv: (emailKey, apiTokenKey) => `We couldn't get your Atlassian account information. Check the ${emailKey} and ${apiTokenKey} environment variables.`,
            personalCredentialsKeytar: `We couldn't get your Atlassian account information. You may need to run ${forge('login')} to log in again.`
        }
    },
    feedback: {
        cmd: 'feedback',
        description: 'let us know what you think about Forge',
        success: 'Thank you for using Forge',
        action: {
            start: `Help us make Forge even better.

For any questions, post them on: ${go('developer-community')}

To report bugs or issues, go to: ${go('forge-project')}

What do you like or don't like about Forge? Share your feedback below or press Ctrl+C to cancel.
`,
            enterFeedbackPrompt: 'Enter your feedback:',
            sendingFeedbackProgress: 'Sending your feedback...',
            error: 'We were unable to send your feedback. Please visit https://community.developer.atlassian.com.',
            success: 'Feedback sent.'
        }
    },
    create: {
        cmd: {
            desc: 'create an app',
            start: 'Creating app...',
            success: (appName) => `Created ${appName}`,
            successDetails: (directory, validEnvironmentOptions) => `\nYour app is ready to work on, deploy, and install. We created ${validEnvironmentOptions.length} environments you can deploy to: ${validEnvironmentOptions
                .map(environment_1.environmentToOption)
                .join(', ')}.\n\nChange to directory ${chalk_1.default.bold(directory)} to see your app files.`
        },
        intro: (givenDirectory) => `Creating an app in directory ${chalk_1.default.bold(givenDirectory)}.\n`,
        introWithCurrentDirectory: (currentDirectory) => `Creating an app in your current directory:\n\n    ${chalk_1.default.bold(currentDirectory)}\n`,
        optionTemplate: 'specify the template to use',
        optionDirectory: 'specify the directory to create (uses the template name by default)',
        optionSpace: 'specify the Developer Space id to use',
        overviewAppName: `\nName your app. The app name can include dashes, spaces, and underscores.\n`,
        overviewTemplates: '\nStart with a template. Each template contains the required files to be a valid app.\n',
        waitTemplates: 'Getting template list...',
        promptName: 'Enter a name for your app:',
        promptCategory: 'Select a category:',
        promptTemplate: 'Select a template:',
        promptProduct: 'Select an Atlassian app or platform tool:',
        taskTemplate: {
            title: 'Downloading template',
            downloading: (template) => `Downloading ${template} template project...`,
            extracting: 'Extracting template'
        },
        taskRegister: 'Registering app',
        taskCreateEnvironments: 'Creating environments',
        taskPackages: 'Installing dependencies',
        error: {
            dirtyDirectory: 'Destination directory is not empty',
            app: {
                creation: "Your app couldn't be created. Try again."
            },
            directory: {
                exists: (path) => `The directory ${path} already exists. Run ${forge('create')} using a different app name.`
            },
            name: {
                tooLong: (max) => `The app name exceeds ${max} characters. Run ${forge('create')} using a shorter app name.`
            },
            template: {
                download: (template) => `Failed to download the ${template} template. Run ${forge('create')} again.`,
                notFound: (template) => `The template ${template} doesn't exist. Run ${forge('create')} using a different template.`,
                noTemplates: 'There are no templates to choose from.',
                unexpectedArchiveFormat: 'Unexpected template format.'
            },
            packages: {
                installFail: `Something went wrong while installing app dependencies. Try running ${forge('create')} again.'
        )} to try again.`
            }
        }
    },
    devSpace: {
        fetching: 'Fetching your Developer Spaces...',
        documentationLink: 'https://developer.atlassian.com/platform/forge/developer-space/developer-spaces-introduction',
        noSpacesFound: (command, documentationLink) => `You are not currently a member of a Developer Space. You must be a member of a Developer Space to ${command} an app. Please contact an admin to be added to an existing space or create a new one. To learn more about your Developer Space, go to: ${documentationLink}\n`,
        selectPrompt: 'Select or create a Developer Space:',
        assignmentInfo: 'You are about to assign your app to a Developer Space. Once you assign your app to the selected Developer Space, all usage and billing for the app will be managed through this space.',
        selectionPrompt: (documentationLink) => `Please select the Developer Space you want to assign your app to. To learn more about your Developer Space, go to: ${documentationLink}`,
        createNewOption: 'Create a new Developer Space',
        createContinuePrompt: 'Do you want to continue?',
        createNewSpaceInfo: (documentationLink) => `\nA new Developer Space will now be created for you. To learn more about your Developer Space, go to: \n${documentationLink}`,
        createMessage: 'Name your Developer Space. The name must be unique and can include dashes, spaces, and underscores.\n',
        createPrompt: 'Enter a name for your Developer Space:',
        nameRequired: 'Developer Space name is required.',
        createInProgress: 'Creating your Developer Space...',
        contributingToSpace: (name) => `${greenTick} You are contributing to this Developer Space: ${name}.\n`,
        assigningToSpace: (name) => `${greenTick} You are assigning your app to this Developer Space: ${name}.\n`,
        createdAndContributing: (name) => `A Developer Space has been created for you. You are contributing to this Developer Space: ${name}.`,
        invalidSpaceName: (spaceName) => `The Developer Space does not exist, or you don't have the correct permissions to access it.`,
        invalidSpaceId: (spaceId) => `Developer Space id is not a valid UUID.`,
        error: {
            fetchOrSelect: (errorMessage) => `Failed to fetch or select Developer Space: ${errorMessage}`,
            create: (errorMessage) => `Failed to create Developer Space: ${errorMessage}`,
            selectedNotFound: 'Selected Developer Space not found',
            nameAlreadyExists: chalk_1.default.red('\nError: The name you have entered for your Developer Space is already in use. Please choose a different name to ensure it is unique.')
        },
        terms: {
            agreement: 'Please review the following agreement before continuing:\n',
            checkbox: '[ ] By continuing, I agree to the Atlassian Developer Terms and the Privacy Policy.',
            links: {
                devTerms: '    - Developer Terms: https://developer.atlassian.com/platform/terms/',
                privacy: '    - Privacy Policy: https://www.atlassian.com/legal/privacy-policy',
                pricing: '    - https://developer.atlassian.com/platform/forge/forge-platform-pricing/'
            },
            pricing: (appName) => `\nIf ${chalk_1.default.cyan(appName)} exceeds the free usage allowance, I agree to be charged monthly for any excess usage based the then-current price above threshold.\n${exports.Text.devSpace.terms.links.pricing}`,
            acceptPrompt: 'Do you accept?',
            accepted: (command) => `\n${greenTick} Terms accepted. Continuing with app ${command}...`
        }
    },
    register: {
        intro: 'Registering the app to you.',
        cmd: {
            desc: "register an app you didn't create so you can run commands for it",
            start: `Registering app...`,
            success: (appName) => `Registered ${appName}`,
            successDetails: (validEnvironmentOptions) => `\nYour app is ready to work on, deploy, and install. We created ${validEnvironmentOptions.length} environments you can deploy to: ${validEnvironmentOptions
                .map(environment_1.environmentToOption)
                .join(', ')}.\n\nUse ${forge('deploy')} to deploy your app to an environment.`
        },
        confirmQuestion: 'Are you sure you want to overwrite the existing app details?'
    },
    env: {
        option: `specify the environment (see your default environment by running ${forge('settings', 'list')})`,
        invalid: 'Invalid environment name',
        developmentOnly: (envKey) => `${(0, environment_1.environmentToOption)(envKey)} cannot be set as default environment. Only development environments can be used.`,
        error: {
            appOwnerNotExist: 'Missing app owner details',
            appNotExist: `Your app could not be found. Make sure the app details in the manifest.yml file are correct before trying again.`,
            envNotExist: (envKey) => `Environment ${chalk_1.default.bold((0, environment_1.environmentToOption)(envKey))} does not exist. Check the environment name and try again.`
        },
        displayEnvironment: (envKey, envType) => {
            if (envType === graphql_types_1.AppEnvironmentType.Development &&
                envKey !== environment_1.DEFAULT_ENVIRONMENT_KEY &&
                envKey !== environment_1.DEFAULT_ENVIRONMENT_OPTION) {
                return `${chalk_1.default.gray('DEV')} ${(0, environment_1.environmentToOption)(envKey)}`;
            }
            return (0, environment_1.environmentToOption)(envKey);
        },
        warn: {
            envWillBeCreated: (envKey) => `${chalk_1.default.bold('Warning:')} Environment ${chalk_1.default.bold((0, environment_1.environmentToOption)(envKey))} does not exist. If you continue, this development environment will be created for you.`
        },
        confirm: 'Do you want to continue?'
    },
    defaultEnv: {
        info: 'You do not have a default development environment set. This is required to run commands without specifying an environment. Make sure not to use sensitive information when naming your default development environment.',
        prompt: 'Enter a name for your default development environment:',
        warn: `${chalk_1.default.bold('Warning:')} A development environment with this name already exists. If you continue, you may be using the same environment as another contributor.`,
        confirm: 'Do you want to continue?',
        setSuccess: (envKey, envType) => `${exports.Text.env.displayEnvironment(envKey, envType)} has been set as your default development environment`,
        createAndSetSuccess: (envKey, envType) => `${exports.Text.env.displayEnvironment(envKey, envType)} has been created and set as your default development environment`,
        settingsInfo: `You can change your default development environment later by running ${forge('settings', 'set')}.`
    },
    varsSet: {
        cmd: {
            desc: 'set an environment variable',
            start: 'Setting environment variable...',
            success: 'Environment variable set.',
            deployTip: (environmentOption) => 'Tip: Changes to environment variables will not apply to existing deployments. ' +
                `Please run ${environmentOption ? forge('deploy', '-e', environmentOption) : forge('deploy')} for your changes to take effect.`
        },
        overview: (environment, environmentType) => `Setting the value of a variable in the ${exports.Text.env.displayEnvironment(environment, environmentType)} environment.`,
        encryptInfo: 'Encrypting a variable means that the value will not be shown in the terminal.',
        promptEncrypt: `Select if you want the value encrypted:`,
        keyInfo: 'Use a new key to create a variable, or use an existing key to override a variable.',
        promptKey: 'Enter the variable key:',
        promptValue: 'Enter the variable value:',
        optionSecret: 'encrypt variable',
        yes: 'Yes',
        no: 'No'
    },
    varsUnset: {
        cmd: {
            desc: 'remove an environment variable',
            start: (environment, envType) => `Unsetting the variable in the ${exports.Text.env.displayEnvironment(environment, envType)} environment.`,
            success: (key) => `\n${greenTick} ${key} variable removed.`
        }
    },
    varsList: {
        hint: `\nRun ${forge('variables', 'list')} to see your environment variables.\n`,
        cmd: 'list the environment variables',
        empty: (environment, envType) => `There are no variables in the ${exports.Text.env.displayEnvironment(environment, envType)} environment.\n\nUse ${forge('variables', 'set')} to create a variable.\n`,
        encryptedValue,
        overview: (environment, envType) => `Showing variables from the ${exports.Text.env.displayEnvironment(environment, envType)} environment:\n`,
        postfix: `\nNote, the values of encrypted variables are shown as ${encryptedValue}.\n`
    },
    providers: {
        desc: 'manage external providers'
    },
    configureProvider: {
        cmd: {
            desc: 'configure provider credentials',
            start: 'Configuring provider credentials...',
            success: 'oauth provider credentials configuration is finished.'
        },
        overview: (environment) => `Configuring provider in the ${(0, environment_1.environmentToOption)(environment)} environment.`,
        providerKeyInfo: 'Use a provider key from the list for configuration.',
        noProviders: "Count't find providers in the manifest file. Add one.",
        promptProviderKey: 'Select provider to configure:',
        optionClientSecret: 'client secret',
        promptClientSecret: 'Enter the client secret:'
    },
    environment: {
        desc: 'manage app environments'
    },
    createEnvironment: {
        cmd: {
            desc: 'create a new development environment',
            start: 'Creating environment...',
            success: (envKey, envType) => `Created ${exports.Text.env.displayEnvironment(envKey, envType)}`
        },
        overview: 'Create a new development environment.',
        promptEnvironmentKey: 'Enter a name for your environment:',
        successMessage: 'You can now tunnel or deploy to this new development environment.',
        optionEnvironmentKey: 'specify a name for the environment'
    },
    listEnvironment: {
        cmd: {
            desc: 'view all environments for this app'
        },
        overview: 'Showing all environments of the app:\n'
    },
    deleteEnvironment: {
        cmd: {
            desc: 'delete an existing development environment',
            start: 'Deleting environment(s)...'
        },
        overview: 'Delete an existing development environment.',
        info: 'Environments with existing installations cannot be deleted.\n',
        prompt: 'Select development environment:',
        confirmationInfo: 'You are deleting the following environment(s):',
        promptConfirmation: 'Do you want to continue?',
        individualSuccessMessage: (envKey, envType) => `${log_symbols_1.default.info} ${exports.Text.env.displayEnvironment(envKey, envType)} deleted successfully.`,
        successMessage: 'Environment(s) deleted.',
        optionEnvironmentKey: 'specify the environment to delete',
        warningMessage: `${chalk_1.default.bold('Warning:')} When deleting a development environment, you may impact in progress deployments or tunnels.`,
        noEnvironmentMessage: 'There are no development environments to delete.',
        hasInstallationError: (envKey) => `${(0, environment_1.environmentToOption)(envKey)} cannot be deleted because the environment is installed on a site. You can show all the current installations of your app by running ${forge('install', 'list')}.`
    },
    storage: {
        cmd: {
            desc: 'manage storage for your app'
        }
    },
    entitiesIndexes: {
        cmd: {
            desc: 'manage indexes for custom entities present in your app'
        }
    },
    entitiesIndexesList: {
        cmd: {
            desc: 'List indexes for all custom entities present in your app'
        },
        missingEntities: 'No entities were declared in manifest'
    },
    artifact: {
        error: {
            noDeployUrl: "Couldn't find deployment URL",
            noPresignedUrls: "Couldn't find presigned URLs",
            noUploadId: "Couldn't find uploadId",
            noManifestInZip: (manifestFilename) => `Couldn't find ${manifestFilename} file in the zip archive. Add one.`,
            noManifestAtPath: (path) => `We couldn't find the artifact file ${path}.`,
            empty: 'The provided artifact file was empty.',
            invalidYaml: (manifestFilename) => `The ${manifestFilename} file is not a valid YAML. Fix it and try again.`
        }
    },
    upload: {
        error: {
            notFound: (path) => `Couldn't find the file: ${path}`,
            empty: (path) => `File ${path} appears to be empty.`,
            status: (status, responseBody) => `Upload failed with status ${status} and body:\n${responseBody}`
        }
    },
    eligibility: {
        cmd: {
            cmdName: 'eligibility',
            desc: 'check if your app is eligible for certain programs like Runs on Atlassian',
            option: {
                majorVersion: 'specify a major version'
            },
            error: {
                invalidMajorVersion: 'Invalid major version number'
            },
            start: 'Checking eligibility...',
            end: 'Checking eligibility...',
            status: {
                notEligible: (envKey, envType, version, reason) => `${log_symbols_1.default.info} The version of your app [${version}] that's deployed to [${exports.Text.env.displayEnvironment(envKey, envType)}] is not eligible for the Runs on Atlassian program.\n${log_color_1.LogColor.warn(itemList(reason))}`,
                eligible: (envKey, envType, version) => `${log_symbols_1.default.info} The version of your app [${version}] that's deployed to [${exports.Text.env.displayEnvironment(envKey, envType)}] is eligible for the Runs on Atlassian program.`
            },
            rule: {
                conversion: (rule) => {
                    switch (rule) {
                        case 'HAS_REMOTES':
                            return 'App is using remote services';
                        case 'HAS_CONNECT_MODULES':
                            return 'App has Connect modules';
                        case 'HAS_DEFINED_EGRESS':
                            return 'App is egressing data';
                        case 'HAS_EXPOSED_CREDENTIALS':
                            return 'App is exposing credentials';
                        case 'HAS_NON_DARE_COMPLIANT_SQL_MODULE':
                            return 'App is using an SQL module that is in Preview';
                        case 'HAS_EGRESS_WEBTRIGGER_MODULE':
                            return 'App is using a webtrigger module that can egress data';
                        default:
                            return rule;
                    }
                }
            }
        }
    },
    version: {
        cmd: {
            cmdName: 'version',
            desc: 'app version information'
        },
        diff: {
            cmdName: 'compare',
            error: {
                noVersionProvided: 'Please provide 2 versions to compare'
            },
            option: {
                version1: '1st version to compare',
                version2: '2nd version to compare',
                environment1: '1st environment to compare',
                environment2: '2nd environment to compare',
                outFile: 'specify a file to output the results'
            },
            desc: `returns the details of two versions of the app for comparison. Details include:\n${itemList([
                'deployment date',
                'egress',
                'analytics',
                'policies',
                'scopes',
                'connect keys',
                'functions',
                'remotes',
                'modules',
                'license'
            ])}`,
            start: 'Comparing app versions...',
            end: 'Comparing app versions...',
            details: {
                banner: (input) => {
                    const env1Display = exports.Text.env.displayEnvironment(input.env1Key, input.env1Type);
                    const env2Display = input.env2Key && input.env2Type ? exports.Text.env.displayEnvironment(input.env2Key, input.env2Type) : '';
                    if (env2Display) {
                        return `${log_symbols_1.default.info} Comparison between app versions [${chalk_1.default.bold(input.version1)} in ${env1Display}] and [${chalk_1.default.bold(input.version2)} in ${env2Display}] is shown below:`;
                    }
                    return `${log_symbols_1.default.info} Comparison between app versions [${chalk_1.default.bold(input.version1)} and ${chalk_1.default.bold(input.version2)}] in [${env1Display}] is shown below:`;
                }
            }
        },
        check: {
            cmdName: 'details',
            option: {
                majorVersion: 'specify a major version',
                json: 'output results in JSON format',
                outFile: 'specify a file to output the results'
            },
            error: {
                invalidMajorVersion: (property) => {
                    const version = property ? ` for ${property}` : '';
                    return `Invalid major version number${version}`;
                }
            },
            desc: `returns the details of a specific version of the app. Details include:\n${itemList([
                'egress',
                'analytics',
                'policies',
                'scopes',
                'connect keys',
                'functions',
                'remotes',
                'modules',
                'license'
            ])}`,
            start: 'Getting app version details...',
            end: 'Getting app version details...',
            details: {
                banner: (envKey, envType, version) => {
                    const envDisplay = exports.Text.env.displayEnvironment(envKey, envType);
                    return `${log_symbols_1.default.info} App [${version}] in [${envDisplay}] includes the following:`;
                },
                prompt: {
                    options: {
                        banner: 'Select option:',
                        choices: {
                            all: 'Show all properties',
                            manual: 'Manual selection'
                        }
                    },
                    properties: {
                        banner: 'Select properties that you are interested in:',
                        info: 'Note: Changes to the properties below may trigger major version updates in Atlassian systems.\n',
                        headers: ['Property', 'Description'],
                        descriptions: {
                            scopes: 'Scopes that the app has access to',
                            egress: 'Network permissions',
                            analytics: 'Analytics',
                            policies: 'Content security policies (Custom UI)',
                            functions: 'Function modules used by the app',
                            modules: 'Modules used by the app (other than functions & remotes)',
                            remotes: 'Remote modules used by the app (Remote backend, Connect or External Auth)',
                            connectKeys: 'Connect on Forge',
                            license: 'Does the app require a license?'
                        }
                    }
                },
                writeToFile: (file) => `Writing to file: ${file}`,
                license: (requiresLicense) => `${requiresLicense ? 'Yes' : 'No'}`
            }
        },
        list: {
            cmdName: 'list',
            option: {
                json: 'output results in JSON format',
                outFile: 'specify a file to output the results'
            },
            desc: `returns a summary of all major versions of the app. Summary includes:\n${itemList([
                'version number',
                'deployment date',
                'egress',
                'analytics',
                'policies',
                'scopes',
                'connect keys',
                'functions',
                'remotes',
                'modules',
                'license'
            ])}`,
            start: 'Getting app version list...',
            end: 'Getting app version list...',
            details: {
                banner: (envKey, envType, versions) => {
                    const envDisplay = exports.Text.env.displayEnvironment(envKey, envType);
                    return `${log_symbols_1.default.info} Details of a total of [${versions} major versions] in [${envDisplay}] can be seen below:`;
                }
            }
        },
        upgrade: {
            cmd: {
                cmdName: 'bulk-upgrade',
                desc: 'upgrades installations from one major version to another version.'
            },
            start: {
                cmdName: 'start',
                option: {
                    json: 'output results in JSON format',
                    outFile: 'specify a file to output the results',
                    version1: 'source version to upgrade in a non-interactive mode',
                    version2: 'target version to upgrade to in a non-interactive mode'
                },
                desc: `upgrades installations using one major version to another version. The version selection list displays:\n${itemList(['major version number', 'deployment date', 'number of installations'])}`,
                overViewVersionTable: (versions, environment) => `\nDetails for a total of [${versions} major versions] in [${environment}] can be seen below.\nWhere there are no upgrade paths available, use \`forge version compare\` to compare versions and see more information:\n`,
                promptVersionTable: 'Getting app version list...',
                selectTargetVersionToUpgrade: (installations) => `Please select version to upgrade existing ${installations} installations to:`,
                error: {
                    missingVersionUpgradeParameters: `Missing parameters:\nError: [version bulk-upgrade start --non-interactive] requires --from-version and --to-version`,
                    appVersionRolloutRunning: `App version rollout for this app environment is already running. Use \`forge version bulk-upgrade list\` to identify the running upgrade and \`forge version bulk-upgrade cancel\` to cancel.`,
                    permissionDeniedError: (fromVersion, toVersion, environmentKey) => `User does not have required permissions: \nError: [version bulk-upgrade start --non-interactive --from-version ${fromVersion} --to-version ${toVersion}] requires Admin or Deployer permissions in the [${environmentKey}] environment.`,
                    noUpgradePathAvailable: (fromVersion, toVersion) => `From and to versions specify a combination for which an update is not available:\nError: [version bulk-upgrade start --non-interactive --from-version ${fromVersion} --to-version ${toVersion}] does not specify a valid to and from combination. Run \`forge version bulk-upgrade start\` interactively to see available versions.`,
                    inValidVersionNumberSpecified: (fromVersion, toVersion) => `Invalid version number specified:\nError: [version bulk-upgrade start --non-interactive --from-version ${fromVersion} --to-version ${toVersion}] specifies a [to-version|from-version] that does not exist. Run \`forge version bulk-upgrade start\` interactively to see available versions.`,
                    inValidMajorVersionNumberSpecified: (majorVersion) => `Invalid version number specified:\nError: [version bulk-upgrade start --non-interactive] specifies a [major version: ${majorVersion}] that does not exist. Run \`forge version bulk-upgrade start\` interactively to see available versions.`,
                    noTargetVersionAvailable: 'There are no upgrade paths available, use `forge version compare` to compare versions and see more information:',
                    tooManyRequestsFromAccount: `The capacity for concurrent app rollout requests from your account has been breached. Please try again after some time.`,
                    tooManyRequestsGlobally: `System is unavailable for app rollout requests due to breach in capacity. Please try again after some time.`
                },
                appVersionRolloutSuccess(appRolloutVersionId) {
                    return `Your upgrade has been queued with upgrade ID ${appRolloutVersionId}. To view that status of your update please use the \`forge version bulk-upgrade list\` command.`;
                },
                warningMessage: (sourceVersionId, targetVersionId, installations) => `${chalk_1.default.bold('Warning:')} You are planning to move ${installations} installations from version ${sourceVersionId} to version ${targetVersionId}.`,
                promptConfirmation: 'Do you want to continue?'
            },
            list: {
                cmdName: 'list',
                option: {
                    outFile: 'specify a file to output the results',
                    majorVersion: 'specify a major version'
                },
                desc: `returns a summary of version update requests. Details include:\n${itemList([
                    'upgrade ID',
                    'upgrade request status',
                    'start date',
                    'completed date',
                    'from version',
                    'to version',
                    'number of updates completed',
                    'number of updates pending',
                    'number of updates failed'
                ])}`,
                start: 'Getting app version upgrade list...',
                end: 'Getting app version upgrade list...',
                details: {
                    banner: (envKey, envType, updates) => {
                        if (!envType) {
                            return `${log_symbols_1.default.info} Details of a total of [${updates} updates] can be seen below. Records may not be available indefinitely.`;
                        }
                        const envDisplay = exports.Text.env.displayEnvironment(envKey, envType);
                        return `${log_symbols_1.default.info} Details of a total of [${updates} updates] in [${envDisplay}] can be seen below. Records may not be available indefinitely.`;
                    }
                }
            },
            cancel: {
                cmdName: 'cancel',
                option: {
                    json: 'output results in JSON format',
                    outFile: 'specify a file to output the results',
                    appRolloutId: 'app rollout version Id to cancel'
                },
                desc: `cancels a version upgrade that is in progress.`,
                error: {
                    missingCancelVersionUpgradeParameters: `\nMissing parameters:\nError: [version bulk-upgrade cancel] requires --app-upgrade-id`,
                    permissionDeniedError(environmentKey) {
                        return `User does not have permission to cancel the upgrade:\nError: [version bulk-upgrade cancel] requires Admin or Deployer permissions in the [${environmentKey}] environment.`;
                    },
                    noUpdateInProgress(environmentKey) {
                        return `No updates are in progress for this app/environment:\nError: [version bulk-upgrade cancel] did not succeed. No upgrades are in progress for this app in the [${environmentKey}] environment.`;
                    },
                    inValidRolloutIdSpecified: `Invalid rollout id specified:\nError: [version bulk-upgrade cancel] specifies a rollout id that does not exist. Run \`forge version bulk-upgrade list\` to see rollouts running.`
                },
                appVersionRolloutCancelSuccess(appRolloutVersionId) {
                    return `Your upgrade with upgrade ID ${appRolloutVersionId} has been cancelled.`;
                },
                warningMessage: (appRolloutVersionId, sourceVersionId, targetVersionId, installationComplete, totalInstallations) => `${chalk_1.default.bold('Warning:')} You are planning to cancel the upgrade with upgrade ID ${appRolloutVersionId} from version ${sourceVersionId} to version ${targetVersionId} that is in progress. ${installationComplete} of ${totalInstallations} installations have already been upgraded.`,
                promptConfirmation: 'Do you want to continue?'
            }
        }
    },
    build: {
        cmd: {
            desc: '(Preview) build and upload your app',
            startNotice: `Building and uploading your app. \n${ctrlC}\n`,
            start: 'Building and uploading your app...',
            success: (buildTag) => `(Preview) Build successful with build tag: ${buildTag}`
        },
        buildTag: {
            description: '(Preview) specify a custom build tag for build',
            error: {
                invalidBuildTag: (maxLength) => `Invalid build tag; tag must be ${maxLength} characters or less.`,
                emptyBuildTag: 'Invalid build tag; tag cannot be empty.',
                invalidBuildTagFormat: 'Invalid build tag; tags are case-insensitive and must start with a letter or number and can only contain alphanumeric characters, underscores, hyphens, and periods.'
            }
        },
        taskLint: {
            lintError: log_color_1.LogColor.error(`Error: The build failed due to errors in the app code. Fix the errors before rerunning ${forge('build')}, or run ${forge('build', '--no-verify')} to skip the linter.\n`),
            lintWarning: (numWarnings) => {
                const { pluralCheckedTotal } = checkLintTotalPlurals(0, numWarnings, 0, 0);
                return log_color_1.LogColor.warn(`${pluralCheckedTotal} found. Run ${forge('lint')} to review the warnings.`);
            }
        },
        list: {
            cmd: {
                desc: '(Preview) list builds for your app'
            },
            limit: (defaultLimit) => `Specify the number of builds to show (default is ${defaultLimit})`,
            listingBuilds: '(Preview) Showing builds for your app:',
            noBuildsFound: 'No builds found.',
            error: {
                invalidLimit: 'Invalid limit; limit can only contain positive integers.'
            }
        },
        manifestVariables: {
            error: log_color_1.LogColor.error(`Error: Manifest environment variables are not supported for builds. Please remove the environment variables from your manifest.yml before rerunning ${forge('build')}.\n`)
        }
    },
    deploy: {
        cmd: {
            desc: 'deploy your app to an environment',
            start1: (envKey, envType, buildTag) => {
                const buildTagText = buildTag ? ` using build with tag ${buildTag}` : '';
                return `Deploying your app${buildTagText} to the ${exports.Text.env.displayEnvironment(envKey, envType)} environment.\n${ctrlC}\n`;
            },
            start2: (appName, envKey, envType, buildTag) => {
                const buildTagText = buildTag ? ` using build with tag ${buildTag}` : '';
                return `Deploying ${appName}${buildTagText} to ${exports.Text.env.displayEnvironment(envKey, envType)}...`;
            },
            success: 'Deployed\n',
            successDetails: (appName, envKey, envType, buildTag) => {
                const buildTagText = buildTag ? ` using build with tag ${buildTag}` : '';
                return `Deployed ${appName}${buildTagText} to the ${exports.Text.env.displayEnvironment(envKey, envType)} environment.`;
            },
            distributePageLink: (appId) => `To install on a site that you're an admin of, run ${forge('install')}.\n` +
                'To install on any other site, generate an installation link in the developer console and share it with the site admin: ' +
                `https://developer.atlassian.com/console/myapps/${appId}/manage/distribution`
        },
        taskLint: {
            lintError: log_color_1.LogColor.error(`Error: The deploy failed due to errors in the app code. Fix the errors before rerunning ${forge('deploy')}, or run ${forge('deploy', '--no-verify')} to skip the linter.\n`),
            lintWarning: (numWarnings) => {
                const { pluralCheckedTotal } = checkLintTotalPlurals(0, numWarnings, 0, 0);
                return log_color_1.LogColor.warn(`${pluralCheckedTotal} found. Run ${forge('lint')} to review the warnings.`);
            }
        },
        hasNoAppInstallationsForEnv: {
            hasNoAppInstallationsForEnvError: log_color_1.LogColor.error(`Error: The deployment failed due to errors while trying to determine if the app has any installations for the deployed environment.`)
        },
        environmentKey: {
            missingEnvironmentKeyError: log_color_1.LogColor.error('Environment must be specified when deploying your app.')
        },
        majorVersion: {
            description: 'specify a major version to update (Preview)',
            warning: (majorVersion) => `${chalk_1.default.bold('Warning:')} You\'re about to deploy changes to major version ${majorVersion} of your app. All sites using version ${majorVersion} will automatically apply these changes.\n`,
            confirm: `Continue?`,
            invalidMajorVersionError: 'Invalid major version number'
        },
        buildTag: {
            description: '(Preview) specify a build tag to deploy (from forge build)'
        },
        connectKeyChange: {
            continueChange: `Do you wish to continue with changing the Connect key?`,
            continueDelete: `Do you wish to continue with deleting the Connect key?`,
            mpacAppConnectKeyChangeAnalyticsError: 'Cannot change app.connect.key for an app with an Atlassian Marketplace listing.',
            mpacAppConnectKeyChangeError: (mpacAppKey, connectKey) => log_color_1.LogColor.error(`Cannot change the app.connect.key from \'${mpacAppKey}\' to \'${connectKey}\'. The app's Connect key must match the Atlassian Marketplace key.\n`),
            connectKeyChangeWarning: (environment, migrationKey, connectKey) => `WARNING: Changing the app.connect.key in ${(0, environment_1.environmentToOption)(environment)} from \'${migrationKey}\' to \'${connectKey}\' affects features using the Connect key as an identifier. ` +
                `\nLearn more about the impact of this change at ${go('forge-connect-key-changes')}.\n`,
            connectKeyDeleteWarning: (environment) => `WARNING: You're about to delete the app.connect.key of the app in ${(0, environment_1.environmentToOption)(environment)}. ` +
                `\nIf you proceed, non-Forge Connect installations using the Connect key will no longer be replaced by future Forge installations of the app, and will co-exist. ` +
                `\nLearn more at ${go('forge-connect-key-deletion')}.\n`,
            connectKeyMutationInProductionError: (migrationKey, connectKey) => log_color_1.LogColor.error(`Cannot change the app.connect.key from \'${migrationKey}\' to \'${connectKey}\'. The app's Connect key cannot be mutated in production after deployment.\n`),
            connectKeyMutationInProductionAnalyticsError: 'Cannot mutate app.connect.key for an app in production.'
        },
        taskPackage: {
            title: 'Packaging app files',
            packageBundledFiles: 'Packaging bundled files',
            packageFile: (fileName, filePath) => `File added to archive: ${filePath}` + fileName ? `, from ${fileName}` : '',
            archiveCreated: (archivePath) => `Archive created: ${archivePath}`
        },
        taskUpload: {
            title: 'Uploading app',
            uploadingArchive: (uploadUrl) => `Uploading archive to ${uploadUrl}...`,
            uploadingResources: () => 'Uploading resources'
        },
        taskDeploy: {
            serverStepStarted: (name) => name,
            serverStepFailed: 'Deployment failed'
        },
        error: {
            notFound: "Couldn't find app deployment"
        },
        outdatedInstallations: `We've detected new scopes or egress URLs in your app.\n` +
            `Run ${forge('install', '--upgrade')} and restart your tunnel to put them into effect.`,
        postDeploymentRoaEligibilityFailure: (appVersion, envKey, envType) => `${log_symbols_1.default.info} The version of your app [${appVersion}] that was just deployed to [${exports.Text.env.displayEnvironment(envKey, envType)}] is not eligible for the Runs on Atlassian program. Run ${forge('eligibility')} to know more.\n\nTo know more about Runs on Atlassian, go to ${go('runs-on-atlassian')}.`,
        postDeploymentRoaEligibilitySuccess: (appVersion, envKey, envType) => `${log_symbols_1.default.info} The version of your app [${appVersion}] that was just deployed to [${exports.Text.env.displayEnvironment(envKey, envType)}] is eligible for the Runs on Atlassian program.\n\nTo know more about Runs on Atlassian, go to ${go('runs-on-atlassian')}.`,
        listIndexes: (environment) => `Run ${forge('storage', 'entities', 'indexes', 'list', '-e', (0, environment_1.environmentToOption)(environment))} to check the status of the indexes.`,
        reindexingInProgress: {
            continueDeployment: 'Reindexing is currently in progress. Are you sure you want to deploy?',
            successfulDeployment: 'Deployment successful. Please note - indexing currently in progress.'
        },
        egressURL: {
            error: (message) => {
                return `Invalid Egress permissions: ${message}\nLearn more at https://developer.atlassian.com/platform/forge/add-content-security-and-egress-controls/`;
            }
        },
        crossContext: {
            enableError: `Unable to deploy an app to an environment with an existing installation in an Atlassian app that is not the required Atlassian app.\nRun ${chalk_1.default.bold('forge uninstall')} to uninstall your app from any non-required Atlassian apps in this environment before retrying ${chalk_1.default.bold('forge deploy')}.`,
            modifyError: `Unable to modify the required Atlassian app for an environment with existing installations.\nRun ${chalk_1.default.bold('forge uninstall')} to uninstall your app from all Atlassian apps in this environment before retrying ${chalk_1.default.bold('forge deploy')}.`
        }
    },
    install: {
        cmd: {
            description: 'manage app installations',
            start: (envKey, envType, product) => {
                const productText = product ? `in ${product} ` : '';
                return `Installing your app ${productText}on to ${exports.Text.env.displayEnvironment(envKey, envType)}...`;
            },
            end: (displayTick, product) => `${displayTick ? greenTick + ' ' : ''}Install in ${product} complete!`
        },
        booleanToScope: (isLatest) => (isLatest ? `(Latest)` : `(Out-of-date)`),
        alreadyInstalledInRequiredProduct: (product) => `\nYou have already installed this app into ${chalk_1.default.bold(product)}.`,
        installingToRequiredProduct: (product) => `\nYour app will be installed into ${chalk_1.default.bold(product)}. Once this is done, you can install your app into any other Atlassian apps.\n`,
        installingToOptionalProduct: (product) => `\nThis app will be installed into ${chalk_1.default.bold(product)}.\n`,
        installConfirmation: (product, site) => `Installing your app onto ${product} on ${site}.\n${ctrlC}\n`,
        bannerSite: `\nInstalling your app onto an Atlassian site.\n${ctrlC}\n`,
        bannerWorkspace: `\nInstalling your app onto the selected workspace.\n${ctrlC}\n`,
        devAppInstallWarning: `${chalk_1.default.bold('WARNING:')} You are about to install a development app to a production site. If you do not intend to test your app, we strongly recommend that you deploy your app to production and install the production version instead.`,
        majorVersionIsNotLatest: (versionToInstall) => `WARNING: You are about to install a previous version of the app. (${versionToInstall})`,
        devAppInstallConfirm: `Are you sure you want to proceed?`,
        optionConfirmScopes: 'skip confirmation of scopes for the app before installing or upgrading the app',
        optionUpgrade: 'upgrade an existing installation',
        optionLicense: 'specify the license value for the app (allowed values: active, standard, advanced, inactive, and trial)',
        optionLicenseModes: 'specify the list of license mode value for the app (allowed values: user-access)',
        optionUsersWithAccess: 'specify the list of Atlassian Account IDs(aaid) for users who have access to the app',
        optionMajorVersion: 'specify the major version to install',
        listScopes: (scopes) => `Your app will be installed with the following scopes:\n${scopes
            .map(({ name, requiresInteractiveConsent }) => `- ${name}${requiresInteractiveConsent ? ' (requires user consent)' : ''}`)
            .join('\n')}\n`,
        listEgressAddresses: (egressAddresses) => `Your app will exchange data with the following urls:\n${egressAddresses.map((url) => `- ${url}`).join('\n')}\n`,
        permissionsMismatch: (environment) => `The scopes or egress URLs in the manifest are different from the scopes in your most recent deployment to ${(0, environment_1.environmentToOption)(environment)}. Try running ${forge('deploy', '-e', (0, environment_1.environmentToOption)(environment))} before installing.\n`,
        multiProductScopesDetected: (productsToInstall, productsToUpgrade, site, environment) => `\nWe detected your app requires scopes across multiple Atlassian apps.\nRun ${forge('install')} for each of the following:\n${itemList([
            ...productsToUpgrade.map((product) => forge('install', '--upgrade', '-p', (0, case_1.capital)(product), '-s', site, '-e', (0, environment_1.environmentToOption)(environment))),
            ...productsToInstall.map((product) => forge('install', '-p', (0, case_1.capital)(product), '-s', site, '-e', (0, environment_1.environmentToOption)(environment)))
        ])}`,
        promptForPermissionsConfirmation: (permissionsMismatchInDevelopment) => permissionsMismatchInDevelopment
            ? 'Are you sure you want to continue installing the app?'
            : 'Do you want to continue?',
        success: {
            banner: (envKey, envType, product, site) => `Your app in the ${exports.Text.env.displayEnvironment(envKey, envType)} environment is now installed in ${product} on ${buildTerminalLink(site)}. You can install the app into other Atlassian apps by running the ${chalk_1.default.bold('forge install')} command again.`
        },
        error: {
            activationIdMissing: (url, context) => `Atlassian app is not activated on ${url}. Enable ${context} in your suite or contact your administrator for assistance.`,
            invalidAtlassianSite: (url) => `The URL you entered doesn't belong to an Atlassian site: ` +
                `\n${url.toString()} ` +
                `\n\nRun the command using a different URL.`,
            invalidWorkspace: (url) => `The URL you entered is not a valid workspace: ` +
                `\n${url.toString()} ` +
                `\n\nRun the command using a different URL.`,
            url: (url) => `Site URL is invalid: ${url}`,
            site: (url) => `Site is invalid: ${url}`,
            alreadyInstalledError: `Installation error: App is already installed.\nIf you're trying to upgrade your app, use the ${forge('install', '--upgrade')} command.`,
            alreadyInstalledErrorWithMajorVersion: (envKey, envType) => `The app in the ${exports.Text.env.displayEnvironment(envKey, envType)} environment is already installed on this site. Uninstall the app before trying again.`,
            serverSideInstallationError: (message) => `Installation error: ${message}`,
            noDeploymentFound: (environment) => `Forge apps must be deployed before installation. Deploy your app by running ${forge('deploy', '-e', (0, environment_1.environmentToOption)(environment))}.`,
            permissionsDeniedInstructions: (requestId, appId) => `Insufficient permissions to install app (requestId: ${requestId})` +
                '\n\nTo install the app on this site, generate an installation link ' +
                'in the developer console and share it with the site admin: ' +
                `https://developer.atlassian.com/console/myapps/${appId}/distribution`,
            appendRequestIdToErrorMessage: (message, requestId) => `${message} For more help on this issue, please reach out to support (${buildTerminalLink('https://developer.atlassian.com/support')}) and provide them the following request ID: ${requestId}`,
            majorVersionNotFound: 'The major version you specified does not exist. Check the version number and try again.',
            majorVersionAndUpgrade: 'Cannot use the major version flag with the upgrade flag'
        },
        failedAll: (site, environment) => `Your app in ${(0, environment_1.environmentToOption)(environment)} was not installed on any Atlassian apps on ${chalk_1.default.bold(site)}.`,
        security: {
            banner: (site) => `\n${chalk_1.default.gray('=== ')}Security questions\n
Forge apps installed on ${site} must comply with our corporate security guidelines.
Read the guidelines on the page below before answering the required security questions:
${buildTerminalLink('https://hello.atlassian.net/wiki/x/iIC1Hg')}\n`,
            questions: [
                'Does the app store, process, or transmit any Personal Data?',
                'Does the app acquire, store, or process credit card and/or payment information?',
                'Does the app store or transmit any data beyond the Atlassian cloud (for example, through API calls to external products or services)?',
                'Does the app make administrative changes to Atlassian products or services?'
            ],
            notTrustedApp: {
                warn: (site) => `\nYou answered ${chalk_1.default.bold('yes')} to one or more of the questions. Corporate security needs to review your app before you install it on ${site}.\n`,
                confirmApproval: `Has corporate security approved your app?`,
                corpSecurityHelpdesk: `\nCreate a legal ticket to request an app review here:\n
${buildTerminalLink('https://jira.sec.internal.atlassian.com/servicedesk/customer/portal/8/create/88')}

When corporate security has approved the app, you can proceed with the installation.\n`
            }
        },
        authorization: {
            banner: `\n${chalk_1.default.gray('=== ')}Authorize your app\n`,
            link: (link) => `Follow the prompts at this URL to authorize your app:
${buildTerminalLink(link)}\n`,
            openBrowser: `Press any key to open the URL in your default browser.`
        }
    },
    harmonization: {
        installation: {
            errors: {
                concurrentSync: `Install has failed due to a background syncing clash. Try installing your app again in 10 minutes. If you see this error again, raise a thread at ${go('cdac-connect-forge')}.`,
                placeholderMacroCollision: 'Confluence macro key is already used by another app. Macro keys must be globally unique. Prefixing with your app.key name ensures compatibility with other apps.',
                placeholderFailedDescriptorValidation: 'One or more connectModules are defined incorrectly in your manifest.yml. Check the module definitions and deploy before trying again.'
            }
        }
    },
    upgrade: {
        bannerSite: `\nUpgrading your app on the Atlassian site.\n`,
        bannerWorkspace: `\nUpgrading your app on the selected workspace.\n`,
        cmd: {
            start: (envKey, envType) => `Upgrading your app in ${exports.Text.env.displayEnvironment(envKey, envType)}...`,
            end: (displayTick) => `${displayTick ? greenTick + ' ' : ''}Upgrade complete!`,
            error: `Upgrade failed`
        },
        listScopes: (scopes) => `Your app will be upgraded with the following additional scopes:\n${scopes
            .map(({ name, requiresInteractiveConsent }) => `- ${name}${requiresInteractiveConsent ? ' (requires user consent)' : ''}`)
            .join('\n')}\n`,
        listEgressAddresses: (egressAddresses) => `Your app will exchange data with the following urls:\n${egressAddresses.map((url) => `- ${url}`).join('\n')}\n`,
        permissionsMismatch: (environment) => `The scopes or egress URLs in the manifest are different from the scopes in your most recent deployment to ${(0, environment_1.environmentToOption)(environment)}. Try running ${forge('deploy', '-e', (0, environment_1.environmentToOption)(environment))} before upgrading.\n`,
        promptForPermissionsConfirmation: (permissionsMismatchInDevelopment) => permissionsMismatchInDevelopment
            ? 'Are you sure you want to continue upgrading the app?'
            : 'Do you want to continue?',
        success: {
            banner: (envKey, envType, product, site) => `Your app in the ${exports.Text.env.displayEnvironment(envKey, envType)} environment is now the latest in ${product} on ${buildTerminalLink(site)}.`
        },
        alreadyUpdated: {
            spinnerSite: 'Site is already at the latest version',
            spinnerWorkspace: 'Workspace is already at the latest version',
            banner: (environment, product, site) => `\nYour app in the ${(0, environment_1.environmentToOption)(environment)} environment is at the latest in ${product} on ${buildTerminalLink(site)}.`
        },
        error: {
            serverSideInstallationError: (message) => `Upgrade error: ${message}`
        }
    },
    installList: {
        cmd: 'list app installations',
        banner: `\nShowing all the current installations of your app:`,
        noResourceId: 'Unknown site with no resource ID',
        noCloudId: 'Unknown workspace with no cloud ID',
        noResourceIdInWorkspace: 'Unknown workspace with no resource ID',
        noInstallations: `The app is not installed anywhere.\nRun ${forge('install')} to install your app on an Atlassian site.\n`
    },
    deployList: {
        cmd: 'list app deployments',
        banner: `Showing latest deployments of your app:`,
        noDeployments: `No deployments found for this app.\nRun ${forge('deploy')} to deploy your app to an environment.`
    },
    tunnel: {
        cmd: 'start a tunnel to connect your local code with the app running in the development environment',
        optionDebugger: 'enable debugger mode',
        debuggerPort: 'starting port to use for debugging, multiple handlers will get subsequent ports. It is only used for Node runtime debugger',
        functionHandlers: 'list of function handlers declared on manifest to debug, separated by space. This option must be specified if debug mode is enabled.  It is only used for Node runtime debugger',
        preamble: 'Tunnel redirects requests you make to your local machine. This occurs for any Atlassian site where your app is installed in the specific development environment. You will not see requests from other users.',
        startingTunnel: (environmentKey, envType) => `Tunnelling to: ${exports.Text.env.displayEnvironment(environmentKey, envType)}`,
        startedServer: (port, isDebug) => `Listening for requests${isDebug ? ' on local port ' + port : ''}...`,
        selfManagedTunnel: (tunnelUrl, port) => `Warning: You are currently using a self-managed tunnel. Please bind your tunnel (${tunnelUrl}) to the local host on port ${port}.`,
        startedTunnel: (tunnelUrl) => `Started tunnel at address: ${tunnelUrl}.`,
        stoppingTunnel: 'Stopping tunnel...',
        stoppedTunnel: 'Tunnel stopped.',
        tunnelStatusChange: (status) => `Tunnel connection status changed: ${status}.`,
        functionHandlersMustBeDefined: `${chalk_1.default.bold('--debugFunctionHandlers')} flag must be defined in debug mode.`,
        debugArgumentNameMismatch: (arg) => `Arguments of ${chalk_1.default.bold('--debugFunctionHandlers')}, namely '${arg}', must be function handlers defined in the manifest.`,
        invalidDebugStartingPortNumber: (port) => `${chalk_1.default.bold('--debugStartingPort')} ${port} must be a valid port number.`,
        unableToAuthenticateDocker: (errCode) => `Docker authentication process exited with code: ${errCode}.`,
        unableToPullProxySidecarImage: (errMessage) => `Unable to pull the proxy sidecar image. Make sure to run 'forge containers docker-login' first. Full error: ${errMessage}`,
        unableToStartDockerComposeStack: (errMessage) => `Cannot start docker compose stack. This usually happens when Docker isn't installed or running. To fix this: Start a docker engine then retry the command. Full error: ${errMessage}`,
        unableToStopDockerComposeStack: (serviceKey, errMessage) => `Failed to stop docker-compose stack for ${serviceKey}. Full error: ${errMessage}`,
        invoke: (requestId, handler) => `invocation: ${requestId} ${handler}`,
        invocationTimeout: (timeout) => `Function result will not be returned to the Forge platform, as the function did not complete within ${timeout} seconds. In invocations outside tunnel, functions that exceed the time limit are terminated.`,
        customUI: {
            fileServed: (filename, resourceKey) => `Serving file ${filename} for resource ${resourceKey}`,
            fileProxied: (filename, resourceKey, tunnelPort) => `Received proxy request. ${exports.Text.tunnel.customUI.fileServed(filename, resourceKey)} from specified address http://localhost:${tunnelPort}`,
            warning: {
                cspViolation: (localUrl, violation) => `CSP violation detected for '${violation}' while serving content at ${localUrl}\nFor an app to share data with external resources or use custom CSP, follow the steps in: ${go('forge-content-security-and-egress-controls')}\n`
            }
        },
        container: {
            invoke: (req, port) => `Proxying request to service ${req.method} http://${req.host}:${port}${req.path}`,
            error: (cause) => `Failed to proxy request: ${cause}`
        },
        preBundleTask: (title) => `${log_color_1.LogColor.trace('===')} ${title}`,
        lintFailed: chalk_1.default.red(`${chalk_1.default.bold('Error:')} Linting failed due to errors in the app code.`),
        bundlingHeader: 'Bundling code...',
        bundlingSucceeded: 'App code bundled.',
        resourcesBundlingSucceeded: `${greenTick} Resources bundled.`,
        functionsBundlingSucceeded: `${greenTick} Functions bundled.`,
        cloudflaredLog: (data) => `[cloudflared]: ${data}`,
        tunnelWithLocalCloudflared: 'Establishing forge tunnel with the local cloudflared binary',
        connectUsingSelfManagedTunnel: 'Connect using self-managed tunnel',
        tunnelLocalPort: 'Optional: Specify the local port to bind your tunnel',
        error: {
            create: (message) => `Couldn't create tunnel, message: ${message}`,
            delete: (message) => `Couldn't delete tunnel, message: ${message}`,
            handler: {
                notFound: (handler) => `Function with handler "${handler}" was not found`
            },
            manifestChangeDetected: `Changes to ${manifest_1.MANIFEST_FILE} have been detected. You will need to deploy your forge app to apply these changes.`,
            dockerNotInstalled: (dockerDownloadLink) => 'Cannot find Docker. This command requires Docker to run your app locally. ' +
                `Get Docker at the following URL before rerunning the command:\n\n${dockerDownloadLink}`,
            dockerDaemonNotRunning: (err, isVerbose) => `Docker is not running. This command requires Docker to run your app locally. Open Docker before rerunning the command.` +
                `${isVerbose ? '\n\nError details: ' + err : ''}`,
            serverNotStartedOnPort: (tunnelPort) => `Failed to connect to localhost:${tunnelPort}. Check that your service is running.`,
            cloudflaredError: 'Failed to start cloudflared. Rerunning the command with --verbose may give more details.',
            cloudflaredExit: (code) => code
                ? `Cloudflared exited. Rerunning the command with --verbose may give more details.`
                : `Cloudflared exited with code: ${code}. Rerunning the command with --verbose may give more details.`,
            cloudflaredUnavailableError: `Please check for any network restrictions that may be blocking the ${chalk_1.default.bold('cloudflared')} package installation, and then reinstall the Forge CLI.\n` +
                `See ${buildTerminalLink('https://developer.atlassian.com/platform/forge/enterprise/use-forge-cli-on-corporate-network/#use-the-forge-cli-on-a-corporate-network')}. \n` +
                'Alternatively, you can install cloudflared on your machine.',
            invalidSelfManagedTunnelUrl: (url) => `Invalid self-managed tunnel URL: ${url}.`,
            invalidSelfManagedTunnelUrlProtocol: (protocol) => `The tunnel URL must use the HTTPS protocol. Received: ${protocol}.`,
            invalidSelfManagedTunnelPort: (port) => `Invalid tunnel port: ${port}. Port must be between 1 and 65535.`,
            invalidInvokeRequestForAppId: (requestAppId) => `The provided self-managed tunnel is being used for a different app (App ID: ${requestAppId}). Please stop any other tunnels using the same tunnel URL and restart the tunnel.`,
            invalidInvokeRequestForAppEnv: (requestEnvId) => `The provided self-managed tunnel is being used for a different app environment (environment ID: ${requestEnvId}). Please stop any other tunnels using the same tunnel URL and restart the tunnel.`,
            errorValidatingInvokeRequest: (message) => `Error validating tunnel invocation request: ${message}.`
        }
    },
    installationId: {
        prompt: "Enter the app's installation ID:",
        errors: {
            invalid: `Invalid installation ID. Run ${forge('install', 'list')} to see the installation IDs for the app.`,
            notFound: (installationId) => `No installation found for installation ID: ${installationId}.`
        }
    },
    uninstall: {
        cmd: {
            desc: 'uninstall the app from an Atlassian site',
            start: 'Uninstalling...',
            success: (isMulti) => (isMulti ? 'Uninstalling...\n\n' : 'Uninstalled\n\n')
        },
        interactive: {
            desc: 'Select where to uninstall the app:',
            progressInfo: `To uninstall your app from a site or workspace, select it from the list.\nPress Ctrl+C to cancel.`,
            done: `\n${log_symbols_1.default.success} Apps uninstalled`,
            confirmOptionalContexts: 'This will uninstall the app from all Atlasian apps and platform tools in this site. Are you sure you want to continue?'
        },
        info: 'Uninstalling...',
        done: (product, domain, environment, isMulti) => `${isMulti ? log_symbols_1.default.info : log_symbols_1.default.success} Uninstalled from the ${(0, environment_1.environmentToOption)(environment)} environment in ${product} on ${buildTerminalLink(domain)}.`,
        failed: (product, domain, environment) => `Failed to uninstall the app from the ${(0, environment_1.environmentToOption)(environment)} environment in ${product} on ${buildTerminalLink(domain)}. Try rerunning the command, or ask for help if you continue to see this error.`,
        missingUninstallTask: `Cannot uninstall the app: something went wrong with starting the uninstall task.`
    },
    webtrigger: {
        cmd: 'get a web trigger URL',
        copy: (url) => `\nCopy your web trigger URL below to start using it:\n\n${buildTerminalLink(url)}`,
        optionFuncKey: 'web trigger key from the manifest.yml file',
        overviewFuncKey: `\nGetting the web trigger URL for the provided context.\n\nPress Ctrl+C to cancel.\n`,
        promptFuncKey: 'Select a web trigger:',
        overViewInstallationTable: `\nGetting the web trigger URL by an app installation.\n\nPress Ctrl+C to cancel.\n`,
        promptInstallationTable: 'Select an installation:',
        error: {
            funcKey: "The given web trigger key doesn't exist in the manifest.yml file.",
            noWebtriggers: "The manifest.yml file doesn't contain any web triggers. Add a web trigger before rerunning this command.",
            creationError: (message) => `Web trigger URL creation error: ${message}`
        }
    },
    logs: {
        cmd: 'view app logs',
        optionInvocation: 'view logs for a given invocation ID',
        optionLimit: 'number of log lines to return',
        optionGroup: 'group logs by invocation ID',
        optionSince: 'view logs since the specified time. valid formats: YYYY-MM-DD, ISO 8061 timestamp or a relative time (e.g: 5m, 10h, 2d)',
        optionContainers: 'view container logs',
        invalidSinceOption: (since) => `Invalid date-time format: '${since}'. Date filter will not be applied.\n`,
        invalidOptionWithContainersCmd: (option) => `The '${option}' option is not supported for container logs.\n`
    },
    lint: {
        blurb: "The linter checks the app code for known errors. Warnings are issues you should fix, but they won't stop the app code from building.\nPress Ctrl+C to cancel.\n",
        cmd: 'check the source files for common errors',
        running: `Running ${forge('lint')}...`,
        noProblems: 'No issues found.',
        noFixableProblem: chalk_1.default.red(`  Issue found is not automatically fixable with ${forge('lint')}.`),
        noFixableProblems: chalk_1.default.red(`  Issues found are not automatically fixable with ${forge('lint')}.`),
        filename: chalk_1.default.underline,
        linterFailed: (linterClass, failure) => chalk_1.default.yellow(`${chalk_1.default.bold('Warning:')} Could not perform some linting actions for ${chalk_1.default.bold(linterClass)} due to unhandled error "${failure}".\n`),
        fixed: (numFixableErrors, numFixableWarnings) => {
            const { pluralCheckedFixableErrors, pluralCheckedFixableWarnings } = checkLintTotalPlurals(0, 0, numFixableErrors, numFixableWarnings);
            return `${greenTick} Fixed ${pluralCheckedFixableErrors} and ${pluralCheckedFixableWarnings}`;
        },
        fixFollowUp: `Run ${forge('lint')} to review outstanding errors and warnings`,
        error: (line, column, message, reference) => getLintMessage(line, column, message, 'error', log_color_1.LogColor.error, reference),
        summary: (numErrors, numWarnings, numFixableErrors, numFixableWarnings) => {
            const { pluralCheckedErrors, pluralCheckedWarnings, pluralCheckedTotal } = checkLintTotalPlurals(numErrors, numWarnings, numFixableErrors, numFixableWarnings);
            const colourFunction = numErrors ? log_color_1.LogColor.error : log_color_1.LogColor.warn;
            const warningCharacter = numErrors ? 'X' : '⚠';
            return colourFunction(`${warningCharacter} ${pluralCheckedTotal} (${pluralCheckedErrors}, ${pluralCheckedWarnings})`);
        },
        fixSummary: (numErrors, numFixableErrors, numFixableWarnings) => {
            const { pluralCheckedFixableErrors, pluralCheckedFixableWarnings } = checkLintTotalPlurals(0, 0, numFixableErrors, numFixableWarnings);
            const colourFunction = numErrors ? log_color_1.LogColor.error : log_color_1.LogColor.warn;
            return colourFunction(`  Run ${forge('lint', '--fix')} to automatically fix ${pluralCheckedFixableErrors} and ${pluralCheckedFixableWarnings}.\n`);
        },
        warning: (line, column, message, reference) => getLintMessage(line, column, message, 'warning', log_color_1.LogColor.warn, reference)
    },
    containers: {
        cmd: {
            desc: 'manage containers and container images'
        },
        create: {
            cmd: {
                desc: 'create new container definition',
                keyOption: 'specify the name of the container'
            },
            prompt: {
                overview: 'Create a new container.',
                entry: 'Enter a name for your container:'
            },
            creatingNewContainer: (key) => `Creating new container with key '${key}'.`,
            start: 'Creating container...',
            success: 'Container created.',
            createdRepositoryURI: (uri) => `New repository URI: ${uri}`
        },
        repositories: {
            cmd: {
                desc: 'list image repository for all containers'
            },
            listingRepositories: 'Listing repository for containers.',
            noContainersFound: `No containers found.`
        },
        images: {
            cmd: {
                desc: 'manage container images'
            },
            list: {
                cmd: {
                    desc: 'list all images for the container',
                    keyOption: 'specify the name of the container'
                },
                prompt: {
                    overview: 'List all images for a container.',
                    entry: 'Enter the name of the container to list images for:'
                },
                listingImages: (key) => `Listing images for container with key '${key}'.`,
                noImagesFound: `No images found.`,
                promptNextPage: 'Load next page?'
            }
        },
        login: {
            cmd: {
                desc: 'get login password for the image repository',
                onlyPassword: 'display only the password'
            },
            truncatedPassword: (password) => `${password.substring(0, 12)}...<truncated>`
        },
        delete: {
            cmd: {
                desc: 'delete container definition along with the associated image repository and all of its images',
                keyOption: 'specify the key of the container'
            },
            interactive: {
                desc: 'Select container to delete:',
                progressInfo: `To delete a container, select it from the list.\nPress Ctrl+C to cancel.`,
                noContainersFound: `This app does not have any containers.\nRun ${chalk_1.default.bold('forge containers create')} to create a container for your app.`
            },
            deletingContainer: (key) => `Deleting container definition with key '${key}'.`,
            warning: 'Deleting container is irreversible and will delete all images associated with it.',
            confirmation: (key) => `Type the container key [${key}] to confirm deletion:`,
            abortedDeletion: 'Aborted.',
            start: 'Deleting container...',
            success: 'Container deleted.'
        },
        dockerLogin: {
            cmd: {
                desc: 'authenticate to container registry'
            }
        }
    },
    show: {
        cmd: {
            desc: "display information about the deployed app's containers and services"
        },
        services: {
            cmd: {
                desc: 'display information about deployed app services',
                serviceKeyOption: 'specify the name of the service'
            },
            overview: 'Showing service information.',
            specificService: (serviceKey, environment) => `Showing service: ${chalk_1.default.bold(serviceKey)} deployed in the '${environment}' environment.`,
            allServices: (environment) => `Showing all services defined and deployed in the '${environment}' environment:`,
            noServicesFound: (environment) => `No services found in the '${environment}' environment.`
        },
        containers: {
            cmd: {
                desc: 'display information about deployed app containers for a given service',
                serviceKeyOption: 'specify the name of a service',
                containerKeyOption: 'specify the name of a container'
            },
            overview: 'Showing container information for a service.',
            prompt: {
                entry: 'Select a service:'
            },
            noContainersFound: (environment) => `No service containers found in the '${environment}' environment.`,
            specifiedServiceNotFound: (service, environment) => `No service '${service}' found in the '${environment}' environment.`,
            specifiedContainerNotFound: (service, container, environment) => `No container '${container}' found for the service '${service}' in the '${environment}' environment.`,
            noContainersFoundForService: (service, environment) => `No containers found for the service '${service}' in the '${environment}' environment.`,
            specificContainer: (containerKey) => `Container: ${chalk_1.default.bold(containerKey)}`,
            noInstancesFoundForContainer: (containerKey, service, environment) => `No instances found for the container '${containerKey}' for the service '${service}' in the '${environment}' environment.`
        }
    },
    stub: {
        error: (newName, oldName) => `The ${forge(oldName)} command has been deprecated and replaced by ${forge(newName)}.`
    },
    customPrompts: {
        table: {
            promptMessage: (message) => `${chalk_1.default.green('?')} ${message}`,
            headerMessage: (message, singleOption) => `${chalk_1.default.bold(message)} ${chalk_1.default.dim(singleOption ? ' (Use the Enter key to select)' : ' (Use the spacebar to select multiple)')}`
        },
        singleSelectionTable: {
            doneHeaderMessage: (message) => `${chalk_1.default.bold(message)}`,
            decorateSelected: (site) => `${chalk_1.default.cyan(site)}`
        }
    },
    variables: {
        description: 'manage app environment variables'
    },
    settings: {
        description: 'manage Forge CLI settings',
        analytics: {
            banner: `We are continuously working to improve the developer experience in Forge. CLI usage helps us do just that. Select ${chalk_1.default.bold('yes')} below to agree to our collection of analytics data through our tools. You can use ${forge('settings')} to manage your settings at any time.`,
            promptMessage: 'Allow Forge to collect CLI usage and error reporting information?'
        },
        set: {
            description: (choices) => `update Forge CLI setting (choices: ${choices.join(', ')})`,
            invalidSetting: (choices) => `Invalid setting specified. Valid settings: ${choices.join(', ')}`,
            invalidValue: `Invalid value specified. Valid values: true, false`,
            success: (setting, value) => `${greenTick} Successfully set ${setting} as ${value}.`
        },
        list: {
            description: 'list Forge CLI settings'
        },
        usageAnalytics: {
            description: 'Allow Forge to collect CLI usage and error reporting information'
        },
        defaultEnvironment: {
            description: 'Change your default development environment',
            info: `To view all environments for this app, run ${forge('environments', 'list')}.`
        }
    },
    assistant: {
        description: '[⚠️ experimental feature] manage AI assistant settings (Rovo/Gemini)',
        on: {
            description: `[⚠️ experimental feature] enable AI assistant for error analysis (specify name: rovo or gemini)
When errors occur during Forge command execution, error details will be sent to your AI agent to help you understand and resolve issues.`
        },
        off: {
            description: 'disable AI assistant for error analysis'
        },
        enabled: (assistantName) => `${greenTick} ${assistantName} assistant enabled.`,
        disabled: `${greenTick} Assistant disabled. Error analysis will not be performed during Forge CLI commands.`,
        alreadyDisabled: 'Assistant is already disabled',
        enableConfirmation: '⚠️ Are you sure you want to enable the assistant? This is an experimental feature. When errors occur during Forge command execution, error details will be sent to your AI agent automatically to help you understand and resolve issues.'
    },
    nonInteractive: {
        description: 'run the command without input prompts',
        error: {
            missingRequiredOption: (command, requiredOptions) => `${command} --non-interactive requires ${requiredOptions.join(' ')}`,
            missingAnalyticsPreferences: `--non-interactive requires an analytics setting. Use ${forge('settings', 'set', 'usage-analytics', '<value>')}.`
        }
    },
    customScopes: {
        validation: {
            failed: 'Failed to validate',
            formatError: (path, message) => `${path ?? 'root'}: ${message ?? 'Unknown validation error'}`
        }
    }
};
