Skip to content

Conversation

@amotarao
Copy link
Member

Summary

  • microCMS スキーマの型定義とバリデーションライブラリを実装
  • 13種類のフィールドタイプをサポート(text, textArea, richEditor, richEditorV2, media, mediaList, date, boolean, select, relation, relationList, number, iframe)
  • Zod v4 による厳密なバリデーション(enum による選択肢の検証を含む)
  • ビルド時に JSON Schema を自動生成

Test plan

  • 全テストが通ることを確認
  • schema-examples の実際の JSON ファイルでバリデーションが成功することを確認
  • ビルドが成功し、schema.json が生成されることを確認

🤖 Generated with Claude Code

amotarao and others added 9 commits December 30, 2025 23:14
- Add Zod schema definitions for all microCMS field types
- Support 13 field kinds: text, textArea, richEditor, richEditorV2, media, mediaList, date, boolean, select, relation, relationList, number, iframe
- Add comprehensive validation rules for each field type
- Add test suite with schema-examples validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add richEditorOptionSchema enum (29 options)
- Add richEditorV2OptionSchema enum (28 options)
- Add mediaListLayoutSchema enum (4 layouts)
- Update field schemas to use enum validators

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add scripts/generate-json-schema.ts to output schema.json
- Update build script to run tsc and schema generation
- Export schema.json in package.json exports

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Dec 30, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

新しいパッケージ microcms-api-schema-schema を追加し、Zod ベースの API スキーマ定義・検証、JSON Schema 生成スクリプト、テスト、TypeScript 設定、および CI(型チェック・テスト)を導入しました。

Changes

Cohort / File(s) 変更内容
GitHub Actions CI 設定
\.github/workflows/ci.yml
ジョブ名を format-checkci に変更。type-checkpnpm --filter microcms-api-schema-schema type-check)と testpnpm --filter microcms-api-schema-schema test)ステップを追加。
パッケージメタ・設定
packages/microcms-api-schema-schema/package.json, packages/microcms-api-schema-schema/tsconfig.json, packages/microcms-api-schema-schema/vitest.config.ts, packages/microcms-api-schema-schema/.gitignore, packages/microcms-api-schema-schema/README.md
パッケージメタ、スクリプト(dev/build/type-check/test 等)、公開設定、TypeScript/Vitest 設定、.gitignore、README を追加。バージョンを 0.0.1-alpha.0 に設定。
スキーマ定義(公開 API)
packages/microcms-api-schema-schema/src/schema.ts, packages/microcms-api-schema-schema/src/index.ts
Zod による包括的な apiSchemaSchema(各種 apiFields 定義・検証)を実装し、apiSchemaSchema と型 ApiSchemaSchema をエクスポート。index で再エクスポートを追加。
スキーマ JSON 生成スクリプト
packages/microcms-api-schema-schema/scripts/generate-json-schema.ts
apiSchemaSchema を JSON Schema に変換して dist/schema.json を出力するスクリプトを追加。
テスト
packages/microcms-api-schema-schema/src/schema.test.ts, packages/microcms-api-schema-schema/src/schema-examples.test.ts
Vitest テストを追加:公式例・複合フィールドの正/負ケース検証および schema-examples の検証。
スキーマサンプル
schema-examples/min-max.json
多数フィールドタイプの最小/最大バリアントを網羅する大規模サンプル JSON を追加。

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer
  participant GH as GitHub Actions
  participant PN as pnpm (workspace)
  participant Test as Vitest / Node tests
  participant Script as generate-json-schema (Node)
  participant FS as Filesystem (dist)

  Dev->>GH: push / PR
  GH->>PN: run ci job (includes format-check)
  PN->>PN: run type-check (pnpm --filter ... type-check)
  PN->>GH: type-check result
  GH->>PN: run test (pnpm --filter ... test)
  PN->>Test: execute Vitest suites
  Test->>Script: tests may import/run generate-json-schema
  Script->>FS: write dist/schema.json
  Test->>PN: test result
  PN->>GH: report status
  GH->>Dev: status (success/failure)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 新しい箱にスキーマを詰めたよ、Zod の庭でぴょん
