Crowi

プラグインアーキテクチャ

Crowi 2.0 のプラグインの仕組みと設計思想 (RFC-0001 / RFC-0002)

Crowi 2.0 は、ファイルストレージ・全文検索・レンダラ・認証・通知といった 本来コアと独立した関心事を、独立配布可能な プラグイン として切り出した アーキテクチャを採用しています。設計の経緯は RFC-0001 (プラグインアーキテクチャ) と RFC-0002 (レンダラプラグインアーキテクチャ) を参照してください。

設計の原則

Crowi のプラグインモデルは、次のいくつかの原則の上に成り立っています。

  • バッテリー同梱: プラグインを 1 つも追加しなくても、初期状態の Crowi は完結した Wiki として動作します。ローカルファイルストレージ、MongoDB ベースの検索、メール + パスワード認証、アプリ内通知がデフォルトで 有効です。
  • npm パッケージとして配布: プラグインは特別な形式ではなく、通常の npm パッケージです。グローバルなプラグインレジストリや curl パイプ式の インストーラはありません。
  • plugin-free な api: @crowi/api は SDK (@crowi/plugin-api) と コアのみを同梱し、ドライバは一切含みません。プラグインは別の runner プロジェクト (後述) が所有するため、プラグインの追加・削除 はそのプロジェクトの依存と設定を変えるだけで完結し、api のイメージを 焼き直す必要はありません。
  • v2.x の間は API 安定: @crowi/plugin-api@2.x に対して書かれた プラグインは、v2 系のすべてのマイナーバージョンで動作し続けます。

Tip: プラグインの実行はサンドボックス化されていません。プラグインは サーバと同じ Node 権限で動作します。信頼できる発行元のパッケージのみを 導入してください。

プラグインの種類

Crowi のプラグインは、貢献する拡張ポイントによっておおよそ次の種類に 分かれます。1 つのプラグインが複数の拡張ポイントを実装することもできます。

  • ストレージ / 検索 / メール — それぞれ「ドライバ」を crowi.config.jsonstorage.driver / search.driver / mail.driver で選択します。複数の ドライバプラグインを導入しておき、設定でどれを使うか切り替えられます。
  • レンダラ — 本文の記法を足します。ドライバ選択はありません。
  • 認証 — 外部アカウントでのサインインを足します。
  • 通知 / 連携 — 通知の宛先と、受信 Webhook などの HTTP ルートを足します。
  • ベース (設定のみ) — 後続のプラグインに資格情報を共有します。

拡張ポイントの型は プラグイン SDK、配布しているプラグインと ドライバ名の一覧は ファーストパーティプラグイン に あります。

暗黙のデフォルトプラグイン

3 つのドライバは crowi.config.json に列挙しなくても 毎回 読み込ま れるため、素のインストールではプラグイン設定が一切不要です。

  • @crowi/plugin-storage-local — ローカルファイルストレージ
  • @crowi/plugin-search-mongo — MongoDB の $regex 検索 (デフォルト の検索ドライバ。Elasticsearch / OpenSearch はオプトイン)
  • @crowi/plugin-mail-smtp — SMTP メール

追加のプラグインを列挙して *.driver を切り替えると、これらのデフォルト の上に選択肢が積み増されます。

CrowiPluginPluginContext

プラグインは @crowi/plugin-apiCrowiPlugin 型を満たすオブジェクトを デフォルトエクスポート し、コアの状態には register* に渡される PluginContext からだけ触れます (コアを直接 import しません)。フィールドとメンバーの一覧は プラグイン SDK にあります。

runner プロジェクトと @crowi/runner ライブラリ

「runner」という語が指す 2 つのものを混同しないでください。

  • runner プロジェクト は、プラグインを 所有 する小さな api ランタイム プロジェクトです。@crowi/api と選んだ @crowi/plugin-* を依存に持つ package.jsoncrowi.config.json.env からなる通常の npm プロジェクトです。モノレポにはリファレンス実装 apps/crowi-runner (パッケージ名 @crowi/runner-app、private) が同梱されており、 セルフホストする運用者はこれと等価なものを自前で用意します。
  • @crowi/runner (-app なし) は packages/runner にある内部 ライブラリです。これは 解決エンジン で、crowi.config.json を読み、 createRequire で列挙されたプラグインを runner プロジェクトの node_modules/ から読み込みます。

プラグイン解決

api パッケージ自身はプラグインを依存に持ちません。プラグインの npm 名を 解決するのは @crowi/runner ライブラリの役割で、api を起動する runner プロジェクトに対して解決を行います。

  1. crowi.config.json を読み、plugins 配列に列挙された名前を取得します (暗黙のデフォルトプラグインを先頭に追加します)。
  2. createRequire(<projectDir>/package.json) (ここで projectDir は runner プロジェクト) を使って、その npm 名を runner プロジェクトの node_modules/ から解決します。
  3. 各プラグインの requires を BFS で辿り、推移的な依存も読み込みます。
  4. 結果として、解決済みの CrowiPlugin インスタンス一覧が api の起動 シーケンスに渡されます。

つまり、運用者がプラグインを 1 つ追加するには次の 2 つを行うだけです。

  • runner プロジェクトの package.json の依存にプラグインを加える
  • crowi.config.jsonplugins にそのパッケージ名を列挙する (必要なら 対応する *.driver も切り替える)

api の再ビルドは伴いません。具体的な手順は プラグインの導入と設定 を参照してください。

起動シーケンスでの位置づけ

プラグインは、設定とモデルの準備が終わった後、レガシーな mailer / slack 初期化の前に起動します。レンダラのコアパイプライン (TOC / wikilink / メンション / コードブロック) は プラグインより先に 登録されるため、 レンダラプラグインはコアの登録の上に追記する形になります。

関連ページ

On this page