Customize NPM command line

Time:2021-11-27

Entry file

  • Custom dependent modules:

    • Module is inpackage.jsonPass inmainField defines the exposed entry of the package;

      • Module originated fromnode, syntax supported by defaultcommonjsstandard
      • Module if usedES ModuleGrammar writing, throughmoduleField definition entry (used with packaging tools)
  • Custom command line:

    • If you are providing command line tools, you need topkg#binField to define the exposed command name and the actually executed file

This article describes the declaration of custom command line. Please check the NPM dependency packageLinks: Custom NPM packages

development environment

  • [] automatic logging
  • [] version update

~Husky6 + is used. The configuration is different from the old version. Please pay attention to the version when following the article~

  1. husky

    • install
     npm install husky --save-dev
     npx husky install
    • to configurerun-script: auto start after dependency installationGit hooks

      "prepare": "husky install"
      • Add test hook

        #UNIX system available
         npx husky add .husky/pre-commit "npm run test"
         #Windows creates a file with the following command (quotation marks are not a standard syntax on the windows command line)
         npx husky add .husky/pre-commit
         #Find the new file under Windows environment, edit the file, and specify the command
         #!/bin/sh
         . "$(dirname "$0")/_/husky.sh"
        
         npm run test
  2. commitlint

    • commitlintSubmit information verification tool

      • It needs to be used in conjunction with the verification specification. The official website defaults to the specification@commitlint/config-conventional——The verification specification can be customized.

         npm i -D commitlint @commitlint/config-conventional
    • commitlintbinding@commitlint/config-conventional

      # Unix
      echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
      # Windows
      echo module.exports = {extends: ['@commitlint/config-conventional']} > commitlint.config.js
    • to configureGit hook: on submissioncommit msgPerform parameter verification——Write inrun-scriptInvalid in

      #UNIX system available
       npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
       #Windows creates a file with the following command (quotation marks are not a standard syntax in the windows environment)
       npx husky add .husky/commit-msg
       #Find the new file under Windows environment, edit the file, and specify the command
       #!/bin/sh
       . "$(dirname "$0")/_/husky.sh"
      
       npx --no-install commitlint --edit $1
  3. standard-version

    • Installation dependency
     npm i --save-dev standard-version
    • to configurerun-scriptGit auto upgrade version number before publishing + generate log + submit:

      "prepublishOnly": "standard-version && git push --follow-tags origin master"

      Note:Don’t use it hereprepublishHook, where is the hooknpm iRuntime, notnpm publishRun at.

debugging

  1. Enter localNPMpackage

    • npm linkCreate soft link to globalnodeIn the environment
  2. Enter project a that needs to import dependent packages

    • npm link <packageName>Establish soft link dependency
  3. Switch to project a directory structure on the command line

    #Call
    npx <packageName> -h

development

NPMPackage iscommonJSSyntax, usingrequire(), notimport...from...Introduce dependencies.

And, ifNPMPackage syntax usageES6+Grammar writing, must useES Moduleofimportexport defaultExport method, do not mix

Several common command line aids are recommended:

  • shelljs

    • Execute script program
    • Shelljs cannot execute interactive commands and will lose interactivity. Interactive commands are still recommendedchild_process
    • Shelljs executes the output of the command to lose color visualization, which can be realized throughRelated solutions
  • inquirer

    • Command line user interface
  • chalk

    • Command line log style
    • Nested and chainable
  • commander

    • Custom command line parameters

organization structure

|- .husky
|- bin
  |-Actv2-use.js // single file command
  |-Actv2.js // the entry file is only used for transit
|- lib
  |-Actv2.js // main file
|- .gitignore
|- .npmrc
|- package.json
|- README.md

package.jsonto configure

{
  "name": "actv2",
  "version": "1.0.0",
  "description": "",
  "bin": "bin/actv2.js",
  "main": "lib/actv2.js",
  "scripts": {
    "prepare": "npx husky install",
    "prepublishOnly": "standard-version && git push --follow-tags origin master",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@commitlint/config-conventional": "^13.2.0",
    "commitlint": "^13.2.1",
    "husky": "^7.0.2",
    "standard-version": "^9.3.1"
  },
  "dependencies": {
    "chalk": "^4.1.2",
    "commander": "^8.2.0",
    "fs-extra": "^10.0.0",
    "inquirer": "^8.2.0",
    "shelljs": "^0.8.4"
  }
}

