💾blob-storage
- プラグイン
- valtown
- ソース
- GitHub で見る ↗
説明
次のような場合に使用: valにシンプルなキー/バリュー形式の永続化が必要なとき — JSONドキュメント、キャッシュされたレスポンス、アップロードされたファイル、またはバイナリアセットなど。 `std/blob` API、キーの一覧取得と削除、アカウントグローバルまたはvalスコープでのストレージ、およびストレージの制限についてカバーします。
原文を表示
Use when a val needs simple key/value persistence — JSON documents, cached responses, uploaded files, or binary assets. Covers the std/blob API, listing and deleting keys, account-global or val scoping, and storage limits.
ユースケース
- ✓シンプルなキー/バリュー形式の永続化が必要なとき
- ✓JSONドキュメントを保存するとき
- ✓キャッシュされたレスポンスを管理するとき
- ✓アップロードされたファイルを保存するとき
- ✓バイナリアセットを管理するとき
本文(日本語訳)
Blob Storage
Val Town は std/blob モジュールを通じて、組み込みのキー/バリュー型 Blob ストレージを提供しています。
JSON ドキュメント、キャッシュされた API レスポンス、アップロードされたファイル、バイナリアセットなど、文字列をキーとしてシンプルな値を永続化する必要がある場合に活用してください。
SQL でクエリを行うリレーショナルデータや構造化データには、代わりに std/sqlite を使用してください。
スコープ: インポート方法によってアカウントグローバルまたは val 単位になる
Blob ユーティリティには 2 種類のエクスポートがあります。
global.ts はユーザーアカウント全体にスコープされ、main.ts は val 自身にスコープされます。
新しい val には main.ts インターフェースと val スコープを使用することを推奨します。
スコープ付きインポート:
/**
* `main.ts` からインポートすると、val スコープの Blob インターフェースが利用できます。
*/
import { blob } from "https://esm.town/v/std/blob/main.ts";
グローバルインポート:
/**
* `global.ts` からインポートすると、アカウント全体にスコープされた
* Blob インターフェースが利用できます。
*/
import { blob } from "https://esm.town/v/std/blob/global.ts";
/**
* このエントリーポイントは `v/std/blob` としても利用可能です。
* 古い val ではこちらが一般的です。
*/
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 }、キーが存在しない場合は undefined
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_"); // オプションのキープレフィックスフィルター
// entries = [{ key, size, lastModified }, …]
for (const { key } of entries) {
await blob.delete(key);
}
await blob.copy("config", "config.bak"); // 新しいキーで複製
await blob.move("draft", "published"); // 名前変更 / 移動
list(prefix?) は { key: string; size: number; lastModified: string } の配列を返します。
キー文字列そのものではなく、オブジェクトの配列である点に注意してください。
制限事項
- キーの長さ: 最大 512 文字
- 総ストレージ容量: 無料プランで 10 MB、Pro プランで 1 GB(アカウント内の全 Blob で共有)
- 大容量データや構造化データセットは、1 つの巨大な Blob としてではなく
std/sqliteに保存してください。
ツールによる Blob の読み書き
storeBlob、readBlob、listBlobs、deleteBlob ツールを、個人アカウントではなく組織が所有する val に対して使用する場合は、org パラメーターに組織のハンドルを渡すことで、その組織の Blob ストレージにアクセスできます。
例: { key: "myapp:config", org: "some-org" }
これはツール呼び出し時のみ必要です。val 内のコードは、所有アカウントのストレージに自動的にアクセスします。
なお、storeBlob は 100 KB までの UTF-8 テキストを受け付けます。それより大きいデータやバイナリ Blob は、コード内で blob.set を使用して書き込んでください。
ルール
- キーはフラットな名前空間として扱ってください。整理のため、また
listのスコープを絞るために、プレフィックス(feature:subkey)を活用してください。 getJSONはキーが存在しない場合にundefinedを返し、getはValTownBlobNotFoundErrorをスローします。キーが存在しない場合の処理をそれぞれ適切に行ってください。- Blob にシークレットを保存しないでください。認証情報には環境変数を使用してください。
リファレンス
完全な API ドキュメント: https://docs.val.town/std/blob/
原文(English)を表示
Blob Storage
Val Town provides built-in key/value blob storage via the std/blob module. Reach for it whenever a val needs to persist simple values — JSON documents, cached API responses, uploaded files, or binary assets — keyed by a string. For relational or structured data you query with SQL, prefer std/sqlite instead.
Scoping: account-global or per-val depending on import
There are two exports of the blob utility: global.ts, which is scoped to the user account, and main.ts, which is scoped to the val itself. Prefer the main.ts interface and val scoping for new vals.
Here is the scoped import:
/**
* Importing from `main.ts` provides an interface to val-scoped blobs.
*/
import { blob } from "https://esm.town/v/std/blob/main.ts";
Here are the global imports:
/**
* 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";
The scoped & global blob interfaces have the same methods.
Scoped & global blobs are stored separately: you cannot access global blobs with the scoped interface or vice versa.
Basic usage (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 returns undefined when the key is missing, so guard before using the result:
const config = (await blob.getJSON("config")) ?? { theme: "light", count: 0 };
Raw and binary data
Use set/get for strings, binary, or any BodyInit. get returns a standard Response, so use its body helpers (.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();
Unlike getJSON, get throws ValTownBlobNotFoundError if the key doesn't exist — wrap it in try/catch when the key may be absent.
Listing, deleting, copying
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?) returns an array of { key: string; size: number; lastModified: string } — objects, not bare key strings.
Limits
- Key length: up to 512 characters.
- Total storage: 10 MB on the free plan, 1 GB on Pro — shared across all blobs in the account.
- Store large or structured datasets in
std/sqliterather than as one giant blob.
Reading/writing blobs via tools
When using the storeBlob, readBlob, listBlobs, or deleteBlob tools against a val owned by an organization (not your personal account), pass the org handle as the org parameter so the call hits that organization's blob storage. Example: { key: "myapp:config", org: "some-org" }. This only matters for the tool calls — code inside the val reads and writes its owning account's storage automatically. Note storeBlob accepts UTF-8 text up to 100 KB; write larger or binary blobs from code with blob.set.
Rules
- Treat keys as a flat namespace. Use prefixes (
feature:subkey) for organization and to scopelist. getJSONreturnsundefinedfor missing keys;getthrowsValTownBlobNotFoundError. Handle the absent case accordingly.- Don't store secrets in blobs — use environment variables for credentials.
Reference
Full API docs: https://docs.val.town/std/blob/
原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。