From 57b1880e9e63f5d3e82ea14a8d851904666d0825 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:14:17 +0900 Subject: [PATCH 01/23] setup workspace --- pnpm-workspace.yaml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 pnpm-workspace.yaml diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..dee51e9 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" From eb6cfa088e711b8a82569a3061e2cc9386a296a5 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:14:39 +0900 Subject: [PATCH 02/23] setup schema --- packages/schema/.gitignore | 1 + packages/schema/README.md | 26 + packages/schema/package.json | 33 ++ packages/schema/src/index.ts | 2 + packages/schema/tsconfig.json | 20 + packages/schema/vitest.config.ts | 3 + pnpm-lock.yaml | 890 +++++++++++++++++++++++++++++++ 7 files changed, 975 insertions(+) create mode 100644 packages/schema/.gitignore create mode 100644 packages/schema/README.md create mode 100644 packages/schema/package.json create mode 100644 packages/schema/src/index.ts create mode 100644 packages/schema/tsconfig.json create mode 100644 packages/schema/vitest.config.ts diff --git a/packages/schema/.gitignore b/packages/schema/.gitignore new file mode 100644 index 0000000..1521c8b --- /dev/null +++ b/packages/schema/.gitignore @@ -0,0 +1 @@ +dist diff --git a/packages/schema/README.md b/packages/schema/README.md new file mode 100644 index 0000000..6584e52 --- /dev/null +++ b/packages/schema/README.md @@ -0,0 +1,26 @@ +# @microcms-schema/schema + +microCMS のスキーマ定義とバリデーションライブラリ + +## 概要 + +このパッケージは、microCMS のスキーマを TypeScript で型安全に定義し、Zod によるランタイムバリデーションを提供します。 + +## インストール + +```bash +pnpm add @microcms-schema/schema +``` + +## 開発 + +```bash +# ビルド +pnpm build + +# 開発モード(watch) +pnpm dev + +# テスト +pnpm test +``` diff --git a/packages/schema/package.json b/packages/schema/package.json new file mode 100644 index 0000000..1d18134 --- /dev/null +++ b/packages/schema/package.json @@ -0,0 +1,33 @@ +{ + "name": "@microcms-schema/schema", + "version": "0.1.0", + "description": "", + "license": "MIT", + "files": [ + "dist", + "src" + ], + "type": "module", + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "scripts": { + "build": "tsc", + "dev": "tsc --watch", + "test": "vitest" + }, + "dependencies": { + "zod": "^4.2.1" + }, + "devDependencies": { + "@types/node": "^24.10.4", + "typescript": "^5.7.3", + "vitest": "^4.0.16" + } +} diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts new file mode 100644 index 0000000..4356958 --- /dev/null +++ b/packages/schema/src/index.ts @@ -0,0 +1,2 @@ +// microCMS Schema Definition and Validation Library +export const version = "0.1.0"; diff --git a/packages/schema/tsconfig.json b/packages/schema/tsconfig.json new file mode 100644 index 0000000..b6aff44 --- /dev/null +++ b/packages/schema/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022"], + "moduleResolution": "bundler", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "**/*.test.ts"] +} diff --git a/packages/schema/vitest.config.ts b/packages/schema/vitest.config.ts new file mode 100644 index 0000000..8fb6f2d --- /dev/null +++ b/packages/schema/vitest.config.ts @@ -0,0 +1,3 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46b2cc4..c549920 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,183 @@ importers: specifier: ^0.21.0 version: 0.21.0 + packages/schema: + dependencies: + zod: + specifier: ^4.2.1 + version: 4.2.1 + devDependencies: + '@types/node': + specifier: ^24.10.4 + version: 24.10.4 + typescript: + specifier: ^5.7.3 + version: 5.9.3 + vitest: + specifier: ^4.0.16 + version: 4.0.16(@types/node@24.10.4)(yaml@2.8.2) + packages: + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@oxfmt/darwin-arm64@0.21.0': resolution: {integrity: sha512-defgGcchFCq2F7f5Nr3E4VXYW1sUhBGmIejgcPZ1gSsc8FAeT+vP5cSeGnDv+kcX+OKFDt89C67c31qZ6yZBsQ==} cpu: [arm64] @@ -60,6 +235,160 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-android-arm-eabi@4.54.0': + resolution: {integrity: sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.54.0': + resolution: {integrity: sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.54.0': + resolution: {integrity: sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.54.0': + resolution: {integrity: sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.54.0': + resolution: {integrity: sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.54.0': + resolution: {integrity: sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.54.0': + resolution: {integrity: sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.54.0': + resolution: {integrity: sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.54.0': + resolution: {integrity: sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.54.0': + resolution: {integrity: sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.54.0': + resolution: {integrity: sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.54.0': + resolution: {integrity: sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.54.0': + resolution: {integrity: sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.54.0': + resolution: {integrity: sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.54.0': + resolution: {integrity: sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.54.0': + resolution: {integrity: sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.54.0': + resolution: {integrity: sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openharmony-arm64@4.54.0': + resolution: {integrity: sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.54.0': + resolution: {integrity: sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.54.0': + resolution: {integrity: sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.54.0': + resolution: {integrity: sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.54.0': + resolution: {integrity: sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==} + cpu: [x64] + os: [win32] + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@24.10.4': + resolution: {integrity: sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==} + + '@vitest/expect@4.0.16': + resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==} + + '@vitest/mocker@4.0.16': + resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.0.16': + resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==} + + '@vitest/runner@4.0.16': + resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==} + + '@vitest/snapshot@4.0.16': + resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==} + + '@vitest/spy@4.0.16': + resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==} + + '@vitest/utils@4.0.16': + resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==} + ansi-escapes@7.2.0: resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} engines: {node: '>=18'} @@ -72,10 +401,18 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -98,13 +435,42 @@ packages: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + get-east-asian-width@1.4.0: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} @@ -135,6 +501,9 @@ packages: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -147,6 +516,14 @@ packages: resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==} engines: {node: '>=20.17'} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} @@ -156,15 +533,29 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} hasBin: true + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + restore-cursor@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -172,6 +563,14 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rollup@4.54.0: + resolution: {integrity: sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -180,6 +579,16 @@ packages: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -196,14 +605,116 @@ packages: resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + tinypool@2.0.0: resolution: {integrity: sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==} engines: {node: ^20.0.0 || >=22.0.0} + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + vite@7.3.0: + resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.0.16: + resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.16 + '@vitest/browser-preview': 4.0.16 + '@vitest/browser-webdriverio': 4.0.16 + '@vitest/ui': 4.0.16 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -213,8 +724,91 @@ packages: engines: {node: '>= 14.6'} hasBin: true + zod@4.2.1: + resolution: {integrity: sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==} + snapshots: + '@esbuild/aix-ppc64@0.27.2': + optional: true + + '@esbuild/android-arm64@0.27.2': + optional: true + + '@esbuild/android-arm@0.27.2': + optional: true + + '@esbuild/android-x64@0.27.2': + optional: true + + '@esbuild/darwin-arm64@0.27.2': + optional: true + + '@esbuild/darwin-x64@0.27.2': + optional: true + + '@esbuild/freebsd-arm64@0.27.2': + optional: true + + '@esbuild/freebsd-x64@0.27.2': + optional: true + + '@esbuild/linux-arm64@0.27.2': + optional: true + + '@esbuild/linux-arm@0.27.2': + optional: true + + '@esbuild/linux-ia32@0.27.2': + optional: true + + '@esbuild/linux-loong64@0.27.2': + optional: true + + '@esbuild/linux-mips64el@0.27.2': + optional: true + + '@esbuild/linux-ppc64@0.27.2': + optional: true + + '@esbuild/linux-riscv64@0.27.2': + optional: true + + '@esbuild/linux-s390x@0.27.2': + optional: true + + '@esbuild/linux-x64@0.27.2': + optional: true + + '@esbuild/netbsd-arm64@0.27.2': + optional: true + + '@esbuild/netbsd-x64@0.27.2': + optional: true + + '@esbuild/openbsd-arm64@0.27.2': + optional: true + + '@esbuild/openbsd-x64@0.27.2': + optional: true + + '@esbuild/openharmony-arm64@0.27.2': + optional: true + + '@esbuild/sunos-x64@0.27.2': + optional: true + + '@esbuild/win32-arm64@0.27.2': + optional: true + + '@esbuild/win32-ia32@0.27.2': + optional: true + + '@esbuild/win32-x64@0.27.2': + optional: true + + '@jridgewell/sourcemap-codec@1.5.5': {} + '@oxfmt/darwin-arm64@0.21.0': optional: true @@ -239,6 +833,126 @@ snapshots: '@oxfmt/win32-x64@0.21.0': optional: true + '@rollup/rollup-android-arm-eabi@4.54.0': + optional: true + + '@rollup/rollup-android-arm64@4.54.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.54.0': + optional: true + + '@rollup/rollup-darwin-x64@4.54.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.54.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.54.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.54.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.54.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.54.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.54.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.54.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.54.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.54.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.54.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.54.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.54.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.54.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.54.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.54.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.54.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.54.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.54.0': + optional: true + + '@standard-schema/spec@1.1.0': {} + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/node@24.10.4': + dependencies: + undici-types: 7.16.0 + + '@vitest/expect@4.0.16': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + chai: 6.2.2 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.16(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.2))': + dependencies: + '@vitest/spy': 4.0.16 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.0(@types/node@24.10.4)(yaml@2.8.2) + + '@vitest/pretty-format@4.0.16': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.16': + dependencies: + '@vitest/utils': 4.0.16 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.0.16': {} + + '@vitest/utils@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + tinyrainbow: 3.0.3 + ansi-escapes@7.2.0: dependencies: environment: 1.1.0 @@ -247,10 +961,14 @@ snapshots: ansi-styles@6.2.3: {} + assertion-error@2.0.1: {} + braces@3.0.3: dependencies: fill-range: 7.1.1 + chai@6.2.2: {} + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -268,12 +986,56 @@ snapshots: environment@1.1.0: {} + es-module-lexer@1.7.0: {} + + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + eventemitter3@5.0.1: {} + expect-type@1.3.0: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 + fsevents@2.3.3: + optional: true + get-east-asian-width@1.4.0: {} husky@9.1.7: {} @@ -311,6 +1073,10 @@ snapshots: strip-ansi: 7.1.2 wrap-ansi: 9.0.2 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -320,6 +1086,10 @@ snapshots: nano-spawn@2.0.0: {} + nanoid@3.3.11: {} + + obug@2.1.1: {} + onetime@7.0.0: dependencies: mimic-function: 5.0.1 @@ -337,10 +1107,22 @@ snapshots: '@oxfmt/win32-arm64': 0.21.0 '@oxfmt/win32-x64': 0.21.0 + pathe@2.0.3: {} + + picocolors@1.1.1: {} + picomatch@2.3.1: {} + picomatch@4.0.3: {} + pidtree@0.6.0: {} + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -348,6 +1130,36 @@ snapshots: rfdc@1.4.1: {} + rollup@4.54.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.54.0 + '@rollup/rollup-android-arm64': 4.54.0 + '@rollup/rollup-darwin-arm64': 4.54.0 + '@rollup/rollup-darwin-x64': 4.54.0 + '@rollup/rollup-freebsd-arm64': 4.54.0 + '@rollup/rollup-freebsd-x64': 4.54.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.54.0 + '@rollup/rollup-linux-arm-musleabihf': 4.54.0 + '@rollup/rollup-linux-arm64-gnu': 4.54.0 + '@rollup/rollup-linux-arm64-musl': 4.54.0 + '@rollup/rollup-linux-loong64-gnu': 4.54.0 + '@rollup/rollup-linux-ppc64-gnu': 4.54.0 + '@rollup/rollup-linux-riscv64-gnu': 4.54.0 + '@rollup/rollup-linux-riscv64-musl': 4.54.0 + '@rollup/rollup-linux-s390x-gnu': 4.54.0 + '@rollup/rollup-linux-x64-gnu': 4.54.0 + '@rollup/rollup-linux-x64-musl': 4.54.0 + '@rollup/rollup-openharmony-arm64': 4.54.0 + '@rollup/rollup-win32-arm64-msvc': 4.54.0 + '@rollup/rollup-win32-ia32-msvc': 4.54.0 + '@rollup/rollup-win32-x64-gnu': 4.54.0 + '@rollup/rollup-win32-x64-msvc': 4.54.0 + fsevents: 2.3.3 + + siginfo@2.0.0: {} + signal-exit@4.1.0: {} slice-ansi@7.1.2: @@ -355,6 +1167,12 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@3.10.0: {} + string-argv@0.3.2: {} string-width@7.2.0: @@ -372,12 +1190,82 @@ snapshots: dependencies: ansi-regex: 6.2.2 + tinybench@2.9.0: {} + + tinyexec@1.0.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tinypool@2.0.0: {} + tinyrainbow@3.0.3: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + typescript@5.9.3: {} + + undici-types@7.16.0: {} + + vite@7.3.0(@types/node@24.10.4)(yaml@2.8.2): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.54.0 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.4 + fsevents: 2.3.3 + yaml: 2.8.2 + + vitest@4.0.16(@types/node@24.10.4)(yaml@2.8.2): + dependencies: + '@vitest/expect': 4.0.16 + '@vitest/mocker': 4.0.16(vite@7.3.0(@types/node@24.10.4)(yaml@2.8.2)) + '@vitest/pretty-format': 4.0.16 + '@vitest/runner': 4.0.16 + '@vitest/snapshot': 4.0.16 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.3.0(@types/node@24.10.4)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.10.4 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -385,3 +1273,5 @@ snapshots: strip-ansi: 7.1.2 yaml@2.8.2: {} + + zod@4.2.1: {} From c84d2171daca8c8206abefd01726d06881fdb98f Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:33:12 +0900 Subject: [PATCH 03/23] add min-max example --- schema-examples/min-max.json | 332 +++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 schema-examples/min-max.json diff --git a/schema-examples/min-max.json b/schema-examples/min-max.json new file mode 100644 index 0000000..1509189 --- /dev/null +++ b/schema-examples/min-max.json @@ -0,0 +1,332 @@ +{ + "apiFields": [ + { "fieldId": "text_min", "name": "テキストフィールド 最小", "kind": "text", "required": false }, + { + "fieldId": "text_max", + "name": "テキストフィールド 最大", + "kind": "text", + "description": "説明文", + "required": true, + "selectItems": [], + "selectInitialValue": [], + "multipleSelect": false, + "textSizeLimitValidation": { "textSize": { "min": 1, "max": 30 } }, + "patternMatchValidation": { "regexp": { "pattern": "\\d", "flags": "gi" } }, + "isUnique": true + }, + { + "fieldId": "textarea_min", + "name": "テキストエリア 最小", + "kind": "textArea", + "required": false + }, + { + "fieldId": "textarea_max", + "name": "テキストエリア 最大", + "kind": "textArea", + "required": true, + "textSizeLimitValidation": { "textSize": { "min": 1, "max": 10 } }, + "patternMatchValidation": { "regexp": { "pattern": "\\d", "flags": "gi" } } + }, + { + "fieldId": "rich_min", + "name": "リッチエディタ 最小", + "kind": "richEditorV2", + "required": false + }, + { + "fieldId": "rich_max", + "name": "リッチエディタ 最大", + "kind": "richEditorV2", + "description": "説明文", + "required": true, + "richEditorV2Options": [ + "undo", + "redo", + "bold", + "italic", + "underline", + "code", + "listBullet", + "link", + "file", + "table", + "horizontalRule", + "textAlign", + "oembedly", + "clean", + "color", + "size", + "customClass", + "headerThree", + "headerFour", + "headerFive", + "paragraph", + "strike", + "blockquote", + "codeBlock", + "listOrdered", + "image", + "headerOne" + ], + "richEditorV2ColorList": [ + { "id": "KDKsIv0jXZ", "value": "rgb(255, 255, 255)" }, + { "id": "vHyfNOIY51", "value": "rgb(156, 102, 102)" }, + { "id": "y1berGb1f3", "value": "rgb(180, 68, 68)" } + ], + "richEditorV2HideColorPicker": true, + "richEditorV2FontSizeList": [{ "id": "Sp9MppHN43", "name": "表示名", "value": "120" }], + "customClassList": [{ "id": "nL3_cmKOxf", "name": "表示名", "value": "class名" }] + }, + { + "fieldId": "rich_ex_h1", + "name": "リッチエディタ h1以外", + "kind": "richEditorV2", + "required": true, + "richEditorV2Options": [ + "headerThree", + "headerFour", + "headerFive", + "undo", + "redo", + "paragraph", + "bold", + "italic", + "underline", + "strike", + "code", + "blockquote", + "codeBlock", + "listBullet", + "listOrdered", + "link", + "image", + "file", + "table", + "horizontalRule", + "textAlign", + "customClass", + "oembedly", + "clean", + "color", + "size", + "headerTwo" + ] + }, + { "fieldId": "image_min", "name": "画像 最小", "kind": "media", "required": false }, + { + "fieldId": "image_max", + "name": "画像 最大", + "kind": "media", + "description": "説明文", + "required": true, + "imageSizeValidation": { "imageSize": { "width": 100, "height": 100 } } + }, + { + "fieldId": "multi_image_min", + "name": "複数画像 最小", + "kind": "mediaList", + "required": false + }, + { + "fieldId": "multi_image_max", + "name": "複数画像 最大", + "kind": "mediaList", + "description": "説明文", + "required": true, + "imageSizeValidation": { "imageSize": { "width": 100, "height": 100 } }, + "mediaListLayout": "HORIZONTAL_SCROLL" + }, + { + "fieldId": "multi_image_2column", + "name": "複数画像 2カラム", + "kind": "mediaList", + "required": false, + "mediaListLayout": "GRID_2" + }, + { + "fieldId": "multi_image_3column", + "name": "複数画像 3カラム", + "kind": "mediaList", + "required": false, + "mediaListLayout": "GRID_3" + }, + { + "fieldId": "multi_image_4column", + "name": "複数画像 4カラム", + "kind": "mediaList", + "required": false, + "mediaListLayout": "GRID_4" + }, + { "fieldId": "date_min", "name": "日時 最小", "kind": "date", "required": false }, + { + "fieldId": "date_max", + "name": "日時 最大", + "kind": "date", + "description": "説明文", + "required": true, + "dateFormat": true + }, + { "fieldId": "bool_min", "name": "真偽値 最小", "kind": "boolean", "required": false }, + { + "fieldId": "bool_max", + "name": "真偽値 最大", + "kind": "boolean", + "description": "説明文", + "required": true, + "booleanInitialValue": true + }, + { + "fieldId": "select_min", + "name": "セレクトフィールド 最小", + "kind": "select", + "required": false, + "selectItems": [], + "selectInitialValue": [], + "multipleSelect": false + }, + { + "fieldId": "select_max", + "name": "セレクトフィールド 最大", + "kind": "select", + "required": true, + "selectItems": [ + { "id": "viO1_AW73E", "value": "item1" }, + { "id": "6bnahbE--K", "value": "item2" } + ], + "selectInitialValue": ["viO1_AW73E"], + "multipleSelect": true + }, + { "fieldId": "relation_min", "name": "参照 最小", "kind": "relation", "required": false }, + { + "fieldId": "relation_max", + "name": "参照 最大", + "kind": "relation", + "description": "説明文", + "required": true, + "referenceDisplayItem": "eO9ST_qUoe" + }, + { + "fieldId": "relation_multi_min", + "name": "複数参照 最小", + "kind": "relationList", + "required": false + }, + { + "fieldId": "relation_multi_max", + "name": "複数参照 最大", + "kind": "relationList", + "description": "説明文", + "required": true, + "referenceDisplayItem": "eO9ST_qUoe", + "relationListCountLimitValidation": { "relationListCount": { "min": 1, "max": 3 } } + }, + { "fieldId": "number_min", "name": "数字 最小", "kind": "number", "required": false }, + { + "fieldId": "number_max", + "name": "数字 最大", + "kind": "number", + "description": "説明文", + "required": true, + "numberSizeLimitValidation": { "numberSize": { "min": 1, "max": 300 } } + }, + { + "fieldId": "iframe_min", + "name": "拡張フィールド 最小", + "kind": "iframe", + "required": false, + "iframeUrl": "https://example.com" + }, + { + "fieldId": "iframe_max", + "name": "拡張フィールド 最大", + "kind": "iframe", + "description": "説明文", + "required": true, + "iframeUrl": "https://example.com" + }, + { + "fieldId": "rich_legacy_min", + "name": "旧リッチエディタ 最小", + "kind": "richEditor", + "required": false + }, + { + "fieldId": "rich_legacy_max", + "name": "旧リッチエディタ 最大", + "kind": "richEditor", + "description": "説明文", + "required": true, + "richEditorImageSize": true, + "richEditorOptions": [ + "headerThree", + "headerFour", + "headerFive", + "paragraph", + "sizeSmall", + "sizeNormal", + "sizeLarge", + "sizeHuge", + "bold", + "italic", + "underline", + "strike", + "code", + "background", + "color", + "align", + "blockquote", + "codeBlock", + "listOrdered", + "listBullet", + "indentRemove", + "indentAdd", + "scriptSub", + "scriptSuper", + "link", + "image", + "oembedly", + "clean", + "headerOne" + ] + }, + { + "fieldId": "rich_legacy_ex_h1", + "name": "旧リッチエディタ h1以外", + "kind": "richEditor", + "required": false, + "richEditorOptions": [ + "headerFour", + "headerFive", + "paragraph", + "sizeSmall", + "sizeNormal", + "sizeLarge", + "sizeHuge", + "bold", + "italic", + "underline", + "strike", + "code", + "background", + "color", + "align", + "blockquote", + "codeBlock", + "listOrdered", + "listBullet", + "indentRemove", + "indentAdd", + "scriptSub", + "scriptSuper", + "link", + "image", + "oembedly", + "clean", + "headerThree", + "headerTwo" + ] + } + ], + "customFields": [] +} From 60dd6488a05b41c1cd523995aa387c26df38f7a5 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:34:29 +0900 Subject: [PATCH 04/23] implement schema validation with zod MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- packages/schema/src/index.ts | 3 +- packages/schema/src/schema-examples.test.ts | 68 +++++++ packages/schema/src/schema.test.ts | 200 ++++++++++++++++++++ packages/schema/src/schema.ts | 181 ++++++++++++++++++ 4 files changed, 450 insertions(+), 2 deletions(-) create mode 100644 packages/schema/src/schema-examples.test.ts create mode 100644 packages/schema/src/schema.test.ts create mode 100644 packages/schema/src/schema.ts diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts index 4356958..8c6fb97 100644 --- a/packages/schema/src/index.ts +++ b/packages/schema/src/index.ts @@ -1,2 +1 @@ -// microCMS Schema Definition and Validation Library -export const version = "0.1.0"; +export { apiFieldSchema, apiSchema } from "./schema.js"; diff --git a/packages/schema/src/schema-examples.test.ts b/packages/schema/src/schema-examples.test.ts new file mode 100644 index 0000000..98152a5 --- /dev/null +++ b/packages/schema/src/schema-examples.test.ts @@ -0,0 +1,68 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, test } from "vitest"; +import { apiSchema } from "./schema.js"; + +const SCHEMA_EXAMPLES_DIR = join(__dirname, "../../../schema-examples"); + +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 = apiSchema.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 = apiSchema.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 = apiSchema.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 = apiSchema.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"); + const content = readFileSync(filePath, "utf-8"); + const schema = JSON.parse(content); + + const result = apiSchema.safeParse(schema); + if (!result.success) { + console.error(result.error); + } + expect(result.success).toBe(true); + }); +}); diff --git a/packages/schema/src/schema.test.ts b/packages/schema/src/schema.test.ts new file mode 100644 index 0000000..265be28 --- /dev/null +++ b/packages/schema/src/schema.test.ts @@ -0,0 +1,200 @@ +import { describe, expect, test } from "vitest"; +import { apiSchema } from "./schema.js"; + +describe("microCMSSchemaSchema", () => { + test("official-categories.json のスキーマをバリデーションできる", () => { + const schema = { + apiFields: [ + { + fieldId: "name", + name: "カテゴリ名", + kind: "text", + required: false, + isUnique: false, + }, + ], + customFields: [], + }; + + const result = apiSchema.safeParse(schema); + expect(result.success).toBe(true); + }); + + test("official-news.json のスキーマをバリデーションできる", () => { + const schema = { + apiFields: [ + { + fieldId: "title", + name: "タイトル", + kind: "text", + required: false, + isUnique: false, + }, + { + fieldId: "content", + name: "内容", + kind: "richEditorV2", + required: false, + }, + { + fieldId: "category", + name: "カテゴリ", + kind: "relation", + required: false, + }, + ], + customFields: [], + }; + + const result = apiSchema.safeParse(schema); + expect(result.success).toBe(true); + }); + + test("official-blogs.json のスキーマをバリデーションできる", () => { + const schema = { + apiFields: [ + { + fieldId: "title", + name: "タイトル", + kind: "text", + required: false, + isUnique: false, + }, + { + fieldId: "content", + name: "内容", + kind: "richEditorV2", + required: false, + }, + { + fieldId: "eyecatch", + name: "アイキャッチ", + kind: "media", + required: false, + }, + { + fieldId: "category", + name: "カテゴリ", + kind: "relation", + required: false, + }, + ], + customFields: [], + }; + + const result = apiSchema.safeParse(schema); + expect(result.success).toBe(true); + }); + + test("複雑なスキーマをバリデーションできる", () => { + const schema = { + apiFields: [ + { + fieldId: "text_max", + name: "テキストフィールド 最大", + kind: "text", + description: "説明文", + required: true, + selectItems: [], + selectInitialValue: [], + multipleSelect: false, + textSizeLimitValidation: { textSize: { min: 1, max: 30 } }, + patternMatchValidation: { regexp: { pattern: "\\d", flags: "gi" } }, + isUnique: true, + }, + { + 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名" }], + }, + { + fieldId: "image_max", + name: "画像 最大", + kind: "media", + description: "説明文", + required: true, + imageSizeValidation: { imageSize: { width: 100, height: 100 } }, + }, + { + fieldId: "select_max", + name: "セレクトフィールド 最大", + kind: "select", + required: true, + selectItems: [ + { id: "viO1_AW73E", value: "item1" }, + { id: "6bnahbE--K", value: "item2" }, + ], + selectInitialValue: ["viO1_AW73E"], + multipleSelect: true, + }, + { + fieldId: "relation_multi_max", + name: "複数参照 最大", + kind: "relationList", + description: "説明文", + required: true, + referenceDisplayItem: "eO9ST_qUoe", + relationListCountLimitValidation: { + relationListCount: { min: 1, max: 3 }, + }, + }, + { + fieldId: "number_max", + name: "数字 最大", + kind: "number", + description: "説明文", + required: true, + numberSizeLimitValidation: { numberSize: { min: 1, max: 300 } }, + }, + ], + customFields: [], + }; + + const result = apiSchema.safeParse(schema); + expect(result.success).toBe(true); + }); + + test("不正なスキーマはバリデーションエラーになる", () => { + const invalidSchema = { + apiFields: [ + { + fieldId: "test", + // name が欠けている + kind: "text", + required: false, + }, + ], + customFields: [], + }; + + const result = apiSchema.safeParse(invalidSchema); + expect(result.success).toBe(false); + }); + + test("不正な kind はバリデーションエラーになる", () => { + const invalidSchema = { + apiFields: [ + { + fieldId: "test", + name: "テスト", + kind: "invalid_kind", + required: false, + }, + ], + customFields: [], + }; + + const result = apiSchema.safeParse(invalidSchema); + expect(result.success).toBe(false); + }); +}); diff --git a/packages/schema/src/schema.ts b/packages/schema/src/schema.ts new file mode 100644 index 0000000..6bf28fa --- /dev/null +++ b/packages/schema/src/schema.ts @@ -0,0 +1,181 @@ +import { z } from "zod"; + +const textSizeLimitValidationSchema = z.object({ + textSize: z.object({ + min: z.number().optional(), + max: z.number().optional(), + }), +}); + +const patternMatchValidationSchema = z.object({ + regexp: z.object({ + pattern: z.string(), + flags: z.string().optional(), + }), +}); + +const imageSizeValidationSchema = z.object({ + imageSize: z.object({ + width: z.number(), + height: z.number(), + }), +}); + +const numberSizeLimitValidationSchema = z.object({ + numberSize: z.object({ + min: z.number().optional(), + max: z.number().optional(), + }), +}); + +const relationListCountLimitValidationSchema = z.object({ + relationListCount: z.object({ + min: z.number().optional(), + max: z.number().optional(), + }), +}); + +const selectItemSchema = z.object({ + id: z.string(), + value: z.string(), +}); + +const richEditorV2ColorListItemSchema = z.object({ + id: z.string(), + value: z.string(), +}); + +const richEditorV2FontSizeListItemSchema = z.object({ + id: z.string(), + name: z.string(), + value: z.string(), +}); + +const customClassListItemSchema = z.object({ + id: z.string(), + name: z.string(), + value: z.string(), +}); + +const baseFieldSchema = z.object({ + fieldId: z.string(), + name: z.string(), + description: z.string().optional(), + required: z.boolean(), +}); + +// テキストフィールド (text) +const textFieldSchema = baseFieldSchema.extend({ + kind: z.literal("text"), + isUnique: z.boolean().optional(), + textSizeLimitValidation: textSizeLimitValidationSchema.optional(), + patternMatchValidation: patternMatchValidationSchema.optional(), + selectItems: z.array(selectItemSchema).optional(), + selectInitialValue: z.array(z.string()).optional(), + multipleSelect: z.boolean().optional(), +}); + +// テキストエリア (textArea) +const textAreaFieldSchema = baseFieldSchema.extend({ + kind: z.literal("textArea"), + textSizeLimitValidation: textSizeLimitValidationSchema.optional(), + patternMatchValidation: patternMatchValidationSchema.optional(), +}); + +// リッチエディタ (richEditorV2) +const richEditorV2FieldSchema = baseFieldSchema.extend({ + kind: z.literal("richEditorV2"), + richEditorV2Options: z.array(z.string()).optional(), + richEditorV2ColorList: z.array(richEditorV2ColorListItemSchema).optional(), + richEditorV2HideColorPicker: z.boolean().optional(), + richEditorV2FontSizeList: z.array(richEditorV2FontSizeListItemSchema).optional(), + customClassList: z.array(customClassListItemSchema).optional(), +}); + +// 旧リッチエディタ (richEditor) +const richEditorFieldSchema = baseFieldSchema.extend({ + kind: z.literal("richEditor"), + richEditorImageSize: z.boolean().optional(), + richEditorOptions: z.array(z.string()).optional(), +}); + +// 画像 (media) +const mediaFieldSchema = baseFieldSchema.extend({ + kind: z.literal("media"), + imageSizeValidation: imageSizeValidationSchema.optional(), +}); + +// 複数画像 (mediaList) +const mediaListFieldSchema = baseFieldSchema.extend({ + kind: z.literal("mediaList"), + imageSizeValidation: imageSizeValidationSchema.optional(), + mediaListLayout: z.string().optional(), +}); + +// 日時 (date) +const dateFieldSchema = baseFieldSchema.extend({ + kind: z.literal("date"), + dateFormat: z.boolean().optional(), +}); + +// 真偽値 (boolean) +const booleanFieldSchema = baseFieldSchema.extend({ + kind: z.literal("boolean"), + booleanInitialValue: z.boolean().optional(), +}); + +// セレクトフィールド (select) +const selectFieldSchema = baseFieldSchema.extend({ + kind: z.literal("select"), + selectItems: z.array(selectItemSchema), + selectInitialValue: z.array(z.string()), + multipleSelect: z.boolean(), +}); + +// コンテンツ参照 (relation) +const relationFieldSchema = baseFieldSchema.extend({ + kind: z.literal("relation"), + referenceDisplayItem: z.string().optional(), +}); + +// 複数コンテンツ参照 (relationList) +const relationListFieldSchema = baseFieldSchema.extend({ + kind: z.literal("relationList"), + referenceDisplayItem: z.string().optional(), + relationListCountLimitValidation: relationListCountLimitValidationSchema.optional(), +}); + +// 数字 (number) +const numberFieldSchema = baseFieldSchema.extend({ + kind: z.literal("number"), + numberSizeLimitValidation: numberSizeLimitValidationSchema.optional(), +}); + +// 拡張フィールド (iframe) +const iframeFieldSchema = baseFieldSchema.extend({ + kind: z.literal("iframe"), + iframeUrl: z.string(), +}); + +export const apiFieldSchema = z.discriminatedUnion("kind", [ + textFieldSchema, + textAreaFieldSchema, + richEditorFieldSchema, + richEditorV2FieldSchema, + mediaFieldSchema, + mediaListFieldSchema, + dateFieldSchema, + booleanFieldSchema, + selectFieldSchema, + relationFieldSchema, + relationListFieldSchema, + numberFieldSchema, + iframeFieldSchema, +]); + +export const apiSchema = z.object({ + apiFields: z.array(apiFieldSchema), + customFields: z.array(z.unknown()), +}); + +export type ApiSchema = z.infer; From 04271e8d2125c8d832158206b79659d60f3b1447 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:39:17 +0900 Subject: [PATCH 05/23] rename to microcms-api-schema-schema --- packages/schema/README.md | 4 ++-- packages/schema/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/schema/README.md b/packages/schema/README.md index 6584e52..fe48153 100644 --- a/packages/schema/README.md +++ b/packages/schema/README.md @@ -1,4 +1,4 @@ -# @microcms-schema/schema +# microcms-api-schema-schema microCMS のスキーマ定義とバリデーションライブラリ @@ -9,7 +9,7 @@ microCMS のスキーマ定義とバリデーションライブラリ ## インストール ```bash -pnpm add @microcms-schema/schema +pnpm add microcms-api-schema-schema ``` ## 開発 diff --git a/packages/schema/package.json b/packages/schema/package.json index 1d18134..dc587e8 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -1,5 +1,5 @@ { - "name": "@microcms-schema/schema", + "name": "microcms-api-schema-schema", "version": "0.1.0", "description": "", "license": "MIT", From 6d2fcb6ed55c45de363292710635f7156d789411 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:39:37 +0900 Subject: [PATCH 06/23] add enum validation for field options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- packages/schema/src/schema.ts | 72 +++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/packages/schema/src/schema.ts b/packages/schema/src/schema.ts index 6bf28fa..af82d8c 100644 --- a/packages/schema/src/schema.ts +++ b/packages/schema/src/schema.ts @@ -35,6 +35,72 @@ const relationListCountLimitValidationSchema = z.object({ }), }); +const richEditorOptionSchema = z.enum([ + "headerOne", + "headerTwo", + "headerThree", + "headerFour", + "headerFive", + "paragraph", + "sizeSmall", + "sizeNormal", + "sizeLarge", + "sizeHuge", + "bold", + "italic", + "underline", + "strike", + "code", + "background", + "color", + "align", + "blockquote", + "codeBlock", + "listOrdered", + "listBullet", + "indentRemove", + "indentAdd", + "scriptSub", + "scriptSuper", + "link", + "image", + "oembedly", + "clean", +]); + +const richEditorV2OptionSchema = z.enum([ + "undo", + "redo", + "bold", + "italic", + "underline", + "strike", + "code", + "listBullet", + "listOrdered", + "link", + "file", + "image", + "table", + "horizontalRule", + "textAlign", + "oembedly", + "clean", + "color", + "size", + "customClass", + "headerOne", + "headerTwo", + "headerThree", + "headerFour", + "headerFive", + "paragraph", + "blockquote", + "codeBlock", +]); + +const mediaListLayoutSchema = z.enum(["HORIZONTAL_SCROLL", "GRID_2", "GRID_3", "GRID_4"]); + const selectItemSchema = z.object({ id: z.string(), value: z.string(), @@ -85,7 +151,7 @@ const textAreaFieldSchema = baseFieldSchema.extend({ // リッチエディタ (richEditorV2) const richEditorV2FieldSchema = baseFieldSchema.extend({ kind: z.literal("richEditorV2"), - richEditorV2Options: z.array(z.string()).optional(), + richEditorV2Options: z.array(richEditorV2OptionSchema).optional(), richEditorV2ColorList: z.array(richEditorV2ColorListItemSchema).optional(), richEditorV2HideColorPicker: z.boolean().optional(), richEditorV2FontSizeList: z.array(richEditorV2FontSizeListItemSchema).optional(), @@ -96,7 +162,7 @@ const richEditorV2FieldSchema = baseFieldSchema.extend({ const richEditorFieldSchema = baseFieldSchema.extend({ kind: z.literal("richEditor"), richEditorImageSize: z.boolean().optional(), - richEditorOptions: z.array(z.string()).optional(), + richEditorOptions: z.array(richEditorOptionSchema).optional(), }); // 画像 (media) @@ -109,7 +175,7 @@ const mediaFieldSchema = baseFieldSchema.extend({ const mediaListFieldSchema = baseFieldSchema.extend({ kind: z.literal("mediaList"), imageSizeValidation: imageSizeValidationSchema.optional(), - mediaListLayout: z.string().optional(), + mediaListLayout: mediaListLayoutSchema.optional(), }); // 日時 (date) From 86bfc840d95727a8a7c7b3e23379d0e4e8c33835 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:42:46 +0900 Subject: [PATCH 07/23] update min-max --- schema-examples/min-max.json | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/schema-examples/min-max.json b/schema-examples/min-max.json index 1509189..4e12eea 100644 --- a/schema-examples/min-max.json +++ b/schema-examples/min-max.json @@ -189,12 +189,35 @@ "fieldId": "select_max", "name": "セレクトフィールド 最大", "kind": "select", + "description": "説明文", + "required": true, + "selectItems": [ + { "id": "nSvCqkxNsk", "value": "item1" }, + { "id": "LMmv5JEb4A", "value": "item2" } + ], + "selectInitialValue": ["nSvCqkxNsk"], + "multipleSelect": false + }, + { + "fieldId": "select_multi_min", + "name": "セレクトフィールド 最小", + "kind": "select", + "required": false, + "selectItems": [], + "selectInitialValue": [], + "multipleSelect": true + }, + { + "fieldId": "select_multi_max", + "name": "セレクトフィールド 最大", + "kind": "select", + "description": "説明文", "required": true, "selectItems": [ { "id": "viO1_AW73E", "value": "item1" }, { "id": "6bnahbE--K", "value": "item2" } ], - "selectInitialValue": ["viO1_AW73E"], + "selectInitialValue": ["viO1_AW73E", "6bnahbE--K"], "multipleSelect": true }, { "fieldId": "relation_min", "name": "参照 最小", "kind": "relation", "required": false }, From 543e4093abce981f804fd56cba2cfced10c76af4 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:49:51 +0900 Subject: [PATCH 08/23] add JSON Schema generation on build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- packages/schema/package.json | 7 +++++-- packages/schema/scripts/generate-json-schema.ts | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 packages/schema/scripts/generate-json-schema.ts diff --git a/packages/schema/package.json b/packages/schema/package.json index dc587e8..40f112d 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -15,10 +15,13 @@ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" - } + }, + "./schema.json": "./dist/schema.json" }, "scripts": { - "build": "tsc", + "build": "pnpm build:tsc && pnpm build:schema", + "build:tsc": "tsc", + "build:schema": "node scripts/generate-json-schema.ts", "dev": "tsc --watch", "test": "vitest" }, diff --git a/packages/schema/scripts/generate-json-schema.ts b/packages/schema/scripts/generate-json-schema.ts new file mode 100644 index 0000000..17b01a0 --- /dev/null +++ b/packages/schema/scripts/generate-json-schema.ts @@ -0,0 +1,14 @@ +import { writeFileSync, mkdirSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { z } from "zod"; +import { apiSchema } from "../src/schema.ts"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const distDir = join(__dirname, "../dist"); + +mkdirSync(distDir, { recursive: true }); + +writeFileSync(join(distDir, "schema.json"), JSON.stringify(z.toJSONSchema(apiSchema), null, 2)); + +console.log("Generated schema.json"); From 25ed77a1faf56846374921a4c12dd6d13596c5da Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:49:59 +0900 Subject: [PATCH 09/23] v0.0.0 --- packages/schema/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/schema/package.json b/packages/schema/package.json index 40f112d..bd76129 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -1,6 +1,6 @@ { "name": "microcms-api-schema-schema", - "version": "0.1.0", + "version": "0.0.0", "description": "", "license": "MIT", "files": [ From 5f3e498f1a3e9d17ab46d27c768821b00401c0fe Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:51:41 +0900 Subject: [PATCH 10/23] rename apiSchemaSchema --- packages/schema/scripts/generate-json-schema.ts | 7 +++++-- packages/schema/src/index.ts | 2 +- packages/schema/src/schema-examples.test.ts | 12 ++++++------ packages/schema/src/schema.test.ts | 14 +++++++------- packages/schema/src/schema.ts | 6 +++--- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/packages/schema/scripts/generate-json-schema.ts b/packages/schema/scripts/generate-json-schema.ts index 17b01a0..b073c60 100644 --- a/packages/schema/scripts/generate-json-schema.ts +++ b/packages/schema/scripts/generate-json-schema.ts @@ -2,13 +2,16 @@ import { writeFileSync, mkdirSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { z } from "zod"; -import { apiSchema } from "../src/schema.ts"; +import { apiSchemaSchema } from "../src/schema.ts"; const __dirname = dirname(fileURLToPath(import.meta.url)); const distDir = join(__dirname, "../dist"); mkdirSync(distDir, { recursive: true }); -writeFileSync(join(distDir, "schema.json"), JSON.stringify(z.toJSONSchema(apiSchema), null, 2)); +writeFileSync( + join(distDir, "schema.json"), + JSON.stringify(z.toJSONSchema(apiSchemaSchema), null, 2), +); console.log("Generated schema.json"); diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts index 8c6fb97..7fa3c38 100644 --- a/packages/schema/src/index.ts +++ b/packages/schema/src/index.ts @@ -1 +1 @@ -export { apiFieldSchema, apiSchema } from "./schema.js"; +export { apiSchemaSchema, ApiSchemaSchema } from "./schema.js"; diff --git a/packages/schema/src/schema-examples.test.ts b/packages/schema/src/schema-examples.test.ts index 98152a5..48f8c77 100644 --- a/packages/schema/src/schema-examples.test.ts +++ b/packages/schema/src/schema-examples.test.ts @@ -1,7 +1,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test } from "vitest"; -import { apiSchema } from "./schema.js"; +import { apiSchemaSchema } from "./schema.js"; const SCHEMA_EXAMPLES_DIR = join(__dirname, "../../../schema-examples"); @@ -11,7 +11,7 @@ describe("schema-examples のファイルをバリデーション", () => { const content = readFileSync(filePath, "utf-8"); const schema = JSON.parse(content); - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); if (!result.success) { console.error(result.error); } @@ -23,7 +23,7 @@ describe("schema-examples のファイルをバリデーション", () => { const content = readFileSync(filePath, "utf-8"); const schema = JSON.parse(content); - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); if (!result.success) { console.error(result.error); } @@ -35,7 +35,7 @@ describe("schema-examples のファイルをバリデーション", () => { const content = readFileSync(filePath, "utf-8"); const schema = JSON.parse(content); - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); if (!result.success) { console.error(result.error); } @@ -47,7 +47,7 @@ describe("schema-examples のファイルをバリデーション", () => { const content = readFileSync(filePath, "utf-8"); const schema = JSON.parse(content); - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); if (!result.success) { console.error(result.error); } @@ -59,7 +59,7 @@ describe("schema-examples のファイルをバリデーション", () => { const content = readFileSync(filePath, "utf-8"); const schema = JSON.parse(content); - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); if (!result.success) { console.error(result.error); } diff --git a/packages/schema/src/schema.test.ts b/packages/schema/src/schema.test.ts index 265be28..7377e05 100644 --- a/packages/schema/src/schema.test.ts +++ b/packages/schema/src/schema.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "vitest"; -import { apiSchema } from "./schema.js"; +import { apiSchemaSchema } from "./schema.js"; describe("microCMSSchemaSchema", () => { test("official-categories.json のスキーマをバリデーションできる", () => { @@ -16,7 +16,7 @@ describe("microCMSSchemaSchema", () => { customFields: [], }; - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); expect(result.success).toBe(true); }); @@ -46,7 +46,7 @@ describe("microCMSSchemaSchema", () => { customFields: [], }; - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); expect(result.success).toBe(true); }); @@ -82,7 +82,7 @@ describe("microCMSSchemaSchema", () => { customFields: [], }; - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); expect(result.success).toBe(true); }); @@ -160,7 +160,7 @@ describe("microCMSSchemaSchema", () => { customFields: [], }; - const result = apiSchema.safeParse(schema); + const result = apiSchemaSchema.safeParse(schema); expect(result.success).toBe(true); }); @@ -177,7 +177,7 @@ describe("microCMSSchemaSchema", () => { customFields: [], }; - const result = apiSchema.safeParse(invalidSchema); + const result = apiSchemaSchema.safeParse(invalidSchema); expect(result.success).toBe(false); }); @@ -194,7 +194,7 @@ describe("microCMSSchemaSchema", () => { customFields: [], }; - const result = apiSchema.safeParse(invalidSchema); + const result = apiSchemaSchema.safeParse(invalidSchema); expect(result.success).toBe(false); }); }); diff --git a/packages/schema/src/schema.ts b/packages/schema/src/schema.ts index af82d8c..6620900 100644 --- a/packages/schema/src/schema.ts +++ b/packages/schema/src/schema.ts @@ -223,7 +223,7 @@ const iframeFieldSchema = baseFieldSchema.extend({ iframeUrl: z.string(), }); -export const apiFieldSchema = z.discriminatedUnion("kind", [ +const apiFieldSchema = z.discriminatedUnion("kind", [ textFieldSchema, textAreaFieldSchema, richEditorFieldSchema, @@ -239,9 +239,9 @@ export const apiFieldSchema = z.discriminatedUnion("kind", [ iframeFieldSchema, ]); -export const apiSchema = z.object({ +export const apiSchemaSchema = z.object({ apiFields: z.array(apiFieldSchema), customFields: z.array(z.unknown()), }); -export type ApiSchema = z.infer; +export type ApiSchemaSchema = z.infer; From 8e3a094d9a41039222522093daba4eba77dbd15b Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Tue, 30 Dec 2025 23:54:11 +0900 Subject: [PATCH 11/23] add test step to CI workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2689e3b..75d2647 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: pull_request: jobs: - format-check: + ci: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -24,3 +24,6 @@ jobs: - name: Check format run: pnpm format --check + + - name: Run tests + run: pnpm --filter microcms-api-schema-schema test run From 55f120e86ee5cb6f7635f85ece4ab46266b8c627 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Wed, 31 Dec 2025 11:04:46 +0900 Subject: [PATCH 12/23] =?UTF-8?q?test,=20test:watch=20=E5=88=86=E9=9B=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 +- packages/schema/package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 75d2647..98243d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,4 +26,4 @@ jobs: run: pnpm format --check - name: Run tests - run: pnpm --filter microcms-api-schema-schema test run + run: pnpm --filter microcms-api-schema-schema test diff --git a/packages/schema/package.json b/packages/schema/package.json index bd76129..7c3163f 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -23,7 +23,8 @@ "build:tsc": "tsc", "build:schema": "node scripts/generate-json-schema.ts", "dev": "tsc --watch", - "test": "vitest" + "test": "vitest run", + "test:watch": "vitest" }, "dependencies": { "zod": "^4.2.1" From 58eeb3ca5af93c8144ec2ec24a13c986327f8264 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Wed, 31 Dec 2025 11:06:20 +0900 Subject: [PATCH 13/23] __dirname --- packages/schema/src/schema-examples.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/schema/src/schema-examples.test.ts b/packages/schema/src/schema-examples.test.ts index 48f8c77..8ca51a5 100644 --- a/packages/schema/src/schema-examples.test.ts +++ b/packages/schema/src/schema-examples.test.ts @@ -1,8 +1,12 @@ import { readFileSync } from "node:fs"; -import { join } from "node:path"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; import { describe, expect, test } from "vitest"; import { apiSchemaSchema } from "./schema.js"; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + const SCHEMA_EXAMPLES_DIR = join(__dirname, "../../../schema-examples"); describe("schema-examples のファイルをバリデーション", () => { From ac49f23628782b44da61f276e6437d4be14ca69d Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Wed, 31 Dec 2025 11:14:04 +0900 Subject: [PATCH 14/23] =?UTF-8?q?refactor:=20test.each=20=E3=82=92?= =?UTF-8?q?=E4=BD=BF=E3=81=A3=E3=81=A6=20schema-examples=20=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=81=AE=E9=87=8D=E8=A4=87=E3=82=92=E8=A7=A3?= =?UTF-8?q?=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- packages/schema/src/schema-examples.test.ts | 60 ++++----------------- 1 file changed, 10 insertions(+), 50 deletions(-) diff --git a/packages/schema/src/schema-examples.test.ts b/packages/schema/src/schema-examples.test.ts index 8ca51a5..f26bbc0 100644 --- a/packages/schema/src/schema-examples.test.ts +++ b/packages/schema/src/schema-examples.test.ts @@ -9,57 +9,17 @@ const __dirname = dirname(__filename); const SCHEMA_EXAMPLES_DIR = join(__dirname, "../../../schema-examples"); -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 schemaFiles = [ + "official-categories.json", + "official-news.json", + "official-blogs.json", + "official-banner.json", + "min-max.json", +]; - 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"); +describe("schema-examples のファイルをバリデーション", () => { + test.each(schemaFiles)("%s", (filename) => { + const filePath = join(SCHEMA_EXAMPLES_DIR, filename); const content = readFileSync(filePath, "utf-8"); const schema = JSON.parse(content); From 82ff054f90b0ea48b4db3ac7ff113516c41d0977 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Wed, 31 Dec 2025 11:14:30 +0900 Subject: [PATCH 15/23] rename fn --- packages/schema/src/schema.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/schema/src/schema.test.ts b/packages/schema/src/schema.test.ts index 7377e05..88d64d6 100644 --- a/packages/schema/src/schema.test.ts +++ b/packages/schema/src/schema.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "vitest"; import { apiSchemaSchema } from "./schema.js"; -describe("microCMSSchemaSchema", () => { +describe("apiSchemaSchema", () => { test("official-categories.json のスキーマをバリデーションできる", () => { const schema = { apiFields: [ From db7ae12556887b1f491aa5e856dc07eacfe3de34 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Thu, 1 Jan 2026 12:28:04 +0900 Subject: [PATCH 16/23] rename to microcms-api-schema-schema --- packages/{schema => microcms-api-schema-schema}/.gitignore | 0 packages/{schema => microcms-api-schema-schema}/README.md | 0 packages/{schema => microcms-api-schema-schema}/package.json | 0 .../scripts/generate-json-schema.ts | 0 packages/{schema => microcms-api-schema-schema}/src/index.ts | 0 .../src/schema-examples.test.ts | 0 .../{schema => microcms-api-schema-schema}/src/schema.test.ts | 0 packages/{schema => microcms-api-schema-schema}/src/schema.ts | 0 packages/{schema => microcms-api-schema-schema}/tsconfig.json | 0 .../{schema => microcms-api-schema-schema}/vitest.config.ts | 0 pnpm-lock.yaml | 2 +- 11 files changed, 1 insertion(+), 1 deletion(-) rename packages/{schema => microcms-api-schema-schema}/.gitignore (100%) rename packages/{schema => microcms-api-schema-schema}/README.md (100%) rename packages/{schema => microcms-api-schema-schema}/package.json (100%) rename packages/{schema => microcms-api-schema-schema}/scripts/generate-json-schema.ts (100%) rename packages/{schema => microcms-api-schema-schema}/src/index.ts (100%) rename packages/{schema => microcms-api-schema-schema}/src/schema-examples.test.ts (100%) rename packages/{schema => microcms-api-schema-schema}/src/schema.test.ts (100%) rename packages/{schema => microcms-api-schema-schema}/src/schema.ts (100%) rename packages/{schema => microcms-api-schema-schema}/tsconfig.json (100%) rename packages/{schema => microcms-api-schema-schema}/vitest.config.ts (100%) diff --git a/packages/schema/.gitignore b/packages/microcms-api-schema-schema/.gitignore similarity index 100% rename from packages/schema/.gitignore rename to packages/microcms-api-schema-schema/.gitignore diff --git a/packages/schema/README.md b/packages/microcms-api-schema-schema/README.md similarity index 100% rename from packages/schema/README.md rename to packages/microcms-api-schema-schema/README.md diff --git a/packages/schema/package.json b/packages/microcms-api-schema-schema/package.json similarity index 100% rename from packages/schema/package.json rename to packages/microcms-api-schema-schema/package.json diff --git a/packages/schema/scripts/generate-json-schema.ts b/packages/microcms-api-schema-schema/scripts/generate-json-schema.ts similarity index 100% rename from packages/schema/scripts/generate-json-schema.ts rename to packages/microcms-api-schema-schema/scripts/generate-json-schema.ts diff --git a/packages/schema/src/index.ts b/packages/microcms-api-schema-schema/src/index.ts similarity index 100% rename from packages/schema/src/index.ts rename to packages/microcms-api-schema-schema/src/index.ts diff --git a/packages/schema/src/schema-examples.test.ts b/packages/microcms-api-schema-schema/src/schema-examples.test.ts similarity index 100% rename from packages/schema/src/schema-examples.test.ts rename to packages/microcms-api-schema-schema/src/schema-examples.test.ts diff --git a/packages/schema/src/schema.test.ts b/packages/microcms-api-schema-schema/src/schema.test.ts similarity index 100% rename from packages/schema/src/schema.test.ts rename to packages/microcms-api-schema-schema/src/schema.test.ts diff --git a/packages/schema/src/schema.ts b/packages/microcms-api-schema-schema/src/schema.ts similarity index 100% rename from packages/schema/src/schema.ts rename to packages/microcms-api-schema-schema/src/schema.ts diff --git a/packages/schema/tsconfig.json b/packages/microcms-api-schema-schema/tsconfig.json similarity index 100% rename from packages/schema/tsconfig.json rename to packages/microcms-api-schema-schema/tsconfig.json diff --git a/packages/schema/vitest.config.ts b/packages/microcms-api-schema-schema/vitest.config.ts similarity index 100% rename from packages/schema/vitest.config.ts rename to packages/microcms-api-schema-schema/vitest.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c549920..09d9571 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ importers: specifier: ^0.21.0 version: 0.21.0 - packages/schema: + packages/microcms-api-schema-schema: dependencies: zod: specifier: ^4.2.1 From aefb637b5610f0a04d673d7f97bcdb7b0483210f Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Fri, 2 Jan 2026 15:38:34 +0900 Subject: [PATCH 17/23] =?UTF-8?q?feat:=20type-check=20=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=AA=E3=83=97=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97?= =?UTF-8?q?=20CI=20=E3=81=AB=E7=B5=84=E3=81=BF=E8=BE=BC=E3=81=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 3 +++ packages/microcms-api-schema-schema/package.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98243d3..22bbac7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,5 +25,8 @@ jobs: - name: Check format run: pnpm format --check + - name: Type check + run: pnpm --filter microcms-api-schema-schema type-check + - name: Run tests run: pnpm --filter microcms-api-schema-schema test diff --git a/packages/microcms-api-schema-schema/package.json b/packages/microcms-api-schema-schema/package.json index 7c3163f..22d2cd0 100644 --- a/packages/microcms-api-schema-schema/package.json +++ b/packages/microcms-api-schema-schema/package.json @@ -19,10 +19,11 @@ "./schema.json": "./dist/schema.json" }, "scripts": { + "dev": "tsc --watch", "build": "pnpm build:tsc && pnpm build:schema", "build:tsc": "tsc", "build:schema": "node scripts/generate-json-schema.ts", - "dev": "tsc --watch", + "type-check": "tsc --noEmit", "test": "vitest run", "test:watch": "vitest" }, From d778f66d5f6956aaafd70d0c716bb6fc6afacaf2 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Sat, 3 Jan 2026 17:44:46 +0900 Subject: [PATCH 18/23] =?UTF-8?q?docs:=20README=20=E3=81=AE=E8=AA=AC?= =?UTF-8?q?=E6=98=8E=E3=82=92=20API=20=E3=82=B9=E3=82=AD=E3=83=BC=E3=83=9E?= =?UTF-8?q?=E3=81=AE=E3=82=B9=E3=82=AD=E3=83=BC=E3=83=9E=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6=E6=98=8E=E7=A2=BA=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- packages/microcms-api-schema-schema/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/microcms-api-schema-schema/README.md b/packages/microcms-api-schema-schema/README.md index fe48153..0842789 100644 --- a/packages/microcms-api-schema-schema/README.md +++ b/packages/microcms-api-schema-schema/README.md @@ -1,10 +1,10 @@ # microcms-api-schema-schema -microCMS のスキーマ定義とバリデーションライブラリ +microCMS の API スキーマを定義するためのスキーマライブラリ ## 概要 -このパッケージは、microCMS のスキーマを TypeScript で型安全に定義し、Zod によるランタイムバリデーションを提供します。 +このパッケージは、microCMS の API スキーマを TypeScript で型安全に定義し、Zod によるランタイムバリデーションを提供します。 ## インストール From 19a2b1eef15dea69bde90b52e1f62a9d26e825db Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Sat, 3 Jan 2026 17:45:13 +0900 Subject: [PATCH 19/23] rename pkg --- packages/microcms-api-schema-schema/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/microcms-api-schema-schema/package.json b/packages/microcms-api-schema-schema/package.json index 22d2cd0..63ee154 100644 --- a/packages/microcms-api-schema-schema/package.json +++ b/packages/microcms-api-schema-schema/package.json @@ -1,5 +1,5 @@ { - "name": "microcms-api-schema-schema", + "name": "@plainbrew/microcms-api-schema-schema", "version": "0.0.0", "description": "", "license": "MIT", From 703ce0a020d4bd232c480a945445ba96fe1c07ec Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Wed, 7 Jan 2026 23:51:29 +0900 Subject: [PATCH 20/23] =?UTF-8?q?schema.json=20=E3=82=92=20root=20?= =?UTF-8?q?=E3=81=AB=E5=87=BA=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/microcms-api-schema-schema/.gitignore | 1 + packages/microcms-api-schema-schema/package.json | 3 ++- .../microcms-api-schema-schema/scripts/generate-json-schema.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/microcms-api-schema-schema/.gitignore b/packages/microcms-api-schema-schema/.gitignore index 1521c8b..cf9e19f 100644 --- a/packages/microcms-api-schema-schema/.gitignore +++ b/packages/microcms-api-schema-schema/.gitignore @@ -1 +1,2 @@ +/schema.json dist diff --git a/packages/microcms-api-schema-schema/package.json b/packages/microcms-api-schema-schema/package.json index 63ee154..b1e5a8c 100644 --- a/packages/microcms-api-schema-schema/package.json +++ b/packages/microcms-api-schema-schema/package.json @@ -5,6 +5,7 @@ "license": "MIT", "files": [ "dist", + "schema.json", "src" ], "type": "module", @@ -16,7 +17,7 @@ "types": "./dist/index.d.ts", "import": "./dist/index.js" }, - "./schema.json": "./dist/schema.json" + "./schema.json": "./schema.json" }, "scripts": { "dev": "tsc --watch", diff --git a/packages/microcms-api-schema-schema/scripts/generate-json-schema.ts b/packages/microcms-api-schema-schema/scripts/generate-json-schema.ts index b073c60..5e81e10 100644 --- a/packages/microcms-api-schema-schema/scripts/generate-json-schema.ts +++ b/packages/microcms-api-schema-schema/scripts/generate-json-schema.ts @@ -5,7 +5,7 @@ import { z } from "zod"; import { apiSchemaSchema } from "../src/schema.ts"; const __dirname = dirname(fileURLToPath(import.meta.url)); -const distDir = join(__dirname, "../dist"); +const distDir = join(__dirname, "../"); mkdirSync(distDir, { recursive: true }); From bfbb03e760efd1420eaca911afd55c1d73b4d069 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Wed, 7 Jan 2026 23:56:49 +0900 Subject: [PATCH 21/23] =?UTF-8?q?zod=20=E3=82=92=20peerDependencies=20?= =?UTF-8?q?=E5=8C=96,=20v3,4=20=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/microcms-api-schema-schema/package.json | 14 ++++++++++---- packages/microcms-api-schema-schema/src/schema.ts | 2 +- pnpm-lock.yaml | 7 +++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/microcms-api-schema-schema/package.json b/packages/microcms-api-schema-schema/package.json index b1e5a8c..0c733db 100644 --- a/packages/microcms-api-schema-schema/package.json +++ b/packages/microcms-api-schema-schema/package.json @@ -28,12 +28,18 @@ "test": "vitest run", "test:watch": "vitest" }, - "dependencies": { - "zod": "^4.2.1" - }, "devDependencies": { "@types/node": "^24.10.4", "typescript": "^5.7.3", - "vitest": "^4.0.16" + "vitest": "^4.0.16", + "zod": "^4.2.1" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } } } diff --git a/packages/microcms-api-schema-schema/src/schema.ts b/packages/microcms-api-schema-schema/src/schema.ts index 6620900..9c3e3e4 100644 --- a/packages/microcms-api-schema-schema/src/schema.ts +++ b/packages/microcms-api-schema-schema/src/schema.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import * as z from "zod/v4"; const textSizeLimitValidationSchema = z.object({ textSize: z.object({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08213f8..3361fd3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,10 +19,6 @@ importers: version: 0.23.0 packages/microcms-api-schema-schema: - dependencies: - zod: - specifier: ^4.2.1 - version: 4.2.1 devDependencies: '@types/node': specifier: ^24.10.4 @@ -33,6 +29,9 @@ importers: vitest: specifier: ^4.0.16 version: 4.0.16(@types/node@24.10.4)(yaml@2.8.2) + zod: + specifier: ^4.2.1 + version: 4.2.1 packages: From 0da18158fb497772e57b0557da8ddfda6cddfd98 Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Thu, 8 Jan 2026 00:14:45 +0900 Subject: [PATCH 22/23] add prepare script --- packages/microcms-api-schema-schema/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/microcms-api-schema-schema/package.json b/packages/microcms-api-schema-schema/package.json index 28e3149..d3b6b13 100644 --- a/packages/microcms-api-schema-schema/package.json +++ b/packages/microcms-api-schema-schema/package.json @@ -29,7 +29,8 @@ "build:schema": "node scripts/generate-json-schema.ts", "type-check": "tsc --noEmit", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "prepare": "pnpm run build" }, "devDependencies": { "@types/node": "^24.10.4", From 31670225382bcd464a589a4024a7f7cbeb4cf04a Mon Sep 17 00:00:00 2001 From: Amon Sawamura Date: Thu, 8 Jan 2026 00:15:15 +0900 Subject: [PATCH 23/23] v0.0.1-alpha.0 --- packages/microcms-api-schema-schema/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/microcms-api-schema-schema/package.json b/packages/microcms-api-schema-schema/package.json index d3b6b13..103c397 100644 --- a/packages/microcms-api-schema-schema/package.json +++ b/packages/microcms-api-schema-schema/package.json @@ -1,6 +1,6 @@ { "name": "@plainbrew/microcms-api-schema-schema", - "version": "0.0.0", + "version": "0.0.1-alpha.0", "description": "", "license": "MIT", "files": [