ストレージ API

ストレージ API は、スクリプト用の永続データ保存を提供します。ストーリー単位・アカウント単位の両方で利用でき、スクリプト同士でストレージは分離されています。データはキー/バリュー形式で保存されます。

概要

スクリプトには 4 種類のストレージがあります。

  • api.v1.storage
  • api.v1.storyStorage
  • api.v1.historyStorage
  • api.v1.tempStorage

api.v1.storage は標準のストレージで、スクリプトと一緒に保存されます。つまり、アカウントスクリプトかストーリースクリプトかで保存先が変わります。アカウントスクリプトは、ログイン時に読み込まれる必要があるため、通常ストレージの容量に上限があります(現時点では 1 スクリプトあたり 4MB)。

api.v1.storyStorage は、スクリプト種別に関係なく、常に「現在のストーリー」に保存されます(ストーリースクリプトの api.v1.storage とは別物です)。

api.v1.historyStorage は storyStorage と同様に現在のストーリーへ保存されますが、ドキュメント履歴を認識します。値を set すると、その時点の履歴ノードに紐づきます。ドキュメントを undo して、その値を set したノードより前に戻ると、値も以前の状態に戻ります。

api.v1.tempStorage は、現在のセッション中だけ保持され、ストーリーを閉じると消える一時ストレージです。UI パーツの storage key と組み合わせて、UI 状態などの一時データ表示に便利です。

基本操作

どのストレージも基本は同じで、set / get / remove / list を持ちます。

  • set:保存
  • get:取得
  • remove:削除
  • list:設定済みキーの一覧を配列で返す

履歴対応ストレージ(historyStorage)

historyStorage は、ドキュメント履歴ツリー上の特定時点に紐づくのが特徴です。undo/redo に応じて値が自動で巻き戻ります。

基本例

// 現在の履歴ポイントに値を set
await api.v1.historyStorage.set('character-state', {
  health: 100,
  location: 'town'
});

// 値を get
let state = await api.v1.historyStorage.get('character-state');

履歴に応じた挙動

履歴が変化すると、historyStorage の値も自動で切り替わります。

// 履歴ポイント A
await api.v1.historyStorage.set('turn-count', 1);

// 生成などでポイント B に移動
await api.v1.historyStorage.set('turn-count', 2);

// さらに生成してポイント C に移動
await api.v1.historyStorage.set('turn-count', 3);

let count = await api.v1.historyStorage.get('turn-count'); // 3

// undo でポイント B に戻る
// get は自動で 2 に戻る
count = await api.v1.historyStorage.get('turn-count'); // 2

// undo でポイント A に戻る
count = await api.v1.historyStorage.get('turn-count'); // 1

制限

historyStorage は主に undo/redo を想定しています。ユーザーが手動編集で内容を削除した場合など、必ずしも値が自動で巻き戻るわけではありません。また、historyStorage が「履歴ポイント」として扱うのは基本的に生成が発生したタイミングです。生成を伴わない編集だけでは、新しい履歴ポイントが作られません。

一時ストレージ(tempStorage)

tempStorage は、UI パーツの storageKey と組み合わせて UI 上に値を表示したいときに便利です。他のストレージと違って、ディスクやリモートへの保存は発生しません。

tempStorage と UI パーツの併用例

// 一時値を set
await api.v1.tempStorage.set('example-string', 'Alice gives meaning to character strings that are devoid of meaning.');
// 一時値を表示する UI を登録
await api.v1.ui.register([
  {
    type: 'scriptPanel',
    name: 'Temporary Storage Example',
    content: [
      {
        type: 'text',
        text: '{{temp:example-string}}'
      }
    ]
  }
]);
// 後から tempStorage を更新すると UI も自動反映されます。
// 永続保存は発生せず、UI は必要最小限だけ再レンダーされます。
await api.v1.tempStorage.set('example-string', 'Bob considers character strings to be meaningless without context.');

データ型

保存データは即座に JSON としてシリアライズされるため、シリアライズできないものは失われたり変化したりします。詳細は MDN(英語)も参照してください。

参考