型を確かめて、テストでひと跳び
JSON を書いて、dist にしまうよ📦
CI が見守る、緑のランで
バグは穴に落ちないようにぴょんぴょん ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title accurately describes the main objective of the changeset: setting up a new schema package with Zod-based validation.
Description check ✅ Passed The pull request description is clearly related to the changeset, detailing the implementation of a TypeScript schema validation library with Zod, supported field types, and build processes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d40a30 and 3167022.

📒 Files selected for processing (1)
  • packages/microcms-api-schema-schema/package.json

Comment @coderabbitai help to get the list of available commands and usage tips.

amotarao and others added 2 commits December 30, 2025 23:51
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@amotarao amotarao force-pushed the feature/setup-schema-package branch from 47bff4a to 8e3a094 Compare December 30, 2025 14:54
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (6)
packages/schema/vitest.config.ts (1)

1-3: テスト設定の追加を検討してください。

現在の設定は有効ですが、一般的なVitestの設定を追加することで開発体験が向上します。例えば、グローバルなテストAPIの有効化やカバレッジ設定などです。

🔎 推奨される設定例
 import { defineConfig } from "vitest/config";
 
-export default defineConfig({});
+export default defineConfig({
+  test: {
+    globals: true,
+  },
+});
packages/schema/src/schema-examples.test.ts (2)

8-68: テストケースの重複を解消してください。

5つのテストケースが同一のロジックを繰り返しています。test.eachを使用してコードの重複を削減し、保守性を向上させることを推奨します。

