Sequelize のモデル定義ファイルからER図を作成してみた

はじめに

こんにちは。コミューンでソフトウェアエンジニアをしているU2です。
今回は commmune の開発でも使用している typescript-sequelize のモデル定義ファイルからER図を作成していきます。

背景

commmune は豊富な機能を持ちそれに合わせいくつものデータを保持しているので、永続化のためのテーブルが多く存在します。
また、テーブル定義としてはリレーションを持つが、Sequelizeのロジック上使用しないことが理由でモデルファイルにそのリレーションが記述されていないこともあります。
そのため、新規参入者がテーブル全容を把握するのに苦労しています。(そもそも長く開発に関わっている人でも知らないテーブルがあったりする。)

そんな問題を解決するために、Sequelize のモデル定義ファイルからER図を作成しよう!というテーマになります。

実装の大部分は sequelize-erd github.com を使用させていただいております。

本記事のサンプルコードはこちらです。 github.com

やりたいこと

  • sequelize-typescript に sequelize-erd を適用
  • CIでキックし、ER図作成を自動化

実装

環境

  • "typescript": "4.9.4"
  • "sequelize": "6.27.0"
  • "sequelize-typescript": "2.1.5"

前準備

対象となるモデルファイルと sequelize インスタンス生成ファイルを配置します。
モデルの中身は sequelize-typescript の Sample を利用しています。

database
├── models
│   ├── Post.ts
│   └── User.ts
└── sequelize.ts

フォルダ構成に合わせて適宜参照を変更します。Sequelize の dialect は今回 mysql とします。

次に、sequelize-erdから

  • graphvis.js
  • index.js
  • sample.js
  • visRenderer.js

をコピーします。

scripts
└── erd
    ├── graphvis.js
    ├── index.js
    ├── sample.js
    └── visRenderer.js

sequelize-erd が参照しているライブラリと合わせ、必要なパッケージをインストールします。

$ npm i typescript ts-node sequelize sequelize-typescript lodash commander
npx tsc --init

で tsconfig を生成したら事前準備完了です。

実験

ER図の生成

sample.jsgenerate.ts にリネームし、参照を import に修正します。
トランスパイルエラーが出ているので一旦 tsconfig.json に追記し対応します。

"noImplicitAny": false

この状態で sample を実行してみると

$ ts-node scripts/erd/generate.ts
/sequelize-erd-sample/node_modules/sequelize/src/dialects/abstract/connection-manager.js:81
        throw new Error(`Please install ${moduleName} package manually`);
              ^
Error: Please install mysql2 package manually
~~~

パッケージ不足のエラーが出ました。sequelize の dialect を mysql にしているため、mysqlパッケージをインストールする必要がありそうです。dialect を sqlite にしている場合、sqlite3 のインストールを求められます。

素直にインストールし再実行します。

$ npm i mysql2
$ ts-node scripts/erd/generate.ts

すると、プロジェクトルートに svg ファイルができています。成功です!

erd generated

CI化

次にCIに載せていきます。今回はGithub Actionsを使っていきます。
最初に pakcage.json にER図生成コマンドを設定します。

"scripts": {
  "erd:generate": "ts-node ./scripts/erd/generate.ts"
}

次に .github/workflows/gen-erd.yml を追加します。
ymlファイルはこちら github.com

アクション内の値をグローバル変数にセットする際に利用する set-output が2022/10 から非推奨になったようなので github.blog

代わりに、推奨されている $GITHUB_OUTPUT を使用してみています。

run: |
  git status --porcelain | wc -l
  file_count=$(git status --porcelain | wc -l)
  echo "file_count=$file_count" >> $GITHUB_OUTPUT

Github Actions が成功していて

github actions が svgファイルをコミットしていることが確認できました!

実験は成功です!

今後の課題

sequelize-erd が OSS として公開されているため、汎化できそうな切り口を考え fork して公開できるようにしていきたいと考えています。

それから、実際に運用しているテーブル数はかなり多く、ユーザテーブルのような様々なテーブルとのリレーションを持つテーブルが存在するため、1つの画像ファイルとしてER図にすると見辛くなってしまいます。
テーブル全体像の把握やPRのレビュー時のことを考えても、テーブルの系統毎に分割してER図にする必要がありそうです。 (実際のモデル定義ファイル群からER図を生成した一部です) こうしてみると独立したテーブルが散見され、おそらくモデル定義にリレーションを記述していないファイルも多く存在しそうです。
これら独立したテーブルを見て、モデル定義の情報拡充を進めていきたいです。

また、今回は sequelize-erd のコードをscriptsファイルとして配置してしまいましたが、外部ライブラリとして切り離せないかも検討したいところです。

参考サイト

sequelize-erd github.com models file github.com github actions devblog.thebase.in deprecating set-output github.blog

まとめ

運用中のサービスでER図を手動メンテはしたくないが、ER図はあると何かと便利、それなら自動化しようという試みでしたが、概ね上手くいきました。
モデルファイルの追加・更新に対してER図もそれに追随するようになるとPRレビューもしやすくなりそうなので導入を進めていきます。
typescript-sequelize のモデルファイルからER図を自動生成する第一歩を踏み出せたと思います。

次回、fork編


前回同様、今回も業務時間のうち20%を好きな技術課題に当てられる制度を利用して実験を行いました。 前回記事はこちら
tech.commmune.jp

制度についてはこちら
tech.commmune.jp

プロダクトロードマップに乗るような大きな課題から、明日の開発体験を向上させる小さな課題まで、主体的に取り組める環境です!(PRです)

We are hiring!!

forms.gle