diff --git a/messages/messages.md b/messages/messages.md index aaa92631..d796ca2a 100644 --- a/messages/messages.md +++ b/messages/messages.md @@ -1,6 +1,6 @@ # error.prefix -Error: +Error%s: # warning.security @@ -66,10 +66,6 @@ The value must be between %s and %s (inclusive). Warning: -# info.prefix - -Info: - # actions.tryThis Try this: diff --git a/package.json b/package.json index c2d0a80d..55b8ccc5 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@salesforce/core": "^3.11.0", "@salesforce/kit": "^1.5.34", "@salesforce/ts-types": "^1.5.20", - "chalk": "^2.4.2", + "chalk": "^4", "inquirer": "^8.2.0" }, "devDependencies": { diff --git a/src/exported.ts b/src/exported.ts index ed16ed66..335ed9fc 100644 --- a/src/exported.ts +++ b/src/exported.ts @@ -13,7 +13,7 @@ export { Deauthorizer } from './deauthorizer'; export { Progress, Prompter, generateTableChoices } from './ux'; export { SfHook } from './hooks'; export * from './types'; -export { SfCommand, SfCommandInterface } from './sfCommand'; +export { SfCommand, SfCommandInterface, StandardColors } from './sfCommand'; // custom flags import { requiredOrgFlag, requiredHubFlag, optionalOrgFlag } from './flags/orgFlags'; diff --git a/src/sfCommand.ts b/src/sfCommand.ts index 63e6f456..596626ea 100644 --- a/src/sfCommand.ts +++ b/src/sfCommand.ts @@ -16,7 +16,7 @@ import { EnvironmentVariable, } from '@salesforce/core'; import { AnyJson } from '@salesforce/ts-types'; -import chalk from 'chalk'; +import * as chalk from 'chalk'; import { Progress, Prompter, Spinner, Ux } from './ux'; Messages.importMessagesDirectory(__dirname); @@ -28,6 +28,13 @@ export interface SfCommandInterface extends Interfaces.Command { errorCodes?: HelpSection; } +export const StandardColors = { + error: chalk.hex('BF0201'), + warning: chalk.hex('FF9A3C'), + info: chalk.dim, + success: chalk.hex('4BCA81'), +}; + /** * A base command that provides convenient access to CLI help * output formatting. Extend this command and set specific properties @@ -69,6 +76,15 @@ export abstract class SfCommand extends Command { this.lifecycle = Lifecycle.getInstance(); } + /** + * Log a success message that has the standard success message color applied + * + * @param message + * @param args + */ + public logSuccess(message: string): void { + this.log(StandardColors.success(message)); + } /** * Log warning to users. If --json is enabled, then the warning * will be added to the json output under the warnings property. @@ -78,9 +94,9 @@ export abstract class SfCommand extends Command { this.warnings.push(input); const message = typeof input === 'string' ? input : input.message; - colorizedArgs.push(`${chalk.bold.yellow(messages.getMessage('warning.prefix'))} ${message}`); + colorizedArgs.push(`${StandardColors.warning(messages.getMessage('warning.prefix'))} ${message}`); colorizedArgs.push( - ...this.formatActions(typeof input === 'string' ? [] : input.actions || [], { actionColor: chalk.reset }) + ...this.formatActions(typeof input === 'string' ? [] : input.actions || [], { actionColor: StandardColors.info }) ); this.log(colorizedArgs.join(os.EOL)); @@ -94,9 +110,9 @@ export abstract class SfCommand extends Command { const colorizedArgs: string[] = []; const message = typeof input === 'string' ? input : input.message; - colorizedArgs.push(`${chalk.bold(messages.getMessage('info.prefix'))} ${message}`); + colorizedArgs.push(`${StandardColors.info(message)}`); colorizedArgs.push( - ...this.formatActions(typeof input === 'string' ? [] : input.actions || [], { actionColor: chalk.reset }) + ...this.formatActions(typeof input === 'string' ? [] : input.actions || [], { actionColor: StandardColors.info }) ); this.log(colorizedArgs.join(os.EOL)); @@ -255,7 +271,7 @@ export abstract class SfCommand extends Command { } /** - * Format errors and actions for human consumption. Adds 'Error:', + * Format errors and actions for human consumption. Adds 'Error ():', * When there are actions, we add 'Try this:' in blue * followed by each action in red on its own line. * If Error.code is present it is output last in parentheses @@ -264,15 +280,13 @@ export abstract class SfCommand extends Command { */ protected formatError(error: SfCommand.Error): string { const colorizedArgs: string[] = []; - colorizedArgs.push(`${chalk.bold.red(messages.getMessage('error.prefix'))} ${error.message}`); + const errorCode = error.code ? ` (${error.code})` : ''; + const errorPrefix = `${StandardColors.error(messages.getMessage('error.prefix', [errorCode]))}`; + colorizedArgs.push(`${errorPrefix} ${error.message}`); colorizedArgs.push(...this.formatActions(error.actions || [])); if (error.stack && envVars.getString(SfCommand.SF_ENV) === Mode.DEVELOPMENT) { - colorizedArgs.push(chalk.red(`\n*** Internal Diagnostic ***\n\n${error.stack}\n******\n`)); - } - if (error.code) { - colorizedArgs.push(chalk.bold(`\n(${error.code})`)); + colorizedArgs.push(StandardColors.info(`\n*** Internal Diagnostic ***\n\n${error.stack}\n******\n`)); } - return colorizedArgs.join('\n'); } @@ -285,12 +299,12 @@ export abstract class SfCommand extends Command { */ private formatActions( actions: string[], - options: { actionColor: typeof chalk } = { actionColor: chalk.red } + options: { actionColor: chalk.Chalk } = { actionColor: StandardColors.info } ): string[] { const colorizedArgs: string[] = []; // Format any actions. if (actions?.length) { - colorizedArgs.push(`\n${chalk.blue.bold(messages.getMessage('actions.tryThis'))}\n`); + colorizedArgs.push(`\n${StandardColors.info(messages.getMessage('actions.tryThis'))}\n`); actions.forEach((action) => { colorizedArgs.push(`${options.actionColor(action)}`); }); diff --git a/test/unit/sfCommand.test.ts b/test/unit/sfCommand.test.ts index 60db4f4c..dc6a4bf5 100644 --- a/test/unit/sfCommand.test.ts +++ b/test/unit/sfCommand.test.ts @@ -8,7 +8,7 @@ import * as os from 'os'; import { test } from '@oclif/test'; import { Config } from '@oclif/core'; import { expect } from 'chai'; -import { SfdxError } from '@salesforce/core'; +import { SfError } from '@salesforce/core'; import { SfCommand } from '../../src/sfCommand'; class TestCommand extends SfCommand { @@ -25,7 +25,7 @@ describe('info messages', () => { testCommand.info('foo bar baz'); }) .it('should show a info message from a string', (ctx) => { - expect(ctx.stdout).to.include('Info: foo bar baz'); + expect(ctx.stdout).to.include('foo bar baz'); }); test .stdout() @@ -34,17 +34,17 @@ describe('info messages', () => { testCommand.info(new Error('foo bar baz') as SfCommand.Info); }) .it('should show a info message from Error, no actions', (ctx) => { - expect(ctx.stdout).to.include('Info: foo bar baz'); + expect(ctx.stdout).to.include('foo bar baz'); }); test .stdout() .do(() => { const testCommand = new TestCommand([], {} as Config); - const infoError = new SfdxError('foo bar baz', 'foo', ['this', 'is an', 'action']) as Error; + const infoError = new SfError('foo bar baz', 'foo', ['this', 'is an', 'action']) as Error; testCommand.info(infoError as SfCommand.Info); }) - .it('should show a info message from Error, with actions', (ctx) => { - expect(ctx.stdout).to.include('Info: foo bar baz'); + .it('should show a info message, with actions', (ctx) => { + expect(ctx.stdout).to.include('foo bar baz'); expect(ctx.stdout).to.include(['this', 'is an', 'action'].join(os.EOL)); }); }); @@ -71,7 +71,7 @@ describe('warning messages', () => { .stdout() .do(() => { const testCommand = new TestCommand([], {} as Config); - const infoError = new SfdxError('foo bar baz', 'foo', ['this', 'is an', 'action']) as Error; + const infoError = new SfError('foo bar baz', 'foo', ['this', 'is an', 'action']) as Error; testCommand.warn(infoError as SfCommand.Info); }) .it('should show a info message from Error, with actions', (ctx) => { diff --git a/yarn.lock b/yarn.lock index 23f04c11..65c08a42 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1499,18 +1499,18 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" - integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== +chalk@^4, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" + integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0"