Crowi

コントリビュート

Crowi 2.0 の開発に参加するための開発フロー・規約ガイド

このページは、Crowi 2.0 のコードベースに変更を加えるための開発フローと 規約をまとめたものです。開発環境のセットアップ自体は 開発環境をつくる を先に済ませてください。

開発コマンド

スクリプトはリポジトリルートと各パッケージの package.json に定義されて います。pnpm <script> は Turborepo によって自動でパッケージを絞り込み ます。

コマンド用途
pnpm devapi + web + プラグインを並行起動
pnpm dev:api / pnpm dev:web片側だけ起動
pnpm test全パッケージのテスト (api は Jest + supertest。CI では services.mongo コンテナを利用、ローカル開発時は mongodb-memory-server にフォールバック)
pnpm type-check型チェック (api + web + site)
pnpm lintLint。errors=0 が必須 (warning は許容)
pnpm formatBiome によるフォーマット
pnpm build全パッケージのビルド

特定のパッケージだけ動かしたいときは pnpm --filter @crowi/api <script> のように絞り込めます。

Tip: API 契約 (packages/api-contract) を編集したら、 pnpm --filter @crowi/api-contract build で dts を再生成してください。 turbo パイプラインは dev / build / test^build を自動実行 しますが、単発のスクリプトでは手動が必要になることがあります。

Lint と Format

Crowi は Biome をフォーマッタに、ESLint を Linter に使い分けて います。

  • Lint は pnpm lint で実行され、エラー 0 が必須です。warning は 許容されますが、エラーは pre-push フックで弾かれます。
  • Format は Biome が担当します。ステージされたファイルに対して pre-commit フックが自動実行するため、通常は手動実行は不要です。 フックをバイパスした場合のみ pnpm format を使ってください。
  • 既存の any を見かけても、無関係なコードまで巻き込んで直さないで ください。差分は触っている範囲に絞ります。新たな any の追加は 避けてください。

lefthook フック

Git フックは lefthook で管理され、pnpm install 時に自動でセットアップ されます。

フック内容
pre-commitステージされたファイルに Biome フォーマットを適用
pre-pushpnpm lint (errors=0 必須) と pnpm build を実行。packages/api-contract/** に変更があるときは pnpm check:openapi も実行

コミットメッセージ

コミットメッセージは Conventional Commits 形式に従います。

feat(api): add page export endpoint
fix(web): correct notification bell badge count
refactor(merge): deduplicate ws token signer
chore(config): bump dev ports
docs(site): document attachment thumbnails
  • 型は feat / fix / refactor / chore / docs などを使い、 スコープに api / web / api-contract などを書きます。
  • 変更の意図が自明でないときは、なぜその変更をしたのかを説明する 本文を複数段落で添えてください。

Changesets

リリースノートの蓄積には @changesets/cli を使います。v2 開発中も pnpm changeset add で各変更を .changeset/*.md として蓄積していき、 将来のリリース時にリリースノートが自動生成されます。

  • changeset は「ユーザー価値の単位」で 1 つ作ります。機能追加・バグ修正・ 破壊的変更が対象です。
  • 内部リファクタ・コード整理・lint 修正・フォーマット・テスト追加だけ、 あるいはドキュメント更新だけの変更には changeset は不要です。判断基準は 「次の changelog に書いて意味があるか」です。
  • bump レベルは、バグ修正なら patch、新機能なら minor、破壊的変更 なら major を選びます。
pnpm changeset add        # package + bump レベル + 概要を対話的に選ぶ
pnpm changeset status     # 蓄積された未公開 changeset 一覧

TypeScript の指針

  • 新たな any は追加しません。any のあるコードを触るときは、機を見て 適切な型へ少しずつ置き換えます。
  • 1 つの変更で無関係なコードを巻き込まず、差分は焦点を絞ります。
  • フィールドの再定義より Pick<> / Omit<> を優先します。
  • Mongoose ドキュメントの型は models/xxx.tsXxxDocument を import します。

ローカルでの動作確認

ふだんの pnpm test では動かさない、手で立ち上げて確かめる類の検証をまとめます。

共同編集を 2 レプリカで確かめる

同梱の compose 構成から実際に 2 レプリカを立てます。準備は 2 点です — api の固定ホストポート公開を外すこと (レプリカ間で衝突します) と、全レプリカが同じ WS_TOKEN_SECRET を読むように .env に書いておくことです。

# 1. スケール用の override (ホストポート公開を外し、複数レプリカを宣言する)
cat > compose.scale.yml <<'YAML'
services:
  api:
    ports: !override []
    environment:
      CROWI_MULTI_INSTANCE: "2"
YAML

# 2. api を 2 レプリカで起動
docker compose -f docker-compose.yml -f compose.scale.yml --profile app up -d --scale api=2

# 3. 2 つ立っていることを確認
docker compose ps api

2 つのブラウザウィンドウで同じページを開き、それぞれの編集が相手に伝わること、片方のレプリカを止めても再接続して編集が続けられることを確認します。想定される挙動と既知の制約は リアルタイム共同編集の運用 を参照してください。

GCS ストレージドライバをエミュレータで確かめる

GCS ドライバのテストは、通常の CI では起動しない opt-in のエミュレータサービスを使います。

docker compose --profile gcs-test up -d crowi-test-gcs
STORAGE_EMULATOR_HOST=http://127.0.0.1:4443 pnpm --filter @crowi/api test -- --runInBand src/plugin/storage-gcs.emulator.test.ts
docker compose --profile gcs-test stop crowi-test-gcs

エミュレータが検証するのは、アップロード・ダウンロードの往復、オブジェクト名のマッピング、冪等な削除、存在しないオブジェクトの扱い、ローカルから GCS へのコピーです。匿名リクエストを受け付けるだけなので、認証情報の解決や IAM 権限、署名付き URL の可否は再現しません。 そこまで確かめるには実際の GCS バケットが必要です。

Slack 連携をトンネル越しに確かめる

Slack は localhost に到達できないため、ngrok や cloudflared などのトンネルで Crowi を公開します。生成される manifest の request URL をトンネルの公開 URL にするには、環境変数 SLACK_MANIFEST_REQUEST_URL にその公開オリジン (例: https://abc123.ngrok.app) を設定してください。未設定なら CLIENT_URL が使われます。

新しいエンドポイントを追加するには

レガシーの Express + ts-rest スタックは RFC-0006 で完全に廃止されました (2026-05-22 完了)。新しいエンドポイントを追加するときは以下の手順に 従ってください。

  • packages/api-contract/src/ 配下に Zod スキーマと createRoute 定義 (@hono/zod-openapi) を追加します。
  • packages/api/src/hono/handlers/ 配下にハンドラを実装します (管理系 は hono/handlers/admin/ 配下)。
  • hono/app.ts でハンドラを Hono アプリに組み込み、必要なミドルウェアを hono/middleware/ に追加します。
  • Web 側からは、契約から生成された apiClientV2 (型付き Hono RPC クライアント、 createClient が返す CrowiApiClient 型) 経由でエンドポイントを呼び出します。

Crowi 2.0 全体のフェーズ状況はリリースノートに反映されて います。

関連ページ

On this page