S3Worm Client API
The S3Worm class is the primary interface for working with S3WORM. It wraps an S3-compatible bucket and exposes document CRUD, binary uploads, metadata queries, typed repositories, and schema-driven models.
Constructor
import { S3Worm } from "@decoperations/s3worm";
const worm = new S3Worm({
bucket: "my-bucket",
endpoint: "https://gateway.storjshare.io",
region: "us-east-1",
credentials: {
accessKeyId: "...",
secretAccessKey: "...",
},
});
See Configuration for all constructor options and provider-specific examples.
Document Operations
These methods operate on raw JSON documents by path. They are the simplest way to use S3WORM without entities or schemas.
create(path, data)
Create a new JSON document. Throws if a document already exists at the path.
await worm.create("users/alice/profile.json", {
name: "Alice",
role: "admin",
});
| Parameter | Type | Description |
|---|---|---|
path | string | S3 key for the document |
data | any | Object to serialize as JSON |
Returns: Promise<void>
read<T>(path)
Read and parse a JSON document. Returns null if the document does not exist.
const profile = await worm.read<{ name: string; role: string }>(
"users/alice/profile.json"
);
| Parameter | Type | Description |
|---|---|---|
path | string | S3 key for the document |
Returns: Promise<T | null>
update(path, data)
Update an existing document. Throws if the document does not exist.
await worm.update("users/alice/profile.json", {
name: "Alice",
role: "superadmin",
});
save(path, data)
Create or update a document (upsert). Does not check existence first.
await worm.save("config/app-settings.json", {
theme: "dark",
version: "2.1.0",
});
delete(path)
Delete a document. Throws if the document does not exist.
await worm.delete("users/alice/profile.json");
exists(path)
Check if a document exists.
const hasProfile = await worm.exists("users/alice/profile.json");
Returns: Promise<boolean>
list(prefix)
List all object keys under a prefix.
const keys = await worm.list("users/alice/");
// ["users/alice/profile.json", "users/alice/settings.json"]
Returns: Promise<string[]>
Binary Uploads
putBytes(key, data, contentType, options?)
Upload raw binary data to S3. Browser-safe -- works with Uint8Array, ArrayBuffer, and Blob.
const file = document.querySelector("input[type=file]")!.files![0];
await worm.putBytes(
`uploads/${file.name}`,
file,
file.type,
{
onProgress: (pct) => console.log(`${pct}% uploaded`),
}
);
| Parameter | Type | Description |
|---|---|---|
key | string | S3 key for the object |
data | Uint8Array | ArrayBuffer | Blob | Binary data to upload |
contentType | string | MIME type (e.g. "image/png") |
options | PutBytesOptions | Optional. Progress callback. |
Returns: Promise<{ url?: string }>
PutBytesOptions
interface PutBytesOptions {
onProgress?: (percentage: number) => void;
}
The onProgress callback receives 0 at the start and 100 on completion. Intermediate progress values are available when multipart upload is used for large files.
Metadata Operations
listWithMetadata(prefix)
List objects under a prefix with full metadata (size, content type, last modified). Fetches HeadObject for each result with parallel concurrency.
const entries = await worm.listWithMetadata("uploads/");
for (const entry of entries) {
console.log(entry.key, entry.size, entry.contentType, entry.lastModifiedIso);
}
Returns: Promise<WormListEntry[]>
headObject(key)
Fetch metadata for a single object without downloading its body.
const meta = await worm.headObject("uploads/photo.jpg");
console.log(meta.size); // 245760
console.log(meta.contentType); // "image/jpeg"
console.log(meta.lastModifiedIso); // "2026-02-24T10:30:00.000Z"
console.log(meta.etag); // "\"abc123...\""
Returns: Promise<{ size: number; contentType: string; lastModifiedIso: string; etag?: string }>
getPublicUrl(key)
Construct a public URL for a key using path-style addressing. Requires that the client was configured with an endpoint.
const url = worm.getPublicUrl("uploads/photo.jpg");
// "https://gateway.storjshare.io/my-bucket/uploads/photo.jpg"
Returns: string | undefined (undefined if no endpoint is configured)
Types
WormListEntry
Returned by listWithMetadata():
interface WormListEntry {
/** S3 object key */
key: string;
/** File size in bytes */
size: number;
/** MIME content type */
contentType: string;
/** ISO 8601 last-modified timestamp */
lastModifiedIso: string;
}
WormEntity
A simple document reference used by the low-level getString, putString, getJSON, and putJSON methods:
interface WormEntity {
bucketName: string;
key: string;
userId?: string;
filename?: string;
}
Repository Access
getRepository<T>(EntityClass)
Get a class-based Repository<T> for an entity type. See Entity & Repository for full details.
import { Entity } from "@decoperations/s3worm";
class Task extends Entity {
title = "";
done = false;
static getBasePath() { return "tasks"; }
}
const tasks = worm.getRepository(Task);
const all = await tasks.findAll();
Schema-Driven Models
loadSchema(pathOrSchema)
Load a schema configuration from a file path (Node.js only) or a parsed object. Initializes storage resolution and clears cached model repositories.
// From file (Node.js)
worm.loadSchema(".worm/schema.json");
// From object (universal)
worm.loadSchema({
schemaVersion: "1.0",
sourceOfTruth: "local",
storage: { layout: "root" },
models: { /* ... */ },
});
model(name)
Get a SchemaRepository for a named model defined in the loaded schema. Repositories are cached per model name.
const customers = worm.model("Customer");
const c = await customers.findById("abc-123");
Returns: SchemaRepository
view(name)
Get a pre-configured view from the schema. Views are saved queries that return a repository with preset filters.
const active = await worm.view("ActiveCustomers").findAll();
const recent = await worm.view("ActiveCustomers").findAll({ limit: 10 });
Returns: { findAll(overrides?) }
getModelNames()
List all model names defined in the loaded schema.
const models = worm.getModelNames();
// ["Customer", "Invoice", "OrgSettings"]
getSchema()
Get the loaded schema configuration object, or undefined if no schema is loaded.
const schema = worm.getSchema();
ACL & Identity
getPrincipal()
Resolve the current principal from the keychain, or return an anonymous principal.
const principal = await worm.getPrincipal();
// { id: "0x1234...", type: "user", roles: ["admin"] }
checkAccess(modelName, operation, entityId?)
Non-throwing ACL check. Returns { allowed, reason }.
const result = await worm.checkAccess("Customer", "write");
if (!result.allowed) {
console.log("Denied:", result.reason);
}
enforceAccess(modelName, operation, entityId?)
Throwing ACL check. Raises AclDeniedError if the operation is not permitted.
await worm.enforceAccess("Customer", "delete", "abc-123");
// throws if denied
Access Tokens
createAccessToken(options)
Create a scoped, time-limited access token.
const token = await worm.createAccessToken({
subject: "partner-api",
permissions: [
{ model: "Customer", operations: ["read", "list"] },
{ model: "Invoice", operations: ["read"] },
],
expiresIn: "24h",
});
verifyAccessToken(token)
Verify a token's signature, expiration, and revocation status.
const { valid, reason } = await worm.verifyAccessToken(token);
revokeAccessToken(tokenId)
Revoke a previously issued access token.
await worm.revokeAccessToken(token.id);
Factory Function
getS3Worm(options)
A convenience factory that creates an S3Worm instance. Available from all entry points including @decoperations/s3worm/edge.
import { getS3Worm } from "@decoperations/s3worm";
const worm = getS3Worm({
bucketName: "my-bucket",
endpoint: "https://gateway.storjshare.io",
region: "us-east-1",
credentials: {
accessKeyId: "...",
secretAccessKey: "...",
},
});
Note: getS3Worm accepts S3WormOptions (with bucketName) while the S3Worm constructor accepts S3ClientConfig (with bucket).