en un clic
server-architecture
// Use when adding or modifying server-side code (routes, services, socket handlers, DynamoDB operations) to ensure adherence to architecture patterns
// Use when adding or modifying server-side code (routes, services, socket handlers, DynamoDB operations) to ensure adherence to architecture patterns
Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
Use when creating new skills, editing existing skills, or verifying skills work before deployment
| name | server-architecture |
| description | Use when adding or modifying server-side code (routes, services, socket handlers, DynamoDB operations) to ensure adherence to architecture patterns |
サーバー (packages/server/) は以下のレイヤー構成に従う。ルートハンドラにビジネスロジックを直接書かず、ドメイン層・リポジトリ層に分離してテスタビリティとインフラ独立性を確保する。
routes/ ← HTTP ルートハンドラ(バリデーション + レスポンス整形のみ)
socket/ ← Socket.IO イベントハンドラ(認証 + ルーム管理)
domain/ ← ビジネスロジック(純粋関数、インフラ非依存)
repositories/ ← データアクセス抽象化(インターフェース + DynamoDB 実装)
validators/ ← Zod スキーマによるリクエストバリデーション
services/ ← AWS SDK クライアント初期化(DynamoDB, S3, Bedrock)
middleware/ ← Hono ミドルウェア(CORS, JWT 認証)
lib/ ← ユーティリティ(JWT 署名/検証)
ルートハンドラにロジックを書かない。domain/ 配下に純粋関数として定義し、テスト可能にする。
// routes/gacha.ts — ドメインを呼ぶだけ const { rarity } = pullGacha();
</Good>
<Bad>
```typescript
// routes/gacha.ts — ロジック埋め込み、テスト困難
gachaRoutes.post("/pull", async (c) => {
const rand = Math.random();
let cumulative = 0;
for (const [rarity, rate] of Object.entries(GACHA_RATES)) { ... }
});
repositories/types.ts にインターフェースを定義し、repositories/dynamodb/ に DynamoDB 実装を置く。テスト時にインメモリ実装に差し替え可能。
全エンティティに version フィールドを持たせ、更新時に ConditionExpression で検証する。競合時は OptimisticLockError を投げる。
// 更新時: version が一致しなければ例外
UpdateCommand({
ConditionExpression: "version = :currentVersion",
ExpressionAttributeValues: {
":currentVersion": entity.version,
":nextVersion": entity.version + 1,
},
});
型アサーション (c.req.json<T>()) ではなく、Zod スキーマ + @hono/zod-validator で実行時に検証する。
import { zValidator } from "@hono/zod-validator";
import { nfcLoginSchema } from "../validators/schemas";
authRoutes.post("/nfc-login", zValidator("json", nfcLoginSchema), async (c) => {
const { nfcId } = c.req.valid("json"); // 型安全かつ実行時検証済み
});
handshake.auth.token で JWT 認証socket.data にユーザーID・ロールを保持全クライアントに同じデータをブロードキャストしない。ユーザーに見せるべきでない情報(他ユーザーの内部状態等)はマスクまたは除外する。
domain/ に配置されているか