diff --git a/cli.js b/cli.js index e1cb7bd9..86314845 100755 --- a/cli.js +++ b/cli.js @@ -1,6 +1,7 @@ #!/usr/bin/env node import { globbySync } from 'globby' import fs from 'node:fs' +import { parseArgs } from 'node:util' import sortPackageJson from './index.js' import Reporter from './reporter.js' @@ -27,6 +28,25 @@ If file/glob is omitted, './package.json' file will be processed. ) } +function parseCliArguments() { + const { values: options, positionals: patterns } = parseArgs({ + options: { + check: { type: 'boolean', short: 'c', default: false }, + quiet: { type: 'boolean', short: 'q', default: false }, + version: { type: 'boolean', short: 'v', default: false }, + help: { type: 'boolean', short: 'h', default: false }, + }, + allowPositionals: true, + strict: true, + }) + + if (!patterns.length) { + patterns[0] = 'package.json' + } + + return { options, patterns } +} + function sortPackageJsonFile(file, reporter, isCheck) { const original = fs.readFileSync(file, 'utf8') const sorted = sortPackageJson(original) @@ -58,41 +78,33 @@ function sortPackageJsonFiles(patterns, options) { } function run() { - const cliArguments = process.argv.slice(2) + let options, patterns + try { + ;({ options, patterns } = parseCliArguments()) + } catch (error) { + process.exitCode = 2 + console.error(error.message) + if ( + error.code === 'ERR_PARSE_ARGS_UNKNOWN_OPTION' || + error.code === 'ERR_PARSE_ARGS_INVALID_OPTION_VALUE' + ) { + console.error(`Try 'sort-package-json --help' for more information.`) + } + return + } - if ( - cliArguments.some((argument) => argument === '--help' || argument === '-h') - ) { + if (options.help) { return showHelpInformation() } - if ( - cliArguments.some( - (argument) => argument === '--version' || argument === '-v', - ) - ) { + if (options.version) { return showVersion() } - const patterns = [] - let isCheck = false - let shouldBeQuiet = false - - for (const argument of cliArguments) { - if (argument === '--check' || argument === '-c') { - isCheck = true - } else if (argument === '--quiet' || argument === '-q') { - shouldBeQuiet = true - } else { - patterns.push(argument) - } - } - - if (!patterns.length) { - patterns[0] = 'package.json' - } - - sortPackageJsonFiles(patterns, { isCheck, shouldBeQuiet }) + sortPackageJsonFiles(patterns, { + isCheck: options.check, + shouldBeQuiet: options.quiet, + }) } run() diff --git a/reporter.js b/reporter.js index d61e1eb2..e09053dc 100644 --- a/reporter.js +++ b/reporter.js @@ -60,7 +60,7 @@ class Reporter { return } - const { isCheck, isQuiet } = this.#options + const { isCheck, shouldBeQuiet } = this.#options if (isCheck && changedFilesCount) { process.exitCode = 1 @@ -70,7 +70,7 @@ class Reporter { process.exitCode = 2 } - if (isQuiet) { + if (shouldBeQuiet) { return } diff --git a/tests/cli.js b/tests/cli.js index 30388d26..f87574b1 100644 --- a/tests/cli.js +++ b/tests/cli.js @@ -63,6 +63,31 @@ test('run `cli --help` with `--version`', macro.testCLI, { message: 'Should prioritize help over version.', }) +test('run `cli --help=value`', macro.testCLI, { + args: ['--help=value'], + message: 'Should report illegal argument and suggest help.', +}) + +test('run `cli --version=true`', macro.testCLI, { + args: ['--version=true'], + message: 'Should report illegal argument and suggest help.', +}) + +test('run `cli --unknown-option`', macro.testCLI, { + args: ['--unknown-option'], + message: 'Should report unknown option and suggest help.', +}) + +test('run `cli -u` with unknown option', macro.testCLI, { + args: ['-u'], + message: 'Should report unknown option and suggest help.', +}) + +test('run `cli --no-version`', macro.testCLI, { + args: ['--no-version'], + message: 'A snapshot to show how `--no-*` works, not care about result.', +}) + test('run `cli` with no patterns', macro.testCLI, { fixtures: [ { @@ -87,6 +112,11 @@ test('run `cli --quiet` with no patterns', macro.testCLI, { message: 'Should format package.json without message.', }) +test('run `cli --quiet=value`', macro.testCLI, { + args: ['--quiet=value'], + message: 'Should report illegal argument and suggest help.', +}) + test('run `cli -q` with no patterns', macro.testCLI, { fixtures: [ { @@ -111,6 +141,11 @@ test('run `cli --check` with no patterns', macro.testCLI, { message: 'Should not sort package.json', }) +test('run `cli --check=value`', macro.testCLI, { + args: ['--check=value'], + message: 'Should report illegal argument and suggest help.', +}) + test('run `cli --check --quiet` with no patterns', macro.testCLI, { fixtures: [ { @@ -147,6 +182,18 @@ test('run `cli -c -q` with no patterns', macro.testCLI, { message: 'Should support `-q` alias', }) +test('run `cli -cq` with no patterns', macro.testCLI, { + fixtures: [ + { + file: 'package.json', + content: badJson, + expect: badJson, + }, + ], + args: ['-cq'], + message: 'Should support option aggregation', +}) + test('run `cli` on 1 bad file', macro.testCLI, { fixtures: [ { diff --git a/tests/snapshots/cli.js.md b/tests/snapshots/cli.js.md index b939c937..59c23a6a 100644 --- a/tests/snapshots/cli.js.md +++ b/tests/snapshots/cli.js.md @@ -207,6 +207,96 @@ Generated by [AVA](https://avajs.dev). }, } +## run `cli --help=value` + +> Should report illegal argument and suggest help. + + { + args: [ + '--help=value', + ], + fixtures: [], + result: { + errorCode: 2, + stderr: `Option '-h, --help' does not take an argument␊ + Try 'sort-package-json --help' for more information.␊ + `, + stdout: '', + }, + } + +## run `cli --version=true` + +> Should report illegal argument and suggest help. + + { + args: [ + '--version=true', + ], + fixtures: [], + result: { + errorCode: 2, + stderr: `Option '-v, --version' does not take an argument␊ + Try 'sort-package-json --help' for more information.␊ + `, + stdout: '', + }, + } + +## run `cli --unknown-option` + +> Should report unknown option and suggest help. + + { + args: [ + '--unknown-option', + ], + fixtures: [], + result: { + errorCode: 2, + stderr: `Unknown option '--unknown-option'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- "--unknown-option"␊ + Try 'sort-package-json --help' for more information.␊ + `, + stdout: '', + }, + } + +## run `cli -u` with unknown option + +> Should report unknown option and suggest help. + + { + args: [ + '-u', + ], + fixtures: [], + result: { + errorCode: 2, + stderr: `Unknown option '-u'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- "-u"␊ + Try 'sort-package-json --help' for more information.␊ + `, + stdout: '', + }, + } + +## run `cli --no-version` + +> A snapshot to show how `--no-*` works, not care about result. + + { + args: [ + '--no-version', + ], + fixtures: [], + result: { + errorCode: 2, + stderr: `Unknown option '--no-version'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- "--no-version"␊ + Try 'sort-package-json --help' for more information.␊ + `, + stdout: '', + }, + } + ## run `cli` with no patterns > Should format package.json. @@ -265,6 +355,24 @@ Generated by [AVA](https://avajs.dev). }, } +## run `cli --quiet=value` + +> Should report illegal argument and suggest help. + + { + args: [ + '--quiet=value', + ], + fixtures: [], + result: { + errorCode: 2, + stderr: `Option '-q, --quiet' does not take an argument␊ + Try 'sort-package-json --help' for more information.␊ + `, + stdout: '', + }, + } + ## run `cli -q` with no patterns > Should support -q alias. @@ -325,6 +433,24 @@ Generated by [AVA](https://avajs.dev). }, } +## run `cli --check=value` + +> Should report illegal argument and suggest help. + + { + args: [ + '--check=value', + ], + fixtures: [], + result: { + errorCode: 2, + stderr: `Option '-c, --check' does not take an argument␊ + Try 'sort-package-json --help' for more information.␊ + `, + stdout: '', + }, + } + ## run `cli --check --quiet` with no patterns > Should not sort package.json or report a message. @@ -415,6 +541,34 @@ Generated by [AVA](https://avajs.dev). }, } +## run `cli -cq` with no patterns + +> Should support option aggregation + + { + args: [ + '-cq', + ], + fixtures: [ + { + expect: `{␊ + "version": "1.0.0",␊ + "name": "sort-package-json"␊ + }`, + file: 'package.json', + original: `{␊ + "version": "1.0.0",␊ + "name": "sort-package-json"␊ + }`, + }, + ], + result: { + errorCode: 1, + stderr: '', + stdout: '', + }, + } + ## run `cli` on 1 bad file > Should format 1 file. diff --git a/tests/snapshots/cli.js.snap b/tests/snapshots/cli.js.snap index daa91527..63e2fd66 100644 Binary files a/tests/snapshots/cli.js.snap and b/tests/snapshots/cli.js.snap differ