created: 2022-07-04T03:25:00.010Z

class-validatorとclass-transformerを使ってコマンドラインオプションを受け取る

nodejsのコマンドラインパーサーは色々あるが、class-validatorclass-transformer を使ってパースしてみたら、新しく既存のコマンドラインパーサーを使うよりも覚えることも少なくて型安全に引数が受け取れてよかった。

受け取る引数をこんな感じでクラス定義する。

import { IsOptional, IsBoolean, IsString } from "class-validator";

export class Option {
  @IsOptional()
  @IsString()
  tableNamePattern?: string;

  @IsOptional()
  @IsBoolean()
  dryrun?: boolean;
  
  // メソッドもかける
  isToIgnore() {
    ....
  }
}

実装

パースする処理も20行ほどで済む。

import { plainToClass, ClassConstructor } from "class-transformer";
import { validateSync } from "class-validator";
import { camelCase } from "change-case"
import { formatErrors } from './utility';

export const loadOption = <T>(Cls: ClassConstructor<T>, v: unknown) => {
  const obj = plainToClass(Cls, v);
  const errors = validateSync(obj as any);
  if (errors.length) {
    throw OptionError(formatErrors("Faliled to load options.", errors));
  } else {
    return obj as T;
  }
};

export const parseArgs = (argv: string[]) => {
  const entry = [];
  for (const opt of argv) {
    const [, name, param] = opt.match(/--([\w-]+)=(\S+)/) || [];
    if (name?.length && param?.length) {
      entry.push([camelCase(name), param]);
      continue
    }
    const [, flag] = opt.match(/--([\w-]+)/) || [];
    if (flag?.length) {
      entry.push([camelCase(flag), true]);
      continue
    }
  }
  return Object.fromEntries(entry);
};


export class OptionError extends Error {};
会計クイズを解くだけで財務3表がわかる 世界一楽しい決算書の読み方
[ad] 会計クイズを解くだけで財務3表がわかる 世界一楽しい決算書の読み方
大手町のランダムウォーカー, わかる (Kindle版)