diff --git a/package-lock.json b/package-lock.json index 254a471ed0f..11b31c23c4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,8 +25,10 @@ "@oclif/core": "^4.0.28", "@smoya/asyncapi-adoption-metrics": "^2.4.9", "@stoplight/spectral-cli": "6.9.0", + "ansi-colors": "^4.1.3", "chalk": "^4.1.0", "chokidar": "^3.5.2", + "cli-progress": "^3.12.0", "fast-levenshtein": "^3.0.0", "fs-extra": "^11.1.0", "generator-v2": "npm:@asyncapi/generator@^2.4.1", @@ -404,8 +406,11 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/@asyncapi/minimaltemplate": { - "resolved": "test/fixtures/minimaltemplate", - "link": true + "resolved": "file:test/fixtures/minimaltemplate", + "dev": true, + "dependencies": { + "@asyncapi/generator-react-sdk": "^1.1.2" + } }, "node_modules/@asyncapi/modelina-cli": { "version": "4.0.0-next.61", @@ -659,8 +664,11 @@ } }, "node_modules/@asyncapi/newtemplate": { - "resolved": "test/fixtures/newtemplate", - "link": true + "resolved": "file:test/fixtures/newtemplate", + "dev": true, + "dependencies": { + "@asyncapi/generator-react-sdk": "^1.1.1" + } }, "node_modules/@asyncapi/nunjucks-filters": { "version": "2.1.0", @@ -8255,7 +8263,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, "engines": { "node": ">=6" } @@ -23574,18 +23581,6 @@ "optional": true } } - }, - "test/fixtures/minimaltemplate": { - "dev": true, - "dependencies": { - "@asyncapi/generator-react-sdk": "^1.1.2" - } - }, - "test/fixtures/newtemplate": { - "dev": true, - "dependencies": { - "@asyncapi/generator-react-sdk": "^1.1.1" - } } }, "dependencies": { @@ -23856,7 +23851,7 @@ } }, "@asyncapi/minimaltemplate": { - "version": "file:test/fixtures/minimaltemplate", + "dev": true, "requires": { "@asyncapi/generator-react-sdk": "^1.1.2" } @@ -24067,7 +24062,7 @@ } }, "@asyncapi/newtemplate": { - "version": "file:test/fixtures/newtemplate", + "dev": true, "requires": { "@asyncapi/generator-react-sdk": "^1.1.1" } @@ -29857,8 +29852,7 @@ "ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==" }, "ansi-escapes": { "version": "4.3.2", diff --git a/package.json b/package.json index c1a2b0d517c..28a388d4e02 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,10 @@ "@oclif/core": "^4.0.28", "@smoya/asyncapi-adoption-metrics": "^2.4.9", "@stoplight/spectral-cli": "6.9.0", + "ansi-colors": "^4.1.3", "chalk": "^4.1.0", "chokidar": "^3.5.2", + "cli-progress": "^3.12.0", "fast-levenshtein": "^3.0.0", "fs-extra": "^11.1.0", "inquirer": "^8.2.0", diff --git a/src/commands/generate/fromTemplate.ts b/src/commands/generate/fromTemplate.ts index 90d0b731216..61ea40797f0 100644 --- a/src/commands/generate/fromTemplate.ts +++ b/src/commands/generate/fromTemplate.ts @@ -16,6 +16,8 @@ import { intro, isCancel, spinner, text } from '@clack/prompts'; import { inverse, yellow, magenta, green, red } from 'picocolors'; import fetch from 'node-fetch'; import { fromTemplateFlags } from '../../core/flags/generate/fromTemplate.flags'; +import cliProgress from 'cli-progress'; +import colors from 'ansi-colors'; interface IMapBaseUrlToFlag { url: string, @@ -266,42 +268,94 @@ export default class Template extends Command { { exit: 1 }, ); } + const generator = new AsyncAPIGenerator(template, output || path.resolve(os.tmpdir(), 'asyncapi-generator'), options); - const s = interactive ? spinner() : { start: () => null, stop: (string: string) => console.log(string) }; - s.start('Generation in progress. Keep calm and wait a bit'); + console.log('\n'); + const progressBar = new cliProgress.SingleBar({ + format: colors.cyan('{bar}') + ' | {percentage}% | ETA: {eta}s', + barCompleteChar: '\u2588', + barIncompleteChar: '\u2591', + hideCursor: true + }); + + if (interactive) { + progressBar.start(100, 0); + } + try { + let progress = 0; + const progressInterval = setInterval(() => { + if (progress < 95) { + progress += Math.random() * 5; + progressBar.update(progress); + } + }, 300); + await generator.generateFromString(specification.text(), { ...genOption, path: asyncapi }); + + clearInterval(progressInterval); + progressBar.update(100); + progressBar.stop(); } catch (err: any) { - s.stop('Generation failed'); + if (interactive) { + progressBar.stop(); + } throw new GeneratorError(err); } - s.stop(`${yellow('Check out your shiny new generated files at ') + magenta(output) + yellow('.')}\n`); + console.log('\n '); + console.log(`${yellow('Check out your shiny new generated files at ') + magenta(output) + yellow('.')}\n`); +} + +private async generateUsingNewGenerator(asyncapi: string | undefined, template: string, output: string, options: any, genOption: any, interactive = true) { + let specification: Specification; + try { + specification = await load(asyncapi); + } catch (err: any) { + return this.error( + new ValidationError({ + type: 'invalid-file', + filepath: asyncapi, + }), + { exit: 1 }, + ); + } + + const generator = new AsyncAPINewGenerator(template, output || path.resolve(os.tmpdir(), 'asyncapi-generator'), options); + console.log('\n'); + const progressBar = new cliProgress.SingleBar({ + format: colors.cyan('{bar}') + ' | {percentage}% | ETA: {eta}s', + barCompleteChar: '\u2588', + barIncompleteChar: '\u2591', + hideCursor: true + }); + + if (interactive) { + progressBar.start(100, 0); } - private async generateUsingNewGenerator(asyncapi: string | undefined, template: string, output: string, options: any, genOption: any, interactive = true) { - let specification: Specification; - try { - specification = await load(asyncapi); - } catch (err: any) { - return this.error( - new ValidationError({ - type: 'invalid-file', - filepath: asyncapi, - }), - { exit: 1 }, - ); - } - const generator = new AsyncAPINewGenerator(template, output || path.resolve(os.tmpdir(), 'asyncapi-generator'), options); - const s = interactive ? spinner() : { start: () => null, stop: (string: string) => console.log(string) }; - s.start('Generation in progress. Keep calm and wait a bit'); - try { - await generator.generateFromString(specification.text(), { ...genOption, path: asyncapi }); - } catch (err: any) { - s.stop('Generation failed'); - throw new GeneratorError(err); + try { + let progress = 0; + const progressInterval = setInterval(() => { + if (progress < 95) { + progress += Math.random() * 5; + progressBar.update(progress); + } + }, 300); + + await generator.generateFromString(specification.text(), { ...genOption, path: asyncapi }); + + clearInterval(progressInterval); + progressBar.update(100); + progressBar.stop(); + } catch (err: any) { + if (interactive) { + progressBar.stop(); } - s.stop(`${yellow('Check out your shiny new generated files at ') + magenta(output) + yellow('.')}\n`); + throw new GeneratorError(err); } + console.log('\n'); + console.log(`${yellow('Check out your shiny new generated files at ') + magenta(output) + yellow('.')}\n`); +} private async runWatchMode(asyncapi: string | undefined, template: string, output: string, watchHandler: ReturnType) { const specification = await load(asyncapi);