npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

aaron-cli-demo

v1.0.2

Published

### npm cli , shell 命令 demo

Downloads

5

Readme

创建自己的 node cli

npm cli , shell 命令 demo

第一步是利用 npm init 创建一个 npm 项目。创建的package.json文件如下:

{
  "name": "aaron-cli-demo",
  "version": "1.0.0",
  "description": "node cli demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "npm",
    "node",
    "cli",
    "demo"
  ],
  "author": "aaronflower",
  "license": "ISC"
}

下一步,我们需要写一个 js 脚本文件,根据默认约定命令为 index.js 脚本。

#!/usr/bin/env node
console.log('Hello world, node cli demo')

文件中第一行加上#!释伴(Shebang) 是指名用那个解释程序来执行脚本。

接下来,我们需要在package.json文件中添加一个 bin section,key 值是触发脚本执行的命令, value 是相对于 package.json 文件目录的执行文件。

diff --git a/package.json b/package.json
index 251dd01..9463c11 100644
--- a/package.json
+++ b/package.json
@@ -13,5 +13,8 @@
     "demo"
   ],
   "author": "aaronflower",
-  "license": "ISC"
+  "license": "ISC",
+  "bin": {
+    "aaron-cli": "./index.js"
+  }
 }

现在我们就可以全局安装并测试它了。

$ npm i -g
$ aaron-cli
Hello world, node cli demo

大功告成!

注意: npm install -g 实际上是把脚本软链到 node 的全局 bin 目录下。

$ which aaron-cli
/Users/easonzhan/.nvm/versions/node/v7.5.0/bin/aaron-cli
$ readlink $(which aaron-cli)
../lib/node_modules/aaron-cli-demo/index.js

在开发过程中为了方便可以使用 npm link命令直接链接到我们的开发环境的入口文件。

$ npm link
npm WARN [email protected] No repository field.
/Users/easonzhan/.nvm/versions/node/v7.5.0/bin/aaron-cli -> /Users/easonzhan/.nvm/versions/node/v7.5.0/lib/node_modules/cli-demo/index.js
/Users/easonzhan/.nvm/versions/node/v7.5.0/lib/node_modules/cli-demo -> /Users/easonzhan/learning/git_repos/node_/npm-aaronflower

可以看出全局的cli-demo已经是链接的我们的开发目录了。

diff --git a/index.js b/index.js
old mode 100644
new mode 100755
index e69de29..55493da
--- a/index.js
+++ b/index.js
@@ -0,0 +1,3 @@
+#!/usr/bin/env node
+console.log('Hello world, node cli demo')
+console.log('use npm link when developing your npm projet')

经过npm link后在命令中执行aaron-cli会直接看到更新。

$ aaron-cli
Hello world, node cli demo
use npm link when developing your npm projet

当脚本都开发完成后,就可以用npm publish把我们的脚本发布到 npm 库上了。然后大家就可以通过 npm 安装使用我们开发的脚本了。

$ npm i -g aaron-cli-demo
# 发布
$ npm adduser # 省略,默认版本是 1.0.0 中的 package.json 中的版本。
$ npm publish # 如果,package.json 中的 description 是空的话,将会用 README.md 来当作描述。
$ npm i -g cli-demo

引入命令行参数解析

对执行脚本时的命令行参数解析,我们可以使用一个很方便的 commander。下面为我们的主程序加上参数解析功能:

|  #!/usr/bin/env node
| -console.log('Hello world, node cli demo')
| -console.log('use npm link when developing your npm projet')
| +var program = require('commander')
| +program
| +     .arguments('<file>')
| +     .option('-u, --username <username>', 'The user to authenticate to')
| +     .option('-p, --password <password>', 'The user\'s password')
| +     .action(function (file) {
| +             console.log('user: %s, password: %s, file: %s', program.username, program.password, file)
| +     })
| +     .parse(process.argv)

接下来我们可发布我们的 cli-demo 啦。一个新的版本。

~/learning/git_repos/node_/npm-aaronflower on  master! ⌚ 23:27:06
$ npm version patch
v1.0.1

~/learning/git_repos/node_/npm-aaronflower on  master! ⌚ 23:28:26
$ npm publish
+ [email protected]

测试, commander会自动为我们生成 -h, --help 参数哟。

~/learning/git_repos/node_/npm-aaronflower on  master! ⌚ 23:39:07
$ aaron-cli -u aaron --password flower cli-demo-parse.js
user: aaron, password: flower, file: cli-demo-parse.js

~/learning/git_repos/node_/npm-aaronflower on  master! ⌚ 23:39:59
$ aaron-cli -h

  Usage: aaron-cli [options] <file>

  Options:

    -h, --help                 output usage information
    -u, --username <username>  The user to authenticate to
    -p, --password <password>  The user's password

处理用户输入

有些时间脚本也支持用户输入,我们可以使用 process.stdin来处理。但是co-prompt库更加方便使用,co-prompt 是基于 co 来实现的,这样我们就可以使用 ES6 的 yield 语法了。

npm i -S co co-prompt

更新我们的脚本程序:

@@ -1,10 +1,23 @@
-#!/usr/bin/env node
+#!/usr/bin/env node --harmony
+var co = require('co')
+var prompt = require('co-prompt')
 var program = require('commander')
+
 program
        .arguments('<file>')
        .option('-u, --username <username>', 'The user to authenticate to')
        .option('-p, --password <password>', 'The user\'s password')
        .action(function (file) {
-               console.log('user: %s, password: %s, file: %s', program.username, program.password, file)
+               co(function* () {
+                       let username = program.username
+                       let password = program.password
+                       if (!username) {
+                               username = yield prompt('username: ')
+                       }
+                       if (!password) {
+                               password = yield prompt.password('password: ')
+                       }
+                       console.log('user: %s, password: %s, file: %s', username, password, file)
+               })
        })
        .parse(process.argv)

测试,现在我们的命令行参数即支持指定又支持输入了。

~/learning/git_repos/node_/npm-aaronflower on  master! ⌚ 0:08:15
$ aaron-cli -u aaron -p flower foo.js
user: aaron, password: flower, file: foo.js

~/learning/git_repos/node_/npm-aaronflower on  master! ⌚ 0:11:44
$ aaron-cli -u aaron  foo.js
password: *************
user: aaron, password: yesmypassowrd, file: foo.js

~/learning/git_repos/node_/npm-aaronflower on  master! ⌚ 0:11:58
$ aaron-cli  foo.js
username: aaaronflower
password: ******
user: aaaronflower, password: kdiggg, file: foo.js

Links

Building command line tools with Node.js