🔁

Valibot の v0.31.0 への Migration 対応をした。

2024/09/25に公開

まだまだ Zod を採用しているプロダクトが多い。

が、
Finswer では、Schema Validation ライブラリに Zod ではなく、Valibot を採用している。

https://github.com/fabian-hiller/valibot

Migration to 0.31.0

https://valibot.dev/guides/migrate-to-v0.31.0/

Migrating Valibot from an older version to v0.31.0 isn't complicated. Except for the new pipe method, most things remain the same. The following guide will help you to migrate automatically or manually step by step and also point out important differences.

Migration コマンドを実行すればすぐ終わるよ。
と記載があったがそうではなかったため、備忘録として記載しておきます。
(実際は、今後私が v0.31.0 への対応をすることはないのですが。)

Automatic Migration

Guide にもある通り

npx codemod valibot/migrate-to-v0.31.0

こちらのコマンドで以下の変更については、対応してくれます。

  • Input/OutputInferInput/InferOutput
  • v.string([v.uuid()])v.pipe(v.string(), v.uuid())

この変更はさっくりと CLI で対応してもらえたので、
あまり問題がなかったです。

Input/OutputInferInput/InferOutput

命名が変更されただけなので、parser も書きやす立ったのだろう。対応してくれた。

一部発生した問題(理由は謎)
const FormSchema = v.object({
    name: v.string(),
    age: v.number(),
})
type FormInput = Input<typeof FormSchema>

を Migration した際に、一部

const FormSchema = v.object({
    name: v.string(),
    age: v.number(),
})
- type FormInput = Input<typeof FormSchema>
+ type InferInput = InferInput<typeof FormSchema>

となってしまったケースが何件かあった。

詳細に記憶してなくて申し訳ないが、
おそらく Input suffix が悪さをしていたんじゃないかと思われます。

v.string([v.uuid()])v.pipe(v.string(), v.uuid())

他には

- v.number([minValue(10, '10以上にして'), '数字にして'])
+ v.pipe(v.number('数字にして'), v.minValue('10以上にして'))

この変更は、ErrorMessage がどこにあたっているのか?というのが直感的になったように感じます。

Manual Migration

以降は、 CLI での Migration ができなく、
かつ実際に遭遇したもののみを紹介します。

transform の syntax 変更

これはかなり直感的になったので嬉しかったです。
が、かなり使っている箇所が多く、 Migration がかなり辛かったです。

Migration ガイドにもある通り、

- const TransformedSchema = v.transform(v.string(), (input) => input.length);
+ const TransformedSchema = v.pipe(
+   v.string(),
+   v.transform((input) => input.length)
+ );

これもかなりよみやすく、書きやすくった印象です。
v.string() もそれ単体で使うのではなく、他の Validation のルールと併用することが多いため、
v.pipe() をいちいちつけなければならないのか。」というネガティブなイメージもなかったです。

coerce の廃止

同様にこちらも利用頻度が多く辛かったです。
また、 transform へ書き直す必要がありました。

The coerce method has been removed because we felt it was an insecure API. In most cases, you don't want to coerce an unknown input into a specific data typed

まあわかる。

困ったのは、過去の人が書いた Schema で coerce が使われてるパターンである。
「なぜか String にも Number にも対応しなきゃいけない。」みたいなことになっていたりする時がある。

Component から修正をしても良いのだが、
それをすると、それをすると PR のコンテキスト的にやや違和感がある。

そこでは、以下のように対応した

- v.coerce(
-   v.number(),
-   (input) => Number(input)
- );
+ v.pipe(
+   v.union([v.number(), v.string()]),
+   transfer((input) => Number(input))
+ );

確かに、入力される型がわからないなんてことは基本的にないなあ。と思いながら対応した。

所管

すでに膨れた Project で transform などをたくさん使っていたりすると、正直疲れはするが、
かなり読みやすくなった気がする。

読みやすくなったのは、構文的に読みやすくなったのもあるが、
真剣にドキュメントを読んだから単純に理解して読めるようになっただけかもしれない。

結局ドキュメントを読んで手を動かすのが最も早く理解できるのだなと感じた対応でした。

GitHubで編集を提案

Discussion