import { AnyJson } from '@salesforce/ts-types';
import { SfError } from './sfError';
export type Tokens = Array<string | boolean | number | null | undefined>;
export type StructuredMessage = {
    message: string;
    name: string;
    actions?: string[];
};
/**
 * A loader function to return messages.
 *
 * @param locale The local set by the framework.
 */
export type LoaderFunction<T extends string> = (locale: string) => Messages<T>;
export type StoredMessage = string | string[] | {
    [s: string]: StoredMessage;
};
export type StoredMessageMap = Map<string, StoredMessage>;
/**
 * The core message framework manages messages and allows them to be accessible by
 * all plugins and consumers of sfdx-core. It is set up to handle localization down
 * the road at no additional effort to the consumer. Messages can be used for
 * anything from user output (like the console), to error messages, to returned
 * data from a method.
 *
 * Messages are loaded from loader functions. The loader functions will only run
 * when a message is required. This prevents all messages from being loaded into memory at
 * application startup. The functions can load from memory, a file, or a server.
 *
 * In the beginning of your app or file, add the loader functions to be used later. If using
 * json or js files in a root messages directory (`<moduleRoot>/messages`), load the entire directory
 * automatically with {@link Messages.importMessagesDirectory}. Message files must be the following formates.
 *
 * A `.json` file:
 * ```json
 * {
 *    "msgKey": "A message displayed in the user",
 *    "msgGroup": {
 *       "anotherMsgKey": "Another message displayed to the user"
 *    },
 *    "listOfMessage": ["message1", "message2"]
 * }
 * ```
 *
 * A `.js` file:
 * ```javascript
 * module.exports = {
 *    msgKey: 'A message displayed in the user',
 *    msgGroup: {
 *       anotherMsgKey: 'Another message displayed to the user'
 *    },
 *    listOfMessage: ['message1', 'message2']
 * }
 * ```
 *
 * A `.md` file:
 * ```markdown
 * # msgKey
 * A message displayed in the user
 *
 * # msgGroup.anotherMsgKey
 * Another message displayed to the user
 *
 * # listOfMessage
 * - message1
 * - message2
 * ```
 *
 * The values support [util.format](https://nodejs.org/api/util.html#util_util_format_format_args) style strings
 * that apply the tokens passed into {@link Message.getMessage}
 *
 * **Note:** When running unit tests individually, you may see errors that the messages aren't found.
 * This is because `index.js` isn't loaded when tests run like they are when the package is required.
 * To allow tests to run, import the message directory in each test (it will only
 * do it once) or load the message file the test depends on individually.
 *
 * ```typescript
 * // Create loader functions for all files in the messages directory
 * Messages.importMessagesDirectory(__dirname);
 *
 * // or, for ESM code
 * Messages.importMessagesDirectoryFromMetaUrl(import.meta.url)
 *
 * // Now you can use the messages from anywhere in your code or file.
 * // If using importMessageDirectory, the bundle name is the file name.
 * const messages: Messages = Messages.loadMessages(packageName, bundleName);
 *
 * // Messages now contains all the message in the bundleName file.
 * messages.getMessage('authInfoCreationError');
 * ```
 */
