3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SequelizeモデルからER図を自動生成、自動更新する方法

Last updated at Posted at 2024-12-30

はじめに

データベース設計の変更を継続的に追跡し、ドキュメントを最新に保つことは重要です。この記事では、Sequelizeモデルから自動的にER図を生成し、コミット時に自動更新する方法を解説します。

この記事ではモノレポ構成のプロジェクトを例に説明しますが、単一リポジトリでも同様の方法で実装可能です。

どのようなドキュメントが出力されるか?

スクリーンショット 2024-12-30 12.40.14.png

プロジェクト構成例

.
├── frontend/          # フロントエンドプロジェクト
└── backend/          # バックエンドプロジェクト
    ├── src/
    │   ├── models/   # Sequelizeモデル
    │   └── scripts/  # ER図生成スクリプト
    └── erd.svg       # 生成されるER図

モデル定義の例

データベース接続設定(models/index.ts)

src/models/index.ts
import dotenv from 'dotenv';
import { Sequelize } from 'sequelize';

dotenv.config();

const databaseUrl = process.env.DATABASE_URL; // postgres://postgres:password@localhost:5432/board_game_prototype

if (!databaseUrl) {
  throw new Error('DATABASE_URL is not defined');
}

const sequelize = new Sequelize(databaseUrl, {
  dialect: 'postgres',
  protocol: 'postgres',
  logging: false,
});

export default sequelize;

モデル定義例(models/User.ts)

src/models/User.ts
import { DataTypes, Model } from 'sequelize';
import sequelize from './index';

class UserModel extends Model {
  public id!: string;
  public googleId!: string;
  public username!: string;
}

UserModel.init(
  {
    id: {
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
      primaryKey: true,
    },
    googleId: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
    },
    username: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  {
    sequelize,
    modelName: 'User',
  }
);

export default UserModel;

実装手順

1. 必要なパッケージのインストール

npm install --save-dev sequelize-erd @types/node @types/sequelize @types/dotenv

2. ER図生成スクリプト(src/scripts/generateErd.ts)

src/scripts/generateErd.ts
import fs from 'fs';
import path from 'path';
import sequelizeErd from 'sequelize-erd';
import sequelize from '../models';
import { writeFileSync } from 'fs';

const modelsDir = path.join(__dirname, '../models');

(async function () {
  // モデルファイルの自動読み込み
  fs.readdirSync(modelsDir)
    .filter((file) => {
      return file.endsWith('.ts') && file !== 'index.ts';
    })
    .forEach((file) => {
      const modelModule = require(path.join(modelsDir, file));
      const model = modelModule.default;
      if (model && typeof model.initModel === 'function') {
        model.initModel(sequelize);
      }
    });

  // ER図の生成設定
  const svg = await sequelizeErd({
    source: sequelize,
    arrowShapes: {
      BelongsToMany: ['crow', 'crow'],
      BelongsTo: ['inv', 'crow'],
      HasMany: ['crow', 'inv'],
      HasOne: ['dot', 'dot'],
    },
    engine: 'dot',
    arrowSize: 1.2,
    lineWidth: 1,
    color: 'blue',
  });
  writeFileSync('./erd.svg', svg);
  console.log('ERDが正常に生成されました!');
})();

3. package.jsonにスクリプトを追加

package.json
{
  "scripts": {
    "generate-erd": "ts-node src/scripts/generateErd.ts"
  }
}

4. Git pre-commitフックの設定

.husky/pre-commit
#!/usr/bin/env bash

cd backend  # モノレポの場合。単一リポジトリの場合は不要

# ERDを生成
npm run generate-erd

cd ..  # モノレポの場合。単一リポジトリの場合は不要

# 生成されたER図をステージングに追加
if [ -f "backend/erd.svg" ]; then  # パスは適宜調整
  git add backend/erd.svg
  echo "✨ Added backend/erd.svg to staging"
fi

# 正常終了
exit 0

5. READMEへのER図の組み込み

README.md
## ER図

![ER図](backend/erd.svg)

自動生成のメリット

  1. モデル定義との同期

    • Sequelizeモデルの変更が即座にER図に反映
    • 型定義とER図の一貫性を保証
  2. 開発効率の向上

    • モデル定義の変更時に自動的にER図が更新
    • チーム全員が最新のDB構造を把握可能
  3. ドキュメントの保守性

    • コミット時に自動更新されるため、常に最新状態を維持
    • READMEに埋め込まれたER図も自動的に更新

まとめ

Sequelizeモデルを使用したER図の自動生成により:

  • データベース設計の可視化が容易に
  • ドキュメントの自動更新による保守性向上
  • チーム開発での認識共有がスムーズに

が実現できます。この方法は、モノレポ構成でも単一リポジトリでも適用可能です。

参考資料

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?