current position:Home>CLI command line detection tool
CLI command line detection tool
2022-05-15 07:50:13【User 4669777】
When we are doing front-end development , In order to ensure the quality of code submitted by team members , Generally, code quality inspection and code beautification will be carried out on the code , The usual approach is to make a series of configurations , With the help of eslint
、prettier
、lint-staged
、husky
And other tools to realize the detection of code . But this process involves many , Configuration is also cumbersome , Moreover, repeated configuration is required for different projects , It undoubtedly increases everyone's workload , So what I want to solve is this problem , A command line tool is provided to encapsulate the above detection tool , Simplify configuration steps .
How to develop a command line tool
First of all, you should understand what is a command-line tool , The English name of the command line tool is command-line interface
, abbreviation ,CLI
,( Hereinafter referred to as CLI)CLI
Users can interact with the system in real time , Get real-time information of the system , Complete user-defined functions . such as git
、create-react-app
、vue-cli
And so on are the command-line tools that we usually contact .
So back to the title , How to develop a command line tool ?
oclif
brief introduction
Here I use oclif, One can help us quickly build CLI
Framework , And can support Javascript
perhaps Typescript
Language .
oclif
There are two types of command-line tools ,Single-command
and Multi-command
.Single-command
such as ls
perhaps curl
command ,Multi-command
such as git
, Multiple commands can be provided , Be similar to git add
、 git commit
etc. . Here, as needed , I chose Single-command
.
Quick creation
Run the following command line quickly Single-command
Command line :
$ npx oclif single big-lint
Then follow the prompt on the command line , Enter some basic information , You can directly help us create a CLI
engineering .
Execute the following command and enter the following information , It means a CLI
It was created successfully . Here I choose to use Typescript
To create CLI
, After all 2020 Years. , No more Typescript
It's a little hard to say .
$ cd big-lint
$ ./bin/run
hello world from ./src/index.js!
$ ./bin/run --help
Describe the command here
describe the command here
USAGE
$ big-lint [FILE]
OPTIONS
-f, --force
-h, --help show CLI help
-n, --name=name name to print
-v, --version show CLI version
tips: What needs to be noted here is , It's for you CLI
When you name it , It can be executed npm view packageName
To see if the name has been occupied by others , Because we developed CLI
The tool will eventually be released to npm
Upper , If the name is occupied, it cannot be published , It will be more troublesome to change it then .
Now open package.json
file , You can see the main
Field :
{
"main": "src/index.js",
}
main
Field specifies an entry file , It's what we do $ ./bin/run
The file executed when the command is executed .
src/index.js
import {Command, flags} from '@oclif/command'
class HappyLint extends Command {
static description = 'describe the command here'
static flags = {
// add --version flag to show CLI version
version: flags.version({char: 'v'}),
help: flags.help({char: 'h'}),
// flag with a value (-n, --name=VALUE)
name: flags.string({char: 'n', description: 'name to print'}),
// flag with no value (-f, --force)
force: flags.boolean({char: 'f'}),
}
static args = [{name: 'file'}]
async run() {
const {args, flags} = this.parse(HappyLint)
const name = flags.name || 'world'
this.log(`hello ${name} from ./src/index.ts`)
if (args.file && flags.force) {
this.log(`you input --force and --file: ${args.file}`)
}
}
}
export = HappyLint
If you want to use big-lint Instead of ./bin/run command , It can be executed under the project directory npm link command , Then you can use it happily big-lint --help See the effect .
Come here , A simple CLI
The tool is finished , Now let's start our topic , How to implement code detection .
How to realize code detection and code beautification
Detection tools
In order to ensure that each submission to git
Standardization of warehouse code , Front end solutions generally use eslint
、prettier
、lint-staged
coordination git hook
and husky
, stay git commit
When you're done with the code eslint
Specification verification . Next, you need to install the above dependent packages , And then in package.json
File to configure :
{
"lint-staged": {
"src/**/*.js": [
"eslint --fix --ext .js",
"prettier --write",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
}
big-lint
The meaning of existence is to simplify such a process , Omit complicated configuration .
Build your own CLI
Installation dependency
Now? cd
To what we created before big-lint
In Engineering , Execute the following command in the root directory , Install the appropriate package : $ yarn add husky eslint prettier lint-staged eslint-config-airbnb eslint-config-airbnb-base eslint-config-airbnb-typescript eslint-config-prettier eslint-formatter-pretty eslint-plugin-babel eslint-plugin-compat eslint-plugin-eslint-comments eslint-plugin-import eslint-plugin-jest eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-unicorn -S
General train of thought
big-lint
Two detection modes will be provided :
- Test the submitted code
- By designation dir Parameters , Detect the code under the specified path
Parameter description :
big-lint [options] [dir]
Arguments:
dir Specify the path of verification ( Support node Of glob grammar ) [string]
Flags:
--staged, -S only lint git staged files [boolean] [default: false]
--prettier, -p format code with prettier [boolean] [default: false]
--eslint, -e enable lint javascript [boolean] [default: false]
--fix, -f fix all eslint and stylelint auto-fixable problems [boolean] [default: false]
--format, -F output format of console [string] [default: stylish]
--cwd, -c current working directory [default: process.cwd()]
Test the submitted code
adopt --staged
Parameters , To determine whether only the submitted code is currently detected , The way to achieve this is through lint-staged
、husky
、eslint
. Here's how to do it in code :
Definition OPTIONS
src/utils/options.ts
import {flags} from '@oclif/command'
const flagConfig = {
staged: flags.boolean({
char: 'S',
default: false,
description: 'only lint git staged files',
}),
prettier: flags.boolean({
char: 'P',
default: false,
description: 'format code with prettier',
}),
eslint: flags.boolean({
char: 'e',
default: false,
description: 'enabel lint javascript',
}),
fix: flags.boolean({
char: 'f',
default: false,
description: 'fix all eslint and stylelint auto-fixable problems',
}),
cwd: flags.string({
char: 'c',
default: process.cwd(),
description: 'current working directory',
}),
format: flags.string({
char: 'F',
default: 'stylish',
description: 'output format of console',
}),
}
export default flagConfig
Console line execution :
$ big-lint --help
You can see the following information , Explain what we set up flags
It works :
testing js(eslint)
USAGE
$ big-lint [DIR]
ARGUMENTS
DIR Specify the path
OPTIONS
-F, --format=format [default: stylish] output format of console
-P, --prettier format code with prettier
-S, --staged only lint git staged files
-c, --cwd=cwd [default: /Users/Documents/big-lint] current working directory
-e, --eslint enabel lint javascript
-f, --fix fix all eslint and stylelint auto-fixable problems
modify src/index.js
Under the run
Method , according to staged
Parameters to determine which logic to follow .
async run() {
const {args, flags} = this.parse(HappyLint)
const {staged, ...rest} = flags
const {dir} = args
if (staged) {
await this.lintStaged(rest)
} else {
await this.lint({...rest, dir})
}
}
Let's take a look at lintStaged
Code for :
async lintStaged(flags: any) {
const {prettier, eslint, fix, format} = flags
getEslintConfig()
let eslintCommon = fix ? `${eslintPath} --fix` : eslintPath
// Add formatted output
if (format !== 'stylish') {
eslintCommon = `${eslintCommon} -f ${format}`
}
const lintstagedrc = {
...(prettier && {
'*.{js,jsx,ts,tsx,less,scss,sass,css}': [
`${prettierPath} --write`,
'git add',
],
}),
...(eslint && {
'*{.js,.jsx,.ts,.tsx}': [
eslintCommon,
'git add',
],
}),
}
const rcPath = join(__dirname, '.lintstagedrc.json')
writeFileSync(rcPath, JSON.stringify(lintstagedrc))
try {
const child = spawn(lintStagedPath, ['-c', rcPath], {stdio: 'inherit'})
child.on('close', (code: any) => {
process.exit(code) // eslint-disable-line
})
} catch (error) {
}
}
getEslintConfig
Method will first judge whether there is a default in the project root path .eslintrc.js
、 .prettierrc
、.editorconfig
The configuration file , If not, a configuration file will be automatically generated by default and placed in the project root directory .
It's used here cross-spawn
To call... Under the project root path node_modules/.bin/lint-staged
Carry out orders , spawn
The second argument to is an array , Pass in the parameters for executing the command , -c
The parameter specifies lint-staged
Ordered Profile path .
spawn
Function returns a child process , When the child process stdio
Triggered when the stream has been closed close
event , We need to monitor this event , because lint-staged
Failed the inspection , We need to implement process.exite(code)
Method to kill the process .
Come here , lintStaged
The logic is over , Now you can test the effect .
Find a test project , stay package.json
The file is configured as follows :
{
"husky": {
"hooks": {
"pre-commit": "big-lint --eslint --staged"
}
},
}
Add... Under this project .eslintrc.js The configuration file , perform git add, git commit -m 'test', If there is eslint Report errors , You can see the following error message .
Next, let's look at lint
Code for :
async lint(flags: any) {
const {dir, cwd, prettier, eslint, fix, format} = flags
if (dir === undefined) {
this.error('please specify a path to lint')
}
// Support multi-path , Separated by commas
let filePath: any
if (dir.split(',').length !== 0) {
filePath = dir.split(',')
} else {
filePath = dir
}
const allFiles = getFiles(filePath, cwd)
try {
if (eslint) {
getEslintConfig()
const eslintExtensions = ['.js', '.jsx', '.ts', '.tsx']
const files = allFiles.filter(item => endsWithArray(item, eslintExtensions))
if (files.length > 0) {
let args = fix ? ['--fix', ...files] : [...files]
args = format !== 'stylish' ? ['-f', format, ...args] : [...args]
spawn.sync(eslintPath, args, {stdio: 'inherit'})
}
}
if (prettier) {
const prettierExtensions = ['.js', '.jsx', '.ts', '.tsx', '.css', '.less', '.scss', '.sass']
const files = allFiles.filter(item =>
endsWithArray(item, prettierExtensions),
)
if (files.length > 0) {
spawn.sync(prettierPath, ['--write', ...files], {stdio: 'inherit'})
}
}
} catch (error) {
this.error(error)
}
}
adopt getFiles
Method to get the data under the specified path node_modules
All under js file , Check the code .
src/utils/utils.ts
export const getFiles = (patterns: any, cwd: any) => {
const result = globby
.sync(patterns, {
gitignore: true,
ignore: ['**/node_modules/**', '.git'],
onlyFiles: true,
dot: true,
})
.map((item: any) => {
// ignore Packages must use relative paths
return path.relative(cwd, item)
})
return ignore()
.add(getIgnores(cwd))
.filter(result)
}
In the test project pacakge.json
The file is configured as follows :
{
"scripts": {
"lint": "big-lint --eslint 'src/'",
"prettier": "big-lint --prettier 'src/'",
"fix": "big-lintpy-lint --eslint --fix 'src/'"
},
}
perform npm run lint command , It can be done to src Code in the directory eslint Rule checking , perform npm run prettier It can be done to src The code in the directory prettier Code beautification , perform npm run fix It can be done to src Automatic code repair of the code under the directory .
Publish your own CLI Tools
Release your own npm package , First of all npm Register one on the official website npm account number , Enter into CLI Directory , perform $ npm login
, Fill in the login information .
modify package.json
In the document keywords
Field , Here you need to fill in the npm
Package keyword information , If you want your npm
If the package is searched and used by more people ,keywords
Fields need to be described as accurately as possible .
name
Fields and version
Field is a required field ,name
Only one , It can't be used by others ,homepage
The field is yours npm
Home page of package , Because of my npm
The package is open source , So here you fill in github
Address .
After the above information is confirmed to be correct , perform $ npm run prepack
command , Re execution npm publish
The order can be done npm
The release of the package .
github Address
copyright notice
author[User 4669777],Please bring the original link to reprint, thank you.
https://en.chowdera.com/2022/131/202205102047501479.html
The sidebar is recommended
- Which securities company does qiniu school recommend? Is it safe to open an account
- Hyperstyle: complete face inversion using hypernetwork
- What activities are supported by the metauniverse to access reality at this stage?
- P2P swap OTC trading on qredo
- Google | coca: the contrast caption generator is the basic image text model
- SIGIR 2022 | Huawei reloop: self correcting training recommendation system
- Whether you want "melon seed face" or "national character face", the "face changing" technology of Zhejiang University video can be done with one click!
- Sorting of naacl2022 prompt related papers
- Servlet create project
- "Chinese version" Musk was overturned by the original: "if it's true, I want to see him"
guess what you like
[network security] web security trends and core defense mechanisms
[intensive reading] object detection series (10) FPN: introducing multi-scale with feature pyramid
007. ISCSI server chap bidirectional authentication configuration
2021-03-09
plot_ Importance multi classification, sorting mismatch, image value not displayed
[intensive reading] object detection series (XI) retinanet: the pinnacle of one stage detector
How to install MFS environment for ECS
[intensive reading] the beginning of object detection series (XII) cornernet: anchor free
Open source sharing -- a record of students passing through time
MOT:A Higher Order Metric for Evaluating Multi-object Tracking
Random recommended
- How to develop a distributed memory database (1)
- Reverse engineers reverse restore app and code, and localization is like this
- One line command teaches you how to export all the libraries in anaconda
- Bi tools are relatively big. Let's see which one is most suitable for you
- Read the history of database development
- Self cultivation of coder - batterymanager design
- Technology application of swift phantom type phantom in Apple source code learning
- Swiftui advanced skills: what is the use of the technology of swift phantom type phantom
- Swiftui advanced animation Encyclopedia of complex deformation animation is based on accelerate and vector arithmetic (tutorial includes source code)
- What problems remain unsolved in swiftui in 2022
- I'll set the route for fluent
- Flutter drawing process analysis and code practice
- Emoji language commonly used icon collection (interesting Emoji)
- 5.14 comprehensive case 2.0 - automatic induction door
- How to deploy redis service on k8s top?
- Importance of data warehouse specification
- Idea automatically generates serialization ID
- Why is it recommended not to use select * in MySQL?
- Let's talk about why redis needs to store two data structures for the same data type?
- Domain lateral move RDP delivery
- gDvuGqjmDS
- [learn slam orb_slam2 or slam3 from scratch] summary of all blog articles
- 20000 + star ultra lightweight OCR system pp-ocrv3 effect increased by 5% - 11%!
- A configurable canvas clock - Super multi style
- The pp-ocrv3 effect of 20000 + star ultra lightweight OCR system is further improved by 5% - 11%
- MySQL's golden rule: "don't use select *"
- True interview question: why does redis store a data type twice?
- High threshold for large factories? Five exclusive PDFs inside Alibaba will take you forward and win the offer
- Is it really hard to find a job? How on earth can I find a job with high salary without worrying about being laid off
- How to design knowledge center? (code attached)
- OWASP top 10 vulnerability analysis
- Are you still writing comment templates manually? Idea can generate annotation templates of classes and methods with one click. Click in if you don't know
- Numpy core syntax and code sorting summary!
- Can you believe that the swoole timer can realize millisecond task scheduling?
- Detailed explanation of art template engine
- Telephone subsystem of openharmony source code analysis -- call flow
- Yixin Huachen: how to do a good job in digital transformation in the power industry?
- One stop collaboration is really delicious - apipost
- Notes on modern algebra and series of questions: Chapter 1 (introduction of algebraic system)
- Notes on modern algebra and serialization of question types: Chapter 2 (properties of binary operation)