export declare class Messages<T extends string> {
    readonly messages: StoredMessageMap;
    private static loaders;
    private static bundles;
    /**
     * The locale of the messages in this bundle.
     */
    readonly locale: string;
    /**
     * The bundle name.
     */
    readonly bundleName: string;
    /**
     * Create a new messages bundle.
     *
     * **Note:** Use {Messages.loadMessages} unless you are writing your own loader function.
     *
     * @param bundleName The bundle name.
     * @param locale The locale.
     * @param messages The messages. Can not be modified once created.
     */
    constructor(bundleName: string, locale: string, messages: StoredMessageMap);
    /**
     * Internal readFile. Exposed for unit testing. Do not use util/fs.readFile as messages.js
     * should have no internal dependencies.
     *
     * @param filePath read file target.
     * @ignore
     */
    static readFile: (filePath: string) => AnyJson;
    /**
     * Get the locale. This will always return 'en_US' but will return the
     * machine's locale in the future.
     */
    static getLocale(): string;
    /**
     * Set a custom loader function for a package and bundle that will be called on {@link Messages.loadMessages}.
     *
     * @param packageName The npm package name.
     * @param bundle The name of the bundle.
     * @param loader The loader function.
     */
    static setLoaderFunction(packageName: string, bundle: string, loader: LoaderFunction<string>): void;
    /**
     * Generate a file loading function. Use {@link Messages.importMessageFile} unless
     * overriding the bundleName is required, then manually pass the loader
     * function to {@link Messages.setLoaderFunction}.
     *
     * @param bundleName The name of the bundle.
     * @param filePath The messages file path.
     */
    static generateFileLoaderFunction(bundleName: string, filePath: string): LoaderFunction<string>;
    /**
     * Add a single message file to the list of loading functions using the file name as the bundle name.
     * The loader will only be added if the bundle name is not already taken.
     *
     * @param packageName The npm package name.
     * @param filePath The path of the file.
     */
    static importMessageFile(packageName: string, filePath: string): void;
    /**
     * Support ESM plugins who can't use __dirname
     *
     * @param metaUrl pass in `import.meta.url`
     * @param truncateToProjectPath Will look for the messages directory in the project root (where the package.json file is located).
     * i.e., the module is typescript and the messages folder is in the top level of the module directory.
     * @param packageName The npm package name. Figured out from the root directory's package.json.
     */
    static importMessagesDirectoryFromMetaUrl(metaUrl: string, truncateToProjectPath?: boolean, packageName?: string): void;
    /**
     * Import all json and js files in a messages directory. Use the file name as the bundle key when
     * {@link Messages.loadMessages} is called. By default, we're assuming the moduleDirectoryPart is a
     * typescript project and will truncate to root path (where the package.json file is). If your messages
     * directory is in another spot or you are not using typescript, pass in false for truncateToProjectPath.
     *
     * ```
     * // e.g. If your message directory is in the project root, you would do:
     * Messages.importMessagesDirectory(__dirname);
     * ```
     *
     * @param moduleDirectoryPath The path to load the messages folder.
     * @param truncateToProjectPath Will look for the messages directory in the project root (where the package.json file is located).
     * i.e., the module is typescript and the messages folder is in the top level of the module directory.
     * @param packageName The npm package name. Figured out from the root directory's package.json.
     */
    static importMessagesDirectory(moduleDirectoryPath: string, truncateToProjectPath?: boolean, packageName?: string): void;
    /**
     * Load messages for a given package and bundle. If the bundle is not already cached, use the loader function
     * created from {@link Messages.setLoaderFunction} or {@link Messages.importMessagesDirectory}.
     *
     * ```typescript
     * Messages.importMessagesDirectory(__dirname);
     * const messages = Messages.loadMessages('packageName', 'bundleName');
     * ```
     *
     * @param packageName The name of the npm package.
     * @param bundleName The name of the bundle to load.
     */
    static loadMessages(packageName: string, bundleName: string): Messages<string>;
    /**
     * Check if a bundle already been loaded.
     *
     * @param packageName The npm package name.
     * @param bundleName The bundle name.
     */
    static isCached(packageName: string, bundleName: string): boolean;
    /**
     * Get a message using a message key and use the tokens as values for tokenization.
     *
     * If the key happens to be an array of messages, it will combine with OS.EOL.
     *
     * @param key The key of the message.
     * @param tokens The values to substitute in the message.
     *
     * **See** https://nodejs.org/api/util.html#util_util_format_format_args
     * **Note** Unlike util.format(), specifiers are required for a token to be rendered.
     */
    getMessage(key: T, tokens?: Tokens): string;
    /**
     * Get messages using a message key and use the tokens as values for tokenization.
     *
     * This will return all messages if the key is an array in the messages file.
     *
     * ```json
     * {
     *   "myKey": [ "message1", "message2" ]
     * }
     * ```
     *
     * ```markdown
     * # myKey
     * * message1
     * * message2
     * ```
     *
     * @param key The key of the messages.
     * @param tokens The values to substitute in the message.
     *
     * **See** https://nodejs.org/api/util.html#util_util_format_format_args
     * **Note** Unlike util.format(), specifiers are required for a token to be rendered.
     */
    getMessages(key: T, tokens?: Tokens): string[];
    /**
     * Convenience method to create errors using message labels.
     *
     * `error.name` will be the upper-cased key, remove prefixed `error.` and will always end in Error.
     * `error.actions` will be loaded using `${key}.actions` if available.
     *
     * @param key The key of the error message.
     * @param tokens The error message tokens.
     * @param actionTokens The action messages tokens.
     * @param exitCodeOrCause The exit code which will be used by SfdxCommand or the underlying error that caused this error to be raised.
     * @param cause The underlying error that caused this error to be raised.
     */
    createError(key: T, tokens?: Tokens, actionTokens?: Tokens, exitCodeOrCause?: number | Error, cause?: Error): SfError;
    /**
     * Convenience method to create warning using message labels.
     *
     * `warning.name` will be the upper-cased key, remove prefixed `warning.` and will always end in Warning.
     * `warning.actions` will be loaded using `${key}.actions` if available.
     *
     * @param key The key of the warning message.
     * @param tokens The warning message tokens.
     * @param actionTokens The action messages tokens.
     */
    createWarning(key: T, tokens?: Tokens, actionTokens?: Tokens): StructuredMessage;
    /**
     * Convenience method to create info using message labels.
     *
     * `info.name` will be the upper-cased key, remove prefixed `info.` and will always end in Info.
     * `info.actions` will be loaded using `${key}.actions` if available.
     *
     * @param key The key of the warning message.
     * @param tokens The warning message tokens.
     * @param actionTokens The action messages tokens.
     */
    createInfo(key: T, tokens?: Tokens, actionTokens?: Tokens): StructuredMessage;
    /**
     * Formats message contents given a message type, key, tokens and actions tokens
     *
     * `<type>.name` will be the upper-cased key, remove prefixed `<type>.` and will always end in 'Error | Warning | Info.
     * `<type>.actions` will be loaded using `${key}.actions` if available.
     *
     * @param type The type of the message set must 'error' | 'warning' | 'info'.
     * @param key The key of the warning message.
     * @param tokens The warning message tokens.
     * @param actionTokens The action messages tokens.
     * @param preserveName Do not require that the name end in the type ('error' | 'warning' | 'info').
     */
    private formatMessageContents;
    private getMessageWithMap;
}
