Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: refactor cli #285

Merged
merged 1 commit into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ $ sort-package-json "**/package.json" --check

#### `--quiet` flag

In order to silence any successful output, you can run CLI with the `--quiet` flag (or `-q`). This will stop the CLI from outputting if it runs successfully, but will still display errors if they occur. Exit codes will not change.
In order to silence any successful output, you can run CLI with the `--quiet` flag (or `-q`). This will stop the CLI from outputting if it runs successfully, but won't effect error messages and the exit code.

```bash
$ sort-package-json "**/package.json" --check --quiet
Expand Down Expand Up @@ -202,21 +202,27 @@ _Alphabetically ordered._

## Automatically Sort

The package.json file can be sorted automatically before committing, install `husky` and `lint-staged` and add the following to your `package.json` file:
The package.json file can be sorted automatically before committing.

```bash
npm install husky lint-staged --save-dev
npm pkg set scripts.prepare="husky install"
npm run prepare
npx husky add .husky/pre-commit "npx lint-staged"
```

Add the following to your `package.json` file

```json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"package.json": "sort-package-json"
}
}
```

See [Husky](https://github.com/typicode/husky) and [lint-staged](https://github.com/okonet/lint-staged) for more information.

## PFAQ: Potential Frequently Asked Questions

### How does it sort?
Expand Down Expand Up @@ -244,4 +250,3 @@ A lot of people who ask for configuration cite the use case that they simply don
### What?! Why would you want to do this?!

Well, it's nice to have the keys of a package.json in a well sorted order. Almost everyone would agree having "name" at the top of a package.json is sensible (rather than sorted alphabetically or somewhere silly like the bottom), so why not the rest of the package.json?

156 changes: 89 additions & 67 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,91 +3,113 @@ import { globbySync } from 'globby'
import fs from 'node:fs'
import sortPackageJson from './index.js'

const isCheckFlag = (argument) => argument === '--check' || argument === '-c'
const isHelpFlag = (argument) => argument === '--help' || argument === '-h'
const isVersionFlag = (argument) =>
argument === '--version' || argument === '-v'
const isQuietFlag = (argument) => argument === '--quiet' || argument === '-q'
function showVersion() {
const { name, version } = JSON.parse(
fs.readFileSync(new URL('package.json', import.meta.url)),
)

const cliArguments = process.argv.slice(2)
const isCheck = cliArguments.some(isCheckFlag)
const isQuiet = cliArguments.some(isQuietFlag)
console.log(`${name} ${version}`)
}

const stdout = isQuiet ? () => {} : console.log
const stderr = console.error
function showHelpInformation() {
console.log(
`Usage: sort-package-json [options] [file/glob ...]

const isHelp = cliArguments.some(isHelpFlag)
const isVersion = cliArguments.some(isVersionFlag)
Sort package.json files.
If file/glob is omitted, './package.json' file will be processed.

if (isHelp) {
console.log(
`Usage: sort-package-json [OPTION...] [FILE...]
Sort npm package.json files. Default: ./package.json
Strings passed as files are parsed as globs.

-c, --check check if FILES are sorted
-q, --quiet don't output success messages
-h, --help display this help and exit
-v, --version display the version and exit
-c, --check Check if files are sorted
-q, --quiet Don't output success messages
-h, --help Display this help
-v, --version Display the package version
`,
)
process.exit(0)
}
if (isVersion) {
const packageJsonUrl = new URL('package.json', import.meta.url)
const packageJsonBuffer = fs.readFileSync(packageJsonUrl)
const { version } = JSON.parse(packageJsonBuffer)

console.log(`sort-package-json ${version}`)
process.exit(0)
}
function sortPackageJsonFiles(patterns, { isCheck, shouldBeQuit }) {
const files = globbySync(patterns)
const printToStdout = shouldBeQuit ? () => {} : console.log

if (files.length === 0) {
console.error('No matching files.')
process.exitCode = 2
return
}

const patterns = cliArguments.filter(
(argument) => !isCheckFlag(argument) && !isQuietFlag(argument),
)
let notSortedFiles = 0
for (const file of files) {
const packageJson = fs.readFileSync(file, 'utf8')
const sorted = sortPackageJson(packageJson)

if (!patterns.length) {
patterns[0] = 'package.json'
}
if (sorted !== packageJson) {
if (isCheck) {
notSortedFiles++
printToStdout(file)
process.exitCode = 1
} else {
fs.writeFileSync(file, sorted)

printToStdout(`${file} is sorted!`)
}
}
}

const files = globbySync(patterns)
if (isCheck) {
// Print a empty line
printToStdout()

if (files.length === 0) {
stderr('No matching files.')
process.exit(1)
if (notSortedFiles) {
printToStdout(
notSortedFiles === 1
? `${notSortedFiles} of ${files.length} matched file is not sorted.`
: `${notSortedFiles} of ${files.length} matched files are not sorted.`,
)
} else {
printToStdout(
files.length === 1
? `${files.length} matched file is sorted.`
: `${files.length} matched files are sorted.`,
)
}
}
}

let notSortedFiles = 0
function run() {
const cliArguments = process.argv.slice(2)

if (
cliArguments.some((argument) => argument === '--help' || argument === '-h')
) {
return showHelpInformation()
}

if (
cliArguments.some(
(argument) => argument === '--version' || argument === '-v',
)
) {
return showVersion()
}

files.forEach((file) => {
const packageJson = fs.readFileSync(file, 'utf8')
const sorted = sortPackageJson(packageJson)
const patterns = []
let isCheck = false
let shouldBeQuit = false

This comment was marked as outdated.


if (sorted !== packageJson) {
if (isCheck) {
notSortedFiles++
stdout(file)
for (const argument of cliArguments) {
if (argument === '--check' || argument === '-c') {
isCheck = true
} else if (argument === '--quiet' || argument === '-q') {
shouldBeQuit = true
} else {
fs.writeFileSync(file, sorted, 'utf8')
stdout(`${file} is sorted!`)
patterns.push(argument)
}
}
})

if (isCheck) {
stdout()
if (notSortedFiles) {
stdout(
notSortedFiles === 1
? `${notSortedFiles} of ${files.length} matched file is not sorted.`
: `${notSortedFiles} of ${files.length} matched files are not sorted.`,
)
} else {
stdout(
files.length === 1
? `${files.length} matched file is sorted.`
: `${files.length} matched files are sorted.`,
)

if (!patterns.length) {
patterns[0] = 'package.json'
}
process.exit(notSortedFiles)

sortPackageJsonFiles(patterns, { isCheck, shouldBeQuit })
}

run()
Loading