diff --git a/.changeset/five-moles-care.md b/.changeset/five-moles-care.md index 645b03e1a8e..00a0112509f 100644 --- a/.changeset/five-moles-care.md +++ b/.changeset/five-moles-care.md @@ -2,4 +2,4 @@ "@asyncapi/cli": patch --- -Added UI/UX improvements to start command +implemented new UI/UX improvements in config command diff --git a/src/commands/config/analytics.ts b/src/commands/config/analytics.ts index 3cabf71efeb..03b5ca83d0b 100644 --- a/src/commands/config/analytics.ts +++ b/src/commands/config/analytics.ts @@ -3,6 +3,7 @@ import Command from '../../core/base'; import { promises as fPromises } from 'fs'; import { homedir } from 'os'; import { analyticsFlags } from '../../core/flags/config/analytics.flags'; +import { blueBright, redBright } from 'picocolors'; const { readFile, writeFile } = fPromises; @@ -26,7 +27,7 @@ export default class Analytics extends Command { this.log('\nAnalytics enabled.\n'); this.metricsMetadata.analytics_enabled = flags.enable; } else if (!flags.status) { - this.log('\nPlease append the "--disable" flag to the command in case you prefer to disable analytics, or use the "--enable" flag if you want to enable analytics back again. In case you do not know the analytics current status, then you can append the "--status" flag to be aware of it.\n'); + this.log(`\nPlease append the ${blueBright('--disable')} flag to the command if you prefer to disable analytics, or use the ${blueBright('--enable')} flag if you want to enable analytics again. To check the current analytics status, use the ${blueBright('--status')} flag.\n`); return; } await writeFile(analyticsConfigFile, JSON.stringify(analyticsConfigFileContent), { encoding: 'utf8' }); @@ -35,20 +36,20 @@ export default class Analytics extends Command { if (analyticsConfigFileContent.analyticsEnabled === 'true') { this.log('\nAnalytics are enabled.\n'); } else { - this.log('\nAnalytics are disabled. Please append the "--enable" flag to the command in case you prefer to enable analytics.\n'); + this.log(`\n${redBright('Analytics are disabled.')} To enable analytics, use the ${blueBright('--enable')} flag.\n`); } this.metricsMetadata.analytics_status_checked = flags.status; } } catch (e: any) { switch (e.code) { case 'ENOENT': - this.error(`Unable to access the analytics configuration file. We tried to access the ".asyncapi-analytics" file in in the path "${analyticsConfigFile}" but the file could not be found.`); + this.error(`Unable to access the analytics configuration file. We tried to access the ${blueBright('.asyncapi-analytics')} file in the path "${blueBright(analyticsConfigFile)}" but the file could not be found.`); break; case 'EEXIST': - this.error(`Unable to update the analytics configuration file. We tried to update your ".asyncapi-analytics" file in the path "${analyticsConfigFile}" but the file does not exist.`); + this.error(`Unable to update the analytics configuration file. We tried to update your ".asyncapi-analytics" file in the path "${blueBright(analyticsConfigFile)}" but the file does not exist.`); break; default: - this.error(`Unable to change your analytics configuration. Please check the following message for further info about the error:\n\n${e}`); + this.error(`Unable to change your analytics configuration. Please check the following message for further info about the error:\n\n${redBright(e)}`); } } } diff --git a/src/commands/config/context/add.ts b/src/commands/config/context/add.ts index f17e19480fd..616e2b7be38 100644 --- a/src/commands/config/context/add.ts +++ b/src/commands/config/context/add.ts @@ -6,6 +6,7 @@ import { ContextFileWrongFormatError, } from '../../../core/errors/context-error'; import { addFlags } from '../../../core/flags/config/context.flags'; +import { blueBright } from 'picocolors'; export default class ContextAdd extends Command { static description = 'Add a context to the store'; @@ -24,24 +25,16 @@ export default class ContextAdd extends Command { try { await addContext(contextName, specFilePath); - this.log( - `Added context "${contextName}".\n\nYou can set it as your current context: asyncapi config context use ${contextName}\nYou can use this context when needed by passing ${contextName} as a parameter: asyncapi validate ${contextName}` - ); - + this.log(`🎉 Context ${blueBright(contextName)} added successfully!\nYou can set it as your current context:\n ${blueBright('asyncapi')} ${blueBright('config')} ${blueBright('context')} ${blueBright('use')} ${blueBright(contextName)}\nYou can use this context when needed by passing ${blueBright(contextName)} as a parameter:\n ${blueBright('asyncapi')} ${blueBright('validate')} ${blueBright(contextName)}`); if (setAsCurrent) { await setCurrentContext(contextName); - this.log( - `The newly added context "${contextName}", is set as your current context!` - ); + this.log(`\nThe newly added context, ${blueBright(contextName)}, is set as your current context!`); } } catch (e) { if ( e instanceof (MissingContextFileError || ContextFileWrongFormatError) ) { - this.log( - 'You have no context file configured. Run "asyncapi config context init" to initialize it.' - ); - return; + this.error(`Unable to add context. You have no context file configured.\nRun ${blueBright('asyncapi config context init')} to initialize it.`); } throw e; } diff --git a/src/commands/config/context/current.ts b/src/commands/config/context/current.ts index 49067e33dae..45dc1c65fa3 100644 --- a/src/commands/config/context/current.ts +++ b/src/commands/config/context/current.ts @@ -7,6 +7,7 @@ import { ContextNotFoundError, } from '../../../core/errors/context-error'; import { helpFlag } from '../../../core/flags/global.flags'; +import { blueBright } from 'picocolors'; export default class ContextCurrent extends Command { static description = 'Shows the current context that is being used'; @@ -21,27 +22,20 @@ export default class ContextCurrent extends Command { if ( e instanceof (MissingContextFileError || ContextFileWrongFormatError) ) { - this.log( - 'You have no context file configured. Run "asyncapi config context init" to initialize it.' - ); - return; + this.error(`Unable to show current context. You have no context file configured.\nRun ${blueBright('asyncapi config context init')} to initialize it.`); } else if (e instanceof ContextFileEmptyError) { - this.log(`Context file "${CONTEXT_FILE_PATH}" is empty.`); - return; + this.error(`Context file ${blueBright(CONTEXT_FILE_PATH)} is empty.`); } else if ( e instanceof ContextNotFoundError || (fileContent && !fileContent.current) ) { - this.log( - 'No context is set as current. Run "asyncapi config context" to see all available options.' - ); - return; + this.error(`No context is set as current.\nRun ${blueBright('asyncapi config context')} to see all available options.`); } throw e; } if (fileContent) { - this.log(`${fileContent.current}: ${fileContent.context}`); + this.log(`${blueBright(fileContent.current)}: ${fileContent.context}`); } } } diff --git a/src/commands/config/context/edit.ts b/src/commands/config/context/edit.ts index f16409e9141..c08aec7e159 100644 --- a/src/commands/config/context/edit.ts +++ b/src/commands/config/context/edit.ts @@ -7,6 +7,7 @@ import { ContextFileEmptyError, } from '../../../core/errors/context-error'; import { helpFlag } from '../../../core/flags/global.flags'; +import { blueBright } from 'picocolors'; export default class ContextEdit extends Command { static description = 'Edit a context in the store'; @@ -23,20 +24,14 @@ export default class ContextEdit extends Command { try { await editContext(contextName, newSpecFilePath); - this.log( - `Edited context "${contextName}".\n\nYou can set it as your current context: asyncapi config context use ${contextName}\nYou can use this context when needed by passing ${contextName} as a parameter: asyncapi validate ${contextName}` - ); + this.log(`🎉 Context ${blueBright(contextName)} edited successfully!\nYou can set it as your current context:\n ${blueBright('asyncapi')} ${blueBright('config')} ${blueBright('context')} ${blueBright('use')} ${blueBright(contextName)}\nYou can use this context when needed by passing ${blueBright(contextName)} as a parameter:\n ${blueBright('asyncapi')} ${blueBright('validate')} ${blueBright(contextName)}`); } catch (e) { if ( e instanceof (MissingContextFileError || ContextFileWrongFormatError) ) { - this.log( - 'You have no context file configured. Run "asyncapi config context init" to initialize it.' - ); - return; + this.error(`Unable to edit context. You have no context file configured.\nRun ${blueBright('asyncapi config context init')} to initialize it.`); } else if (e instanceof ContextFileEmptyError) { - this.log(`Context file "${CONTEXT_FILE_PATH}" is empty.`); - return; + this.error(`Context file ${blueBright(CONTEXT_FILE_PATH)} is empty.`); } throw e; } diff --git a/src/commands/config/context/init.ts b/src/commands/config/context/init.ts index 40d4dc7ab2c..67c24f3c6ec 100644 --- a/src/commands/config/context/init.ts +++ b/src/commands/config/context/init.ts @@ -2,15 +2,15 @@ import { Args } from '@oclif/core'; import Command from '../../../core/base'; import { initContext } from '../../../core/models/Context'; import { helpFlag } from '../../../core/flags/global.flags'; - +import { blueBright } from 'picocolors'; export default class ContextInit extends Command { static description = 'Initialize context'; static flags = helpFlag(); static contextFilePathMessage = `Specify directory in which context file should be created: - - current directory : asyncapi config context init . (default) - - root of current repository : asyncapi config context init ./ - - user's home directory : asyncapi config context init ~`; + - current directory : ${blueBright('asyncapi config context init .')}(default) + - root of current repository : ${blueBright('asyncapi config context init ./ ')} + - user's home directory : ${blueBright('asyncapi config context init ~`')}`; static args = { 'context-file-path': Args.string({description: `${ContextInit.contextFilePathMessage}`, required: false}) @@ -21,6 +21,6 @@ export default class ContextInit extends Command { const contextFilePath = args['context-file-path']; const contextWritePath = await initContext(contextFilePath as string); - this.log(`Initialized context ${contextWritePath}`); + this.log(`🎉 Context initialized at ${blueBright(contextWritePath)}`); } } diff --git a/src/commands/config/context/list.ts b/src/commands/config/context/list.ts index 2286173c00c..34391a1a0e0 100644 --- a/src/commands/config/context/list.ts +++ b/src/commands/config/context/list.ts @@ -9,6 +9,7 @@ import { ContextFileWrongFormatError, } from '../../../core/errors/context-error'; import { helpFlag } from '../../../core/flags/global.flags'; +import { blueBright } from 'picocolors'; export default class ContextList extends Command { static description = 'List all the stored contexts in the store'; @@ -19,7 +20,7 @@ export default class ContextList extends Command { const fileContent = await loadContextFile(); if (await isContextFileEmpty(fileContent)) { - this.log(`Context file "${CONTEXT_FILE_PATH}" is empty.`); + this.log(`Context file ${blueBright(CONTEXT_FILE_PATH)} is empty.`); return; } @@ -27,16 +28,14 @@ export default class ContextList extends Command { for (const [contextName, filePath] of Object.entries( fileContent.store )) { - this.log(`${contextName}: ${filePath}`); + this.log(`${blueBright(contextName)}: ${filePath}`); } } } catch (e) { if ( e instanceof (MissingContextFileError || ContextFileWrongFormatError) ) { - this.log( - 'You have no context file configured. Run "asyncapi config context init" to initialize it.' - ); + this.log(`Unable to list contexts. You have no context file configured.\nRun ${blueBright('asyncapi config context init')} to initialize it.\n`); return; } throw e; diff --git a/src/commands/config/context/remove.ts b/src/commands/config/context/remove.ts index 9a29cd6770d..c37fcb09b8f 100644 --- a/src/commands/config/context/remove.ts +++ b/src/commands/config/context/remove.ts @@ -7,6 +7,7 @@ import { ContextFileEmptyError, } from '../../../core/errors/context-error'; import { helpFlag } from '../../../core/flags/global.flags'; +import { blueBright } from 'picocolors'; export default class ContextRemove extends Command { static description = 'Delete a context from the store'; @@ -22,18 +23,14 @@ export default class ContextRemove extends Command { try { await removeContext(contextName); - this.log(`${contextName} successfully deleted`); + this.log(`Context ${blueBright(contextName)} removed successfully!\n`); } catch (e) { if ( e instanceof (MissingContextFileError || ContextFileWrongFormatError) ) { - this.log( - 'You have no context file configured. Run "asyncapi config context init" to initialize it.' - ); - return; + this.error(`Unable to remove context. You have no context file configured.\nRun ${blueBright('asyncapi config context init')} to initialize it.`); } else if (e instanceof ContextFileEmptyError) { - this.log(`Context file "${CONTEXT_FILE_PATH}" is empty.`); - return; + this.error(`Context file ${blueBright(CONTEXT_FILE_PATH)} is empty.`); } throw e; } diff --git a/src/commands/config/context/use.ts b/src/commands/config/context/use.ts index 6450d524047..bc4c071f638 100644 --- a/src/commands/config/context/use.ts +++ b/src/commands/config/context/use.ts @@ -7,6 +7,7 @@ import { ContextFileEmptyError, } from '../../../core/errors/context-error'; import { helpFlag } from '../../../core/flags/global.flags'; +import { blueBright } from 'picocolors'; export default class ContextUse extends Command { static description = 'Set a context as current'; @@ -22,17 +23,14 @@ export default class ContextUse extends Command { try { await setCurrentContext(contextName); - this.log(`${contextName} is set as current`); + this.log(`Context ${blueBright(contextName)} is now set as current.`); } catch (e) { if ( e instanceof (MissingContextFileError || ContextFileWrongFormatError) ) { - this.log( - 'You have no context file configured. Run "asyncapi config context init" to initialize it.' - ); - return; + this.error(`Unable to set the current context. You have no context file configured.\nRun ${blueBright('asyncapi config context init')} to initialize it.`); } else if (e instanceof ContextFileEmptyError) { - this.log(`Context file "${CONTEXT_FILE_PATH}" is empty.`); + this.error(`Context file ${blueBright(CONTEXT_FILE_PATH)} is empty.`); return; } throw e; diff --git a/src/commands/config/versions.ts b/src/commands/config/versions.ts index 915f83ccb3f..50052b88d05 100644 --- a/src/commands/config/versions.ts +++ b/src/commands/config/versions.ts @@ -1,5 +1,6 @@ import Command from '../../core/base'; import { helpFlag } from '../../core/flags/global.flags'; +import { blueBright, gray } from 'picocolors'; export default class Versions extends Command { static description = 'Show versions of AsyncAPI tools used'; @@ -30,7 +31,7 @@ export default class Versions extends Command { } // Showing information available with `--version` flag. - this.log(this.config.userAgent); + this.log(gray(`\n${this.config.userAgent}\n`)); // Iteration through the array containing all dependencies '@asyncapi/*' // along with their versions. @@ -49,6 +50,6 @@ export default class Versions extends Command { } } - this.log(`Repository: ${this.config.pjson.homepage}`); + this.log(`Repository: ${blueBright(this.config.pjson.homepage)}`); } } diff --git a/test/integration/config/analytics.test.ts b/test/integration/config/analytics.test.ts index 7ac5d4d04a6..eb1b4b243c7 100644 --- a/test/integration/config/analytics.test.ts +++ b/test/integration/config/analytics.test.ts @@ -42,7 +42,7 @@ describe('config:analytics', () => { .stdout() .command(['config:analytics']) .it('should show informational message when no flags are used', (ctx, done) => { - expect(ctx.stdout).to.equal('\nPlease append the "--disable" flag to the command in case you prefer to disable analytics, or use the "--enable" flag if you want to enable analytics back again. In case you do not know the analytics current status, then you can append the "--status" flag to be aware of it.\n\n'); + expect(ctx.stdout).to.equal('\nPlease append the --disable flag to the command if you prefer to disable analytics, or use the --enable flag if you want to enable analytics again. To check the current analytics status, use the --status flag.\n\n'); expect(ctx.stderr).to.equal(''); done(); }); diff --git a/test/integration/context.test.ts b/test/integration/context.test.ts index 83044c53391..76590b253cb 100644 --- a/test/integration/context.test.ts +++ b/test/integration/context.test.ts @@ -56,7 +56,7 @@ describe('config:context, positive scenario', () => { .command(['config:context:add', 'test', './test/integration/specification.yml']) .it('should add new context called "test"', (ctx, done) => { expect(ctx.stdout).to.equals( - 'Added context "test".\n\nYou can set it as your current context: asyncapi config context use test\nYou can use this context when needed by passing test as a parameter: asyncapi validate test\n' + '🎉 Context test added successfully!\nYou can set it as your current context:\n asyncapi config context use test\nYou can use this context when needed by passing test as a parameter:\n asyncapi validate test\n' ); expect(ctx.stderr).to.equals(''); done(); @@ -86,7 +86,7 @@ describe('config:context, positive scenario', () => { .stdout() .command(['config:context:edit', 'test', './test/specification2.yml']) .it('should edit existing context "test"', (ctx, done) => { - expect(ctx.stdout).to.contain('Edited context "test".'); + expect(ctx.stdout).to.contain('🎉 Context test edited successfully!'); expect(ctx.stderr).to.equals(''); done(); }); @@ -98,7 +98,7 @@ describe('config:context, positive scenario', () => { .stdout() .command(['config:context:use', 'code']) .it('should update the current context', (ctx, done) => { - expect(ctx.stdout).to.equals('code is set as current\n'); + expect(ctx.stdout).to.equals('Context code is now set as current.\n'); expect(ctx.stderr).to.equals(''); done(); }); @@ -114,7 +114,7 @@ describe('config:context, positive scenario', () => { .stdout() .command(['config:context:remove', 'code']) .it('should remove existing context', (ctx, done) => { - expect(ctx.stdout).to.equals('code successfully deleted\n'); + expect(ctx.stdout).to.equals('Context code removed successfully!\n\n'); expect(ctx.stderr).to.equals(''); done(); }); @@ -126,7 +126,7 @@ describe('config:context, positive scenario', () => { .stdout() .command(['config:context:init']) .it('should initialize new empty context file without a switch', (ctx, done) => { - expect(ctx.stdout).to.contain('Initialized context'); + expect(ctx.stdout).to.contain('🎉 Context initialized at'); expect(ctx.stderr).to.equals(''); done(); }); @@ -138,7 +138,7 @@ describe('config:context, positive scenario', () => { .stdout() .command(['config:context:init', '.']) .it('should initialize new empty context file with switch "."', (ctx, done) => { - expect(ctx.stdout).to.contain('Initialized context'); + expect(ctx.stdout).to.contain('🎉 Context initialized at'); expect(ctx.stderr).to.equals(''); done(); }); @@ -150,7 +150,7 @@ describe('config:context, positive scenario', () => { .stdout() .command(['config:context:init', './']) .it('should initialize new empty context file with switch "./"', (ctx, done) => { - expect(ctx.stdout).to.contain('Initialized context'); + expect(ctx.stdout).to.contain('🎉 Context initialized at'); expect(ctx.stderr).to.equals(''); done(); }); @@ -162,7 +162,7 @@ describe('config:context, positive scenario', () => { .stdout() .command(['config:context:init', '~']) .it('should initialize new empty context file with switch "~"', (ctx, done) => { - expect(ctx.stdout).to.contain('Initialized context'); + expect(ctx.stdout).to.contain('🎉 Context initialized at'); expect(ctx.stderr).to.equals(''); done(); }); @@ -279,7 +279,7 @@ describe('config:context, negative scenario', () => { .it( 'should output info message (to stdout, NOT stderr) about absence of context file.', (ctx, done) => { - expect(ctx.stdout).to.contain('You have no context file configured.'); + expect(ctx.stdout).to.contain('Unable to list contexts. You have no context file configured.'); expect(ctx.stderr).to.equals(''); done(); }