共同編集の拡張モジュール
History、Thread Comment、Worktree、File、サーバー側の Office 変換による共同編集の拡張を理解します。
History、Thread Comment、File、Worktree は必要に応じて有効化できる独立した拡張モジュールです。Transport、ID システム、物理 DB を再利用できますが、Service、Middleware、Event、Database Adapter、ライフサイクルの境界は個別に持ちます。
サーバー側の Office 変換は File と Collaboration Service を組み合わせます。Office ファイルと共同編集 Unit を相互に変換し、独自の Service、Endpoint、Middleware を持ちます。
モジュールの関係
| 拡張モジュール | 基本の共同編集との関係 |
|---|---|
| History | 基本 Events を監視して派生履歴インデックスを構築 |
| Thread Comment | 基本の Unit Room を再利用。コメントのアンカーは基本コンテンツに属する |
| File | Unit が参照する画像、添付、交換ファイルを保存。Unit データにはファイル ID だけを記録 |
| Office Exchange | 基本 Service で Unit を作成・読み取りし、File でファイルを読み書き |
| Worktree | 基本の Unit と OT を再利用し、下書きをトランクにマージ |
History、Thread Comment、File、Worktree はそれぞれ Middleware、Events、Database Adapter を設定します。
バージョン履歴
History は Unit 作成と確定した変更セットを、ユーザー向けの履歴項目にまとめます。これは派生インデックスであり、Unit 内容の正本は基本 Collaboration Service の確定済み変更セットです。
const historyService = new UniverHistoryService({ collabService, dbAdapter: historyDatabase, userProvider,});transport.register(new UniverHistoryEndpoint(historyService));History Service の生成時に、基本 Service の unitCreated と changesetCommitted Events を購読してインデックスを更新します。dispose() はこれらの購読を解除します。既定のポリシーは変更セットごとに履歴を作らず、時間枠と特別な mutation によってまとめます。
History は getHistoryList、listHistoryCreators、getHistoryChangesets の読み取り Middleware を提供します。索引は Service 内部で維持します。userProvider は名前やアバターなどの表示情報を補完するだけで、認証や認可はしません。Event Listener が失敗しても確定済みの基本変更セットはロールバックされないため、History は常に再構築可能な派生データとして扱います。
スレッドコメント
Comment Service は Sheets と Docs のコメント本文、返信、編集、削除、解決状態を管理します。
const commentService = new UniverCommentService({ database: commentDatabase, userProvider,});transport.register( new UniverCommentEndpoint({ service: commentService, roomHost: collabEndpoint, }),);コメント本文は Comment Adapter に属します。Sheet や Doc の内容に追従するアンカーは基本のスナップショットと変更セットに残ります。Comment Endpoint は主 Collaboration Endpoint の Unit Room で comment_update を配信できますが、リアルタイムメッセージがコメント状態の正本ではありません。クライアントはコメント一覧を再取得して復帰できます。
Comment Service は追加、一覧、返信、解決/再開、編集、削除の Middleware と commentCommitted Event を提供します。基本 Service の読み取り・編集ポリシーは継承しません。
ファイルストレージ
File は Univer クライアントがアップロードするバイナリファイルを保存します。Unit に挿入した画像と添付、およびインポートとエクスポートの元ファイルと結果ファイルです。Unit データにはファイル ID だけを記録し、クライアントは読み込み時に ID をダウンロード URL に解決するため、snapshot と changeset は小さいままです。
const fileService = new UniverFileService({ database: fileDatabase, blobStore,});transport.register(new UniverFileEndpoint(fileService));メタデータと内容は独立した 2 つの契約です。IFileDatabaseAdapter がファイルレコードを、IFileBlobStore が内容を保存します。交換用の一時ファイルはアップロードした本人だけがアクセスでき、Service が定期的に掃除します。Unit の画像と添付は upload、signUrl、download の Middleware で Unit の権限に従って制御します。
サーバー側の Office 変換
Exchange Service は Office ファイルを共同編集 Unit としてインポートし、Unit をファイルとしてエクスポートします。変換は @univerjs-pro/exchange-node に依存し、Unit の作成と読み取りは Collaboration Service、元ファイルと結果ファイルの保存は File Service を通じて行います。
const exchangeService = new UniverExchangeService({ collabService, fileService });transport.register(new UniverExchangeEndpoint(exchangeService));インポートとエクスポートは task です。クライアントが task を作成し、結果をポーリングします。インポートは Core Service の createUnit Middleware、エクスポートは readUnitData Middleware を通ります。Exchange 自身の import と export Middleware はレート制限、クォータ、監査に使います。
| Unit | インポート | エクスポート |
|---|---|---|
| Sheet | xls, xlsx, csv, tsv | xlsx, csv, tsv |
| Doc | doc, docx | docx |
| Slide | ppt, pptx | pptx |
| Base | xls, xlsx, csv, tsv | xlsx, csv |
task は Service インスタンス内に保持されるため、インポートとエクスポートのノードは 1 つだけデプロイし、Exchange の 3 つのルートをすべてそのノードに送ります。
Worktree の下書きとマージ
Worktree は 1 つ以上の Unit に隔離した下書き、凍結、マージ評価、Unit ごとのマージを追加します。
create → draft → ready → merging → merged ↑ │ └ reopen┘draft / ready → discardedconst worktreeService = new UniverCollabWorktreeService({ trunk: { service: collabService, dbAdapter: coreDatabase, }, dbAdapter: worktreeDatabase,});Worktree は (worktreeID, unitID) ごとに独立した下書き変更セットを保存し、基本 Service の Unit、OT、送信エンジンを再利用します。追加編集を受け付けるのは draft 状態だけです。markReady() が現在の下書きリビジョンを凍結し、mergeWorktree() が Unit を 1 つずつトランクにマージします。
Worktree Service は独立したライフサイクル、読み取り、下書きの submit/apply/commit Middleware と、作成、状態変更、マージ結果、下書き変更セットのコミットに対応する Events を持ちます。トランクへの最終書き込みは基本 Service 自身の Middleware を通ります。
複数 Unit のマージは Unit 間でアトミックではありません。アプリケーションは各 Unit のマージ結果を表示してください。
独立した拡張ポイント
拡張を有効にするときは各境界を個別に検討します。
| 境界 | 基本 | History | Comment | File | Worktree |
|---|---|---|---|---|---|
| Service | 独立 | 独立 | 独立 | 独立 | 独立 |
| Middleware | 共有しない | 基本から継承しない | 基本から継承しない | 基本から継承しない | 基本から継承しない |
| Event | 基本ライフサイクル | 基本 Events を監視 | commentCommitted | — | Worktree のライフサイクル/コミット |
| Database Adapter | 基本 Adapter | History Adapter | Comment Adapter | File Adapter と Blob Store | Worktree Adapter |
同じデータベースを使っても、これらの Adapter は別の契約を持つ別オブジェクトです。Service と Adapter も個別に破棄します。
Office Exchange は Core と File のストレージを再利用します。自身の import、export Middleware を実行した後も、インポートとエクスポートは Core と File の Middleware を通ります。
機能の選択
| 製品要件 | モジュール | 最初のサンプル |
|---|---|---|
| ユーザー向けバージョン履歴 | History Service、Endpoint、Adapter | pnpm example:history |
| Sheet・Doc のコメント | Comment Service、Endpoint、Adapter | pnpm example:comments |
| 画像、添付、ファイルストレージ | File Service、Endpoint、Adapter、Blob Store | pnpm example:file-service |
| サーバーでの Office 入出力 | Exchange Service、Endpoint + File | pnpm example:exchange |
| 隔離した下書き、レビュー、マージ | Worktree Service、Endpoint、Client、Adapter | pnpm example:worktree |
実行コマンドとページ URL はサンプル一覧を参照してください。
Web SDK の履歴 UI への接続
History Endpoint を共同編集のエンドポイントとともに公開します。Web SDK の historyServerUrl は /{unitId}/list、/{unitId}/creators、/{unitId}/cs の共通プレフィックスで、既定値は /universer-api/history です。別のパスを使う場合は、ホストの History プラグインと製品の History UI プラグインに同じ URL を設定します。
復元は共同編集の mutation として送信され、独立した履歴復元 REST API は使いません。共同編集の読み込み、送信、認可の設定を維持してください。createUnitComparisonEngine() による完全なスナップショット同士の読み取り専用比較には履歴サービスは不要です。バージョンの保存や復元は行いません。
このガイドはいかがですか?