コンテンツにスキップ

Devtools

@sh1n4ps/plasma-devtools は、実行中の plasma クライアントを検査する 3 つの方法を提供します:

  1. PlasmaDevtools — 開発中にアプリに配置する React パネルコンポーネント。
  2. useDevtoolsSnapshot — 独自のパネルを構築したい場合に、現在の sync 状態を返す hook。
  3. attachDevtoolsBridge — Chrome DevTools 拡張機能(または任意の外部インスペクタ)向けの window.postMessage ブリッジ。
Terminal window
pnpm add @sh1n4ps/plasma-devtools

アプリの他の部分を変更する必要はありません。

import { PlasmaDevtools } from "@sh1n4ps/plasma-devtools"
import { plasma } from "./main"
function App() {
return (
<>
<YourAppUI />
{import.meta.env.DEV && (
<PlasmaDevtools client={plasma} dbName="todos" schema={schema} />
)}
</>
)
}

このパネルは:

  • 右下隅に小さなバッジ(plasma · N⏳)としてドッキングします。
  • 展開すると以下を表示します:
    • 現在の clientID / clientGroupID
    • pull cookie(base64 ペイロード)
    • schemaVersion
    • outbox の深さ + 個別のエントリリスト
    • 最近の onError イベント

プロダクションに出荷されないよう import.meta.env.DEV の背後にゲートしてください。

独自のパネルやステータスウィジェットを構築するため:

import { useDevtoolsSnapshot } from "@sh1n4ps/plasma-devtools"
function SyncStatus() {
const snap = useDevtoolsSnapshot(client, {
dbName: "todos",
schema,
refreshIntervalMs: 500,
})
return (
<div>
Outbox: {snap.outbox.length}<br />
Cookie: {snap.cookie ?? "none"}<br />
Client: {snap.clientID ?? "..."}<br />
</div>
)
}

DevtoolsSnapshot を返します:

interface DevtoolsSnapshot {
readonly clientID: string | null
readonly cookie: string | null
readonly outbox: readonly MutationEnvelope[]
readonly schemaVersion: string | null
}

IndexedDB は変更ストリームを安価に公開しないため、この hook は refreshIntervalMs(デフォルト 500ms)で IDB をポーリングします。より速いフィードバックが欲しければ間隔を調整してください(隠しバッジには 25ms で十分、可視パネルには 500ms で十分です)。

attachDevtoolsBridge — postMessage ブリッジ

Section titled “attachDevtoolsBridge — postMessage ブリッジ”

ページの外側からクライアントを観測・制御したい Chrome DevTools 拡張機能(または任意の外部インスペクタ)向け:

import { attachDevtoolsBridge } from "@sh1n4ps/plasma-devtools"
const dispose = attachDevtoolsBridge(client, {
dbName: "todos",
schema,
refreshIntervalMs: 500,
// このオリジンにのみメッセージを送る(デフォルト: "*")。
// プロダクションの機密性のために拡張機能のオリジンに絞る。
targetOrigin: "*",
// どのオリジンがコマンドメッセージを送れるか(デフォルト:
// "same-origin")。拡張機能のオリジンの配列に設定するか、
// どこからでもコマンドを受け入れるなら "*"。
allowedOrigins: "same-origin",
})
// 後で
dispose()

ブリッジは window.postMessage を介して 4 種類のメッセージを送ります:

方向 種類 目的
page → extension hello アタッチ時の「ランタイム存在」アナウンス
page → extension state-update sync 状態のスナップショット(refreshIntervalMs ごと)
extension → page command アクションのリクエスト: flushpullreset-local-stateping
page → extension command-result 先の command に対する OK/error レスポンス、requestId でキー付け

すべてのメッセージの source フィールドは "plasma-devtools" なので、受信側は無関係なメッセージをフィルタできます:

window.addEventListener("message", (event) => {
if (!isDevtoolsMessage(event.data)) return
// ... plasma-devtools メッセージを処理
})

拡張機能側は @sh1n4ps/plasma-devtools には含まれていません(別の Chrome 拡張機能プロジェクトです)。構築するには:

  1. content script が plasma-devtools メッセージのリスナーを注入します。
  2. postMessage を介してコマンドを送り返します。
  3. state-update ペイロードを使って DevTools パネルをレンダリングします。

プロトコルの型はすべて @sh1n4ps/plasma-devtools からエクスポートされています:

import type {
DevtoolsStateSnapshot,
StateUpdateMessage,
CommandMessage,
CommandResultMessage,
HelloMessage,
DevtoolsMessage,
} from "@sh1n4ps/plasma-devtools"

リスナーでユニオン型を使い、TypeScript にすべての分岐を網羅的にチェックさせてください。