🔎 リファクタリング案
 describe("schema-examples のファイルをバリデーション", () => {
-  test("official-categories.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-categories.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("official-news.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-news.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("official-blogs.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-blogs.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("official-banner.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-banner.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("min-max.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "min-max.json");
+  test.each([
+    "official-categories.json",
+    "official-news.json",
+    "official-blogs.json",
+    "official-banner.json",
+    "min-max.json",
+  ])("%s", (filename) => {
+    const filePath = join(SCHEMA_EXAMPLES_DIR, filename);
     const content = readFileSync(filePath, "utf-8");
     const schema = JSON.parse(content);
 
     const result = apiSchemaSchema.safeParse(schema);
     if (!result.success) {
       console.error(result.error);
     }
     expect(result.success).toBe(true);
   });
 });

14-18: エラー報告の改善を検討してください。

console.errorでエラーを出力していますが、より詳細なエラーメッセージを提供するためにexpectのカスタムメッセージやresult.error.format()の使用を検討してください。

🔎 改善案
     const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
+    expect(result.success, result.success ? "" : JSON.stringify(result.error.format(), null, 2)).toBe(true);
packages/schema/package.json (1)

2-2: パッケージ名の重複を確認してください。

パッケージ名に「schema」が2回含まれています(microcms-api-schema-schema)。意図的な命名でない場合は、microcms-api-schemaなどへの変更を検討してください。

packages/schema/scripts/generate-json-schema.ts (1)

12-15: エラーハンドリングの追加を推奨します。

ファイル書き込み操作にエラーハンドリングがありません。ビルドスクリプトでは、失敗時に明確なエラーメッセージを出力することで、CI/CDでのデバッグが容易になります。

🔎 提案する修正
-writeFileSync(
-  join(distDir, "schema.json"),
-  JSON.stringify(z.toJSONSchema(apiSchemaSchema), null, 2),
-);
-
-console.log("Generated schema.json");
+try {
+  writeFileSync(
+    join(distDir, "schema.json"),
+    JSON.stringify(z.toJSONSchema(apiSchemaSchema), null, 2),
+  );
+  console.log("Generated schema.json");
+} catch (error) {
+  console.error("Failed to generate schema.json:", error);
+  process.exit(1);
+}
packages/schema/src/schema.test.ts (1)

4-4: describeブロック名の不一致について。

describeブロック名がmicroCMSSchemaSchemaとなっていますが、実際のエクスポート名はapiSchemaSchemaです。一貫性のため、名前を揃えることを推奨します。

🔎 提案する修正
-describe("microCMSSchemaSchema", () => {
+describe("apiSchemaSchema", () => {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 77cd979 and 8e3a094.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • .github/workflows/ci.yml
  • packages/schema/.gitignore
  • packages/schema/README.md
  • packages/schema/package.json
  • packages/schema/scripts/generate-json-schema.ts
  • packages/schema/src/index.ts
  • packages/schema/src/schema-examples.test.ts
  • packages/schema/src/schema.test.ts
  • packages/schema/src/schema.ts
  • packages/schema/tsconfig.json
  • packages/schema/vitest.config.ts
  • pnpm-workspace.yaml
  • schema-examples/min-max.json
🧰 Additional context used
🧬 Code graph analysis (1)
packages/schema/scripts/generate-json-schema.ts (1)
packages/schema/src/schema.ts (1)
  • apiSchemaSchema (242-245)
🔇 Additional comments (16)
packages/schema/.gitignore (1)

1-1: 問題ありません。

ビルド成果物を除外する標準的な設定です。

packages/schema/README.md (1)

1-26: 明確なドキュメントです。

パッケージの概要、インストール方法、開発コマンドが適切に記載されています。

packages/schema/src/index.ts (1)

1-1: 適切なパブリックAPIの定義です。

スキーマと型を明確にエクスポートしています。

pnpm-workspace.yaml (1)

1-2: 標準的なモノレポ設定です。

pnpmワークスペースの設定として適切です。

.github/workflows/ci.yml (1)

10-26: CI設定の改善が適切です。

ジョブ名の変更とフォーマットチェックの設定は適切です。

packages/schema/package.json (1)

31-35: 開発依存関係は適切です。

TypeScript、Vitest、型定義のバージョンが適切に設定されています。CI で Node 24 を使用しているため、@types/node のバージョンも適合しています。

packages/schema/tsconfig.json (1)

1-20: LGTM!

TypeScript設定は適切です。ES2022ターゲット、ESNextモジュール、bundlerモジュール解決は現代的なパッケージに適しており、strictモードと宣言ファイル生成も正しく設定されています。

packages/schema/src/schema.test.ts (2)

89-165: LGTM!

複雑なスキーマのテストケースは、多様なフィールドタイプとバリデーションオプションを包括的にカバーしています。richEditorV2Options、カラーリスト、フォントサイズリスト、カスタムクラスなどの高度な設定もテストされています。


167-199: LGTM!

ネガティブテストケースが適切に実装されています。必須フィールドの欠落と無効なkind値の両方をカバーしており、スキーマバリデーションの堅牢性を確認できます。

schema-examples/min-max.json (1)

1-355: LGTM!

この例ファイルは、13種類のフィールドタイプすべてについて、最小構成と最大構成の両方を網羅しています。バリデーション設定、レイアウトオプション、リッチエディタ設定など、包括的なテストデータとして優れています。

packages/schema/src/schema.ts (5)

242-245: customFieldsの型定義について確認してください。

customFieldsz.array(z.unknown())として定義されています。将来的にカスタムフィールドのスキーマを追加する予定であれば、TODOコメントを追加しておくと、意図が明確になります。


226-240: LGTM!

z.discriminatedUnionkindフィールドで使用しているのは、フィールドタイプの識別に最適なアプローチです。これにより、型安全性とバリデーションのパフォーマンスが向上します。


38-69: LGTM!

旧リッチエディタのオプションスキーマは、レガシーAPIの仕様に沿った適切なenum定義です。


71-100: LGTM!

richEditorV2のオプションスキーマは、新しいエディタの機能セットを正確に反映しています。


133-142: このレビューコメントは不正確です。テキストフィールドでセレクト関連プロパティを持つことはmicroCMSの仕様です。

テスト結果から、テキストフィールドはselectItemsselectInitialValuemultipleSelectをオプションプロパティとして持つことが意図的な設計であることが確認されました。実際のスキーマ例(min-max.json)では、テキストフィールド(text_max)がこれらのプロパティを含みながら正常にバリデーションされています。一方、セレクトフィールドではこれらが必須プロパティ(optional指定なし)となっており、テキストフィールドとは異なる扱いになっています。テストスイートでもこの構造が期待動作として定義されており、問題はありません。

packages/schema/scripts/generate-json-schema.ts (1)

4-5: Zod v4のz.toJSONSchemaの使用は正しい。

z.toJSONSchema(apiSchemaSchema)は正しく使用されています。パラメータなしでの呼び出しは有効で、デフォルトのdraft-2020-12ターゲットで動作します。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/schema/src/schema-examples.test.ts (1)

12-72: コードの重複を削減することを推奨します。

5つのテストケースが同一のパターンを繰り返しています。test.each()を使用してパラメータ化テストにリファクタリングすることで、保守性と可読性が向上します。

🔎 リファクタリング案
 describe("schema-examples のファイルをバリデーション", () => {
-  test("official-categories.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-categories.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("official-news.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-news.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("official-blogs.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-blogs.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("official-banner.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "official-banner.json");
-    const content = readFileSync(filePath, "utf-8");
-    const schema = JSON.parse(content);
-
-    const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
-  });
-
-  test("min-max.json", () => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "min-max.json");
+  test.each([
+    "official-categories.json",
+    "official-news.json",
+    "official-blogs.json",
+    "official-banner.json",
+    "min-max.json",
+  ])("%s", (filename) => {
-    const filePath = join(SCHEMA_EXAMPLES_DIR, "min-max.json");
+    const filePath = join(SCHEMA_EXAMPLES_DIR, filename);
     const content = readFileSync(filePath, "utf-8");
     const schema = JSON.parse(content);
 
     const result = apiSchemaSchema.safeParse(schema);
     if (!result.success) {
       console.error(result.error);
     }
     expect(result.success).toBe(true);
   });
 });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e3a094 and 58eeb3c.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • packages/schema/package.json
  • packages/schema/src/schema-examples.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/schema/package.json
  • .github/workflows/ci.yml
🔇 Additional comments (1)
packages/schema/src/schema-examples.test.ts (1)

7-10: 過去のレビュー指摘が正しく修正されています。

ESMモジュールで__dirnameを使用するための正しい実装になっています。fileURLToPathdirnameを使用して__dirnameを構築し、それを使ってSCHEMA_EXAMPLES_DIRを設定しています。

amotarao and others added 4 commits December 31, 2025 11:14
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
packages/microcms-api-schema-schema/src/schema.ts (1)

244-244: customFieldsの型定義を検討してください。

z.unknown()は柔軟性がありますが、カスタムフィールドの構造が既知であれば、より具体的な型を定義することで型安全性が向上します。現時点で構造が未定の場合は、TODOコメントを追加しておくと将来の実装者に役立ちます。

packages/microcms-api-schema-schema/src/schema-examples.test.ts (1)

20-31: テスト構造は適切です。

test.eachを使用したパラメータ化テストにより、複数のスキーマファイルを効率的にテストできています。

エラー発生時により詳細な情報を表示するため、console.errorの代わりにVitestのexpectでカスタムメッセージを含めることも検討できます。

🔎 オプションの改善案
     const result = apiSchemaSchema.safeParse(schema);
-    if (!result.success) {
-      console.error(result.error);
-    }
-    expect(result.success).toBe(true);
+    expect(result.success, `Validation failed for ${filename}: ${JSON.stringify(result.error?.issues, null, 2)}`).toBe(true);
packages/microcms-api-schema-schema/package.json (1)

4-4: パッケージの説明を追加してください。

descriptionフィールドが空です。npmやパッケージマネージャーでの検索性向上のため、パッケージの目的を簡潔に記述することを推奨します。

🔎 提案
-  "description": "",
+  "description": "Type definitions and Zod validation for microCMS API schemas",
packages/microcms-api-schema-schema/src/schema.test.ts (3)

5-87: 公式スキーマのテストケースは良好です。

3つの公式スキーマ(categories、news、blogs)に対するバリデーションテストが適切に実装されています。基本的なカバレッジとして十分です。

任意の改善案として、result.success === true の場合に、パース結果のデータ構造も検証することで、テストの精度を向上できます。


89-165: 複雑なスキーマテストの分割を検討してください。

このテストは複数のフィールドタイプ(text、richEditorV2、media、select、relationList、number)を一度に検証しています。テストが失敗した場合、どのフィールドが問題かを特定するのが困難になる可能性があります。

フィールドタイプごとに個別のテストケースに分割することで、デバッグが容易になり、テストの可読性も向上します。

🔎 フィールドタイプ別のテスト分割例
+  test("テキストフィールドの詳細バリデーション", () => {
+    const schema = {
+      apiFields: [
+        {
+          fieldId: "text_max",
+          name: "テキストフィールド 最大",
+          kind: "text",
+          description: "説明文",
+          required: true,
+          textSizeLimitValidation: { textSize: { min: 1, max: 30 } },
+          patternMatchValidation: { regexp: { pattern: "\\d", flags: "gi" } },
+          isUnique: true,
+        },
+      ],
+      customFields: [],
+    };
+    const result = apiSchemaSchema.safeParse(schema);
+    expect(result.success).toBe(true);
+  });
+
+  test("richEditorV2フィールドの詳細バリデーション", () => {
+    const schema = {
+      apiFields: [
+        {
+          fieldId: "rich_max",
+          name: "リッチエディタ 最大",
+          kind: "richEditorV2",
+          description: "説明文",
+          required: true,
+          richEditorV2Options: ["undo", "redo", "bold", "italic", "underline", "code"],
+          richEditorV2ColorList: [
+            { id: "KDKsIv0jXZ", value: "rgb(255, 255, 255)" },
+            { id: "vHyfNOIY51", value: "rgb(156, 102, 102)" },
+          ],
+          richEditorV2HideColorPicker: true,
+          richEditorV2FontSizeList: [{ id: "Sp9MppHN43", name: "表示名", value: "120" }],
+          customClassList: [{ id: "nL3_cmKOxf", name: "表示名", value: "class名" }],
+        },
+      ],
+      customFields: [],
+    };
+    const result = apiSchemaSchema.safeParse(schema);
+    expect(result.success).toBe(true);
+  });
+  
+  // 他のフィールドタイプについても同様に分割...

167-199: ネガティブテストでエラー詳細の検証を追加することを推奨します。

現在のネガティブテストは result.success === false のみを検証していますが、具体的なエラーメッセージや issues 配列を検証することで、テストの精度を向上できます。これにより、正しいバリデーションがトリガーされていることを確認でき、エラーメッセージのカバレッジも向上します。

🔎 エラー詳細検証の追加例
  test("不正なスキーマはバリデーションエラーになる", () => {
    const invalidSchema = {
      apiFields: [
        {
          fieldId: "test",
          // name が欠けている
          kind: "text",
          required: false,
        },
      ],
      customFields: [],
    };

    const result = apiSchemaSchema.safeParse(invalidSchema);
    expect(result.success).toBe(false);
+   if (!result.success) {
+     expect(result.error.issues).toHaveLength(1);
+     expect(result.error.issues[0].path).toContain("name");
+     expect(result.error.issues[0].code).toBe("invalid_type");
+   }
  });

  test("不正な kind はバリデーションエラーになる", () => {
    const invalidSchema = {
      apiFields: [
        {
          fieldId: "test",
          name: "テスト",
          kind: "invalid_kind",
          required: false,
        },
      ],
      customFields: [],
    };

    const result = apiSchemaSchema.safeParse(invalidSchema);
    expect(result.success).toBe(false);
+   if (!result.success) {
+     expect(result.error.issues).toHaveLength(1);
+     expect(result.error.issues[0].path).toContain("kind");
+   }
  });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82ff054 and aefb637.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .github/workflows/ci.yml
  • packages/microcms-api-schema-schema/.gitignore
  • packages/microcms-api-schema-schema/README.md
  • packages/microcms-api-schema-schema/package.json
  • packages/microcms-api-schema-schema/scripts/generate-json-schema.ts
  • packages/microcms-api-schema-schema/src/index.ts
  • packages/microcms-api-schema-schema/src/schema-examples.test.ts
  • packages/microcms-api-schema-schema/src/schema.test.ts
  • packages/microcms-api-schema-schema/src/schema.ts
  • packages/microcms-api-schema-schema/tsconfig.json
  • packages/microcms-api-schema-schema/vitest.config.ts
✅ Files skipped from review due to trivial changes (3)
  • packages/microcms-api-schema-schema/vitest.config.ts
  • packages/microcms-api-schema-schema/README.md
  • packages/microcms-api-schema-schema/.gitignore
🧰 Additional context used
🧬 Code graph analysis (3)
packages/microcms-api-schema-schema/src/schema.ts (1)
packages/microcms-api-schema-schema/src/index.ts (2)
  • apiSchemaSchema (1-1)
  • ApiSchemaSchema (1-1)
packages/microcms-api-schema-schema/src/schema-examples.test.ts (2)
packages/microcms-api-schema-schema/src/index.ts (1)
  • apiSchemaSchema (1-1)
packages/microcms-api-schema-schema/src/schema.ts (1)
  • apiSchemaSchema (242-245)
packages/microcms-api-schema-schema/scripts/generate-json-schema.ts (1)
packages/microcms-api-schema-schema/src/schema.ts (1)
  • apiSchemaSchema (242-245)
🔇 Additional comments (9)
packages/microcms-api-schema-schema/src/index.ts (1)

1-1: LGTM!

ESMモジュールとして正しく.js拡張子を使用しており、パブリックAPIサーフェスの構成が適切です。

packages/microcms-api-schema-schema/tsconfig.json (1)

1-20: LGTM!

ESMライブラリとして適切なTypeScript設定です。bundlerモジュール解決、strict mode、declaration生成の設定が正しく構成されています。

packages/microcms-api-schema-schema/src/schema.ts (1)

242-245: LGTM!

スキーマ定義は包括的で、13種類のフィールドタイプすべてを正しくカバーしています。z.discriminatedUnionの使用により、kindフィールドに基づく効率的な型判別が可能になっています。

packages/microcms-api-schema-schema/src/schema-examples.test.ts (1)

1-9: LGTM!

ESMモジュールでの__dirname代替パターンが正しく実装されています。import.meta.urlfileURLToPathの組み合わせは標準的なアプローチです。

packages/microcms-api-schema-schema/scripts/generate-json-schema.ts (1)

1-17: LGTM!

Zod v4のz.toJSONSchemaを使用したJSON Schema生成スクリプトが適切に実装されています。Node.js 24のネイティブTypeScriptサポートにより、.tsファイルを直接実行できます。

.github/workflows/ci.yml (1)

10-32: LGTM!

CIワークフローが適切に構成されています。pnpm --filterを使用したモノレポでのパッケージ指定、type-checkとtestステップの追加が正しく実装されています。

packages/microcms-api-schema-schema/package.json (1)

1-38: LGTM!

パッケージ構成が適切です。ESMモジュールとしての設定、エクスポート構成、ビルドスクリプトが正しく定義されています。

packages/microcms-api-schema-schema/src/schema.test.ts (2)

1-2: インポート部分は適切です。

必要な依存関係が正しくインポートされています。


92-104: このレビューコメントは正しくありません。スキーマの設計により、テキストフィールドでこれらのプロパティが意図的に許容されています。

スキーマ定義(src/schema.ts)を確認したところ、textFieldSchemaselectItemsselectInitialValuemultipleSelect をオプションプロパティとして明示的に定義しています。一方、selectFieldSchema ではこれらは必須プロパティです。テストコードのフィールド定義はスキーマの設計に完全に準拠しており、問題ありません。

amotarao and others added 2 commits January 3, 2026 17:44
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/microcms-api-schema-schema/package.json (1)

4-4: 説明フィールドが空です。

パッケージの説明を追加することをお勧めします。これにより、パッケージの目的がより明確になります。

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aefb637 and 19a2b1e.

📒 Files selected for processing (2)
  • packages/microcms-api-schema-schema/README.md
  • packages/microcms-api-schema-schema/package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/microcms-api-schema-schema/README.md
🔇 Additional comments (4)
packages/microcms-api-schema-schema/package.json (4)

6-9: srcディレクトリを含める意図を確認してください。

files配列に"src"が含まれています。通常、npmパッケージはdist(コンパイル済み)ファイルのみを配布し、ソースファイルは含めません。ソースマップやTypeScriptの直接インポートをサポートする目的であれば問題ありませんが、意図的でない場合はパッケージサイズが不必要に増加する可能性があります。


10-20: エントリーポイントの設定が適切です。

ESMモジュールタイプ、メインエントリーポイント、およびエクスポートマップの設定が正しく構成されています。schema.jsonの専用エクスポートも、ビルド時に生成されるJSONスキーマを公開する意図と一致しています。


21-29: スクリプト設定が適切です。

ビルド、型チェック、テストのスクリプトが適切に構成されています。ビルドの順序(TypeScriptコンパイル→スキーマ生成)も正しく、build:schemaでのTypeScriptファイルの直接実行もNode.js 24のネイティブサポートにより問題ありません。


30-37: 依存関係の設定が適切です。

Zod 4.2.1およびその他の開発依存関係のバージョン指定は適切です。TypeScript、Vitest、Node型定義のバージョンも最新で、パッケージの要件と一致しています。

@amotarao amotarao changed the title Setup schema package with Zod validation microCMS API スキーマバリデーションパッケージの実装 Jan 7, 2026
@amotarao amotarao merged commit 051abe9 into main Jan 7, 2026
1 check passed
@amotarao amotarao deleted the feature/setup-schema-package branch January 7, 2026 15:15
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @packages/microcms-api-schema-schema/package.json:
- Around line 40-47: The peerDependencies allow Zod v3 but schema.ts imports
from the v4-only path "zod/v4", causing runtime import errors for v3 users;
either change the import in schema.ts to import from "zod" (to maintain v3/v4
compatibility) or restrict package.json peerDependencies to "^4.0.0" only (if
you want to support v4 exclusively). Locate the import statement in schema.ts
that references "zod/v4" and update it to "zod" for compatibility, or update the
peerDependencies entry in package.json to "zod": "^4.0.0" to enforce v4-only
support and remove the v3 range and optional metadata accordingly.

In @packages/microcms-api-schema-schema/src/schema.ts:
- Line 1: Change the Zod import to be compatible with both v3 and v4 by
replacing the current import source "zod/v4" with the generic "zod"; update the
import statement that brings in the z namespace (used across this file by
symbols like z.object, z.enum, z.discriminatedUnion) so consumers using Zod v3
won't fail to resolve the module.
🧹 Nitpick comments (1)
packages/microcms-api-schema-schema/src/schema.ts (1)

242-245: customFieldsの型定義を検討してください。

customFieldsz.array(z.unknown())を使用していますが、カスタムフィールドの構造がある程度分かっている場合は、より具体的なスキーマを定義することで型安全性が向上します。

現在の実装で十分な柔軟性がある場合は、このままで問題ありません。

♻️ より具体的な型定義の例

もしカスタムフィールドが特定の構造を持つ場合:

const customFieldSchema = z.object({
  id: z.string(),
  // その他の既知のフィールド
});

export const apiSchemaSchema = z.object({
  apiFields: z.array(apiFieldSchema),
  customFields: z.array(customFieldSchema),
});

または、キーと値のペアの場合:

export const apiSchemaSchema = z.object({
  apiFields: z.array(apiFieldSchema),
  customFields: z.record(z.string(), z.unknown()),
});
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19a2b1e and 2d40a30.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • packages/microcms-api-schema-schema/.gitignore
  • packages/microcms-api-schema-schema/package.json
  • packages/microcms-api-schema-schema/scripts/generate-json-schema.ts
  • packages/microcms-api-schema-schema/src/schema.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/microcms-api-schema-schema/scripts/generate-json-schema.ts
🔇 Additional comments (6)
packages/microcms-api-schema-schema/.gitignore (1)

1-2: LGTM!

生成されたファイルを適切に除外しています。

.github/workflows/ci.yml (1)

10-32: LGTM!

CIジョブの名前変更と、型チェックおよびテストステップの追加は適切です。

packages/microcms-api-schema-schema/package.json (2)

6-24: LGTM!

パッケージの設定、ファイルリスト、およびexportsマップは適切に構成されています。


25-33: LGTM!

スクリプトの定義は適切です。Node.js 24のTypeScriptサポートにより、build:schemaスクリプトは正しく動作します。

packages/microcms-api-schema-schema/src/schema.ts (2)

126-240: LGTM!

フィールドスキーマの設計は優れています。baseFieldSchemaを拡張し、kindフィールドで識別する判別共用体パターンは、型安全性と保守性の両方を提供します。13種類のフィールドタイプすべてが適切に定義されています。


247-247: LGTM!

z.inferを使用した型エクスポートは適切です。

Comment on lines +40 to 47
"peerDependencies": {
"zod": "^3.25.0 || ^4.0.0"
},
"peerDependenciesMeta": {
"zod": {
"optional": true
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify zod import paths in schema.ts and related files

echo "=== Searching for zod imports ==="
rg -n "from ['\"]zod" packages/microcms-api-schema-schema/src/

echo ""
echo "=== Searching for zod require statements ==="
rg -n "require\(['\"]zod" packages/microcms-api-schema-schema/src/

Repository: plainbrew/microcms-schema

Length of output: 229


peerDependenciesとインポートパスの不一致を修正してください。

schema.ts"zod/v4"からインポートしていますが、このエクスポートパスはZod 4にのみ存在します。一方、package.jsonのpeerDependenciesはZod v3と v4の両方を許可しているため、ユーザーがZod 3をインストールするとインポートエラーが発生します。

以下のいずれかの対応が必要です:

  1. v3との互換性を維持する場合: schema.tsのインポートを"zod"に変更
  2. v4のみをサポートする場合: peerDependenciesを"^4.0.0"のみに制限
🤖 Prompt for AI Agents
In @packages/microcms-api-schema-schema/package.json around lines 40 - 47, The
peerDependencies allow Zod v3 but schema.ts imports from the v4-only path
"zod/v4", causing runtime import errors for v3 users; either change the import
in schema.ts to import from "zod" (to maintain v3/v4 compatibility) or restrict
package.json peerDependencies to "^4.0.0" only (if you want to support v4
exclusively). Locate the import statement in schema.ts that references "zod/v4"
and update it to "zod" for compatibility, or update the peerDependencies entry
in package.json to "zod": "^4.0.0" to enforce v4-only support and remove the v3
range and optional metadata accordingly.

@@ -0,0 +1,247 @@
import * as z from "zod/v4";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

インポートパスをZod v3との互換性のために修正してください。

"zod/v4"からのインポートはZod 4専用です。package.jsonのpeerDependenciesがv3とv4の両方を許可しているため、v3ユーザーはこのインポートに失敗します。

v3との互換性を維持する場合は、以下のように変更してください:

-import * as z from "zod/v4";
+import * as z from "zod";

現在のコードで使用されているZod API(z.objectz.enumz.discriminatedUnionなど)は、v3とv4の両方で動作します。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import * as z from "zod/v4";
import * as z from "zod";
🤖 Prompt for AI Agents
In @packages/microcms-api-schema-schema/src/schema.ts at line 1, Change the Zod
import to be compatible with both v3 and v4 by replacing the current import
source "zod/v4" with the generic "zod"; update the import statement that brings
in the z namespace (used across this file by symbols like z.object, z.enum,
z.discriminatedUnion) so consumers using Zod v3 won't fail to resolve the
module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants