Skip to content
UniKVS
English
Esc
↑↓navigate↵open⌘Jpreview
On this page

@unikvs/s3.bun

Learn how to use @unikvs/s3.bun to store data in S3-compatible object storage from Bun.

Overview

@unikvs/s3.bun is a Bun-only storage plugin that saves byte arrays to S3-compatible object storage using Bun’s built-in S3 client. Bun only It does not depend on AWS SDK; it dynamically imports S3Client from the bun module for object operations. It handles byte arrays only. write accepts Uint8Array<ArrayBuffer> and read returns Uint8Array<ArrayBuffer>.

Install it as follows.

npm install @unikvs/s3.bun
pnpm add @unikvs/s3.bun
yarn add @unikvs/s3.bun
bun add @unikvs/s3.bun
nub add @unikvs/s3.bun
aube add @unikvs/s3.bun

It depends on @unikvs/core. No AWS SDK is required.

Usage

The storage class is S3.

import { S3 } from "@unikvs/s3.bun";
new S3(bucket: string, options: S3StorageOptions = {})
Argument Type Description
bucket string The destination bucket name. All operations use it.
options S3StorageOptions Bun’s S3Options without bucket, plus allowRepair. Defaults to an empty object.
options.allowRepair boolean Whether to allow repair writes. Defaults to false. When false, write and getWritable for repairs (where vars["unikvs:repair"] is true) throw RepairNotAllowedError.

S3StorageOptions accepts accessKeyId, secretAccessKey, sessionToken, region, endpoint, virtualHostedStyle, partSize, queueSize, retry, and more. Omitted fields are resolved by Bun from environment variables such as S3_ACCESS_KEY_ID and AWS_ACCESS_KEY_ID. Values in options take precedence over environment variables.

The lifecycle is as follows. Right after instantiation, isOpen is false. Calling open() creates an internal S3Client and sets true. open() is asynchronous because it uses a dynamic import. Calling close() drops the reference and resets to false. Bun’s S3Client has no dispose API, so there is no release step.

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();

Object Layout

Keys map directly to object keys. No prefixing or escaping is applied.

UniKVS key S3 object key
test.txt test.txt
folder/テスト #123.dat folder/テスト #123.dat

Single writes use S3Client.write, reads use S3File.arrayBuffer, existence checks use S3Client.exists, and deletions use S3Client.delete. clear lists all objects in the bucket with S3Client.list, advances pages via continuationToken, and deletes them 25 at a time in parallel. No prefix filtering is applied.

Streams and Multipart

A single write saves with S3Client.write, and a single read converts the S3File.arrayBuffer result into Uint8Array.

Writable streams use the NetworkSink returned by S3File.writer, so large payloads benefit from multipart upload.

const writable = storage.getWritable({ key, vars, signal });

The arguments are vars, key, and signal. The part size is read from vars. The @unikvs/s3.bun:partSize key takes precedence, falling back to @unikvs/s3:partSize. Specify a positive integer in bytes. When omitted, Bun’s default of 5 MiB applies.

If signal is already aborted, it throws StorageAbortedError without starting. Bun’s NetworkSink has no abort API, so an in-flight request cannot be canceled mid-write. Calling close() after an abort rejects with the signal reason and never completes the object. Incomplete multipart uploads are not exposed as objects, so partial contents can never be read.

Obtain a readable stream as follows.

const readable = storage.getReadable({ key, signal });

Internally it calls S3File.stream and relays chunks while checking signal. Failures for missing keys surface as S3Error when the stream is read.

Errors

Error When thrown
UnsupportedRuntimeError Thrown by open() when the runtime has no Bun global. A shared error from @unikvs/core.
StorageNotOpenError Thrown by close() when the storage is not open.
InvalidPartSizeError Thrown by getWritable when the part size in vars is not a positive integer. A shared error from @unikvs/core.
StorageAbortedError Thrown when the signal for getWritable is already aborted. A shared error from @unikvs/core.
  • read on a missing key fails with an error. Use exists beforehand when needed.
  • delete on a missing key does not fail.
  • Failures such as auth errors reject the stream’s close() with the failure reason.

Examples

A minimal example against S3-compatible storage. The endpoint and credentials are dummy values for common S3-compatible storage (such as MinIO). Create the bucket beforehand.

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();

Was this page helpful?