7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

npmのCLIパッケージを作成する

Last updated at Posted at 2022-01-07

初めてnpmのCLIパッケージを作成してみました。

コマンドライン引数の受け取りやプロンプトの表示など、難しそうなイメージだった部分も、ライブラリを使うことで手軽に実装できたので、それらを紹介したいと思います。

作成したパッケージ

利用しなくなったプロジェクトの node_modulesdist フォルダを探して削除するための clean-node-projects というパッケージを作成しました。

npx clean-node-projects とすることで、そのパスの配下のフォルダが検索され、どれを削除するか選ぶことができます。
clean-node-projects_demo.gif

CLIパッケージの基本

コマンドラインから呼び出すアプリを作るためには、

まず package.jsonbin という項目に、 { コマンド名: 実行ファイルパス } を記載します。

  ...
  "bin": {
    "test-cli": "./bin/test-cli"
  },

実行ファイルは、ファイル名を指定するだけで実行できるように、nodeのシェバンを書きます。

bin/test-cli
#!/usr/bin/env node

console.log('Hello world');

このパッケージをnpmに公開すれば、 test-cli を実行することで Hello world と表示されるアプリができます。

便利なライブラリ

yargs

yargsは、受け取ったコマンドライン引数を使いやすい形に整えたり、かっこいいヘルプメッセージを生成してくれるライブラリです。

bin/test-cli
#!/usr/bin/env node

const yargs = require('yargs');

const slicedArgs = process.argv.slice(2); // 最初の2つは受け取った引数ではないので除外
const argv = yargs(slicedArgs)
  .option('option-a', {
    alias: 'a',
    description: 'オプションA',
    type: 'number'
  })
  .option('option-b', {
    alias: 'b',
    description: 'オプションB',
    type: 'array',
    default: ['foo', 'bar']
  })
  .help().argv;

console.log(argv.a);
console.log(argv.b);

上記のファイルを test-cli --help のように実行すると以下のようなメッセージが表示されます。

オプション:
      --version   バージョンを表示                                        [真偽]
  -a, --option-a  オプションA                                            [数値]
  -b, --option-b  オプションB                  [配列] [デフォルト: ["foo","bar"]]
      --help      ヘルプを表示                                            [真偽]

test-cli -a 100 のように実行すると、指定した型で値を取得できることがわかります。

console.log(argv.a); // => 100
console.log(argv.b); // => [ 'foo', 'bar' ] (デフォルト値)

inquirer

inquirerは、対話型のインターフェースを簡単に実装できるライブラリです。

チェックボックス選択式の例

bin/test-cli
#!/usr/bin/env node

const inquirer = require('inquirer');

const prompt = async () => {
  const result = await inquirer.prompt({
    type: 'checkbox',
    name: 'folders',
    message: 'Select folders to remove',
    choices: ['aaa/bbb/ccc', 'aaa/bbb/ddd', 'aaa/bbb/eee', 'fff/ggg/hhh']
  });

  console.log(result.folders);
};

prompt();

上記を実行すると、以下のようにスペースで選択したり a で全選択したりできる入力受付状態になります。
スクリーンショット 2022-01-07 22.14.00.png

console.log(result.folders); // => [ 'aaa/bbb/ccc', 'aaa/bbb/ddd' ]

columnify

columnifyは、データを列を揃えて見やすく表示するためのライブラリです。

bin/test-cli
#!/usr/bin/env node

const columnify = require('columnify');

const result = columnify([
  { path: '/aaa/bbb/ccc', 'last access': '2022/01/01', size: '20MB'},
  { path: '/aaa/bbb/ddd', 'last access': '2022/01/03', size: '40MB'},
  { path: '/aaa/bbb/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'last access': '2022/01/07', size: '90MB'}
], { maxWidth: 40 });

console.log(result);

実行結果

PATH                                     LAST ACCESS SIZE
/aaa/bbb/ccc                             2022/01/01  20MB
/aaa/bbb/ddd                             2022/01/03  40MB
/aaa/bbb/eeeeeeeeeeeeeeeeeeeeeeeeeeeeee… 2022/01/07  90MB
eeeee                                                    

結果は文字列で得られるので、inquirerと組み合わせて綺麗に表示する際は色々工夫が必要でした。

感想

素晴らしいライブラリの製作者の方々に感謝です。

もしよければ clean-node-projects も使ってみていただけると嬉しいです。

今後モチベーションが続けば、ちゃんとテストを書いて、ファイル読み込みを並列に実行するなど、改善できたら良いなと思っています。

参考

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?