blob-storage について
Val Town の `std/blob` モジュールで単純な値を永続化する方法を解説します。val 単位とアカウント全体のストレージ、データ操作、`std/sqlite` を使う場合を説明します。
主な機能
- 01JSON と生データの保存
- 02val 単位またはアカウント全体の Blob
- 03一覧表示、削除、コピー操作
- 04キーがない場合の処理案内
- 05容量制限と利用上の注意
活用シーン
- 01val 設定の永続化
- 02API レスポンスのキャッシュ
- 03アップロードファイルやバイナリアセットの保存
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ val-town/ plugins --skill blob-storageインストール後、Claude Code で/blob-storageを入力して読み込まれたか確認します。
詳細
Blob Storage
Val Town は、std/blob モジュールを通じて組み込みのキー/値 Blob ストレージを提供します。JSON ドキュメント、キャッシュされた API レスポンス、アップロードされたファイル、バイナリーアセットなど、文字列をキーとしてシンプルな値を永続化する必要がある場合に利用してください。SQL でクエリするリレーショナルデータや構造化データには、代わりに std/sqlite を使用してください。
スコープ:インポートによってアカウント全体または val ごとに設定
Blob ユーティリティには 2 つのエクスポートがあります。ユーザーアカウントをスコープとする global.ts と、val 自体をスコープとする main.ts です。新しい val では、main.ts のインターフェースと val スコープの使用を推奨します。
スコープ付きのインポートは次のとおりです。
/**
* Importing from `main.ts` provides an interface to val-scoped blobs.
*/
import { blob } from "https://esm.town/v/std/blob/main.ts";
グローバルのインポートは次のとおりです。
/**
* Importing from `global.ts` provides a blob interface that is scoped
* to your account.
*/
import { blob } from "https://esm.town/v/std/blob/global.ts";
/**
* This entrypoint is also available as `v/std/blob`. This is common
* in older vals.
*/
import { blob } from "https://esm.town/v/std/blob";
スコープ付きとグローバルの blob インターフェースは、同じメソッドを備えています。
スコープ付き Blob とグローバル Blob は別々に保存されます。スコープ付きインターフェースからグローバル Blob にアクセスすることも、その逆もできません。
基本的な使い方(JSON)
import { blob } from "https://esm.town/v/std/blob/main.ts";
await blob.setJSON("config", { theme: "dark", count: 0 });
const config = await blob.getJSON("config");
// config = { theme: "dark", count: 0 }, or undefined if the key doesn't exist
getJSON はキーが存在しない場合に undefined を返すため、結果を使う前に確認してください。
const config = (await blob.getJSON("config")) ?? { theme: "light", count: 0 };
生データとバイナリーデータ
文字列、バイナリー、または任意の BodyInit には、set/get を使用してください。get は標準の Response を返すため、本文を扱うヘルパー(.text()、.json()、.arrayBuffer()、.blob())を使用します。
await blob.set("logo.png", imageBytes); // string | BodyInit (Blob, ArrayBuffer, ReadableStream, …)
const res = await blob.get("logo.png");
const bytes = await res.arrayBuffer();
getJSON とは異なり、get はキーが存在しないと ValTownBlobNotFoundError をスローします。キーが存在しない可能性がある場合は、try/catch で囲んでください。
一覧表示、削除、コピー
const entries = await blob.list("user_"); // optional key prefix filter
// entries = [{ key, size, lastModified }, …]
for (const { key } of entries) {
await blob.delete(key);
}
await blob.copy("config", "config.bak"); // duplicate under a new key
await blob.move("draft", "published"); // rename / relocate
list(prefix?) は { key: string; size: number; lastModified: string } の配列を返します。キー文字列だけではなく、オブジェクトが返されます。
制限
- キーの長さ: 最大 512 文字です。
- 合計ストレージ容量: 無料プランでは 10 MB、Pro では 1 GB です。アカウント内のすべての Blob で共有されます。
- 大規模または構造化されたデータセットは、1 つの巨大な Blob としてではなく、
std/sqliteに保存してください。
ツールを使った Blob の読み書き
組織が所有する val(個人アカウントではなく)に対して storeBlob、readBlob、listBlobs、deleteBlob ツールを使う場合は、その組織の Blob ストレージにアクセスできるよう、org パラメーターに組織のハンドルを指定してください。例:{ key: "myapp:config", org: "some-org" }。これはツール呼び出しでのみ必要です。val 内のコードは、所有するアカウントのストレージを自動的に読み書きします。storeBlob が受け付けるのは最大 100 KB の UTF-8 テキストです。これより大きい Blob やバイナリー Blob は、コードから blob.set を使って書き込んでください。
ルール
- キーはフラットな名前空間として扱ってください。整理と
listの範囲指定には、プレフィックス(feature:subkey)を使用します。 getJSONはキーが存在しない場合にundefinedを返し、getはValTownBlobNotFoundErrorをスローします。存在しない場合を適切に処理してください。- Blob にシークレットを保存しないでください。認証情報には環境変数を使用してください。
リファレンス
API ドキュメント全文:https://docs.val.town/std/blob/