From 14cbd0cd3bb101379e8166e6afa12c9331de523c Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Tue, 19 Sep 2023 14:56:09 +0530 Subject: [PATCH 01/11] handle the case if the file is not present. --- src/commands/new/file.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/commands/new/file.ts b/src/commands/new/file.ts index 98159a3f6d4..83c3a5fa043 100644 --- a/src/commands/new/file.ts +++ b/src/commands/new/file.ts @@ -160,11 +160,16 @@ export default class NewFile extends Command { console.log(`File ${fileNameToWriteToDisk} already exists. Ignoring...`); return; } - } catch (e) { - // File does not exist. Proceed creating it... + } catch (e:any ) { + + if (e.code === 'EACCES') { + console.error('Permission denied to read the file. You do not have the necessary permissions.'); + } else { + await writeFile(fileNameToWriteToDisk, asyncApiFile, { encoding: 'utf8' }); + console.log(`Created file ${fileNameToWriteToDisk}...`); + + } } - await writeFile(fileNameToWriteToDisk, asyncApiFile, { encoding: 'utf8' }); - console.log(`Created file ${fileNameToWriteToDisk}...`); } } From 972cef0a351c572ae3ee994a9b584b88417c4fb6 Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Tue, 26 Sep 2023 22:56:15 +0530 Subject: [PATCH 02/11] remove the lint error --- src/commands/new/file.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/commands/new/file.ts b/src/commands/new/file.ts index 83c3a5fa043..fbe83632133 100644 --- a/src/commands/new/file.ts +++ b/src/commands/new/file.ts @@ -160,16 +160,13 @@ export default class NewFile extends Command { console.log(`File ${fileNameToWriteToDisk} already exists. Ignoring...`); return; } - } catch (e:any ) { - + } catch (e:any) { if (e.code === 'EACCES') { console.error('Permission denied to read the file. You do not have the necessary permissions.'); } else { await writeFile(fileNameToWriteToDisk, asyncApiFile, { encoding: 'utf8' }); console.log(`Created file ${fileNameToWriteToDisk}...`); - } } - } } From 0bb6b5dfcd2ae27e9a8c301bd339ca86ecae27d3 Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Sat, 30 Sep 2023 19:09:17 +0530 Subject: [PATCH 03/11] made the required changes. --- src/commands/new/file.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/commands/new/file.ts b/src/commands/new/file.ts index fbe83632133..37b8edf263f 100644 --- a/src/commands/new/file.ts +++ b/src/commands/new/file.ts @@ -162,11 +162,10 @@ export default class NewFile extends Command { } } catch (e:any) { if (e.code === 'EACCES') { - console.error('Permission denied to read the file. You do not have the necessary permissions.'); - } else { - await writeFile(fileNameToWriteToDisk, asyncApiFile, { encoding: 'utf8' }); - console.log(`Created file ${fileNameToWriteToDisk}...`); + this.error('Permission denied to read the file. You do not have the necessary permissions.'); } } + await writeFile(fileNameToWriteToDisk, asyncApiFile, { encoding: 'utf8' }); + console.log(`Created file ${fileNameToWriteToDisk}...`); } } From 3750452423101880b54d865a242a7b3cf7d72108 Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Thu, 5 Oct 2023 09:44:08 +0530 Subject: [PATCH 04/11] Added the latest version of asyncapi in the for generator template of glee. --- assets/create-glee-app/templates/default/asyncapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/create-glee-app/templates/default/asyncapi.yaml b/assets/create-glee-app/templates/default/asyncapi.yaml index 5c4c673e3bc..2e77ec64d71 100644 --- a/assets/create-glee-app/templates/default/asyncapi.yaml +++ b/assets/create-glee-app/templates/default/asyncapi.yaml @@ -1,4 +1,4 @@ -asyncapi: 2.1.0 +asyncapi: 2.6.0 info: title: Hello, Glee! version: 0.1.0 From 29b2df3fc83008a9d223e33adff5655a962befe0 Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Sat, 14 Oct 2023 02:44:20 +0530 Subject: [PATCH 05/11] added the hook . --- bin/run | 1 - package.json | 10 ++++++---- src/hooks/command_not_found/myhook.ts | 8 ++++++++ test/hooks/command_not_found/myhook.test.ts | 9 +++++++++ test/tsconfig.json | 6 +----- 5 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 src/hooks/command_not_found/myhook.ts create mode 100644 test/hooks/command_not_found/myhook.test.ts diff --git a/bin/run b/bin/run index fcaebe51129..330b6c39987 100755 --- a/bin/run +++ b/bin/run @@ -6,7 +6,6 @@ oclif.run() .then(require('@oclif/core/flush')) .catch((err) => { const oclifHandler = require('@oclif/core/handle'); - console.error(err.message); return oclifHandler(err.message); }); diff --git a/package.json b/package.json index e4977822120..2301604cbe7 100644 --- a/package.json +++ b/package.json @@ -103,9 +103,9 @@ "oclif": { "commands": "./lib/commands", "bin": "asyncapi", - "plugins": [ - "@oclif/plugin-not-found" - ], + "plugins": [], + "hooks": { + "command_not_found": ["./lib/hooks/command_not_found/myhook"] }, "macos": { "identifier": "com.asyncapi.cli" }, @@ -151,7 +151,9 @@ "release": "semantic-release", "test": "npm run test:unit", "test:unit": "cross-env NODE_ENV=development TEST=1 CUSTOM_CONTEXT_FILENAME=\"test.asyncapi-cli\" CUSTOM_CONTEXT_FILE_LOCATION=\"\" nyc --extension .ts mocha --require ts-node/register --require test/helpers/init.js --reporter spec --timeout 100000 \"test/**/*.test.ts\"", - "get-version": "echo $npm_package_version" + "get-version": "echo $npm_package_version", + "createhook": "oclif generate hook myhook --event=command_not_found", + "createhookinit": "oclif generate hook inithook --event=init" }, "types": "lib/index.d.ts" } diff --git a/src/hooks/command_not_found/myhook.ts b/src/hooks/command_not_found/myhook.ts new file mode 100644 index 00000000000..3a1223e40c6 --- /dev/null +++ b/src/hooks/command_not_found/myhook.ts @@ -0,0 +1,8 @@ +import {Hook} from '@oclif/core' + +const hook: Hook<'command_not_found'> = async function (opts) { + if(opts.id === "help"){ process.stdout.write(`help hook running ${opts.id}\n`))} + +} + +export default hook diff --git a/test/hooks/command_not_found/myhook.test.ts b/test/hooks/command_not_found/myhook.test.ts new file mode 100644 index 00000000000..28fb6c936fd --- /dev/null +++ b/test/hooks/command_not_found/myhook.test.ts @@ -0,0 +1,9 @@ +import {expect, test} from '@oclif/test' + +describe('hooks', () => { + test + .stdout() + .hook('init', {id: 'mycommand'}) + .do(output => expect(output.stdout).to.contain('example hook running mycommand')) + .it('shows a message') +}) diff --git a/test/tsconfig.json b/test/tsconfig.json index 8c82b0a0459..fa355fb9797 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -3,9 +3,5 @@ "compilerOptions": { "noEmit": true, }, - "references": [ - { - "path": "../" - } - ] + } From 9b42245782d90b8d00b722d57ea74a71210e5432 Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Sat, 14 Oct 2023 02:50:42 +0530 Subject: [PATCH 06/11] fixed bug --- src/hooks/command_not_found/myhook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/command_not_found/myhook.ts b/src/hooks/command_not_found/myhook.ts index 3a1223e40c6..93145c8e0a9 100644 --- a/src/hooks/command_not_found/myhook.ts +++ b/src/hooks/command_not_found/myhook.ts @@ -1,7 +1,7 @@ import {Hook} from '@oclif/core' const hook: Hook<'command_not_found'> = async function (opts) { - if(opts.id === "help"){ process.stdout.write(`help hook running ${opts.id}\n`))} + if(opts.id === "help"){ process.stdout.write(`help hook running ${opts.id}\n`)} } From 6a53b610d193901922c081ee04a0197b61d1380c Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Sat, 14 Oct 2023 02:52:44 +0530 Subject: [PATCH 07/11] added the semicolon --- src/hooks/command_not_found/myhook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/command_not_found/myhook.ts b/src/hooks/command_not_found/myhook.ts index 93145c8e0a9..e7f25286295 100644 --- a/src/hooks/command_not_found/myhook.ts +++ b/src/hooks/command_not_found/myhook.ts @@ -1,7 +1,7 @@ import {Hook} from '@oclif/core' const hook: Hook<'command_not_found'> = async function (opts) { - if(opts.id === "help"){ process.stdout.write(`help hook running ${opts.id}\n`)} + if(opts.id === "help"){ process.stdout.write(`help hook running ${opts.id}\n`)}; } From a1afe8be00b26b07273ac767e611e80c4e571458 Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Sat, 14 Oct 2023 02:57:22 +0530 Subject: [PATCH 08/11] ran lint command --- src/hooks/command_not_found/myhook.ts | 9 ++++----- test/hooks/command_not_found/myhook.test.ts | 12 ++++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/hooks/command_not_found/myhook.ts b/src/hooks/command_not_found/myhook.ts index e7f25286295..ad7625674b9 100644 --- a/src/hooks/command_not_found/myhook.ts +++ b/src/hooks/command_not_found/myhook.ts @@ -1,8 +1,7 @@ -import {Hook} from '@oclif/core' +import {Hook} from '@oclif/core'; const hook: Hook<'command_not_found'> = async function (opts) { - if(opts.id === "help"){ process.stdout.write(`help hook running ${opts.id}\n`)}; - -} + if (opts.id === 'help') { process.stdout.write(`help hook running ${opts.id}\n`);} +}; -export default hook +export default hook; diff --git a/test/hooks/command_not_found/myhook.test.ts b/test/hooks/command_not_found/myhook.test.ts index 28fb6c936fd..29e1413428d 100644 --- a/test/hooks/command_not_found/myhook.test.ts +++ b/test/hooks/command_not_found/myhook.test.ts @@ -1,9 +1,9 @@ -import {expect, test} from '@oclif/test' +import {expect, test} from '@oclif/test'; describe('hooks', () => { test - .stdout() - .hook('init', {id: 'mycommand'}) - .do(output => expect(output.stdout).to.contain('example hook running mycommand')) - .it('shows a message') -}) + .stdout() + .hook('init', {id: 'mycommand'}) + .do(output => expect(output.stdout).to.contain('example hook running mycommand')) + .it('shows a message'); +}); From 6a82b6cea4730bb510e8ead6a53221b1ec15b9ae Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Sat, 14 Oct 2023 16:01:20 +0530 Subject: [PATCH 09/11] Added the test --- src/hooks/command_not_found/myhook.ts | 2 +- test/hooks/command_not_found/myhook.spec.ts | 10 ++++++++++ test/hooks/command_not_found/myhook.test.ts | 9 --------- 3 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 test/hooks/command_not_found/myhook.spec.ts delete mode 100644 test/hooks/command_not_found/myhook.test.ts diff --git a/src/hooks/command_not_found/myhook.ts b/src/hooks/command_not_found/myhook.ts index ad7625674b9..3f4077a2324 100644 --- a/src/hooks/command_not_found/myhook.ts +++ b/src/hooks/command_not_found/myhook.ts @@ -1,7 +1,7 @@ import {Hook} from '@oclif/core'; const hook: Hook<'command_not_found'> = async function (opts) { - if (opts.id === 'help') { process.stdout.write(`help hook running ${opts.id}\n`);} + if (opts.id === 'help') { process.stdout.write(`${opts.id} command not found.\n`);} }; export default hook; diff --git a/test/hooks/command_not_found/myhook.spec.ts b/test/hooks/command_not_found/myhook.spec.ts new file mode 100644 index 00000000000..bab80936b07 --- /dev/null +++ b/test/hooks/command_not_found/myhook.spec.ts @@ -0,0 +1,10 @@ +import {expect, test} from '@oclif/test'; + +describe('hooks', () => { + test + .stdout() + .hook('command_not_found', {id: 'help'}) + .do(output => expect(output.stdout).to.contain('help command not found.')) + .it('shows a message'); +}); + diff --git a/test/hooks/command_not_found/myhook.test.ts b/test/hooks/command_not_found/myhook.test.ts deleted file mode 100644 index 29e1413428d..00000000000 --- a/test/hooks/command_not_found/myhook.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {expect, test} from '@oclif/test'; - -describe('hooks', () => { - test - .stdout() - .hook('init', {id: 'mycommand'}) - .do(output => expect(output.stdout).to.contain('example hook running mycommand')) - .it('shows a message'); -}); From 51d1a6fbb2bc3fc6d9772fb3e2903664b1f8ffaf Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Wed, 18 Oct 2023 23:38:34 +0530 Subject: [PATCH 10/11] fixed the bug of help command. --- package-lock.json | 11 +++- package.json | 7 ++- src/hooks/command_not_found/myhook.ts | 74 +++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2e51498524d..9c78ddc49b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "ajv": "^8.12.0", "chalk": "^4.1.0", "chokidar": "^3.5.2", + "fast-levenshtein": "^3.0.0", "fs-extra": "^11.1.0", "indent-string": "^4.0.0", "inquirer": "^8.2.0", @@ -54,6 +55,7 @@ "@oclif/test": "^2", "@swc/core": "^1.3.2", "@types/chai": "^4.3.6", + "@types/fast-levenshtein": "^0.0.2", "@types/fs-extra": "^11.0.1", "@types/inquirer": "^8.1.3", "@types/js-yaml": "^4.0.5", @@ -6279,6 +6281,12 @@ "version": "1.20.4", "license": "MIT" }, + "node_modules/@types/fast-levenshtein": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@types/fast-levenshtein/-/fast-levenshtein-0.0.2.tgz", + "integrity": "sha512-h9AGeNlFimLtFUlEZgk+hb3LUT4tNHu8y0jzCUeTdi1BM4e86sBQs/nQYgHk70ksNyNbuLwpymFAXkb0GAehmw==", + "dev": true + }, "node_modules/@types/fs-extra": { "version": "11.0.1", "dev": true, @@ -10873,7 +10881,8 @@ }, "node_modules/fast-levenshtein": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", "dependencies": { "fastest-levenshtein": "^1.0.7" } diff --git a/package.json b/package.json index 2301604cbe7..4dc4d686fec 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "ajv": "^8.12.0", "chalk": "^4.1.0", "chokidar": "^3.5.2", + "fast-levenshtein": "^3.0.0", "fs-extra": "^11.1.0", "indent-string": "^4.0.0", "inquirer": "^8.2.0", @@ -50,6 +51,7 @@ "@oclif/test": "^2", "@swc/core": "^1.3.2", "@types/chai": "^4.3.6", + "@types/fast-levenshtein": "^0.0.2", "@types/fs-extra": "^11.0.1", "@types/inquirer": "^8.1.3", "@types/js-yaml": "^4.0.5", @@ -105,7 +107,10 @@ "bin": "asyncapi", "plugins": [], "hooks": { - "command_not_found": ["./lib/hooks/command_not_found/myhook"] }, + "command_not_found": [ + "./lib/hooks/command_not_found/myhook" + ] + }, "macos": { "identifier": "com.asyncapi.cli" }, diff --git a/src/hooks/command_not_found/myhook.ts b/src/hooks/command_not_found/myhook.ts index 3f4077a2324..19b9b350ff3 100644 --- a/src/hooks/command_not_found/myhook.ts +++ b/src/hooks/command_not_found/myhook.ts @@ -1,7 +1,75 @@ -import {Hook} from '@oclif/core'; +import {Hook, toConfiguredId, CliUx} from '@oclif/core'; +import chalk from 'chalk'; +import {default as levenshtein} from 'fast-levenshtein'; +import { Help } from '@oclif/core'; -const hook: Hook<'command_not_found'> = async function (opts) { - if (opts.id === 'help') { process.stdout.write(`${opts.id} command not found.\n`);} +export const closest = (target: string, possibilities: string[]): string => + possibilities + .map((id) => ({distance: levenshtein.get(target, id, {useCollator: true}), id})) + .sort((a, b) => a.distance - b.distance)[0]?.id ?? ''; + +const hook: Hook.CommandNotFound = async function (opts) { + if (opts.id === '--help') { + const help = new Help(this.config); + help.showHelp(['--help']); + return; + } + const hiddenCommandIds = new Set(opts.config.commands.filter((c) => {c.hidden;}).map((c) => c.id)); + const commandIDs = [...opts.config.commandIDs, ...opts.config.commands.flatMap((c) => c.aliases)].filter( + (c) => !hiddenCommandIds.has(c), + ); + //here we get the command ids and hidden command ids. + + if (commandIDs.length === 0) {return;} + // now we we return if the command id are not there. + + let binHelp = `${opts.config.bin} help`; + + const idSplit = opts.id.split(':'); + if (opts.config.findTopic(idSplit[0])) { + // if valid topic, update binHelp with topic + binHelp = `${binHelp} ${idSplit[0]}`; + } + + //if there is a topic in the opts we just upgrade the our commnad like + + // alter the suggestion in the help scenario so that help is the first command + // otherwise the user will be presented 'did you mean 'help'?' instead of 'did you mean "help "?' + let suggestion = (/:?help:?/).test(opts.id) + ? ['help', ...opts.id.split(':').filter((cmd) => cmd !== 'help')].join(':') + : closest(opts.id, commandIDs); + + let readableSuggestion = toConfiguredId(suggestion, this.config); + const originalCmd = toConfiguredId(opts.id, this.config); + this.warn(`${chalk.yellow(originalCmd)} is not a ${opts.config.bin} command.`); + + let response = ''; + try { + if (opts.id === 'help') {readableSuggestion = '--help';} + response = await CliUx.ux.prompt(`Did you mean ${chalk.blueBright(readableSuggestion)}? [y/n]`, {timeout: 10_000}); + } catch (error) { + this.log(''); + this.debug(error); + } + + if (response === 'y') { + // this will split the original command from the suggested replacement, and gather the remaining args as varargs to help with situations like: + // confit set foo-bar -> confit:set:foo-bar -> config:set:foo-bar -> config:set foo-bar + let argv = opts.argv?.length ? opts.argv : opts.id.split(':').slice(suggestion.split(':').length); + if (suggestion.startsWith('help:')) { + // the args are the command/partial command you need help for (package:version) + // we created the suggestion variable to start with "help" so slice the first entry + argv = suggestion.split(':').slice(1); + // the command is just the word "help" + suggestion = 'help'; + } + if (opts.id === 'help') { + return this.config.runCommand('--help'); + } + return this.config.runCommand(suggestion, argv); + } + + this.error(`Run ${chalk.bold.cyan(binHelp)} for a list of available commands.`, {exit: 127}); }; export default hook; From f8cdf92c7f2394c132f2c9be7cfc80e48479d6a3 Mon Sep 17 00:00:00 2001 From: ayush-coder-hai Date: Thu, 19 Oct 2023 23:12:27 +0530 Subject: [PATCH 11/11] made small change. --- src/hooks/command_not_found/myhook.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/command_not_found/myhook.ts b/src/hooks/command_not_found/myhook.ts index 19b9b350ff3..ef2698c94b9 100644 --- a/src/hooks/command_not_found/myhook.ts +++ b/src/hooks/command_not_found/myhook.ts @@ -14,13 +14,13 @@ const hook: Hook.CommandNotFound = async function (opts) { help.showHelp(['--help']); return; } - const hiddenCommandIds = new Set(opts.config.commands.filter((c) => {c.hidden;}).map((c) => c.id)); + const hiddenCommandIds = new Set(opts.config.commands.filter((c) => c.hidden).map((c) => c.id)); const commandIDs = [...opts.config.commandIDs, ...opts.config.commands.flatMap((c) => c.aliases)].filter( (c) => !hiddenCommandIds.has(c), ); - //here we get the command ids and hidden command ids. if (commandIDs.length === 0) {return;} + // now we we return if the command id are not there. let binHelp = `${opts.config.bin} help`;