import { AnyJson } from '@salesforce/ts-types'; import { SfError } from './sfError'; export type Tokens = Array; 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 = (locale: string) => Messages; export type StoredMessage = string | string[] | { [s: string]: StoredMessage; }; export type StoredMessageMap = Map; /** * 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 (`/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 { 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): 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; /** * 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; /** * 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 */ 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 */ 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 * * `.name` will be the upper-cased key, remove prefixed `.` and will always end in 'Error | Warning | Info. * `.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; }