コンテンツにスキップ

guinness-backend ディレクトリアーキテクチャ

guinness-backend モノレポは Bun を使用する Turborepo ワークスペースです。4 つのアプリ(ユーザー API、管理者 API、MCP v2 サーバー、PostgreSQL マイグレーション)と 4 つの共有パッケージを含みます。インフラストラクチャのトポロジーについては 管理者インフラストラクチャ および ユーザーインフラストラクチャ を参照してください。

リポジトリ構成

guinness-backend/
  apps/
    app/                    # @guinness-backend/app — ユーザー向け REST API(Hono + Bun)
    admin/                  # @guinness-backend/admin — 管理者向け REST API(Hono + Bun)
    mcp-v2/                 # @guinness-backend/mcp-v2 — Model Context Protocol サーバー
    migration-pg/           # @guinness-backend/migration-pg — PostgreSQL スキーママイグレーション(Drizzle Kit)
  packages/
    models/                 # @guinness-backend/models — PostgreSQL Drizzle ORM スキーマ
    utils/                  # @guinness-backend/utils — 共有ユーティリティ(認証、エラー、ページネーション等)
    guinness-backend-sdk/   # 共有バックエンド・テストヘルパー
    typescript-config/      # @guinness-backend/typescript-config — 共有 tsconfig
  docs/                     # MkDocs ドキュメントサイト
  bin/                      # 運用スクリプト(RDS/DocDB 向け SSM セッション)
  api-collections/          # API コレクションファイル(Postman/Bruno)

アプリ構造パターン

各 API アプリ(app、admin、mcp-v2)は 4 層アーキテクチャに従います:routes → services → repositories → models。

apps/app/src/
  server.ts                   # Bun サーバーエントリポイント
  app.ts                      # Hono アプリ設定
  config/
    env.ts                    # 環境変数バリデーション(Zod)
    database.ts               # データベース接続設定
    cognito.ts                # AWS Cognito クライアント設定
  middlewares/
    protected-route.ts        # JWT 認証ミドルウェア
    error-handler.ts          # グローバルエラーハンドリング
    rate-limit.ts             # レート制限
    winston-logger.ts         # リクエストログ
  routes/v1/                  # HTTP ハンドラー(ドメイン別ファイル)
  services/                   # ビジネスロジック(ドメイン別ファイル)
  repositories/               # データアクセス — Drizzle クエリ(ドメイン別ファイル)
  schemas/
    components/               # OpenAPI コンポーネントスキーマ(Zod)
    routes/                   # ルート別リクエスト/レスポンススキーマ(Zod)
  types/
    endpoint/                 # エンドポイント別型定義
  lib/
    database.ts               # DB 接続プールシングルトン
    server.ts                 # サーバーセットアップヘルパー
  utils/
    pagination.ts             # ページネーションヘルパー
    security.ts               # セキュリティユーティリティ

admin アプリはこのパターンを拡張し、追加の認可ミドルウェア(require-admin-access、require-organization-access、require-project-access、require-user-access、resolve-actor-admin、access-level-rank)を備えています。

リクエストフロー

リクエストは以下の順序でレイヤーを通過します。

Client Request
    ↓
Middlewares(認証・ログ・エラーハンドリング)
    ↓
Routes(リクエストバリデーション・レスポンスフォーマット)
    ↓
Services(ビジネスロジック)
    ↓
Repositories(データアクセス)
    ↓
Database / External Services(AWS Cognito, S3, SQS)

ミドルウェアパイプライン

ミドルウェア ファイル 役割
requestId() hono/request-id トレース用の一意なリクエスト ID を付与
winstonLogger() middlewares/winston-logger.ts リクエスト / レスポンスの構造化ログ(所要時間含む)
cors() hono/cors クロスオリジンリソース共有
compress() hono/compress Gzip レスポンス圧縮
rateLimit() middlewares/rate-limit.ts リクエストレート制限
protectedRoute middlewares/protected-route.ts JWT 検証・Cognito sub 抽出
errorHandler middlewares/error-handler.ts 集中エラーハンドリング・統一フォーマット返却