Entry file

Example of entry file:

#!/usr/bin/env node
var { program } = require('commander')

program
.command('add')
. argument ('< module >', 'new project module')
. option ('- y, -- yes',' set this module as deployment module ')
.action((moduleName, options) => {
  require('..')().add(moduleName, options)
})

program
. command ('use < module > ',' specify deployment module ')
.alias('u')

program
  . option ('- V, -- version', 'view version')
  . helpoption ('- H, -- help', 'view help');


program.parse(process.argv)

var opts = program.opts()

if (opts.version) {
  process.stdout.write(
    'actv2 ' + require('../package.json').version + '\n')
} else {
  process.stdout.write(
    'actv2\n' +
    '\n' +
    'Options:\n' +
    '  --version Show version number\n' +
    '  --help    Show help\n' +
    '\n' +
    'Usage:\n' +
    '  actv2 --help\n'
  )
}

Among them,#!/usr/bin/env nodeIs a required line, which is specified after installing the command linenodeThe environment executes the command line.

#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
  "$basedir/node"  "$basedir/../actv2/bin/actv2.js" "[email protected]"
  ret=$?
else
  node  "$basedir/../actv2/bin/actv2.js" "[email protected]"
  ret=$?
fi
exit $ret

Vs. missing#!/usr/bin/env node

#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac

"$basedir/../actv2/lib/run.js"   "[email protected]"
exit $?

Parameter analysis

With the help ofcommanderThird party Toolkit

  1. statement

    Program. Option ('') // optional parameters
      Program. Requiredoption() // required parameter
      program.requiredOption('-c, --cheese <type>', 'pizza must have cheese'); // < Type > value is required, and [type] value is optional
  2. analysis

     program.parse(process.argv)
  3. Value

     program.opts().name
     program.getOptionValue(<name>)

Subcommand

With the help ofcommanderThird party Toolkit

Declaration method

  • bindingactionofcommandstatement

    • commandStatement as long asOne parameter

      //Example
      program
      . command ('clone < source > [destination] '// the first line has only one parameter
      .description('clone a repository into a newly created directory')
      .option('-y, --yes', 'options.yes')
      .action((source, destination, options, command) => {
      console.log('clone command called');
      });
  • Separate executable

    • commandAdding a description parameter to the declaration indicates the declaration method of the executable file

      #The file that outputs the following code is the entry file
      program
      .version('0.1.0')
      . command ('install [name],'install one or more packages') // in the directory where the entry file is located, retrieve the ` < entry file name > - install ` file
      . command ('search [query] ','search with optional query'). Alise ('s') // in the directory where the entry file is located, retrieve the ` < entry file name > - Search ` file
      .command('update', 'update installed packages', { executableFile: 'myUpdateSubCommand' })
      .command('list', 'list packages installed', { isDefault: true });

      Complete example of stand-alone execution file:

      //Statement
      program
      .command('use <module>', 'assign module')
      .alias('u')

      useCommand definition

      #!/usr/bin/env node
      var chalk = require('chalk');
      var { program } = require('commander');
      var Message = require('../config/messages')
      var createdFile = require('../utils/createFile')
      
      Program. Option ('- V, -- version [version]','specify version number ','0.0.3') // NPX < commander name > use < modulename > - V 0.0.1
      program.parse(process.argv)
      
      Var modulename = program. Args // get the < modulename... > List
      var { version } = program.opts()
      
      if (moduleName.length !== 1) {
      process.stdout.write(chalk.redBright(Message.deployOnly) + '\n')
      process.exitCode = 0
      } else {
      //
      }

implement

> npx actv2 -h
Usage: actv2 [options] [command]

Options:
  -5. -- version view version
  -h. -- help view and use help

Commands:
  add [options] <module>
  Use|u < module > specifies the deployment module
  help [command]          display help for command
> npx actv2 add -h
Usage: actv2 add [options] <module>

Arguments:
  Module add project module

Options:
  -y. -- yes set the module as the deployment module
  -h, --help  display help for command