🗂️

TypeScriptでCLIツールを作りたい人のためのnpmプロジェクト

に公開

対象読者

  • TypeScriptを使い慣れている
  • ウェブアプリばかり書いている。コマンドラインツールも書きたい
  • 個人的なツールをどこに置けばいいかわからずに ~/bin とかに置いている

個人的なスクリプトをどこに置くか

適当にシェルスクリプトを書いて ~/bin に置いている、これは自分の話です。あれはメンテしづらい。やめたほうがいい。

最近は別の方法でCLIツールを配置している。結論から言うと、ご自分のホームにプロジェクト一覧みたいなフォルダがあると思いますが、あそこに新しいCLIコマンド用のプロジェクトフォルダを作成する。そこに置く。

$ tree ~
myProjects
├── project1
├── project2
└── project3
$ mkdir myProjects/my-utils

パッケージの作り方

npm パッケージをインストールするとコマンドが使えるのをご存知でしょう。あれを使う。インストールは面倒だからしたくない。まったくです。実はインストールはする必要がない。npm linkすればシステムのどこからでもそのプロジェクトのスクリプトを直接実行できる。

ここではtsxでTypeScriptのスクリプトを直接実行している。ビルドとか面倒なのでしない。工程は少ないのが正義。

$ cd myProjects/my-utils
$ hx package.json
$ cat package.json
{
  "name": "my-utils",
  "version": "1.0.0",
  "bin": {
    "mytool": "./cli.js"
  }
}
$ cat ./cli.js
#!/usr/bin/env tsx
console.log('Hello world!)
$ chmod +x ./cli.js
$ npm link
$ mytool
Hello world!
$ ls -l $(realpath $(which  mytool))
-rwxr-xr-x 1 my-name staff 48  4  9 17:03 /Users/my-name/myProjects/myutils/cli.js
# プロジェクト内のファイルを直接実行できるようになっている

そのフォルダを消したくなったらどうするか? 言われる前にGitHub管理しているはずなので、そこからインストールする。

$ cd ~/myProjects/my-utils
$ npm unlink -g my-utils
$ which mytool
$ npm install -g git+https://github.com/my-name/my-utils.git
$ mytool
Hello world!

これでインストールできるから、ローカルフォルダはいつでも消せる。

メンテしたくなったら一度npm uninstall -gしたあと、cloneしてまた npm linkすれば以前の状態に戻る。

npm uninstall -g my-utils
gh repo clone my-name/my-utils
cd my-utils
npm link

ここまでのフォルダ構成

最小構成のフォルダ構成はこう

myProjects
├── myutils
│   ├── cli.js
│   ├── package-lock.json
│   └── package.json

Q&A

  • package.jsonmainいらないんですか?
    • いらないです。あれはこのパッケージがimportされたときにどのファイルを読み込むかを指定するものです。このパッケージはimportされないので不要
  • authors, repository, homepageとかは
    • 警告が鬱陶しければ書いてください

直近で作ったCLIツールのフォルダ構成

Google Sheet のデータを読んで Google Calendar に書くツールを書いた。それのフォルダ構成はこうなった。

tsxで動く。でもバンドルしても動くかどうか実験してみたかった。動いた。

my-tool-latest
├── README.md
├── package.json                    # binにmtl(./bin/index.ts), my-tool-latest(./dist/index.js)
├── pnpm-lock.yaml
├── bin
│   ├── index.ts                    # tsx直接実行のエントリポイント、src/index.tsをimport
│   └── my-tool-latest.js           # バンドル実行のエントリポイント、dist/index.jsをimport
├── src                             # ✍🏻TypeScriptソース置き場 ここが作業場
│   ├── index.ts                    # 実質のエントリポイント
│   ├── consola.ts
│   ├── fetchSpreadsheet.ts
│   ├── getFlatEvents.ts
│   └── registerEvents.ts
├── dist                            # バンドルファイル置き場
│   └── index.js
├── .env                            # 環境変数設定
├── .gitignore
├── .prettierrc
├── .vscode
│   └── tasks.json
├── client_secret_5xxxxxxxx8-vxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com.json # Googleサービスにアクセスするためのキー的なやつ
└── tsup.config.ts

おわりに

npmのコマンドインストール機能ステキ。brewのFormulaとはおさらばだ。

Discussion