データモデル
プラグイン独自テーブル plg_<scope>_<name>_* の命名・自動付与列と、同期・無効化まわりの挙動。
プラグインは原則として 独自テーブルで完結させます。 コアデータ(社員・部署等)の読み取りは コア API 連携 を参照(直接 DB 参照は不可)。
niyase.data で CRUD
manifest の tables[] で宣言したテーブルを、ブリッジ経由で操作します。
const niyase = useNiyase();
await niyase.data.list("task", { limit: 50 }); // → { items, nextCursor? }
await niyase.data.get("task", id);
await niyase.data.create("task", { title: "現場A" });
await niyase.data.update("task", id, { status: "DONE" });
await niyase.data.remove("task", id); // ソフトデリート
内部的には /nplg/:pluginId/:table を叩きます(ユーザーセッション + 現在のスペースで認可)。
未宣言のテーブル名・列は 400 で拒否されます。
物理テーブル名の規約
manifest の論理テーブル名は、各環境のローダが以下に展開します。手計算する必要はありません(ブリッジ・同期・DB ブラウザで表示される実名を確認したいときのための規約です)。
plg_<scope>_<name>_<table>
| 変換 | 説明 |
|---|---|
@ を除去 | テーブル名に使えない |
- → _ | PostgreSQL の慣例 |
/ → _ | 名前空間とプラグイン名の区切り(単一アンダースコア) |
プレフィックス plg_ | コアテーブルとの衝突防止 |
例: @your-org/tasks の task → plg_your_org_tasks_task。
Postgres の識別子上限(63 文字)に収まるよう、プラグイン名・テーブル名は簡潔にしてください。
この規則は cloud(Postgres)・desktop(PGlite)・mobile(SQLite)・DevKit の MOCK ブリッジで共通です。
テーブル定義の追加プロパティ
tables[] の各エントリは name / columns に加え、以下を宣言できます。
| プロパティ | 必須 | 説明 |
|---|---|---|
resource | 必須 | 権限リソース名。plg:<pluginId>:<resource>:<action> という権限文字列の一部になり、テーブルごとの RLS ポリシーがここから生成されます。宣言しないテーブルは作れません(fail-closed) |
shared | 任意 | "connection-read" / "connection-readwrite"。PROVIDER↔CLIENT 型で、CLIENT に共有するテーブルにのみ宣言します(pairedPluginId を持つ defaultRole: "PROVIDER" のマニフェストでのみ有効) |
自動付与カラム
ローダが以下を自動付与するため、columns に書く必要はありません。cloud・desktop・mobile・MOCK の全実行系で同一のベース列契約です。
id(主キー)workspace_idcreated_at/updated_atdeleted_at(ソフトデリート)
マスタデータの投入
テーブルは有効化のたびに空の状態で作成されます。既定マスタ(初期データ)の自動投入はありません。
マスタが必要な場合は、csv / json をプラグインのバンドルアセットとして同梱し、UI(例:「設定」タブの「マスタ投入」ボタン)から niyase.data.create / 一括投入 API でユーザーが明示的に投入する形にしてください。ユーザーはそのまま編集できます。
旧仕様にあった「業種別プリセット(
industryPresets[].seedData)による自動シード」は廃止済みです。新規プラグインでは使いません。
カラム型
プラットフォーム非依存の 3 型で宣言します(ローダが各 DB の物理型に翻訳します)。
| 型 | 用途 |
|---|---|
TEXT | 文字列・日付(ISO)・列挙 |
INTEGER | 整数・金額(円を整数管理) |
REAL | 小数 |
同期とテーブルのライフサイクル
plg_* テーブルは他のスペースデータと同じ同期ストリームに乗りますが、プラグインならではの挙動がいくつかあります。有効化・無効化・端末間のエラーに遭遇したときの参考にしてください。
無効化・アンインストール = テーブルの DROP(想定内の挙動)
プラグインを無効化すると、サーバー側は該当テーブルの RLS ポリシー・masked view・書込ガードを即座に外し、アクセスを遮断します。続けて desktop / mobile のローカル DB では、そのプラグインのテーブルが物理的に DROP されます(データは削除ではなく、サーバー側では論理的に保持されたままアクセス遮断される一方、端末上のコピーは丸ごと消えます)。
これはバグではなく「剥奪の契約」と呼ばれる設計上の挙動です。ユーザーがプラグインを無効化・アンインストールしたら、あなたのプラグインのローカルテーブルは消えるものとして設計してください。 再度有効化すると、次回の同期でテーブルが再作成され、サーバー側に残っていたデータが初回フル取得で戻ります。
スキーマの反映は「握手」で自動化される
端末は定期的にサーバーとスキーマ版数を突き合わせます(stateless なハッシュ値による握手)。manifest にテーブル・列を追加してプラグインをリリースすると、この版数が変わり、端末は自動的に新しいテーブル・列を取得しにいきます。手動のマイグレーション手順は不要です。新しく生えたテーブルの初回取得は常に全件取得(差分取得ではない)になります。
PROVIDER-CLIENT の共有テーブルはオフラインで見えない
tables[].shared を宣言した共有テーブルは、端末の同期対象から意図的に除外されます。CLIENT 側もオンラインの /nplg-conn/:connectionId/:table 経由でのみアクセスできます。「オフライン時に共有データが見えない」のは既知の制約であり、実装漏れではありません。
同期エラーに遭遇したら: 4xx はテーブル定義の不整合を疑う
以前は未知のテーブルへのアクセスが 500 エラーになっていましたが、現在は 409 Conflict(UNKNOWN_TABLE)で明確に拒否されます。プラグイン開発中にこのエラーに遭遇したら、以下を疑ってください。
- テーブル名がプラグイン ID から正しく導出されているか(物理名を手書きしていないか)
- そのテーブルを
manifest.tables[]に宣言し忘れていないか sharedテーブルをオフライン経路(niyase.data)から読もうとしていないか(共有テーブルはniyase.connections.data(connectionId)を使います)
UNKNOWN_TABLE は「サーバーの権威スキーマにそのテーブルが存在しない」ことが確定した場合にのみ返るため、一時的な通信エラーと区別できます。desktop はこの応答を受けると、剥奪時と同じ手順でローカルの孤児テーブルを自動的に片付けて収束します。