Skip to main content 首页 创作者 interfacex-co-jp skills-frourio-framework frourio-framework-review
frourio-framework-review frourio (Fastify + aspida + zod ベースのTypeScriptフルスタックフレームワーク) 採用プロジェクトの PR / 差分コードレビュー観点。違反検出規約・優先度 (Critical/Warning/Info)・ 検出パターンと修正案・自動生成ファイル編集検出・DTO 変換漏れ検出・ Prisma Model 変換違反検出・hooks 重複検出・useEffect データ取得検出・ センシティブ field 漏洩検出・useFrourioSWR 移行漏れ検出を網羅。 実装規約 skill (frourio-framework) の対となるレビュー観点 skill。 Triggers: "frourio レビュー", "frourio コードレビュー", "frourio PR レビュー", "frourio review", "controller レビュー", "DTO 漏れ", "toDto 検出", "hooks 重複", "useEffect 検出", "useFrourioSWR 移行漏れ", "$server.ts 編集", "$relay.ts 編集", "__generated__ 編集", "frourio-framework-review".
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/InterfaceX-co-jp/skills-frourio-framework --skill frourio-framework-review命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... frourio (Fastify + aspida + zod ベースのTypeScriptフルスタックフレームワーク) の使い方。 ファイルベースルーティング規約、defineController/defineValidators/defineHooks パターン、 動的セグメント、自動生成ファイル ($server.ts, $relay.ts, $api.ts)、aspida型連携、 hooks 経由の JWT decode を controller で取得するパターン、 frourio-framework-prisma-generators による Prisma Model クラス生成と toDto 返却ルール、 フロントエンドでの useFrourioSWR (useEffect 回避) によるデータ取得規約、 新規ルート追加手順を網羅。最新テンプレートは frourio 本体を内蔵 (@frouvel/frourio)。 Triggers: "frourio", "ルート追加", "新しいAPI", "endpoint 追加", "controller 作る", "$server.ts", "$relay.ts", "aspida", "DefineMethods", "defineController", "frourio-framework-prisma-generators", "ModelDto", "toDto", "useFrourioSWR", "useAspidaSWR", "@frouvel/frourio".
name frourio-framework-review description frourio (Fastify + aspida + zod ベースのTypeScriptフルスタックフレームワーク) 採用プロジェクトの PR / 差分コードレビュー観点。違反検出規約・優先度 (Critical/Warning/Info)・ 検出パターンと修正案・自動生成ファイル編集検出・DTO 変換漏れ検出・ Prisma Model 変換違反検出・hooks 重複検出・useEffect データ取得検出・ センシティブ field 漏洩検出・useFrourioSWR 移行漏れ検出を網羅。 実装規約 skill (frourio-framework) の対となるレビュー観点 skill。 Triggers: "frourio レビュー", "frourio コードレビュー", "frourio PR レビュー", "frourio review", "controller レビュー", "DTO 漏れ", "toDto 検出", "hooks 重複", "useEffect 検出", "useFrourioSWR 移行漏れ", "$server.ts 編集", "$relay.ts 編集", "__generated__ 編集", "frourio-framework-review".
allowed-tools ["Read","Grep","Glob","Bash"]
frourio Framework — Code Review
frourio (Fastify + aspida + zod) ベース TypeScript フルスタックフレームワーク採用プロジェクトの
PR / 差分レビュー観点を集約。
違反検出 → 指摘必須。1指摘1行 (位置・問題・修正)。
実装規約 (skill: frourio-framework) の鏡像。実装時規約 vs レビュー時検出観点で役割分離。
0. レビュー優先度
🔴 Critical — 型安全性・セキュリティ・自動生成破壊。即修正
🟡 Warning — 規約逸脱・保守性低下。修正推奨
🔵 Info — スタイル・命名。任意
1. ディレクトリ・ファイル配置 (🔴 Critical)
ルートディレクトリ名と URL マッピングが意図通り
api/foo/_id/ (型指定無し) → _id@string or _id@number に修正
api/foo/[id]/ (Next.js 風) → frourio 規約違反
api/foo/:id/ (Express 風) → frourio 規約違反
find api -type d -name '_*' | grep -v '@string\|@number'
find api -type d \( -name '\[*\]' -o -name ':*' \)
2. 自動生成ファイル編集 (🔴 Critical) 以下が diff に含まれる → 即 reject :
$server.ts (プロジェクトルート)
各ルートの $relay.ts
api/$api.ts
__generated__/ 配下全て (Prisma model + repository 生成物)
git diff --name-only origin/main...HEAD | grep -E '(\$server\.ts|\$relay\.ts|\$api\.ts|__generated__/)'
修正方針: 該当ファイル変更を revert → schema / index.ts 等の 入力側 を修正 → frourio / prisma generate 再実行で再生成。
3. controller.ts (🔴 Critical)
export default async (req) => ({ status : 200 , body : {} });
get : () => ({ body : {} }),
get : ({ query } ) => { const x = query.foo ; ... },
grep -rL 'defineController' api/**/controller.ts
4. API 応答 — DTO 変換 (🔴 Critical) 最重要 : API レスポンスは必ず <Model>Model.toDto() 経由。
const user = await prisma.user .findUnique ({ where : { id } });
return { status : 200 , body : user };
const user = UserModel .fromPrismaValue ({ self : prismaUser });
return { status : 200 , body : user };
return { status : 200 , body : { id : user.id , name : user.name } };
return { status : 200 , body : { ...user.toDto (), password : undefined } };
return { status : 200 , body : user.toDto () };
return { status : 200 , body : user.toPublicDto () };
return { status : 200 , body : users.map (u => u.toDto ()) };
grep -rn 'prisma\.\w\+\.\(findUnique\|findFirst\|findMany\|create\|update\)' api/**/controller.ts
grep -rn 'body:\s*\(await\|prisma\)' api/**/controller.ts
5. Prisma → Model 変換 (🔴 Critical)
const user = new UserModel ({ id, name, ... });
const user = UserModel .fromPrismaValue ({ self : prismaUser });
grep -rn 'new \w\+Model(' src/ usecase/ api/
6. index.ts — 型定義 (🔴 Critical)
export type Methods = DefineMethods <{
get : { resBody : { id : number ; name : string } };
}>;
import type { UserModelDto } from '<shared-types>' ;
export type Methods = DefineMethods <{ get : { resBody : UserModelDto } }>;
grep -rn 'resBody:\s*{' api/**/index.ts | grep -v 'ModelDto\|Dto\b'
7. validators.ts (🟡 Warning)
for d in $(find api -type d -name '_*' ); do
parent=$(dirname "$d " )
[ -f "$parent /validators.ts" ] || echo "missing validators: $parent "
done
8. hooks.ts — auth (🔴 Critical)
get : async (req) => {
if (!req.headers .authorization ) return { status : 401 , body : {...} };
...
}
req.user = await req.jwtVerify ();
grep -rn 'headers\.\(authorization\|cookie\)' api/**/controller.ts
grep -rn 'jwtVerify\|verifyToken' api/**/controller.ts
for f in $(find api/admin -name controller.ts); do
dir =$(dirname "$f " )
found=""
while [ "$dir " != "api" ] && [ "$dir " != "." ] && [ "$dir " != "/" ]; do
if [ -f "$dir /hooks.ts" ]; then found=1; break ; fi
dir =$(dirname "$dir " )
done
[ -z "$found " ] && echo "AUTH BYPASS RISK: $f "
done
9. hooks 重複 — middleware 切り出し (🟡 Warning)
9.1 配置パターン早見表 構成 hooks.ts 配置 理由 admin/ 配下全部に同一認証 + auth/login のみ token 発行各サブ範囲ごと: admin/clients/hooks.ts, admin/report/hooks.ts, admin/sync/hooks.ts (login は親に置けないので) admin/hooks.ts 親集約 → login も認証必須化 → token発行不能admin/ 配下全部に同一認証 + login 系無しadmin/hooks.ts 1個のみ共通祖先1個で全子孫継承 ルート別に異なる scope (admin vs user) admin/hooks.ts (admin scope) + user/hooks.ts (user scope)scope ごとに祖先分離 一部だけ追加 hook (rate limit 等) 既存 auth hooks.ts より下の階層に新規 hooks.ts (auth は祖先継承、rate limit は当該階層追加) hooks 重ねがけ
import type { FastifyRequest , FastifyReply } from 'fastify' ;
export const authAdminMiddleware = async (req : FastifyRequest , reply : FastifyReply ) => {
const payload = await req.server .jwt .verify (token);
if (!hasAdminScope (payload)) { reply.code (403 ).send (...); return reply; }
};
import { defineHooks } from './$relay' ;
import { authAdminMiddleware } from '$/middleware/authAdminMiddleware' ;
export default defineHooks (() => ({ onRequest : authAdminMiddleware }));
find api -name 'hooks.ts' -exec wc -l {} \; | awk '$1 > 15'
grep -rh '^import' api/**/hooks.ts | sort | uniq -c | sort -rn | head
for f in $(find api -name hooks.ts); do
dir =$(dirname "$f " )
imports=$(grep -oE 'from .+/middleware/\w+' "$f " | sort -u)
parent=$(dirname "$dir " )
while [ "$parent " != "api" ] && [ "$parent " != "." ] && [ "$parent " != "/" ]; do
if [ -f "$parent /hooks.ts" ]; then
for imp in $imports ; do
if grep -q "$imp " "$parent /hooks.ts" 2>/dev/null; then
echo "DUPLICATE INJECTION: $f also injects $imp already from $parent /hooks.ts"
fi
done
fi
parent=$(dirname "$parent " )
done
done
grep -lE 'defineHooks\(\(\) => \(\{ onRequest: \w+ \}\)\)' api/**/hooks.ts
10. Prisma Schema — DTO アノテーション (🔴 Critical) // ❌ password が hidden 指定無し → toDto() で漏洩
model User {
password String
}
// ❌ controller で手動 omit (自前ロジック)
return { status: 200, body: { ...user.toDto(), password: undefined } };
grep -nE '^\s+(password|apiKey|secret|token|refreshToken)\s+String' schema.prisma | \
grep -v '@dto(hidden'
11. Prisma バージョン整合 (🔴 Critical) node -e "
const p = require('./package.json');
const a = (p.dependencies||{})['@prisma/client'];
const b = (p.devDependencies||{})['prisma'] || (p.dependencies||{})['prisma'];
if (a !== b) console.log('VERSION MISMATCH:', { '@prisma/client': a, prisma: b });
"
12. 共有型エクスポート (🟡 Warning)
grep -rn '__generated__' frontend/src/ web/src/
13. フロントエンド — データ取得 (🔴 Critical)
useEffect (() => {
adminApiClient.admin .users .$get().then (setUsers);
}, []);
const [data, setData] = useState ();
useEffect (() => {
if (!id) return ;
adminApiClient.admin .tenants ._tenantId (id).$get().then (setData);
}, [id]);
const { data } = useAspidaSWR (adminApiClient.admin .users );
const { data } = useFrourioSWR (adminApiClient.admin .users );
const { data } = useFrourioSWR (
id ? adminApiClient.admin .tenants ._tenantId (id) : null ,
);
const { data } = useFrourioSWR (adminApiClient.hq .projects , {
query : { status : 'IN_PROGRESS' },
});
grep -rnB1 -A5 'useEffect' frontend/src/ | grep -E '(\.\$get\(|\.\$post\(|fetch\()'
grep -rn 'useAspidaSWR' frontend/src/
14. 生成コマンド実行漏れ (🟡 Warning)
git diff --name-only origin/main...HEAD | grep -q 'schema\.prisma' && \
! git diff --name-only origin/main...HEAD | grep -q '__generated__/' && \
echo "WARN: schema 変更あり、__generated__ 未更新 → prisma generate 漏れ"
git diff --name-only origin/main...HEAD | grep -q 'api/.*/index\.ts' && \
! git diff --name-only origin/main...HEAD | grep -qE '\$server\.ts|\$relay\.ts' && \
echo "WARN: index.ts 変更あり、生成物未更新 → frourio 生成漏れの可能性"
15. 型エラー / ビルド (🔴 Critical) npx tsc --noEmit
npm run generate && git diff --exit-code
16. レビュー実行手順
git diff --name-only origin/main...HEAD で差分ファイル一覧
セクション 2 (自動生成ファイル編集) — 即 reject 判定
セクション 1, 3-6, 8, 10, 11, 13, 15 (🔴 Critical) — 全数チェック
セクション 7, 9, 12, 14 (🟡 Warning) — サンプリング or 全数
検出 → genshijin-review 形式で出力
レビュー出力フォーマット (genshijin-review 互換) [file:line] 🔴/🟡/🔵 [問題]: [修正案]
api/users/_id@string/controller.ts:12 🔴 Prisma 生値直接返却: user.toDto() に変更
api/users/index.ts:5 🔴 自前 resBody 型定義: UserModelDto を import 使用
prisma/schema.prisma:34 🔴 password に @dto(hidden: true) 欠落: コメント追加
frontend/pages/users.tsx:18 🔴 useEffect でデータ取得: useFrourioSWR に置換
$server.ts:1 🔴 自動生成ファイル編集: 元に戻し frourio CLI 再実行
api/admin/report/hooks.ts:5-65 🟡 hooks ロジックコピペ: middleware/authAdminMiddleware に切り出し
api/foo/_id/index.ts 🔴 動的セグメント型指定欠落: _id@string or _id@number に rename
package.json:12 🔴 prisma バージョン不整合: prisma と @prisma/client を同一バージョン (>= 7.2.0) に揃える
関連 skill
実装規約: frourio-framework skill (skills/frourio-framework/SKILL.md)
実装規約 (rule 形式): rules/frourio-framework-activate.md
レビュー規約 (rule 形式): rules/frourio-framework-review.md