From f345194c3bb8844dff2b0232da4b59c34c60e0a9 Mon Sep 17 00:00:00 2001 From: Viacheslav Turovskyi Date: Mon, 29 May 2023 15:31:20 +0300 Subject: [PATCH] feat: add `versions` to output versions of AsyncAPI tools used (#361) (#555) --- src/commands/config/versions.ts | 56 +++++++++++++++++++++++++++ test/commands/config/versions.test.ts | 27 +++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/commands/config/versions.ts create mode 100644 test/commands/config/versions.test.ts diff --git a/src/commands/config/versions.ts b/src/commands/config/versions.ts new file mode 100644 index 00000000000..76ce1953328 --- /dev/null +++ b/src/commands/config/versions.ts @@ -0,0 +1,56 @@ +import { Flags } from '@oclif/core'; +import Command from '../../base'; + +export default class Versions extends Command { + static description = 'Show versions of AsyncAPI tools used'; + + static flags = { + help: Flags.help({ char: 'h' }), + }; + + async run() { + const dependencies: string[] = []; + let dependency = ''; + + // Preparation of the array with all dependencies '@asyncapi/*' along with + // their versions. + for (const key in this.config.pjson.dependencies) { + // Making sure with .indexOf() that only package names which START with + // string '@asyncapi' are considered. + if (key.indexOf('@asyncapi', 0) === 0) { + // Avoiding obvious crash on manual removal or alteration of an + // '@asyncapi' package. + try { + // Goofy name `importedPJSON` is chosen to distinguish from name `pjson` + // used in `@oclif` source code. + const importedPJSON = await import(`${key}/package.json`); + dependencies.push(`${key}/${importedPJSON.default.version}`); + } catch (e) { + dependencies.push(`${key}/` + '`package.json` not found'); + } + } + } + + // Showing information available with `--version` flag. + this.log(this.config.userAgent); + + // Iteration through the array containing all dependencies '@asyncapi/*' + // along with their versions. + for (let i = 0; i < dependencies.length; i++) { + // Minimization of the theoretical possibility of a Generic Object + // Injection Sink, at the same time disabling eslint parsing for this + // line since it is actually a false positive. + // https://github.com/eslint-community/eslint-plugin-security/issues/21#issuecomment-530184612 + // https://github.com/eslint-community/eslint-plugin-security/issues/21#issuecomment-1157887653 + // https://web.archive.org/web/20150430062816/https://blog.liftsecurity.io/2015/01/15/the-dangers-of-square-bracket-notation + dependency = dependencies[i]; // eslint-disable-line + if (i !== dependencies.length - 1) { + this.log(` ├${dependency}`); + } else { + this.log(` └${dependency}\n`); + } + } + + this.log(`Repository: ${this.config.pjson.homepage}`); + } +} diff --git a/test/commands/config/versions.test.ts b/test/commands/config/versions.test.ts new file mode 100644 index 00000000000..cf385a4a75e --- /dev/null +++ b/test/commands/config/versions.test.ts @@ -0,0 +1,27 @@ +import { test } from '@oclif/test'; + +describe('versions', () => { + describe('config:versions', () => { + test + .stderr() + .stdout() + .command(['config:versions']) + .it('should show versions of AsyncAPI tools used', (ctx, done) => { + expect(ctx.stdout).toContain('@asyncapi/cli/'); + expect(ctx.stdout).toContain('├@asyncapi/'); + expect(ctx.stdout).toContain('└@asyncapi/'); + expect(ctx.stderr).toEqual(''); + done(); + }); + + test + .stderr() + .stdout() + .command(['config:versions']) + .it('should show address of repository of AsyncAPI CLI', (ctx, done) => { + expect(ctx.stdout).toContain('https://github.com/asyncapi/cli'); + expect(ctx.stderr).toEqual(''); + done(); + }); + }); +});