🗂
Zod でコマンドライン引数をパースするだけのツールを作った
自分が欲しい物がなかったのでサクッとでっち上げました
なぜ作ったか
- 軽量で TS フレンドリな CLI ツールがほしい
-
oclif がサブコマンドまで管理してくれるが色々と過剰
- ジェネレータの生成コードが最新バージョンのものではなく怪しい(メンテされてる?)
- tsconfig の縛りがあったり、他のライブラリの一部に混ぜづらい
- type: module で実行できない (手元にESM生成物があった)
-
cmd-ts が使いづらい
- 単なるバリデータではなく実行 handler まで渡さないといけない
- これ以上ライブラリ専用の DSL を覚えたくない
- => 引数パースを突っ込むだけの zod のラッパーでいいじゃん
使い方
$ npm install --save zodiarg zod
// npx ts-node examples/sample.ts --name mizchi --age 34 --dry xxx 1
import { z } from "zod";
import { asNumberString, asBooleanString, parse } from "zodiarg";
const parsed = parse(
{
// --key value | --key=value
options: {
name: z.string().describe("input your name"),
env: z.enum(['a', 'b']).describe("env"),
age: asNumberString.default('1').describe("xxx"), // parse as number
active: asBooleanString.default('false') // parse as boolean
},
// --flagA, --flagB
flags: {
dry: z.boolean().default(false),
shortable: z.boolean().default(false).describe("shortable example"),
},
// ... positional args: miz 10
args: [
z.string().describe("input your first name"),
z.string().regex(/^\d+$/).transform(Number)
],
// alias map: s => shortable
alias: {
s: 'shortable',
}
},
process.argv.slice(2),
// Options(default)
// { help: true, helpWithNoArgs: true }
);
type ParsedInput = typeof parsed; // Inferenced by Zod
main(parsed).catch((err) => {
console.error(err);
process.exit(1);
});
async function main(input: ParsedInput) {
console.log('Parsed Input', input);
}
実行
$ npx ts-node examples/sample.ts --name mizchi --age 34 --dry xxx 1 -s --env a
Parsed Input {
flags: { dry: true, shortable: true },
options: { name: 'mizchi', env: 'a', age: 34 },
args: [ 'xxx', 1 ]
}
-h
や --help
があるとヘルプを実行します
$ npx ts-node examples/sample.ts -h
OPTIONS:
--name <string> input your name
--env <enum: [a] [b]> env
--age (Optional: 1) xxx
FLAGS:
--dry
--shortable, -s shortable example
ARGS:
0 input your first name
1
便利な点
- zod の enum や正規表現で入力を表現できる
- 引数パース以外余計なことをしない | 実行側に要求しない(これが自分にとって一番大事)
- 簡単な help を自動生成
使ってみてください。 help の生成は雑です。
Discussion