diff --git a/.circleci/config.yml b/.circleci/config.yml index 15e1a2ac..5e2f5a19 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,65 +1,29 @@ ---- -version: 2 -jobs: - node-latest: &test - docker: - - image: node:latest - working_directory: ~/cli - steps: - - checkout - - restore_cache: &restore_cache - keys: - - v1-npm-{{checksum ".circleci/config.yml"}}-{{checksum "yarn.lock"}} - - v1-npm-{{checksum ".circleci/config.yml"}} - - run: - name: Install dependencies - command: yarn - - run: - name: Run tests - command: yarn test - node-12: - <<: *test - docker: - - image: node:12 - node-10: - <<: *test - docker: - - image: node:10 - release: - <<: *test - steps: - - add_ssh_keys - - checkout - - restore_cache: *restore_cache - - run: - name: Install release dependencies - command: | - yarn global add @oclif/semantic-release@3 semantic-release@17 - yarn --frozen-lockfile - - run: - name: Cut release - command: | - export PATH=/usr/local/share/.config/yarn/global/node_modules/.bin:$PATH - semantic-release -e @oclif/semantic-release - - save_cache: - key: v1-yarn-{{checksum ".circleci/config.yml"}}-{{checksum "yarn.lock"}} - paths: - - ~/cli/node_modules - - /usr/local/share/.cache/yarn - - /usr/local/share/.config/yarn +version: 2.1 + +orbs: + release-management: salesforce/npm-release-management@4 workflows: version: 2 - "@oclif/plugin-not-found": + test-and-release: jobs: - - node-latest - - node-12 - - node-10 - - release: - context: org-global - filters: - branches: {only: master} + - release-management/test-package: + matrix: + parameters: + os: + - linux + - windows + node_version: + - latest + - lts + exclude: + - os: windows + node_version: lts + - release-management/release-package: + github-release: true + tag: core-v1 requires: - - node-latest - - node-12 - - node-10 + - release-management/test-package + filters: + branches: + only: main diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ef3a06a4..ff580faf 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,5 +10,4 @@ updates: pull-request-branch-name: separator: "-" ignore: - - dependency-name: "typescript" - dependency-name: "fs-extra" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index dc1ca463..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Node.js CI - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - runs-on: windows-latest - strategy: - matrix: - node-version: [10.x, 12.x] - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: yarn install - env: - CI: true - - run: yarn test - env: - CI: true diff --git a/package.json b/package.json index e53e6c8a..9eac76a7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@oclif/plugin-not-found", "description": "\"did you mean\" for oclif", - "version": "1.2.4", + "version": "2.0.0", "author": "Jeff Dickey @jdxcode", "oclif": { "hooks": { @@ -15,7 +15,7 @@ "bugs": "https://github.com/oclif/plugin-not-found/issues", "dependencies": { "@oclif/color": "^0.x", - "@oclif/command": "^1.6.0", + "@oclif/core": "0.5.3", "cli-ux": "^5.5.1", "fast-levenshtein": "^3.0.0", "lodash": "^4.17.21" @@ -30,19 +30,19 @@ "@types/chai": "^4.2.18", "@types/fast-levenshtein": "^0.0.1", "@types/lodash": "^4.14.170", - "@types/mocha": "^8.2.0", + "@types/mocha": "^8.2.2", "@types/node": "^15.6.1", "@types/supports-color": "^8.1.0", - "chai": "^4.2.0", - "eslint": "^7.27.0", - "eslint-config-oclif": "^3.1.0", + "chai": "^4.3.4", "eslint-config-oclif-typescript": "^0.2.0", + "eslint-config-oclif": "^3.1.0", + "eslint": "^7.27.0", "mocha": "^8.4.0", "ts-node": "^9.1.1", - "typescript": "3.8.3" + "typescript": "^4.2.4" }, "engines": { - "node": ">=8.0.0" + "node": ">=14.0.0" }, "files": [ "/oclif.manifest.json", diff --git a/src/index.ts b/src/index.ts index 87a11ed5..2980ebe5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,41 +1,45 @@ import {color} from '@oclif/color' -import {Hook} from '@oclif/config' +import {Hook, toConfiguredId} from '@oclif/core' import {cli} from 'cli-ux' import * as Levenshtein from 'fast-levenshtein' import * as _ from 'lodash' const hook: Hook.CommandNotFound = async function (opts) { + const hiddenCommandIds = opts.config.commands.filter(c => c.hidden).map(c => c.id) const commandIDs = [ ...opts.config.commandIDs, ..._.flatten(opts.config.commands.map(c => c.aliases)), 'version', - ] + ].filter(c => !hiddenCommandIds.includes(c)) + if (commandIDs.length === 0) return - function closest(cmd: string) { + function closest(cmd: string): string { return _.minBy(commandIDs, c => Levenshtein.get(cmd, c))! } let binHelp = `${opts.config.bin} help` const idSplit = opts.id.split(':') - if (await opts.config.findTopic(idSplit[0])) { + if (opts.config.findTopic(idSplit[0])) { // if valid topic, update binHelp with topic binHelp = `${binHelp} ${idSplit[0]}` } - const suggestion: string = closest(opts.id) - this.warn(`${color.yellow(opts.id)} is not a ${opts.config.bin} command.`) + const suggestion = closest(opts.id) + const readableSuggestion = toConfiguredId(suggestion, this.config) + const originalCmd = toConfiguredId(opts.id, this.config) + this.warn(`${color.yellow(originalCmd)} is not a ${opts.config.bin} command.`) - let response + let response = '' try { - response = await cli.prompt(`Did you mean ${color.blueBright(suggestion)}? [y/n]`, {timeout: 4900}) + response = await cli.prompt(`Did you mean ${color.blueBright(readableSuggestion)}? [y/n]`, {timeout: 4900}) } catch (error) { this.log('') this.debug(error) } if (response === 'y') { - const argv = process.argv - await this.config.runCommand(suggestion, argv.slice(3, argv.length)) + const argv = opts.argv || process.argv.slice(3, process.argv.length) + await this.config.runCommand(suggestion, argv) this.exit(0) } diff --git a/test/hooks/not-found.test.ts b/test/hooks/not-found.test.ts index cfe82404..76201569 100644 --- a/test/hooks/not-found.test.ts +++ b/test/hooks/not-found.test.ts @@ -17,6 +17,16 @@ describe('command_not_found', () => { expect(ctx.stdout).to.be.contain('commands\nhelp') }) + test + .stderr() + .stub(cli, 'prompt', () => async () => 'y') + .stub(process, 'argv', []) + .hook('command_not_found', {id: 'commans', argv: ['foo', '--bar', 'baz']}) + .catch('Unexpected arguments: foo, --bar, baz\nSee more help with --help') + .end('runs hook with suggested command and provided args on yes', (ctx: any) => { + expect(ctx.stderr).to.contain('Warning: commans is not a @oclif/plugin-not-found command.\n') + }) + test .stderr() .stub(cli, 'prompt', () => async () => 'n') diff --git a/yarn.lock b/yarn.lock index 3c74b772..491dd841 100644 --- a/yarn.lock +++ b/yarn.lock @@ -107,6 +107,28 @@ is-wsl "^2.1.1" tslib "^2.0.0" +"@oclif/core@0.5.3": + version "0.5.3" + resolved "https://registry.npmjs.org/@oclif/core/-/core-0.5.3.tgz#ac360e9a37aa8d57c93081906292a13d2c41bd52" + integrity sha512-MtaSCv6O3NagFPHPHYssYSHZ/K2BExI/zB6exaWA9kjycTYgnLABwUjw5kaHmX9WkXDNGOyjaHBhqmoRSozfOA== + dependencies: + "@oclif/linewrap" "^1.0.0" + chalk "^4.1.0" + clean-stack "^3.0.0" + cli-ux "^5.1.0" + debug "^4.1.1" + fs-extra "^9.0.1" + globby "^11.0.1" + indent-string "^4.0.0" + is-wsl "^2.1.1" + lodash.template "^4.4.0" + semver "^7.3.2" + string-width "^4.2.0" + strip-ansi "^6.0.0" + tslib "^2.0.0" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + "@oclif/dev-cli@^1.26.0": version "1.26.0" resolved "https://registry.yarnpkg.com/@oclif/dev-cli/-/dev-cli-1.26.0.tgz#e3ec294b362c010ffc8948003d3770955c7951fd" @@ -225,7 +247,7 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073" integrity sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww== -"@types/mocha@^8.2.0": +"@types/mocha@^8.2.2": version "8.2.2" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0" integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw== @@ -468,6 +490,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -601,7 +628,7 @@ cardinal@^2.1.1: ansicolors "~0.3.2" redeyed "~2.1.0" -chai@^4.2.0: +chai@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== @@ -718,9 +745,9 @@ cli-ux@^4.8.2: supports-hyperlinks "^1.0.1" treeify "^1.1.0" -cli-ux@^5.2.1, cli-ux@^5.5.1: +cli-ux@^5.1.0, cli-ux@^5.2.1, cli-ux@^5.5.1: version "5.5.1" - resolved "https://registry.yarnpkg.com/cli-ux/-/cli-ux-5.5.1.tgz#99d28dae0c3ef7845fa2ea56e066a1d5fcceca9e" + resolved "https://registry.npmjs.org/cli-ux/-/cli-ux-5.5.1.tgz#99d28dae0c3ef7845fa2ea56e066a1d5fcceca9e" integrity sha512-t3DT1U1C3rArLGYLpKa3m9dr/8uKZRI8HRm/rXKL7UTjm4c+Yd9zHNWg1tP8uaJkUbhmvx5SQHwb3VWpPUVdHQ== dependencies: "@oclif/command" "^1.6.0" @@ -1448,6 +1475,16 @@ fs-extra@^8.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.0.1: + version "9.1.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1964,6 +2001,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -3154,10 +3200,10 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -typescript@3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== +typescript@^4.2.4: + version "4.2.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" + integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== union-value@^1.0.0: version "1.0.0" @@ -3174,6 +3220,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"