各レイヤーの実装パターン

Routes レイヤー

HTTP ハンドリング・バリデーション・レスポンス整形を担う。ビジネスロジックは持たず Service に委譲する。

route.openapi(getUser, async (c) => {
  const { user_id } = c.req.valid('param');
  const { sub: requesterUsername } = c.get('auth');

  try {
    const user = await userService.findOneById(user_id, requesterUsername);
    return c.json(formatOutput(user));
  } catch (error) {
    logger.error('Failed to fetch user', { error, user_id });
    throw error;
  }
});

Services レイヤー

ビジネスルールの実装・複数リポジトリの調整・外部サービス(Cognito, S3, SQS)との連携を担う。

export async function findOneById(
  userId: string,
  requesterUsername: string
): Promise<User> {
  const user = await userRepository.findById(userId);
  if (!user) throw new NotFoundError(`User ${userId} not found`);
  if (!hasPermission(requesterUsername, user)) throw new ForbiddenError('Insufficient permissions');
  return user;
}

Repositories レイヤー

Drizzle ORM を使ったデータベース操作のみを担う。ビジネスロジックは持たない。

export async function findById(userId: string): Promise<User | null> {
  const result = await db
    .select()
    .from(users)
    .where(and(eq(users.id, userId), isNull(users.deletedAt)))
    .limit(1);
  return result[0] ?? null;
}

エラーハンドリング

標準エラーレスポンス

すべてのエラーは以下の JSON 形式で返却される。

{
  "error": {
    "message": "Error description",
    "code": "ERROR_CODE",
    "details": {}
  }
}

HTTP ステータスコード

ステータス 用途
400 Bad Request 無効な入力データ
401 Unauthorized 認証がないか無効
403 Forbidden 権限不足
404 Not Found リソースが見つからない
409 Conflict リソースの競合(重複など)
500 Internal Server Error 予期しないサーバーエラー

共有パッケージ責務

パッケージ 主要ファイル 責務
packages/models postgresql/*.ts 全テーブルの Drizzle ORM スキーマ定義、テーブル別ファイル + リレーション
packages/models postgresql/shared/audit-fields.ts 共有監査カラム(created_at, updated_at)
packages/models postgresql/shared/constants.ts 共有 DB 定数
packages/utils src/cognito-jwt.ts Cognito トークンの JWT 検証
packages/utils src/error.ts カスタムエラークラス(Validation, Unauthorized, Forbidden, NotFound, Conflict, InternalServer)
packages/utils src/pagination.ts ページネーションヘルパー
packages/utils src/logger.ts Winston ロガー設定
packages/utils src/encryption.ts 暗号化/復号ユーティリティ
packages/utils src/response.ts API レスポンスフォーマット
packages/utils src/retry.ts 指数バックオフ付きリトライロジック
packages/utils src/request-validation.ts リクエストバリデーションヘルパー
packages/utils src/figma.ts Figma API ヘルパー
packages/guinness-backend-sdk src/test-utils/postgres-container.ts Testcontainers PostgreSQL 設定
packages/guinness-backend-sdk src/test-utils/vitest-global-setup.ts テスト DB 向け Vitest グローバルセットアップ
packages/typescript-config base.json, app.json 共有 tsconfig プリセット

共有依存パッケージ

パッケージ 用途
hono Web フレームワーク(v4.12)— ルーティング、ミドルウェア、OpenAPI
drizzle-orm データベース ORM — PostgreSQL 向けクエリビルダー
drizzle-kit スキーママイグレーションツール
zod (v4) スキーマバリデーション — リクエスト/レスポンス、環境変数
@aws-sdk/client-* AWS SDK — S3, SQS, Cognito, DocumentDB
winston 構造化ログ
testcontainers インテグレーションテスト用 PostgreSQL testcontainers
vitest テストランナー
biome リント + フォーマット
turbo モノレポビルドオーケストレーション
lefthook Git フック管理