@unikvs/s3.bun
Bun の S3 クライアントで S3 互換オブジェクトストレージに保存する @unikvs/s3.bun の使い方を説明します。
概要
@unikvs/s3.bun は、Bun 組み込みの S3 クライアントで S3 互換オブジェクトストレージにバイト列を保存するストレージプラグインです。Bun 専用 AWS SDK には依存せず、bun モジュールの S3Client を動的インポートしてオブジェクトを操作します。扱うデータはバイト列専用です。write は Uint8Array<ArrayBuffer> を受け付け、read は Uint8Array<ArrayBuffer> を返します。
インストールは次のように行います。
npm install @unikvs/s3.bunpnpm add @unikvs/s3.bunyarn add @unikvs/s3.bunbun add @unikvs/s3.bunnub add @unikvs/s3.bunaube add @unikvs/s3.bun依存関係として @unikvs/core を使用します。AWS SDK は不要です。
使い方
ストレージクラスは S3 です。
import { S3 } from "@unikvs/s3.bun";
new S3(bucket: string, options: S3StorageOptions = {})
| 引数 | 型 | 説明 |
|---|---|---|
bucket |
string |
保存先のバケット名です。すべての操作で使います。 |
options |
S3StorageOptions |
Bun の S3Options から bucket を除き、allowRepair を加えた設定です。既定値は空オブジェクトです。 |
options.allowRepair |
boolean |
書き戻しによる書き込みを許可するかどうかです。既定値は false です。false にすると書き戻し(vars["unikvs:repair"] が true)の write・getWritable で RepairNotAllowedError を投げます。 |
S3StorageOptions には accessKeyId・secretAccessKey・sessionToken・region・endpoint・virtualHostedStyle・partSize・queueSize・retry などを指定できます。省略した項目は Bun が環境変数 (S3_ACCESS_KEY_ID、AWS_ACCESS_KEY_ID など) から解決します。options に指定した値は環境変数より優先されます。
ライフサイクルは次のとおりです。生成直後は isOpen が false で、open() で内部に S3Client を作ると true になります。open() は動的インポートを行うため非同期です。close() は保持している参照を破棄して false に戻ります。Bun の S3Client には破棄用の API がないため、解放処理はありません。
import { UniKvs } from "unikvs";
import { S3 } from "@unikvs/s3.bun";
const storage = new S3("my-bucket", {
region: "ap-northeast-1",
});
await storage.open();
const kvs = UniKvs.config().appendStorage(storage).create();
オブジェクト配置
キーはオブジェクトキーにそのまま対応します。プレフィックス付与やエスケープは行いません。
| UniKVS のキー | S3 のオブジェクトキー |
|---|---|
test.txt |
test.txt |
folder/テスト #123.dat |
folder/テスト #123.dat |
単発の書き込みは S3Client.write、読み取りは S3File.arrayBuffer、存在確認は S3Client.exists、削除は S3Client.delete を使用します。clear は S3Client.list でバケット内のすべてのオブジェクトを列挙し、continuationToken でページを進めながら 25 件ずつ並列に削除します。プレフィックスでは絞り込みません。
ストリームとマルチパート
単発の write は S3Client.write で保存し、単発の read は S3File.arrayBuffer の結果を Uint8Array に変換して返します。
書き込みストリームは S3File.writer が返す NetworkSink を使うため、大容量のマルチパートアップロードに対応します。
const writable = storage.getWritable({ key, vars, signal });
引数は vars・key・signal です。パートサイズは vars から読み取ります。@unikvs/s3.bun:partSize を優先し、なければ @unikvs/s3:partSize を参照します。バイト単位の正の整数で指定し、未指定なら Bun の既定値 (5 MiB) に従います。
signal が中断済みなら開始せずに StorageAbortedError を投げます。Bun の NetworkSink には中断用の API がないため、書き込み中の中断で送信済みのリクエストは取り消せません。中断後に close() を呼ぶと signal の理由で拒否され、オブジェクトは完成しません。未完了のマルチパートアップロードはオブジェクトとして公開されないため、途中の内容が読み取られることはありません。
読み取りストリームは次のように取得します。
const readable = storage.getReadable({ key, signal });
内部で S3File.stream を呼び、チャンクごとに signal を確認しながら中継します。存在しないキーの失敗はストリームの読み取り時に S3Error として現れます。
エラー
| エラー | 投げる条件 |
|---|---|
UnsupportedRuntimeError |
Bun グローバルが無いランタイムで open() を呼んだ場合に発生します。@unikvs/core の共通エラーです。 |
StorageNotOpenError |
オープンされていない状態で close() を呼んだ場合に発生します。 |
InvalidPartSizeError |
vars のパートサイズが正の整数でない場合に getWritable が投げます。@unikvs/core の共通エラーです。 |
StorageAbortedError |
getWritable の signal が中断済みの場合に投げます。@unikvs/core の共通エラーです。 |
- 存在しないキーの
readはエラーで失敗します。必要なら事前にexistsを使います。 - 存在しないキーの
deleteはエラーになりません。
使用例
S3 互換ストレージへの最小構成例です。エンドポイントや認証情報はダミー値で、MinIO などへの接続を想定しています。バケットは事前に作っておきます。
import { S3 } from "@unikvs/s3.bun";
const storage = new S3("my-bucket", {
endpoint: "http://127.0.0.1:9000",
region: "ap-northeast-1",
accessKeyId: "minioadmin",
secretAccessKey: "minioadmin",
});
await storage.open();
const signal = AbortSignal.timeout(30_000);
const key = "hello.txt";
const data = new TextEncoder().encode("Hello S3");
await storage.write({ key, data, signal });
const loaded = await storage.read({ key, signal });
console.log(new TextDecoder().decode(loaded));
storage.close();