Asset Cache
名前付きの画像・音声・テキスト素材を asset kind として公開します。
TurboWarp カスタム拡張機能 · Composition API · v0.4.0
Named Data は、非サンドボックスで動く TurboWarp 拡張機能どうしが共有する
データ契約と provider registry です。ある拡張機能が namespace と kind に対して
provider を登録すると、別の拡張機能は namespace + name + kind + scope
で参照を解決し、メタデータとバイト列またはストリームを受け取れます。
payload そのものが registry を経由することはありません。
利用している拡張機能
Named Data 自体のブロックはほとんどありません。価値は、データを持つ拡張機能どうしが
共有する registry にあります。別々にバンドルされた拡張機能も、固定キー
Symbol.for('@kubohiroya/turbowarp-named-data/registry') で同じ registry
を見つけるため、読み込み順やバンドル構成によって registry が分裂しません。
名前付きの画像・音声・テキスト素材を asset kind として公開します。
JSON・YAML の値を structured kind として公開します。schema 識別子も付けられます。
HTML・Markdown 文書を document kind として公開します。
生のバイト列を binary kind として公開し、ほかの拡張機能がストリームで読めるようにします。
はじめに
registry は起動時に固定される機能で、既定では無効です。フラグは バンドルの起動時に一度だけ読まれるため、拡張機能を読み込む前に設定してください。
ホストページで、または動作確認ならエディタのブラウザコンソールで設定します。
globalThis.__TW_NAMED_DATA_FEATURE_FLAGS__ = {
NAMED_DATA_REGISTRY_MVP: true
};
TurboWarp で 拡張機能を追加 → カスタム拡張機能 を選び、次のファイルを指定して サンドボックスなしで実行 を有効にします。
https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-named-data@0.4.0/dist/named-data.js
唯一の真偽ブロックで、共有 registry が導入されたことを確認できます。
もし <named data registry available?> なら
[ready] と言う
仕組み
registry が保持するのは、(namespace, kind) をキーにした provider の登録と、
現在開かれている本体の解放コールバックだけです。payload、保存、キャッシュはすべて
各 provider の中にとどまります。
利用側は参照、表現形式、ターゲットまたはプロジェクトのコンテキストを registry に渡します。 registry は参照の namespace と kind に登録された provider を選び、解決できるかを確認してから stat または openBody を呼びます。利用側はメタデータと借用した本体を受け取り、使い終えたら解放します。
| フィールド | 値 | 意味 |
|---|---|---|
namespace |
英小文字で始まり、a-z 0-9 . - で最大 64 文字 |
論理的な所有ドメイン。kind が異なる provider は同じ namespace を共有できます。 |
name |
provider が定める文字列 | namespace 内での値の名前。 |
kind |
structured、document、binary、asset |
データの種類。namespace と組み合わせて provider を選びます。 |
scope |
target、project |
target にはターゲット識別子、project にはプロジェクト識別子が必要です。互いに代用されることはありません。 |
schemaRef(任意) |
{id, version} |
structured 参照のみ。安定した schema ID と完全な SemVer で、schema 本体は含みません。 |
nativeRepresentation:provider が保存している形式representation:今回の本体で選ばれた形式mediaType、任意の byteLength と sha256- ダイジェストrevision:不透明な文字列。解析や大小比較はしないreplayable:本体を再読できるかUint8Array または ReadableStream<Uint8Array>release(reason) を呼ぶComposition API
ほかのパッケージは副作用のない ESM エントリポイントを import します。import しても TurboWarp 拡張機能は登録されず、契約、registry 関数、機能フラグの宣言だけが公開されます。
pnpm add --save-exact @kubohiroya/turbowarp-named-data@0.4.0
import {
installNamedDataRegistry,
type NamedDataProvider
} from '@kubohiroya/turbowarp-named-data/composition';
const registry = installNamedDataRegistry(runtime);
const provider: NamedDataProvider = {
namespace: 'com.example.notes',
kind: 'document',
canResolve: (ref, rep) => rep === 'markdown',
stat: (ref, rep, ctx) => ({ /* メタデータ */ }),
openBody: (ref, rep, ctx) => ({ /* メタデータ, body, release */ }),
release: () => {}
};
const registration = registry.registerProvider(provider);
同じ (namespace, kind) に 2 つ目の provider を登録すると
NAMED_DATA_PROVIDER_CONFLICT で失敗します。
import {getNamedDataRegistry}
from '@kubohiroya/turbowarp-named-data/composition';
const registry = getNamedDataRegistry(runtime);
const opened = await registry?.openBody(
{namespace: 'com.example.notes', name: 'intro',
kind: 'document', scope: 'project'},
'markdown',
{project: projectIdentity}
);
try {
// opened.body を読む
} finally {
await opened?.release('complete');
}
registry が導入されていなければ getNamedDataRegistry は undefined を返します。
| エクスポート | 用途 |
|---|---|
installNamedDataRegistry(runtime) | 共有 registry を導入する。互換な registry が既にあればそれを返す。 |
getNamedDataRegistry(runtime) | 導入せずに共有 registry を取得する。 |
bindNamedDataRegistryLifecycle(runtime, registry) | PROJECT_STOP_ALL でセッション状態を消去する。解除関数を返し、参照カウントで管理される。 |
NamedDataError、NAMED_DATA_ERROR_CODES | 安定した NAMED_DATA_* コードを投げる・判定する。 |
NAMED_DATA_KINDS、NAMED_DATA_SCOPES、NAMED_DATA_REPRESENTATIONS | 正規の一覧で入力を検証する。 |
FEATURE_FLAGS | バンドル起動時に確定したフラグを読む。 |
型定義は dist/types/composition.d.ts から提供されます。通信で扱える参照の形は
JSON Schema
としても公開しています。
ライフサイクルと schema 識別子
clearSession() を実行します。{lifetime: 'persistent'} を指定しない登録はセッション単位です。解放処理は
冪等なので、provider を複数回解放しても安全です。
structured 参照には schemaRef: {id, version} を付けられます。例:
{id: 'com.example.profile', version: '1.2.0'}。provider はメタデータで
まったく同じ識別子を返す必要があります。registry が運ぶのは識別子だけで、schema 文書、
バリデータ、JSON 値は provider と利用側の責任です。provider が schema 参照を公開するのは、
別の起動時フラグ NAMED_DATA_SCHEMA_REF が有効なとき(既定は無効)だけです。
リファレンス
| やりたいこと | 使うもの | 重要な挙動 |
|---|---|---|
| registry があるかをスクリプトで確かめる | named data registry available? | NAMED_DATA_REGISTRY_MVP が有効な間だけ表示されます。 |
| registry を有効にする | NAMED_DATA_REGISTRY_MVP: true | バンドル起動時に一度だけ読まれます。既定は無効。 |
| schema 識別子を公開する | NAMED_DATA_SCHEMA_REF: true | provider 向けのオプトイン。既定は無効。 |
| データを登録・読み取りする | Composition API | 拡張機能間の API のみで、本体を扱う値ブロックはありません。 |
ブロックの全仕様は英語版の完全なブロックリファレンスを参照してください。
| コード | 意味 |
|---|---|
NAMED_DATA_INVALID_REF | 参照または provider の記述が不正です。 |
NAMED_DATA_INVALID_REGISTRY | 共有シンボルの位置に互換でないオブジェクトがあります。上書きはされません。 |
NAMED_DATA_PROVIDER_CONFLICT | この (namespace, kind) には既に provider が登録されています。 |
NAMED_DATA_PROVIDER_NOT_FOUND | この namespace に provider が登録されていません。 |
NAMED_DATA_KIND_MISMATCH | namespace に provider はあるが、この kind のものはありません。 |
NAMED_DATA_NOT_FOUND | provider にその名前の値がありません。 |
NAMED_DATA_SCOPE_MISMATCH | scope が求めるターゲットまたはプロジェクトの識別子がコンテキストにありません。 |
NAMED_DATA_SCHEMA_NOT_FOUND / …_VERSION_MISMATCH / …_UNRESOLVED | schema 識別子がない、異なる、または解決できません。 |
NAMED_DATA_REPRESENTATION_UNSUPPORTED | provider が要求された表現形式を生成できません。 |
NAMED_DATA_INVALID_METADATA | provider が返したメタデータまたは本体が検証に失敗しました。 |
NAMED_DATA_BODY_TOO_LARGE | 本体が provider または利用側の上限を超えています。 |
NAMED_DATA_ABORTED | コンテキストの AbortSignal が中断を通知しました。 |
NAMED_DATA_PROVIDER_RELEASED | 要求の前または途中で provider が解放されました。 |
トラブル対処
NAMED_DATA_REGISTRY_MVP が true ではありませんでした。
先に globalThis.__TW_NAMED_DATA_FEATURE_FLAGS__ を設定し、エディタを再読み込みしてから
拡張機能を読み込み直してください。読み込み後にフラグを変えても効果はありません。
installNamedDataRegistry または
getNamedDataRegistry を使う必要があります。拡張機能内で作った私的な registry は共有されません。
シンボルの位置に互換でないオブジェクトがある場合は NAMED_DATA_INVALID_REGISTRY で失敗します。
context.target、project scope には context.project が必要です。
registry は一方を他方で代用せず、NAMED_DATA_SCOPE_MISMATCH を報告します。
PROJECT_STOP_ALL で解放されます。長く使う provider は
{lifetime: 'persistent'} で登録し、clearSession() で実行ごとの状態だけを消去してください。