JavaScriptNode.jsoclif

oclifでサブコマンドありのCLIコマンドを作る

やりたいこと aws cloudfront list-distributionsみたいな、サブコマンドありのコマンドを作りたい oclifでサブコマンドありのプロジェクトをセットアップする oclifでプロジェクトを作り […]

広告ここから
広告ここまで

やりたいこと

aws cloudfront list-distributionsみたいな、サブコマンドありのコマンドを作りたい

oclifでサブコマンドありのプロジェクトをセットアップする

oclifでプロジェクトを作ります。

$ npx oclif multi test
npx: 429個のパッケージを28.809秒でインストールしました。
(node:31637) ExperimentalWarning: The fs.promises API is experimental

     _-----_     ╭──────────────────────────╮
    |       |    │      Time to build a     │
    |--(o)--|    │  single-command CLI with │
   `---------´   │  oclif! Version: 1.11.4  │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? npm package name test
? command bin name the CLI will export test
? description test cli
? author hideokamoto @hideokamoto
? version 0.1.0
? license (MIT) 
? node version supported >=8.0.0
? github owner of repository (https://github.com/OWNER/repo) hideokamoto
? github name of repository (https://github.com/owner/REPO) test
? optional components to include (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◉ yarn (npm alternative)
 ◉ mocha (testing framework)
 ◉ circleci (continuous integration/delivery service)
 ◉ appveyor (continuous integration/delivery service)
 ◉ codecov (online code coverage report viewer)
 ◉ typescript (static typing for javascript)
 ◉ tslint (static analysis tool for typescript)
(Move up and down to reveal more choices)

ディレクトリ構成

全部盛りだとこんな感じ。

$ tree -L 2 -I node_modules
.
├── README.md
├── appveyor.yml
├── bin
│   ├── run
│   └── run.cmd
├── lib
│   ├── commands
│   ├── index.d.ts
│   └── index.js
├── package.json
├── src
│   ├── commands
│   └── index.ts
├── test
│   ├── commands
│   ├── helpers
│   ├── mocha.opts
│   └── tsconfig.json
├── tsconfig.json
├── tslint.json
└── yarn.lock

実行するとこんな感じに。

$ ./bin/run -h
VERSION
  test/0.0.0 darwin-x64 node-v10.1.0

USAGE
  $ test [COMMAND]

COMMANDS
  hello  describe the command here
  help   display help for test

$ ./bin/run hello
hello world from ./src/commands/hello.ts

コマンド出力をカスタマイズする

デフォルトで生成されているhelloコマンドの出力を変えてみましょう。ファイルはsrc/commands/hello.tsにあります。

import {Command, flags} from '@oclif/command'

export default class Hello extends Command {
  static description = 'describe the command here'

  static examples = [
    `$ test hello
hello world from ./src/hello.ts!
`,
  ]

  static flags = {
    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(Hello)

    const name = flags.name || 'world'
    this.log(`hello ${name} from ./src/commands/hello.ts`)
    if (args.file && flags.force) {
      this.log(`you input --force and --file: ${args.file}`)
    }
  }
}

オプションをカスタマイズする

static flagsで定義されている内容が、オプションとして利用できます。サンプルではname/help/forceが用意されており、-hしてみるとOPTIONSにきちんと出てきます。

$ ./bin/run hello -h
describe the command here

USAGE
  $ test hello [FILE]

OPTIONS
  -f, --force
  -h, --help       show CLI help
  -n, --name=name  name to print

EXAMPLE
  $ test hello
  hello world from ./src/hello.ts!

ここに--dry-run/-dを追加したい場合、以下のようにすればOKです。

  static flags = {
    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'}),
    'dry-run': flags.boolean({char: 'd', description: 'dry run mode'})
  }

async run()では以下のように変更すればOKです。

  async run() {
    const {args, flags} = this.parse(Hello)

    const name = flags.name || 'world'
    this.log(`hello ${name} from ./src/commands/hello.ts`)
    // flags[FLAG_NAME]で判別できる
    if (flags['dry-run']) {
      // ここにdry-run時の処理を書く
      this.log('dry run mode')
    }
    if (args.file && flags.force) {
      this.log(`you input --force and --file: ${args.file}`)
    }
  }

追加されました。

 ./bin/run hello -h
describe the command here

USAGE
  $ test hello [FILE]

OPTIONS
  -d, --dry-run    dry run mode
  -f, --force
  -h, --help       show CLI help
  -n, --name=name  name to print

EXAMPLE
  $ test hello
  hello world from ./src/hello.ts!

$ ./bin/run hello -d
hello world from ./src/commands/hello.ts
dry run mode

サブコマンドを追加する

次は一番やりたかったサブコマンドの追加をやりましょう。aws cloudfront list-distributionslist-distributions部分ですね。これはstatic argsを見ればOKです。

 static args = [{name: 'file'}]

ここを以下のように変えてみましょう。

  static args = [
    {
      name: 'action',
      required: true,
      description: 'list-distributions, get-distribution'
    }
  ]

これだけで反映されます。

$ ./bin/run hello -h
describe the command here

USAGE
  $ test hello ACTION

ARGUMENTS
  ACTION  list-distributions, get-distribution

required: trueとすることで、必須にできます。

$ ./bin/run hello
 ›   Error: Missing 1 required arg:
 ›   action  list-distributions, get-distribution
 ›   See more help with --help

ちなみに配列形式なので、複数登録できます。

// requiredじゃないものを追加する
  static args = [
    {
      name: 'action',
      required: true,
      description: 'list-distributions, get-distribution'
    }, {
      name: 'file'
    }
  ]

requiredかどうかで表記が変わります。

$ ./bin/run hello -h
describe the command here

USAGE
  $ test hello ACTION [FILE]

ARGUMENTS
  ACTION  list-distributions, get-distribution
  FILE

処理部分では以下のように書けばよさそうです。

    const {args, flags} = this.parse(Hello)
    switch (args.action) {
      case 'list-distributions':
        this.log('list distribution!')
        break
      case 'get-distribution':
        this.log('get-distribution!')
        break
      default: {
        this.error('uh oh!!!')
        // exit with status code
        this.exit(1)
      }
    }

許可してないサブコマンドがきた場合はthis.errorthis.exitで終了させましょう。

コマンドを追加する

サブではなくメインのコマンドも追加してみましょう。追加もコマンドから実行できます。

$ npx oclif command world

     _-----_
    |       |    ╭──────────────────────────╮
    |--(o)--|    │ Adding a command to test │
   `---------´   │      Version: 1.11.4     │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

   create src/commands/world.ts
   create test/commands/world.test.ts
replacing <!-- usage --> in README.md
replacing <!-- commands --> in README.md
replacing <!-- toc --> in README.md

$ ./bin/run world -h
describe the command here

USAGE
  $ test world [FILE]

OPTIONS
  -f, --force
  -h, --help       show CLI help
  -n, --name=name  name to print

簡単ですね。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts