From 2c90e2b019edf39169982a8eacd81d6473a3afdc Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Mon, 19 Jan 2026 12:49:16 +0000 Subject: [PATCH] breaking: Bump zod from v3 to v4 and sveltekit-superforms from 2.27.4 to 2.29.1 (#3067) --- .../bump-zod-and-sveltekit-superforms/plan.md | 553 ++++++++++++++++++ package.json | 4 +- pnpm-lock.yaml | 225 +++---- src/lib/utils/auth_forms.ts | 6 +- src/lib/zod/schema.ts | 47 +- .../(admin)/account_transfer/+page.server.ts | 6 +- src/routes/workbooks/create/+page.server.ts | 6 +- .../workbooks/edit/[slug]/+page.server.ts | 6 +- src/test/lib/utils/auth_forms.test.ts | 6 +- 9 files changed, 683 insertions(+), 176 deletions(-) create mode 100644 docs/dev-notes/2026-01-19/bump-zod-and-sveltekit-superforms/plan.md diff --git a/docs/dev-notes/2026-01-19/bump-zod-and-sveltekit-superforms/plan.md b/docs/dev-notes/2026-01-19/bump-zod-and-sveltekit-superforms/plan.md new file mode 100644 index 000000000..9c90e51f5 --- /dev/null +++ b/docs/dev-notes/2026-01-19/bump-zod-and-sveltekit-superforms/plan.md @@ -0,0 +1,553 @@ +# Zod 3.25.76 → 4.3.5 / sveltekit-superforms 2.27.4 → 2.29.1 アップデート計画 + +**作成日**: 2026-01-19 + +**対象バージョン**: + +- Zod: 3.25.76 → 4.3.5(メジャーバージョンアップ) +- sveltekit-superforms: 2.27.4 → 2.29.1(マイナーバージョンアップ) + +**ステータス**: ✅ 実装完了(デプロイ待ち) + +--- + +## 目次 + +1. [背景](#背景) +2. [破壊的変更と影響](#破壊的変更と影響) +3. [実装戦略](#実装戦略) +4. [実装タスク](#実装タスク) +5. [テスト戦略](#テスト戦略) +6. [検証チェックリスト](#検証チェックリスト) +7. [参考資料](#参考資料) + +--- + +## 背景 + +Zod 4 のリリース(2025年度後半)に伴い、sveltekit-superforms の対応化を検討。Zod 3 から 4 への移行は複数の破壊的変更が含まれるため、段階的なアップグレードを計画。 + +**期間**: 2025-06-04(Zod 4.0.0)~ 2026-01-19(最新版確認) + +**対象**: + +- `zod@3.25.76` → `zod@4.3.5` +- `sveltekit-superforms@2.27.4` → `sveltekit-superforms@2.29.1` + +--- + +## 破壊的変更と影響 + +### 🔴 1. エラーカスタマイズ API の統一 - **HIGH IMPACT** + +| 項目 | Zod 3 | Zod 4 | +| ---------- | --------------------------------------- | ------------------------- | +| API形式 | `{ message: '...' }` | `{ error: '...' }` | +| 削除機能 | `invalid_type_error` / `required_error` | 代替なし(`error`に統一) | +| `errorMap` | 名称変更なし | `error` に名称変更 | + +**プロジェクトへの影響**: + +- **ファイル数**: 1 ファイル([src/lib/zod/schema.ts](src/lib/zod/schema.ts)) +- **変更箇所**: 15+ 箇所のエラーメッセージ定義 +- **影響スキーマ**: `authSchema`, `accountSchema`, `accountTransferSchema`, `workBookSchema`, `workBookTaskSchema` + +**実装例**: + +```typescript +// ❌ Zod 3 +z.string().min(3, { message: '3文字以上入力してください' }); + +// ✅ Zod 4 +z.string().min(3, { error: '3文字以上入力してください' }); +``` + +**対応方針**: 全て `{ error: '...' }` に統一(自動置換可能) + +--- + +### 🔴 2. FormData parsing での default 値挙動変更 - **MEDIUM-HIGH IMPACT** + +| パターン | Zod 3 | Zod 4 | +| ------------------------------------------------------------------ | --------------------------- | ------------------------------------------------------ | +| `z.object({ a: z.string().default('tuna').optional() }).parse({})` | `{}` | `{ a: 'tuna' }` | +| FormData で `urlSlug: ""` 送信 | 空文字が `undefined` に変換 | `.transform()` で `undefined` に変換(default 非適用) | + +**プロジェクトへの影響**: + +- **問題**: `urlSlug` フィールドの空文字列処理 +- **現在の実装**: [src/lib/zod/schema.ts:75-89](src/lib/zod/schema.ts#L75-L89) で `.transform()` で `""` → `undefined` に変換 +- **テスト**: [src/test/lib/zod/workbook_schema.test.ts](src/test/lib/zod/workbook_schema.test.ts) に以下テストあり: + - ✅ `when an url slug is given an empty string` (line 123) + - ✅ `when an url slug is given null` (line 133) + - ✅ `when an url slug is given undefined` (line 143) + +**対応方針**: テストの期待値確認 + `.transform()` 実装の継続 + +--- + +### 🟡 3. z.nativeEnum() の deprecation - **LOW-MEDIUM IMPACT** + +| 変更内容 | +| ------------------------------------------------------ | +| `z.nativeEnum(WorkBookType)` → `z.enum()` への移行推奨 | + +**プロジェクトへの影響**: + +- **使用箇所**: [src/lib/zod/schema.ts:72](src/lib/zod/schema.ts#L72) +- **機能**: `workBookType: z.nativeEnum(WorkBookType)` として使用 +- **動作**: Zod 4 でも機能するが、deprecated 警告が出る可能性 + +**対応方針**: 互換性維持(移行は v5 以降) + +--- + +### 🟡 4. エラーマップ優先順位の変更 - **LOW-MEDIUM IMPACT** + +| バージョン | 優先度 | +| ---------- | ------------------------------------------ | +| Zod 3 | `.parse()` のエラーマップ > スキーマレベル | +| Zod 4 | スキーマレベル > `.parse()` のエラーマップ | + +**プロジェクトへの影響**: + +- sveltekit-superforms が国際化エラーメッセージを処理している場合に影響 +- 現在: **日本語のみ** → 国際化対応なし → **影響なし** + +**対応方針**: 現時点では対応不要 + +--- + +### 🟢 5. 新機能: z.fromJSONSchema(), z.xor(), z.looseRecord(), .exactOptional() - **LOW IMPACT** + +| 機能 | 用途 | +| -------------------- | ------------------------------------------ | +| `z.fromJSONSchema()` | OpenAPI/JSON Schema から自動生成 | +| `z.xor()` | 排他的 union(今後活用可能) | +| `z.looseRecord()` | 部分的バリデーション(今後活用可能) | +| `.exactOptional()` | 厳密オプショナル(`urlSlug` など活用可能) | + +**対応方針**: アップグレード後に活用検討 + +--- + +## 実装戦略 + +### 段階的アップグレード(保守的アプローチ) + +``` +Phase 1: 事前準備 + ↓ +Phase 2: Zod 4 アップグレード + コード修正 + ↓ + [単体テスト実行] ← テスト: ユニットテストのみ + ↓ +Phase 3: sveltekit-superforms アップグレード + adapter 切り替え + ↓ + [統合テスト実行] ← テスト: ユニット + E2E テスト + ↓ +Phase 4: ローカル検証・デプロイ確認 +``` + +**メリット**: + +- 🔍 各フェーズの問題を切り分けやすい +- 📊 Zod の破壊的変更が明確に検出される +- ⚙️ adapter の互換性を確認してから切り替え + +--- + +## 実装タスク + +### 📋 Phase 1: 事前準備 + +- [x] スキーマ全体のバックアップ確認 + - 確認ファイル: [src/lib/zod/schema.ts](src/lib/zod/schema.ts) + - エラーメッセージ数: 15+ + +- [x] FormData パース時の挙動テスト + - テスト確認: [src/test/lib/zod/workbook_schema.test.ts](src/test/lib/zod/workbook_schema.test.ts) + - 特にチェック: `urlSlug` の `""` / `null` / `undefined` テスト + +--- + +### 📋 Phase 2: Zod 4 アップグレード + +#### Step 2.1: パッケージアップグレード + +- [x] `package.json` 更新 + - `zod@3.25.76` → `zod@4.3.5` に変更 + - 変更ファイル: [package.json](package.json) + +- [x] 依存関係インストール + + ```bash + pnpm install + ``` + + - 互換性エラー確認 + - `sveltekit-superforms@2.27.4` との互換性確認(まだ `zod` adapter は使用) + +- [x] ビルド動作確認 + + ```bash + pnpm build + ``` + + - エラー確認 + - 型チェック確認 + +#### Step 2.2: スキーマコード修正 + +- [x] [src/lib/zod/schema.ts](src/lib/zod/schema.ts) のエラーメッセージ API 統一 + - `{ message: '...' }` → `{ error: '...' }` に統一 + - 対象: 全15+箇所 + - `authSchema` の `.min()` / `.max()` / `.regex()` (5 箇所) + - `accountSchema` の `.min()` / `.max()` / `.regex()` (3 箇所) + - `accountTransferSchema` の `.refine()` (1 箇所) + - `workBookTaskSchema` の `.max()` (1 箇所) + - `workBookSchema` の `.min()` / `.max()` / `.refine()` (6 箇所) + +**修正例**: + +```typescript +// Before (Zod 3) +z.string().min(3, { message: '3文字以上入力してください' }); + +// After (Zod 4) +z.string().min(3, { error: '3文字以上入力してください' }); +``` + +#### Step 2.3: TypeScript 型チェック + +- [x] TypeScript エラー確認 + + ```bash + pnpm check + ``` + + - 型推論エラー確認 + - 必要に応じた型修正 + +--- + +### 📋 Phase 3: sveltekit-superforms アップグレード + +#### Step 3.1: パッケージアップグレード + +- [x] `package.json` 更新 + - `sveltekit-superforms@2.27.4` → `sveltekit-superforms@2.29.1` に変更 + - 変更ファイル: [package.json](package.json#L60) + +- [x] 依存関係インストール + + ```bash + pnpm install + ``` + + - 互換性エラー確認 + - Zod 4 との互換性確認 + +- [x] ビルド動作確認 + + ```bash + pnpm build + ``` + + - エラー確認 + +#### Step 3.2: Adapter 切り替え + +- [x] Adapter の `zod()` → `zod4()` 切り替え + + **対象ファイル**: 3 ファイル、計 6 箇所 + + **ファイル 1**: [src/routes/workbooks/create/+page.server.ts](src/routes/workbooks/create/+page.server.ts) + + ```typescript + // Before (Line 3, 27, 55) + import { zod } from 'sveltekit-superforms/adapters'; + ... + const form = await superValidate(null, zod(workBookSchema)); + const form = await superValidate(request, zod(workBookSchema)); + + // After + import { zod4 } from 'sveltekit-superforms/adapters'; + ... + const form = await superValidate(null, zod4(workBookSchema)); + const form = await superValidate(request, zod4(workBookSchema)); + ``` + + **ファイル 2**: [src/routes/workbooks/edit/[slug]/+page.server.ts](src/routes/workbooks/edit/[slug]/+page.server.ts) + + ```typescript + // Before (Line 3, 24, 28) + import { zod } from 'sveltekit-superforms/adapters'; + ... + const form = await superValidate(null, zod(workBookSchema)); + const form = await superValidate(request, zod(workBookSchema)); + + // After + import { zod4 } from 'sveltekit-superforms/adapters'; + ... + const form = await superValidate(null, zod4(workBookSchema)); + const form = await superValidate(request, zod4(workBookSchema)); + ``` + + **ファイル 3**: [src/routes/(admin)/account_transfer/+page.server.ts]() + + ```typescript + // Before (Line 5, 32, 49) + import { zod } from 'sveltekit-superforms/adapters'; + ... + const form = await superValidate(null, zod(accountTransferSchema)); + const form = await superValidate(request, zod(accountTransferSchema)); + + // After + import { zod4 } from 'sveltekit-superforms/adapters'; + ... + const form = await superValidate(null, zod4(accountTransferSchema)); + const form = await superValidate(request, zod4(accountTransferSchema)); + ``` + +- [x] TypeScript 型チェック + + ```bash + pnpm check + ``` + + - 型推論エラー確認 + +--- + +## テスト戦略 + +### 📋 Phase 4: テスト実行(段階的) + +#### Step 4.1: Phase 2 後のテスト(Zod 4 のみ) + +- [x] ユニットテスト実行 + + ```bash + pnpm test:unit + ``` + + - **目的**: Zod 4 のスキーマテスト確認 + - **対象テスト**: + - [src/test/lib/zod/workbook_schema.test.ts](src/test/lib/zod/workbook_schema.test.ts) (63 tests) + - [src/test/lib/zod/auth_schema.test.ts](src/test/lib/zod/auth_schema.test.ts) + - [src/test/lib/zod/account_transfer_schema.test.ts](src/test/lib/zod/account_transfer_schema.test.ts) + - **特に確認**: `urlSlug` の `""` / `null` / `undefined` 挙動 + - **期待**: ✅ 全テスト合格(テスト修正不要の可能性が高い) + +#### Step 4.2: Phase 3 後のテスト(Zod 4 + superforms 2.29.1) + +- [x] ユニットテスト再実行 + + ```bash + pnpm test:unit + ``` + + - **目的**: adapter 切り替え後のスキーマテスト再確認 + - **期待**: ✅ 全テスト合格 + +- [x] E2E テスト実行 + + ```bash + pnpm test:integration + ``` + + - **目的**: フロントエンド・フォーム送信の実装確認 + - **対象テスト**: + - `tests/signin.test.ts` - ログイン・ログアウト + - `tests/toppage.test.ts` - トップページ + - その他 E2E テスト + - **特に確認**: 問題集作成・編集フロー + - **期待**: ✅ 全テスト合格 + +#### Step 4.3: フルテストスイート + +- [x] 統合テスト実行 + + ```bash + pnpm test + ``` + + - **目的**: 全テストの最終確認 + - **構成**: `pnpm test:integration && pnpm test:unit` + - **期待**: ✅ 全テスト合格 + +--- + +### 📋 Phase 5: ローカル検証・デプロイ確認 + +#### Step 5.1: ローカル環境確認 + +- [x] ローカル dev 環境起動 + + ```bash + pnpm dev + ``` + + - **確認項目**: + - サーバー起動時エラー確認 + - ホットリロード動作確認 + - ブラウザコンソールエラー確認 + +- [x] UI 検証 + - 問題集作成画面にアクセス + - フォーム送信(有効な入力値) + - エラーメッセージ表示(無効な入力値) + - 日本語エラーメッセージが表示されることを確認 + +- [x] ユーザー名が 3 文字未満の場合 + ``` + 入力: "ab" + 期待: "3文字以上入力してください" (Zod 4の { error } で表示) + ``` + +#### Step 5.2: コード品質確認 + +- [x] TypeScript チェック + + ```bash + pnpm check + ``` + + - 型エラー確認 + +- [x] Lint / Format + + ```bash + pnpm lint + pnpm format + ``` + + - コード品質確認 + +#### Step 5.3: デプロイ確認 + +- [ ] Vercel preview デプロイ + - GitHub Actions で CI/CD パイプライン確認 + - 自動デプロイが成功することを確認 + - Preview URL でブラウザ検証 + +- [ ] 本番環境への merge + - Main ブランチへの merge + - 本番デプロイ確認 + +--- + +## 検証チェックリスト + +| 項目 | ステータス | 備考 | +| ------------------------------------- | --------------- | ------------ | +| 破壊的変更分析 | ✅ 完了 | Phase 1 完了 | +| Zod パッケージアップグレード | ✅ 完了 | Phase 2.1 | +| Zod スキーマ修正 | ✅ 完了 | Phase 2.2 | +| Zod ユニットテスト | ✅ 完了 | Phase 4.1 | +| sveltekit-superforms アップグレード | ✅ 完了 | Phase 3.1 | +| adapter 切り替え(zod → zod4) | ✅ 完了 | Phase 3.2 | +| ユニットテスト再実行 | ✅ 完了 | Phase 4.2 | +| E2E テスト実行 | ✅ 完了 | Phase 4.3 | +| ローカル dev 起動 | ✅ 完了 | Phase 5.1 | +| 日本語エラーメッセージ表示確認 | ✅ 完了 | Phase 5.2 | +| TypeScript チェック | ✅ 完了 | Phase 5.3 | +| Lint / Format | ✅ 完了 | Phase 5.4 | +| 共有 util ファイルの adapter 切り替え | ✅ 完了 | Phase 3.2.1 | +| テストモック設定の同期更新 | ✅ 完了 | Phase 4.2 | +| Vercel preview デプロイ | ⏳ 次のステップ | Phase 5.5 | +| 本番環境デプロイ | ⏳ 次のステップ | Phase 5.6 | + +--- + +## 参考資料 + +### Zod 公式ドキュメント + +- [Zod v4 Migration Guide](https://zod.dev/v4/changelog) +- [Zod v4 Release Notes](https://zod.dev/v4) +- [Zod v4 Basic Usage](https://zod.dev/basics) + +### sveltekit-superforms ドキュメント + +- [sveltekit-superforms Releases](https://github.com/ciscoheat/sveltekit-superforms/releases) +- [v2.28.0 - Zod 4 adapter 追加](https://github.com/ciscoheat/sveltekit-superforms/releases/tag/v2.28.0) +- [v2.29.1 - Latest fixes](https://github.com/ciscoheat/sveltekit-superforms/releases/tag/v2.29.1) +- [Superforms Documentation](https://superforms.rocks/) + +### プロジェクト関連ファイル + +- **スキーマ定義**: [src/lib/zod/schema.ts](src/lib/zod/schema.ts) +- **スキーマテスト**: + - [src/test/lib/zod/workbook_schema.test.ts](src/test/lib/zod/workbook_schema.test.ts) + - [src/test/lib/zod/auth_schema.test.ts](src/test/lib/zod/auth_schema.test.ts) + - [src/test/lib/zod/account_transfer_schema.test.ts](src/test/lib/zod/account_transfer_schema.test.ts) +- **実装ファイル**: + - [src/routes/workbooks/create/+page.server.ts](src/routes/workbooks/create/+page.server.ts) + - [src/routes/workbooks/edit/[slug]/+page.server.ts](src/routes/workbooks/edit/[slug]/+page.server.ts) + - [src/routes/(admin)/account_transfer/+page.server.ts]() + +### CI/CD + +- **テスト実行**: `pnpm test:unit` (vitest), `pnpm test:integration` (playwright) +- **デプロイ**: GitHub Actions → Vercel +- **環境**: Node.js 20+, pnpm 10.28.0 + +--- + +## 実装完了 + +**実行日時**: 2026-01-19 12:00 - 12:20(約20分) + +**実行者**: GitHub Copilot(自動実装) + +**テスト結果**: + +- ユニットテスト: **1757 passed | 1 skipped** ✅ +- E2E テスト: **18 passed | 1 skipped** ✅ +- Lint/Format: **35 warnings(既存) | 0 新規エラー** ✅ + +**変更ファイル一覧**: + +1. `package.json`: Zod 3.25.76 → 4.3.5、sveltekit-superforms 2.27.4 → 2.29.1 +2. `src/lib/zod/schema.ts`: 20 箇所の `{ message }` → `{ error }` に統一 +3. `src/routes/workbooks/create/+page.server.ts`: `zod` → `zod4` adapter 切り替え +4. `src/routes/workbooks/edit/[slug]/+page.server.ts`: `zod` → `zod4` adapter 切り替え +5. `src/routes/(admin)/account_transfer/+page.server.ts`: `zod` → `zod4` adapter 切り替え +6. `src/lib/utils/auth_forms.ts`: `zod` → `zod4` adapter 切り替え +7. `src/test/lib/utils/auth_forms.test.ts`: モック設定の `zod` → `zod4` 更新 + +--- + +## 教訓 + +### 1. **段階的アップグレードの重要性** + +- Zod 3 → 4 のメジャーバージョンアップを、Phase 分割で対応することで、各フェーズの問題を明確に切り分けられた +- スキーマテスト → adapter 切り替え → E2E テストという段階的検証が効果的 + +### 2. **共有ユーティリティ内の adapter 切り替え漏れ** + +- `auth_forms.ts` のような共有コードの `zod()` → `zod4()` 置換を見落とさないことが重要 +- grep で全プロジェクトをスキャンして、adapter の全使用箇所を確認 + +### 3. **テストモック設定の同期更新** + +- API 変更に伴い、テストの `vi.mock()` 定義も更新する必要がある +- `zod` export → `zod4` export の変更で、テスト実行時のエラーを防止 + +### 4. **エラーメッセージ API の統一** + +- `{ message }` → `{ error }` への置換は全スキーマで一貫性が必要 +- 正規表現検索で全置換箇所を検出可能 + +### 5. **ユニット + E2E テストの双方実施** + +- adapter 切り替え後、ユニットテストと E2E テストの両方を実行してバックエンド・フロントエンド互換性を確認 +- テスト全 pass で本番環境への信頼度が向上 + +### 6. **コード品質チェックの実施** + +- Lint/Format で新規エラーが導入されていないことを確認 +- 既存 warning との区別で、アップグレードの影響範囲を明確化 diff --git a/package.json b/package.json index f6d070a85..141d0b5d5 100644 --- a/package.json +++ b/package.json @@ -57,14 +57,14 @@ "svelte": "5.47.0", "svelte-check": "4.3.5", "svelte-meta-tags": "4.5.0", - "sveltekit-superforms": "2.27.4", + "sveltekit-superforms": "2.29.1", "tailwindcss": "4.1.18", "tslib": "2.8.1", "tsx": "4.21.0", "typescript": "5.9.3", "vite": "7.3.1", "vitest": "4.0.17", - "zod": "3.25.76" + "zod": "4.3.5" }, "type": "module", "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a36b667ec..ad5849bda 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -163,8 +163,8 @@ importers: specifier: 4.5.0 version: 4.5.0(svelte@5.47.0) sveltekit-superforms: - specifier: 2.27.4 - version: 2.27.4(@sveltejs/kit@2.50.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.47.0)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(svelte@5.47.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(@types/json-schema@7.0.15)(esbuild@0.27.1)(svelte@5.47.0)(typescript@5.9.3) + specifier: 2.29.1 + version: 2.29.1(@sveltejs/kit@2.50.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.47.0)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(svelte@5.47.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(@types/json-schema@7.0.15)(svelte@5.47.0)(typescript@5.9.3) tailwindcss: specifier: 4.1.18 version: 4.1.18 @@ -184,8 +184,8 @@ importers: specifier: 4.0.17 version: 4.0.17(@edge-runtime/vm@3.2.0)(@types/node@25.0.9)(@vitest/ui@4.0.17)(jiti@1.21.7)(jsdom@27.4.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1) zod: - specifier: 3.25.76 - version: 3.25.76 + specifier: 4.3.5 + version: 4.3.5 packages: @@ -205,14 +205,11 @@ packages: '@antfu/utils@9.3.0': resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==} - '@ark/regex@0.0.0': - resolution: {integrity: sha512-p4vsWnd/LRGOdGQglbwOguIVhPmCAf5UzquvnDoxqhhPWTP84wWgi1INea8MgJ4SnI2gp37f13oA4Waz9vwNYg==} - - '@ark/schema@0.50.0': - resolution: {integrity: sha512-hfmP82GltBZDadIOeR3argKNlYYyB2wyzHp0eeAqAOFBQguglMV/S7Ip2q007bRtKxIMLDqFY6tfPie1dtssaQ==} + '@ark/schema@0.56.0': + resolution: {integrity: sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA==} - '@ark/util@0.50.0': - resolution: {integrity: sha512-tIkgIMVRpkfXRQIEf0G2CJryZVtHVrqcWHMDa5QKo0OEEBu0tHkRSIMm4Ln8cd8Bn9TPZtvc/kE2Gma8RESPSg==} + '@ark/util@0.56.0': + resolution: {integrity: sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA==} '@asamuzakjp/css-color@4.1.1': resolution: {integrity: sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==} @@ -867,12 +864,6 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@finom/zod-to-json-schema@3.24.11': - resolution: {integrity: sha512-fL656yBPiWebtfGItvtXLWrFNGlF1NcDFS0WdMQXMs9LluVg0CfT5E2oXYp0pidl0vVG53XkW55ysijNkU5/hA==} - deprecated: 'Use https://www.npmjs.com/package/zod-v3-to-json-schema instead. See issue comment for details: https://github.com/StefanTerdell/zod-to-json-schema/issues/178#issuecomment-3533122539' - peerDependencies: - zod: ^4.0.14 - '@floating-ui/core@1.7.3': resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} @@ -900,10 +891,6 @@ packages: '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - '@gcornut/valibot-json-schema@0.42.0': - resolution: {integrity: sha512-4Et4AN6wmqeA0PfU5Clkv/IS27wiefsWf6TemAZrb75uzkClYEFavim7SboeKwbll9Nbsn2Iv0LT/HS5H7orZg==} - hasBin: true - '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -1899,6 +1886,11 @@ packages: resolution: {integrity: sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@valibot/to-json-schema@1.5.0': + resolution: {integrity: sha512-GE7DmSr1C2UCWPiV0upRH6mv0cCPsqYGs819fb6srCS1tWhyXrkGGe+zxUiwzn/L1BOfADH4sNjY/YHCuP8phQ==} + peerDependencies: + valibot: ^1.2.0 + '@vercel/backends@0.0.22': resolution: {integrity: sha512-O+HmKvFkvWbTG7ESN8vOfzBMzjfKdg8qP7/qqqsCK0IqtuihlVOkLRM9Smb5pAgk/QrlTfsBM6fjhneBNcHXtQ==} @@ -2141,8 +2133,11 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} - arktype@2.1.23: - resolution: {integrity: sha512-tyxNWX6xJVMb2EPJJ3OjgQS1G/vIeQRrZuY4DeBNQmh8n7geS+czgbauQWB6Pr+RXiOO8ChEey44XdmxsqGmfQ==} + arkregex@0.0.5: + resolution: {integrity: sha512-ncYjBdLlh5/QnVsAA8De16Tc9EqmYM7y/WU9j+236KcyYNUXogpz3sC4ATIZYzzLxwI+0sEOaQLEmLmRleaEXw==} + + arktype@2.1.29: + resolution: {integrity: sha512-jyfKk4xIOzvYNayqnD8ZJQqOwcrTOUbIU4293yrzAjA3O1dWh61j71ArMQ6tS/u4pD7vabSPe7nG3RCyoXW6RQ==} array-back@3.1.0: resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} @@ -2270,9 +2265,6 @@ packages: buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -2366,8 +2358,8 @@ packages: cjs-module-lexer@1.2.3: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} - class-validator@0.14.2: - resolution: {integrity: sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==} + class-validator@0.14.3: + resolution: {integrity: sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==} class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -2739,9 +2731,6 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - devalue@5.4.2: - resolution: {integrity: sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw==} - devalue@5.6.2: resolution: {integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==} @@ -2788,6 +2777,9 @@ packages: effect@3.18.4: resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==} + effect@3.19.14: + resolution: {integrity: sha512-3vwdq0zlvQOxXzXNKRIPKTqZNMyGCdaFUBfMPqpsyzZDre67kgC1EEHDV4EoQTovJ4w5fmJW756f86kkuz7WFA==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2838,12 +2830,6 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - esbuild-runner@2.2.2: - resolution: {integrity: sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==} - hasBin: true - peerDependencies: - esbuild: '*' - esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -4521,9 +4507,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -4647,8 +4630,8 @@ packages: resolution: {integrity: sha512-LRhAvzhvb4lHLNAcAMJZ2ifUSOif8OuItF4khbssrIeitj01GjpumeeauSnCeAGnSI+X6P2R3Z7S4c5STv4iQQ==} engines: {node: '>=18'} - sveltekit-superforms@2.27.4: - resolution: {integrity: sha512-8iw2nSKUVaBimOw0XGGdI39AihY1r/Plh9LTmxQGYopQaom5PPbDJyU79dUy3bd4K7vlqTdjvMz5FO8IFFzoPQ==} + sveltekit-superforms@2.29.1: + resolution: {integrity: sha512-9Cv1beOVPgm8rb8NZBqLdlZ9cBqRBTk0+6/oHn7DWvHQoAFie1EPjh1e4NHO3Qouv1Zq9QTGrZNDbYcetkuOVw==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 @@ -4837,9 +4820,6 @@ packages: ts-toolbelt@6.15.5: resolution: {integrity: sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==} - tslib@2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -4856,6 +4836,9 @@ packages: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} + typebox@1.0.78: + resolution: {integrity: sha512-xOPmaDSBCMa6vCHFguteJuOcq73HY2aKexdVUi+zE82dCcCp3FMKaM/SfT4fcNNgskLmjauuU8wr0/1fWNN1Og==} + typed-query-selector@2.12.0: resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} @@ -4927,16 +4910,8 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - valibot@0.42.1: - resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} - peerDependencies: - typescript: '>=5' - peerDependenciesMeta: - typescript: - optional: true - - valibot@1.1.0: - resolution: {integrity: sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw==} + valibot@1.2.0: + resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==} peerDependencies: typescript: '>=5' peerDependenciesMeta: @@ -4947,6 +4922,10 @@ packages: resolution: {integrity: sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==} engines: {node: '>= 0.10'} + validator@13.15.26: + resolution: {integrity: sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==} + engines: {node: '>= 0.10'} + vercel@50.4.5: resolution: {integrity: sha512-eF8GZ9XjsFGPKW4z+eN5ilqVqCLuZVoRxo3csBZfaR6TMKbs5kilkcC+HErQKu2gCIQ7Aozo2G7anAejIjzpvA==} engines: {node: '>= 18'} @@ -5201,17 +5180,19 @@ packages: zimmerframe@1.1.4: resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + zod-v3-to-json-schema@4.0.0: + resolution: {integrity: sha512-KixLrhX/uPmRFnDgsZrzrk4x5SSJA+PmaE5adbfID9+3KPJcdxqRobaHU397EfWBqfQircrjKqvEqZ/mW5QH6w==} + peerDependencies: + zod: ^3.25 || ^4.0.14 + zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - - zod@4.1.12: - resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} + zod@4.3.5: + resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} snapshots: @@ -5228,17 +5209,12 @@ snapshots: '@antfu/utils@9.3.0': {} - '@ark/regex@0.0.0': - dependencies: - '@ark/util': 0.50.0 - optional: true - - '@ark/schema@0.50.0': + '@ark/schema@0.56.0': dependencies: - '@ark/util': 0.50.0 + '@ark/util': 0.56.0 optional: true - '@ark/util@0.50.0': + '@ark/util@0.56.0': optional: true '@asamuzakjp/css-color@4.1.1': @@ -5653,11 +5629,6 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@finom/zod-to-json-schema@3.24.11(zod@4.1.12)': - dependencies: - zod: 4.1.12 - optional: true - '@floating-ui/core@1.7.3': dependencies: '@floating-ui/utils': 0.2.10 @@ -5691,17 +5662,6 @@ snapshots: '@floating-ui/utils@0.2.10': {} - '@gcornut/valibot-json-schema@0.42.0(esbuild@0.27.1)(typescript@5.9.3)': - dependencies: - valibot: 0.42.1(typescript@5.9.3) - optionalDependencies: - '@types/json-schema': 7.0.15 - esbuild-runner: 2.2.2(esbuild@0.27.1) - transitivePeerDependencies: - - esbuild - - typescript - optional: true - '@hapi/hoek@9.3.0': optional: true @@ -6651,11 +6611,11 @@ snapshots: '@types/node': 25.0.9 optional: true - '@typeschema/class-validator@0.3.0(@types/json-schema@7.0.15)(class-validator@0.14.2)': + '@typeschema/class-validator@0.3.0(@types/json-schema@7.0.15)(class-validator@0.14.3)': dependencies: '@typeschema/core': 0.14.0(@types/json-schema@7.0.15) optionalDependencies: - class-validator: 0.14.2 + class-validator: 0.14.3 transitivePeerDependencies: - '@types/json-schema' optional: true @@ -6756,6 +6716,11 @@ snapshots: '@typescript-eslint/types': 8.53.0 eslint-visitor-keys: 4.2.1 + '@valibot/to-json-schema@1.5.0(valibot@1.2.0(typescript@5.9.3))': + dependencies: + valibot: 1.2.0(typescript@5.9.3) + optional: true + '@vercel/backends@0.0.22(rollup@4.53.4)(typescript@5.9.3)': dependencies: '@vercel/cervel': 0.0.9(typescript@5.9.3) @@ -7227,11 +7192,16 @@ snapshots: aria-query@5.3.2: {} - arktype@2.1.23: + arkregex@0.0.5: + dependencies: + '@ark/util': 0.56.0 + optional: true + + arktype@2.1.29: dependencies: - '@ark/regex': 0.0.0 - '@ark/schema': 0.50.0 - '@ark/util': 0.50.0 + '@ark/schema': 0.56.0 + '@ark/util': 0.56.0 + arkregex: 0.0.5 optional: true array-back@3.1.0: {} @@ -7338,9 +7308,6 @@ snapshots: buffer-crc32@0.2.13: {} - buffer-from@1.1.2: - optional: true - buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -7449,11 +7416,11 @@ snapshots: cjs-module-lexer@1.2.3: {} - class-validator@0.14.2: + class-validator@0.14.3: dependencies: '@types/validator': 13.15.3 libphonenumber-js: 1.12.25 - validator: 13.15.15 + validator: 13.15.26 optional: true class-variance-authority@0.7.1: @@ -7809,8 +7776,6 @@ snapshots: detect-libc@2.1.2: {} - devalue@5.4.2: {} - devalue@5.6.2: {} devtools-protocol@0.0.1367902: {} @@ -7859,6 +7824,12 @@ snapshots: '@standard-schema/spec': 1.0.0 fast-check: 3.23.2 + effect@3.19.14: + dependencies: + '@standard-schema/spec': 1.0.0 + fast-check: 3.23.2 + optional: true + emoji-regex@8.0.0: {} empathic@2.0.0: {} @@ -7903,13 +7874,6 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - esbuild-runner@2.2.2(esbuild@0.27.1): - dependencies: - esbuild: 0.27.1 - source-map-support: 0.5.21 - tslib: 2.4.0 - optional: true - esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -9610,12 +9574,6 @@ snapshots: source-map-js@1.2.1: {} - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - optional: true - source-map@0.6.1: optional: true @@ -9759,32 +9717,31 @@ snapshots: magic-string: 0.30.21 zimmerframe: 1.1.4 - sveltekit-superforms@2.27.4(@sveltejs/kit@2.50.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.47.0)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(svelte@5.47.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(@types/json-schema@7.0.15)(esbuild@0.27.1)(svelte@5.47.0)(typescript@5.9.3): + sveltekit-superforms@2.29.1(@sveltejs/kit@2.50.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.47.0)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(svelte@5.47.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(@types/json-schema@7.0.15)(svelte@5.47.0)(typescript@5.9.3): dependencies: '@sveltejs/kit': 2.50.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.47.0)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)))(svelte@5.47.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.1)) - devalue: 5.4.2 + devalue: 5.6.2 memoize-weak: 1.0.2 svelte: 5.47.0 ts-deepmerge: 7.0.3 optionalDependencies: '@exodus/schemasafe': 1.3.0 - '@finom/zod-to-json-schema': 3.24.11(zod@4.1.12) - '@gcornut/valibot-json-schema': 0.42.0(esbuild@0.27.1)(typescript@5.9.3) - '@sinclair/typebox': 0.34.41 - '@typeschema/class-validator': 0.3.0(@types/json-schema@7.0.15)(class-validator@0.14.2) + '@typeschema/class-validator': 0.3.0(@types/json-schema@7.0.15)(class-validator@0.14.3) + '@valibot/to-json-schema': 1.5.0(valibot@1.2.0(typescript@5.9.3)) '@vinejs/vine': 3.0.1 - arktype: 2.1.23 - class-validator: 0.14.2 - effect: 3.18.4 + arktype: 2.1.29 + class-validator: 0.14.3 + effect: 3.19.14 joi: 17.13.3 json-schema-to-ts: 3.1.1 superstruct: 2.0.2 - valibot: 1.1.0(typescript@5.9.3) + typebox: 1.0.78 + valibot: 1.2.0(typescript@5.9.3) yup: 1.7.1 - zod: 4.1.12 + zod: 4.3.5 + zod-v3-to-json-schema: 4.0.0(zod@4.3.5) transitivePeerDependencies: - '@types/json-schema' - - esbuild - typescript symbol-tree@3.2.4: {} @@ -10012,9 +9969,6 @@ snapshots: ts-toolbelt@6.15.5: {} - tslib@2.4.0: - optional: true - tslib@2.8.1: {} tsx@4.21.0: @@ -10031,6 +9985,9 @@ snapshots: type-fest@2.19.0: optional: true + typebox@1.0.78: + optional: true + typed-query-selector@2.12.0: {} typescript@4.9.5: {} @@ -10080,17 +10037,15 @@ snapshots: v8-compile-cache-lib@3.0.1: {} - valibot@0.42.1(typescript@5.9.3): + valibot@1.2.0(typescript@5.9.3): optionalDependencies: typescript: 5.9.3 optional: true - valibot@1.1.0(typescript@5.9.3): - optionalDependencies: - typescript: 5.9.3 + validator@13.15.15: optional: true - validator@13.15.15: + validator@13.15.26: optional: true vercel@50.4.5(rollup@4.53.4)(typescript@5.9.3): @@ -10324,11 +10279,13 @@ snapshots: zimmerframe@1.1.4: {} + zod-v3-to-json-schema@4.0.0(zod@4.3.5): + dependencies: + zod: 4.3.5 + optional: true + zod@3.22.4: {} zod@3.23.8: {} - zod@3.25.76: {} - - zod@4.1.12: - optional: true + zod@4.3.5: {} diff --git a/src/lib/utils/auth_forms.ts b/src/lib/utils/auth_forms.ts index 4d5e71fb2..3e387b3f4 100644 --- a/src/lib/utils/auth_forms.ts +++ b/src/lib/utils/auth_forms.ts @@ -1,7 +1,7 @@ import { redirect } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms/server'; -import { zod } from 'sveltekit-superforms/adapters'; +import { zod4 } from 'sveltekit-superforms/adapters'; import type { AuthForm, @@ -65,7 +65,7 @@ const formCreationStrategies: AuthFormCreationStrategies = [ { name: '(Basic case) Use standard superValidate', async run() { - const form = await superValidate(zod(authSchema)); + const form = await superValidate(zod4(authSchema)); return { form: { ...form, message: '' } }; }, }, @@ -118,7 +118,7 @@ const formValidationStrategies: AuthFormValidationStrategies = [ { name: '(Basic Case) Use standard superValidate with request', async run(request: Request) { - const form = await superValidate(request, zod(authSchema)); + const form = await superValidate(request, zod4(authSchema)); return { form: { ...form, message: '' } }; }, }, diff --git a/src/lib/zod/schema.ts b/src/lib/zod/schema.ts index 34769230d..932c4e70a 100644 --- a/src/lib/zod/schema.ts +++ b/src/lib/zod/schema.ts @@ -13,23 +13,23 @@ const ONLY_SINGLE_BYTE_ALPHANUMERIC_CHARACTERS_AND_ = '半角英数字と_のみ export const authSchema = z.object({ username: z .string() - .min(3, { message: INPUT_AT_LEAST_3_CHARACTERS }) - .max(24, { message: DELETE_UNTIL_24_CHARACTERS_ARE_LEFT }) - .regex(/^[\w]*$/, { message: ONLY_SINGLE_BYTE_ALPHANUMERIC_CHARACTERS_AND_ }), + .min(3, { error: INPUT_AT_LEAST_3_CHARACTERS }) + .max(24, { error: DELETE_UNTIL_24_CHARACTERS_ARE_LEFT }) + .regex(/^[\w]*$/, { error: ONLY_SINGLE_BYTE_ALPHANUMERIC_CHARACTERS_AND_ }), password: z .string() - .min(8, { message: '8文字以上入力してください' }) - .max(128, { message: '128文字になるまで削除してください' }) + .min(8, { error: '8文字以上入力してください' }) + .max(128, { error: '128文字になるまで削除してください' }) .regex(/^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)[a-zA-Z\d]{8,128}$/, { - message: '半角英文字(小・大)・数字をそれぞれ1文字以上含めてください', + error: '半角英文字(小・大)・数字をそれぞれ1文字以上含めてください', }), }); export const accountSchema = z .string() - .min(3, { message: INPUT_AT_LEAST_3_CHARACTERS }) - .max(24, { message: DELETE_UNTIL_24_CHARACTERS_ARE_LEFT }) - .regex(/^[\w]*$/, { message: ONLY_SINGLE_BYTE_ALPHANUMERIC_CHARACTERS_AND_ }); + .min(3, { error: INPUT_AT_LEAST_3_CHARACTERS }) + .max(24, { error: DELETE_UNTIL_24_CHARACTERS_ARE_LEFT }) + .regex(/^[\w]*$/, { error: ONLY_SINGLE_BYTE_ALPHANUMERIC_CHARACTERS_AND_ }); export const accountTransferSchema = z .object({ @@ -37,7 +37,7 @@ export const accountTransferSchema = z destinationUserName: accountSchema, }) .refine((data) => data.sourceUserName !== data.destinationUserName, { - message: '新アカウント名は、旧アカウント名とは異なるものを指定してください', + error: '新アカウント名は、旧アカウント名とは異なるものを指定してください', path: ['destinationUserName'], }); @@ -45,27 +45,24 @@ const workBookTaskSchema = z.object({ workBookId: z.number().nonnegative().optional(), taskId: z.string(), priority: z.number().positive(), - comment: z - .string() - .min(0, { message: '' }) - .max(50, { message: '50文字になるまで削除してください' }), // FIXME: 上限は暫定値。 + comment: z.string().min(0, { error: '' }).max(50, { error: '50文字になるまで削除してください' }), // FIXME: 上限は暫定値。 }); export const workBookSchema = z.object({ authorId: z.string(), title: z .string() - .min(3, { message: '3文字以上入力してください' }) - .max(200, { message: '200文字になるまで削除してください' }), + .min(3, { error: '3文字以上入力してください' }) + .max(200, { error: '200文字になるまで削除してください' }), description: z .string() - .min(0, { message: '' }) - .max(300, { message: '300文字になるまで削除してください' }), + .min(0, { error: '' }) + .max(300, { error: '300文字になるまで削除してください' }), editorialUrl: z .string() - .min(0, { message: '' }) - .max(300, { message: '300文字になるまで削除してください' }) - .refine(isValidUrl, { message: 'URLを再入力してください' }), // カリキュラムのトピック解説用のURL。HACK: 「ユーザ作成」の場合も利用できるようにするかは要検討。 + .min(0, { error: '' }) + .max(300, { error: '300文字になるまで削除してください' }) + .refine(isValidUrl, { error: 'URLを再入力してください' }), // カリキュラムのトピック解説用のURL。HACK: 「ユーザ作成」の場合も利用できるようにするかは要検討。 isPublished: z.boolean(), isOfficial: z.boolean(), isReplenished: z.boolean(), // カリキュラムの【補充】を識別するために使用 @@ -82,16 +79,16 @@ export const workBookSchema = z.object({ } return value.length <= 30; }, - { message: '30文字以下になるまで削除してください' }, + { error: '30文字以下になるまで削除してください' }, ) .transform((value) => value === '' || value === null || value === undefined ? undefined : value.toLowerCase(), ) .refine((value) => value === undefined || isValidUrlSlug(value), { - message: '半角英小文字、半角数字、ハイフンのみ使用できます(数字のみは不可)', + error: '半角英小文字、半角数字、ハイフンのみ使用できます(数字のみは不可)', }), workBookTasks: z .array(workBookTaskSchema) - .min(1, { message: '1問以上登録してください' }) - .max(200, { message: '200問以下になるまで削除してください' }), + .min(1, { error: '1問以上登録してください' }) + .max(200, { error: '200問以下になるまで削除してください' }), }); diff --git a/src/routes/(admin)/account_transfer/+page.server.ts b/src/routes/(admin)/account_transfer/+page.server.ts index 67497cebe..5063dff8f 100644 --- a/src/routes/(admin)/account_transfer/+page.server.ts +++ b/src/routes/(admin)/account_transfer/+page.server.ts @@ -2,7 +2,7 @@ // https://superforms.rocks/get-started import { redirect, type Actions } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms/server'; -import { zod } from 'sveltekit-superforms/adapters'; +import { zod4 } from 'sveltekit-superforms/adapters'; import * as userService from '$lib/services/users'; import * as taskResultService from '$lib/services/task_results'; @@ -29,7 +29,7 @@ export async function load({ locals }) { throw redirect(TEMPORARY_REDIRECT, LOGIN_PAGE); } - const form = await superValidate(null, zod(accountTransferSchema)); + const form = await superValidate(null, zod4(accountTransferSchema)); // HACK: accountTransferMessagesは、アカウント移行に関するメッセージを確実に表示するために必要。 // 原因: form送信後にload関数が呼び出されているため。 @@ -46,7 +46,7 @@ export async function load({ locals }) { export const actions: Actions = { default: async ({ request }) => { try { - const form = await superValidate(request, zod(accountTransferSchema)); + const form = await superValidate(request, zod4(accountTransferSchema)); if (!form.valid) { return { diff --git a/src/routes/workbooks/create/+page.server.ts b/src/routes/workbooks/create/+page.server.ts index 0eaaecf36..18fac83d6 100644 --- a/src/routes/workbooks/create/+page.server.ts +++ b/src/routes/workbooks/create/+page.server.ts @@ -1,6 +1,6 @@ import { error, fail, redirect } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms/server'; -import { zod } from 'sveltekit-superforms/adapters'; +import { zod4 } from 'sveltekit-superforms/adapters'; import { workBookSchema } from '$lib/zod/schema'; @@ -24,7 +24,7 @@ export const load = async ({ locals }) => { redirect(TEMPORARY_REDIRECT, '/login'); } - const form = await superValidate(null, zod(workBookSchema)); + const form = await superValidate(null, zod4(workBookSchema)); const author = locals.user; const isAdmin = author.role === Roles.ADMIN; @@ -52,7 +52,7 @@ export const actions = { return fail(FORBIDDEN, { message: '管理者のみ問題集を作成できます。' }); } - const form = await superValidate(request, zod(workBookSchema)); + const form = await superValidate(request, zod4(workBookSchema)); if (!form.valid) { return fail(BAD_REQUEST, { diff --git a/src/routes/workbooks/edit/[slug]/+page.server.ts b/src/routes/workbooks/edit/[slug]/+page.server.ts index 808526d23..48280af43 100644 --- a/src/routes/workbooks/edit/[slug]/+page.server.ts +++ b/src/routes/workbooks/edit/[slug]/+page.server.ts @@ -1,6 +1,6 @@ import { redirect, fail } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms/server'; -import { zod } from 'sveltekit-superforms/adapters'; +import { zod4 } from 'sveltekit-superforms/adapters'; import { getLoggedInUser, canEdit, isAdmin } from '$lib/utils/authorship'; import { Roles } from '$lib/types/user'; @@ -20,7 +20,7 @@ export async function load({ locals, params }) { const slug = params.slug.toLowerCase(); const workBookWithAuthor = await getWorkbookWithAuthor(slug); - const form = await superValidate(null, zod(workBookSchema)); + const form = await superValidate(null, zod4(workBookSchema)); const workBook = { ...workBookWithAuthor.workBook, urlSlug: workBookWithAuthor.workBook.urlSlug ?? undefined, @@ -65,7 +65,7 @@ export async function load({ locals, params }) { export const actions = { default: async ({ request, params }) => { console.log('form -> actions -> update'); - const form = await superValidate(request, zod(workBookSchema)); + const form = await superValidate(request, zod4(workBookSchema)); if (!form.valid) { return { diff --git a/src/test/lib/utils/auth_forms.test.ts b/src/test/lib/utils/auth_forms.test.ts index ef634e0dc..0820cd882 100644 --- a/src/test/lib/utils/auth_forms.test.ts +++ b/src/test/lib/utils/auth_forms.test.ts @@ -21,7 +21,7 @@ vi.mock('sveltekit-superforms/server', () => ({ })); vi.mock('sveltekit-superforms/adapters', () => ({ - zod: vi.fn(), + zod4: vi.fn(), })); vi.mock('$lib/zod/schema', () => ({ @@ -45,7 +45,7 @@ vi.mock('$lib/constants/navbar-links', () => ({ // Import AFTER mocking import { redirect } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms/server'; -import { zod } from 'sveltekit-superforms/adapters'; +import { zod4 } from 'sveltekit-superforms/adapters'; import { initializeAuthForm, @@ -137,7 +137,7 @@ describe('auth_forms', () => { } as unknown as SuperValidated, string>; }); - vi.mocked(zod).mockImplementation((schema: unknown) => schema as any); + vi.mocked(zod4).mockImplementation((schema: unknown) => schema as any); }); afterEach(() => {