valibot
Valibotを使ったスキーマバリデーションを支援します。データの検証やスキーマの作成、入力のパース、またはZodからValibotへの移行が必要な場合に活用してください。モジュール型かつ型安全なスキーマライブラリであるValibotをプロジェクトで効果的に利用できます。
description の原文を見る
Schema validation with Valibot, the modular and type-safe schema library. Use when the user needs to validate data, create schemas, parse inputs, or work with Valibot in their project. Also use when migrating from Zod to Valibot.
SKILL.md 本文
Valibot
このスキルは、構造化データの検証用モジュール型でタイプセーフなスキーマライブラリである Valibot を効果的に操作するのに役立ちます。
このスキルを使用する場合
- ユーザーがValibotでのスキーマ検証について質問する場合
- Valibotスキーマを作成または変更する場合
- ユーザー入力を解析または検証する場合
- ユーザーがValibot、スキーマ、または検証について言及する場合
- ZodからValibotへの移行時
重要: Valibot と Zod - 混同しないこと!
ValiboとZodのAPIは異なります。決して混同しないでください!
主な違い
| 機能 | Zod ❌ | Valibot ✅ |
|---|---|---|
| インポート | import { z } from 'zod' | import * as v from 'valibot' |
| バリデーション | チェーンメソッド: .email().min(5) | パイプライン: v.pipe(v.string(), v.email(), v.minLength(5)) |
| パース | schema.parse(data) | v.parse(schema, data) |
| 安全なパース | schema.safeParse(data) | v.safeParse(schema, data) |
| オプション | z.string().optional() | v.optional(v.string()) |
| Nullable | z.string().nullable() | v.nullable(v.string()) |
| デフォルト値 | z.string().default('x') | v.optional(v.string(), 'x') |
| 変換 | z.string().transform(fn) | v.pipe(v.string(), v.transform(fn)) |
| Refine/Check | z.string().refine(fn) | v.pipe(v.string(), v.check(fn)) |
| Enum | z.enum(['a', 'b']) | v.picklist(['a', 'b']) |
| ネイティブenum | z.nativeEnum(MyEnum) | v.enum(MyEnum) |
| Union | z.union([a, b]) | v.union([a, b]) |
| 判別union | z.discriminatedUnion('type', [...]) | v.variant('type', [...]) |
| Intersection | z.intersection(a, b) | v.intersect([a, b]) |
| Min/max長 | .min(5).max(10) | v.minLength(5), v.maxLength(10) |
| Min/max値 | .gte(5).lte(10) | v.minValue(5), v.maxValue(10) |
| 型推論 | z.infer<typeof Schema> | v.InferOutput<typeof Schema> |
| 入力推論 | z.input<typeof Schema> | v.InferInput<typeof Schema> |
避けるべき一般的な間違い
// ❌ 間違い - これはZodの構文で、Valibotではありません!
const Schema = v.string().email().min(5);
const result = Schema.parse(data);
// ✅ 正しい - Valibotは関数とパイプラインを使用します
const Schema = v.pipe(v.string(), v.email(), v.minLength(5));
const result = v.parse(Schema, data);
// ❌ 間違い - Zodスタイルのオプション
const Schema = v.object({
name: v.string().optional(),
});
// ✅ 正しい - Valibotはoptional()でラップします
const Schema = v.object({
name: v.optional(v.string()),
});
// ❌ 間違い - Zodスタイルのデフォルト値
const Schema = v.string().default("hello");
// ✅ 正しい - Valibotは第2引数を使用します
const Schema = v.optional(v.string(), "hello");
インストール
npm install valibot # npm
yarn add valibot # yarn
pnpm add valibot # pnpm
bun add valibot # bun
ワイルドカードでインポート(推奨):
import * as v from "valibot";
または個別インポート:
import { object, string, pipe, email, parse } from "valibot";
メンタルモデル
ValibotのAPIは3つの主要な概念に分かれています:
1. スキーマ
スキーマは期待されるデータ型を定義します。これは出発点です。
import * as v from "valibot";
// プリミティブスキーマ
const StringSchema = v.string();
const NumberSchema = v.number();
const BooleanSchema = v.boolean();
const DateSchema = v.date();
// 複雑なスキーマ
const ArraySchema = v.array(v.string());
const ObjectSchema = v.object({
name: v.string(),
age: v.number(),
});
2. メソッド
メソッドはスキーマの使用または変更を支援します。スキーマは常に最初の引数です。
// パース
const result = v.parse(StringSchema, "hello");
const safeResult = v.safeParse(StringSchema, "hello");
// 型ガード
if (v.is(StringSchema, data)) {
// dataはstringとして型付けされます
}
3. アクション
アクションは pipe() 内のデータを検証または変換します。パイプライン内でのみ使用できます。
// アクションはpipe()内で使用されます
const EmailSchema = v.pipe(
v.string(),
v.trim(),
v.email(),
v.endsWith("@example.com"),
);
パイプライン
パイプラインはスキーマを検証と変換のアクションで拡張します。パイプラインは常にスキーマで始まり、その後にアクションが続きます。
import * as v from "valibot";
const UsernameSchema = v.pipe(
v.string(),
v.trim(),
v.minLength(3, "ユーザー名は少なくとも3文字である必要があります"),
v.maxLength(20, "ユーザー名は最大20文字である必要があります"),
v.regex(
/^[a-z0-9_]+$/i,
"ユーザー名には文字、数字、アンダースコアのみを含めることができます",
),
);
const AgeSchema = v.pipe(
v.number(),
v.integer("年齢は整数である必要があります"),
v.minValue(0, "年齢は負の値にはできません"),
v.maxValue(150, "年齢は150を超えることはできません"),
);
一般的なバリデーションアクション
文字列の検証:
v.email()— 有効なメールアドレス形式v.url()— 有効なURL形式v.uuid()— 有効なUUID形式v.regex(pattern)— 正規表現パターンにマッチv.minLength(n)— 最小長v.maxLength(n)— 最大長v.length(n)— 正確な長さv.nonEmpty()— 空でない文字列v.startsWith(str)— 文字列で始まるv.endsWith(str)— 文字列で終わるv.includes(str)— 文字列を含む
数値の検証:
v.minValue(n)— 最小値 (>=)v.maxValue(n)— 最大値 (<=)v.gtValue(n)— より大きい (>)v.ltValue(n)— より小さい (<)v.integer()— 整数である必要がありますv.finite()— 有限である必要がありますv.safeInteger()— 安全な整数範囲v.multipleOf(n)— nの倍数である必要があります
配列の検証:
v.minLength(n)— 最小項目数v.maxLength(n)— 最大項目数v.length(n)— 正確な項目数v.nonEmpty()— 少なくとも1項目v.includes(item)— 項目を含むv.excludes(item)— 項目を含まない
check() による カスタム検証
const PasswordSchema = v.pipe(
v.string(),
v.minLength(8),
v.check(
(input) => /[A-Z]/.test(input),
"パスワードは大文字を含む必要があります",
),
v.check((input) => /[0-9]/.test(input), "パスワードは数字を含む必要があります"),
);
値の変換
これらのアクションは型を変更せずに値を変更します:
文字列の変換:
v.trim()— 前後の空白を削除v.trimStart()— 前の空白を削除v.trimEnd()— 後ろの空白を削除v.toLowerCase()— 小文字に変換v.toUpperCase()— 大文字に変換
数値の変換:
v.toMinValue(n)— 最小値にクリップ (n未満の場合、nに設定)v.toMaxValue(n)— 最大値にクリップ (n超過の場合、nに設定)
const NormalizedEmailSchema = v.pipe(
v.string(),
v.trim(),
v.toLowerCase(),
v.email(),
);
// 数値を範囲0-100にクリップ
const PercentageSchema = v.pipe(v.number(), v.toMinValue(0), v.toMaxValue(100));
型の変換
データ型間の変換には、これらの組み込み変換アクションを使用します:
v.toNumber()— 数値に変換v.toString()— 文字列に変換v.toBoolean()— ブール値に変換v.toBigint()— bigintに変換v.toDate()— Dateに変換
// 文字列を数値に変換
const PortSchema = v.pipe(v.string(), v.toNumber(), v.integer(), v.minValue(1));
// ISO文字列をDateに変換
const TimestampSchema = v.pipe(v.string(), v.isoDateTime(), v.toDate());
// ブール値に変換
const FlagSchema = v.pipe(v.string(), v.toBoolean());
カスタム変換
カスタム変換には v.transform() を使用します:
const DateStringSchema = v.pipe(
v.string(),
v.isoDate(),
v.transform((input) => new Date(input)),
);
// カスタムオブジェクト変換
const UserSchema = v.pipe(
v.object({
firstName: v.string(),
lastName: v.string(),
}),
v.transform((input) => ({
...input,
fullName: `${input.firstName} ${input.lastName}`,
})),
);
オブジェクトスキーマ
基本的なオブジェクト
const UserSchema = v.object({
id: v.number(),
name: v.string(),
email: v.pipe(v.string(), v.email()),
age: v.optional(v.number()),
});
type User = v.InferOutput<typeof UserSchema>;
オブジェクトバリエーション
// 通常のオブジェクト - 未知のキーを削除 (デフォルト)
const ObjectSchema = v.object({ key: v.string() });
// ルースオブジェクト - 未知のキーを許可して保持
const LooseObjectSchema = v.looseObject({ key: v.string() });
// 厳密オブジェクト - 未知のキーでエラー
const StrictObjectSchema = v.strictObject({ key: v.string() });
// Restを含むオブジェクト - 未知のキーをスキーマに対して検証
const ObjectWithRestSchema = v.objectWithRest(
{ key: v.string() },
v.number(), // 未知のキーは数値である必要があります
);
オプションおよびNullableフィールド
const ProfileSchema = v.object({
// 必須
name: v.string(),
// オプション (undefinedまたは欠落可能)
nickname: v.optional(v.string()),
// デフォルト付きオプション
role: v.optional(v.string(), "user"),
// Nullable (nullでもよい)
avatar: v.nullable(v.string()),
// Nullish (nullまたはundefined)
bio: v.nullish(v.string()),
// デフォルト付きNullish
theme: v.nullish(v.string(), "light"),
});
オブジェクトメソッド
const BaseSchema = v.object({
id: v.number(),
name: v.string(),
email: v.string(),
password: v.string(),
});
// 特定のキーを抽出
const PublicUserSchema = v.pick(BaseSchema, ["id", "name"]);
// 特定のキーを除外
const UserWithoutPasswordSchema = v.omit(BaseSchema, ["password"]);
// すべてをオプションにする
const PartialUserSchema = v.partial(BaseSchema);
// すべてを必須にする
const RequiredUserSchema = v.required(PartialUserSchema);
// オブジェクトをマージ
const ExtendedUserSchema = v.object({
...BaseSchema.entries,
createdAt: v.date(),
});
クロスフィールド検証
const RegistrationSchema = v.pipe(
v.object({
password: v.pipe(v.string(), v.minLength(8)),
confirmPassword: v.string(),
}),
v.forward(
v.partialCheck(
[["password"], ["confirmPassword"]],
(input) => input.password === input.confirmPassword,
"パスワードが一致しません",
),
["confirmPassword"],
),
);
配列とタプル
配列
const TagsSchema = v.pipe(
v.array(v.string()),
v.minLength(1, "少なくとも1つのタグが必要です"),
v.maxLength(10, "最大10個のタグが許可されます"),
);
// オブジェクトの配列
const UsersSchema = v.array(
v.object({
id: v.number(),
name: v.string(),
}),
);
タプル
// 特定の型の固定長配列
const CoordinatesSchema = v.tuple([v.number(), v.number()]);
// 型: [number, number]
// Restを含むタプル
const ArgsSchema = v.tupleWithRest(
[v.string()], // 最初の引数は文字列
v.number(), // 残りは数値
);
// 型: [string, ...number[]]
Union と Variant
Union
const StringOrNumberSchema = v.union([v.string(), v.number()]);
const StatusSchema = v.union([
v.literal("pending"),
v.literal("active"),
v.literal("inactive"),
]);
Picklist (文字列/数値リテラル用)
// リテラルのunionより簡潔
const StatusSchema = v.picklist(["pending", "active", "inactive"]);
const PrioritySchema = v.picklist([1, 2, 3]);
Variant (判別union)
判別unionのパフォーマンスを向上させるには variant を使用します:
const EventSchema = v.variant("type", [
v.object({
type: v.literal("click"),
x: v.number(),
y: v.number(),
}),
v.object({
type: v.literal("keypress"),
key: v.string(),
}),
v.object({
type: v.literal("scroll"),
direction: v.picklist(["up", "down"]),
}),
]);
データのパース
parse() — エラーでスロー
import * as v from "valibot";
const EmailSchema = v.pipe(v.string(), v.email());
try {
const email = v.parse(EmailSchema, "jane@example.com");
console.log(email); // 'jane@example.com'
} catch (error) {
console.error(error); // ValiError
}
safeParse() — 結果オブジェクトを返す
const result = v.safeParse(EmailSchema, input);
if (result.success) {
console.log(result.output); // 有効なデータ
} else {
console.log(result.issues); // 問題の配列
}
is() — 型ガード
if (v.is(EmailSchema, input)) {
// inputはstringとして型付けされます
}
設定オプション
// 最初のエラーで中止
v.parse(Schema, data, { abortEarly: true });
// パイプラインを最初のエラーで中止
v.parse(Schema, data, { abortPipeEarly: true });
型推論
import * as v from "valibot";
const UserSchema = v.object({
name: v.string(),
age: v.pipe(v.string(), v.transform(Number)),
role: v.optional(v.string(), "user"),
});
// 出力型 (変換とデフォルト後)
type User = v.InferOutput<typeof UserSchema>;
// { name: string; age: number; role: string }
// 入力型 (変換前)
type UserInput = v.InferInput<typeof UserSchema>;
// { name: string; age: string; role?: string | undefined }
// 問題型
type UserIssue = v.InferIssue<typeof UserSchema>;
エラーハンドリング
カスタムエラーメッセージ
const LoginSchema = v.object({
email: v.pipe(
v.string("メールは文字列である必要があります"),
v.nonEmpty("メールアドレスを入力してください"),
v.email("無効なメールアドレス形式"),
),
password: v.pipe(
v.string("パスワードは文字列である必要があります"),
v.nonEmpty("パスワードを入力してください"),
v.minLength(8, "パスワードは少なくとも8文字である必要があります"),
),
});
エラーのフラット化
const result = v.safeParse(LoginSchema, data);
if (!result.success) {
const flat = v.flatten(result.issues);
// { nested: { email: ['Invalid email format'], password: ['...'] } }
}
問題の構造
各問題には以下が含まれます:
kind: 'schema' | 'validation' | 'transformation'type: 関数名 (例: 'string', 'email', 'min_length')input: 問題のある入力expected: 期待されたものreceived: 受け取ったものmessage: 人間が読めるメッセージpath: ネストされた問題のパスアイテムの配列
フォールバック値
// 静的フォールバック
const NumberSchema = v.fallback(v.number(), 0);
v.parse(NumberSchema, "invalid"); // 0を返す
// 動的フォールバック
const DateSchema = v.fallback(v.date(), () => new Date());
再帰的スキーマ
import * as v from "valibot";
type TreeNode = {
value: string;
children: TreeNode[];
};
const TreeNodeSchema: v.GenericSchema<TreeNode> = v.object({
value: v.string(),
children: v.lazy(() => v.array(TreeNodeSchema)),
});
非同期バリデーション
非同期操作 (例: データベースチェック) には非同期バリアントを使用します:
import * as v from "valibot";
const isUsernameAvailable = async (username: string) => {
// データベースをチェック
return true;
};
const UsernameSchema = v.pipeAsync(
v.string(),
v.minLength(3),
v.checkAsync(isUsernameAvailable, "ユーザー名は既に使用されています"),
);
// parseAsyncを使用する必要があります
const username = await v.parseAsync(UsernameSchema, "john");
JSONスキーマ変換
import { toJsonSchema } from "@valibot/to-json-schema";
import * as v from "valibot";
const EmailSchema = v.pipe(v.string(), v.email());
const jsonSchema = toJsonSchema(EmailSchema);
// { type: 'string', format: 'email' }
命名規則
規則1: 同じ名前 (シンプルさのため推奨)
export const User = v.object({
name: v.string(),
email: v.pipe(v.string(), v.email()),
});
export type User = v.InferOutput<typeof User>;
// 使用方法
const users: User[] = [];
users.push(v.parse(User, data));
規則2: サフィックス付き (入出力が異なる場合に推奨)
export const UserSchema = v.object({
name: v.string(),
age: v.pipe(v.string(), v.transform(Number)),
});
export type UserInput = v.InferInput<typeof UserSchema>;
export type UserOutput = v.InferOutput<typeof UserSchema>;
一般的なパターン
ログインフォーム
const LoginSchema = v.object({
email: v.pipe(
v.string(),
v.nonEmpty("メールアドレスを入力してください"),
v.email("無効なメールアドレス"),
),
password: v.pipe(
v.string(),
v.nonEmpty("パスワードを入力してください"),
v.minLength(8, "パスワードは少なくとも8文字である必要があります"),
),
});
APIレスポンス
const ApiResponseSchema = v.variant("status", [
v.object({
status: v.literal("success"),
data: v.unknown(),
}),
v.object({
status: v.literal("error"),
error: v.object({
code: v.string(),
message: v.string(),
}),
}),
]);
環境変数
const EnvSchema = v.object({
NODE_ENV: v.picklist(["development", "production", "test"]),
PORT: v.pipe(v.string(), v.transform(Number), v.integer(), v.minValue(1)),
DATABASE_URL: v.pipe(v.string(), v.url()),
API_KEY: v.pipe(v.string(), v.minLength(32)),
});
const env = v.parse(EnvSchema, process.env);
日付の処理
// 文字列からDateに
const DateFromStringSchema = v.pipe(
v.string(),
v.isoDate(),
v.transform((input) => new Date(input)),
);
// 日付の検証
const FutureDateSchema = v.pipe(
v.date(),
v.minValue(new Date(), "日付は未来である必要があります"),
);
追加リソース
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- open-circle
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/open-circle/agent-skills / ライセンス: MIT
関連スキル
hugging-face-trackio
Trackioを使用してMLトレーニング実験を追跡・可視化できます。トレーニング中のメトリクスログ記録(Python API)、トレーニング診断のアラート発火、ログされたメトリクスの取得・分析(CLI)が必要な場合に活用してください。リアルタイムダッシュボード表示、Webhookを使用したアラート、HF Space同期、自動化向けのJSON出力に対応しています。
btc-bottom-model
ビットコインのサイクルタイミングモデルで、加重スコアリングシステムを搭載しています。日次パルス(4指標、32ポイント)とウィークリー構造(9指標、68ポイント)の2カテゴリーにわたる13の指標を追跡し、0~100のマーケットヒートスコアを算出します。ETFフロー、ファンディングレート、ロング/ショート比率、恐怖・貪欲指数、LTH-MVRV、NUPL、SOPR(LTH+STH)、LTH供給率、移動平均倍率(365日MA、200週MA)、週次RSI、出来高トレンドに対応します。市場サイクル全体を通じて買いと売りの両方の推奨を提供します。ビットコインの底値拾い、BTCサイクルポジション、買い時・売り時、オンチェーン指標、MVRV、NUPL、SOPR、LTH動向、ETFの流出入、ファンディングレート、恐怖指数、ビットコインが過熱状態か、マイナーコスト、暗号資産市場のセンチメント、BTCのポジションサイジング、「今ビットコインを買うべきか」「BTCが天井をつけているか」「オンチェーン指標は何を示しているか」といった質問の際にこのスキルを活用します。
protein_solubility_optimization
タンパク質の溶解性最適化 - タンパク質の溶解性を最適化します。タンパク質の特性を計算し、溶解性と親水性を予測し、有効な変異を提案します。タンパク質配列の特性計算、タンパク質機能の予測、親水性計算、ゼロショット配列予測を含むタンパク質エンジニアリング業務に使用できます。3つのSCPサーバーから4つのツールを統合しています。
research-lookup
Parallel Chat APIまたはPerplexity sonar-pro-searchを使用して、最新の研究情報を検索できます。学術論文の検索にも対応しています。クエリは自動的に最適なバックエンドにルーティングされるため、論文の検索、研究データの収集、科学情報の検証に活用できます。
tree-formatting
ggtree(R)またはiTOL(ウェブ)を使用して、系統樹の可視化とフォーマットを行います。系統樹を図として描画する際、ツリーレイアウトの選択、分類学に基づく枝やラベルの色付け、クレードの折りたたみ、サポート値の表示、またはツリーへのオーバーレイ追加が必要な場合に使用してください。系統推定(protein-phylogenyスキルを使用)やドメイン注釈(今後の独立したスキル)には使用しないでください。
querying-indonesian-gov-data
インドネシア政府の50以上のAPIとデータソースに接続できます。BPJPH(ハラール認証)、BOM(食品安全)、OJK(金融適正性)、BPS(統計)、BMKG(気象・地震)、インドネシア中央銀行(為替レート)、IDX(株式)、CKAN公開データポータル、pasal.id(第三者法MCP)に対応しています。インドネシア政府データを活用したアプリ開発、.go.idウェブサイトのスクレイピング、ハラール認証の確認、企業の法的適正性の検証、金融機関ステータスの照会、またはインドネシアMCPサーバーへの接続時に使用できます。CSRF処理、CKAN API使用方法、IP制限回避など、すぐに実行可能なPythonパターンを含んでいます。