API Reference
Complete TypeScript API surface for the S3WORM ecosystem.
@decoperations/s3worm
The core package. Provides the ORM client, entities, repositories, schema-driven models, ACLs, keychain, and access tokens.
S3Worm
The main entry point for all operations.
import { S3Worm } from "@decoperations/s3worm";
Constructor
const worm = new S3Worm(config: S3WormConfig);
interface S3WormConfig {
/** S3 bucket name */
bucket: string;
/** AWS region */
region?: string;
/** S3 endpoint URL */
endpoint?: string;
/** AWS credentials */
credentials?: {
accessKeyId: string;
secretAccessKey: string;
};
/** Optional keychain for credential + identity management */
keychain?: Keychain;
/** Optional access token for token-based auth */
token?: AccessTokenData;
/** Optional signing key for token creation */
signingKey?: string;
}
Document Operations
// Create a document (throws if path already exists)
await worm.create(path: string, data: any): Promise<void>;
// Read a document
await worm.read<T>(path: string): Promise<T | null>;
// Update a document (throws if path does not exist)
await worm.update(path: string, data: any): Promise<void>;
// Upsert a document (create or update)
await worm.save(path: string, data: any): Promise<void>;
// Delete a document
await worm.delete(path: string): Promise<void>;
// Check if a document exists
await worm.exists(path: string): Promise<boolean>;
// List all keys under a prefix
await worm.list(prefix: string): Promise<string[]>;
// List keys with metadata
await worm.listWithMetadata(prefix: string): Promise<WormListEntry[]>;
// Get object metadata
await worm.headObject(key: string): Promise<{
size: number;
contentType: string;
lastModifiedIso: string;
etag?: string;
}>;
// Get a public URL for a key
worm.getPublicUrl(key: string): string | undefined;
Binary Operations
// Upload raw bytes
await worm.putBytes(
key: string,
data: Uint8Array | ArrayBuffer | Blob,
contentType: string,
options?: PutBytesOptions
): Promise<{ url?: string }>;
// Low-level string get/put
await worm.getString(entity: WormEntity): Promise<string | null>;
await worm.putString(entity: WormEntity, data: string): Promise<void>;
await worm.getJSON<T>(entity: WormEntity): Promise<T | null>;
await worm.putJSON(entity: WormEntity, data: any): Promise<void>;
Schema Operations
// Load a schema from file path or object
worm.loadSchema(pathOrSchema: string | WormSchemaConfig): void;
// Get a schema-driven repository
worm.model(name: string): SchemaRepository;
// Get a pre-configured view
worm.view(name: string): { findAll(overrides?: Record<string, unknown>): Promise<SchemaEntity[]> };
// Get model names
worm.getModelNames(): string[];
// Get the loaded schema
worm.getSchema(): WormSchemaConfig | undefined;
ACL Operations
// Get the resolved principal
await worm.getPrincipal(): Promise<Principal>;
// Set principal explicitly
worm.setPrincipal(principal: Principal): void;
// Clear cached principal
worm.clearPrincipal(): void;
// Dry-run ACL check
await worm.checkAccess(
modelName: string,
operation: AclOperation,
entityId?: string
): Promise<{ allowed: boolean; reason?: AclDenyReason }>;
// Enforce ACL (throws AclDeniedError on deny)
await worm.enforceAccess(
modelName: string,
operation: AclOperation,
entityId?: string
): Promise<void>;
// Get the ACL evaluator
worm.getAclEvaluator(): AclEvaluator;
// Get the keychain
worm.getKeychain(): Keychain | undefined;
Token Operations
// Create a scoped access token
await worm.createAccessToken(options: {
subject: string;
permissions: TokenPermission[];
expiresIn?: string;
expiresAt?: string;
}): Promise<AccessTokenData>;
// Verify a token
await worm.verifyAccessToken(token: AccessTokenData): Promise<{
valid: boolean;
reason?: string;
}>;
// Revoke a token
await worm.revokeAccessToken(tokenId: string): Promise<void>;
Class-Based Repository
// Get a repository for a hand-written Entity class
worm.getRepository<T extends Entity>(entityClass: EntityConstructor<T>): Repository<T>;
Entity
Base class for hand-written entity types.
import { Entity } from "@decoperations/s3worm";
class BlogPost extends Entity {
title: string = "";
content: string = "";
static getBasePath(): string {
return "posts";
}
}
Properties
| Property | Type | Description |
|---|---|---|
id | string | Entity ID (auto-generated on save) |
createdAt | string? | ISO 8601 creation timestamp |
updatedAt | string? | ISO 8601 last-modified timestamp |
Methods
| Method | Returns | Description |
|---|---|---|
static getBasePath() | string | S3 prefix for this entity type |
getFileName() | string | Filename ({id}.json by default) |
getPath() | string | Full S3 key (basePath/fileName) |
clone() | this | Shallow clone |
toJSON() | object | Plain object (for JSON.stringify) |
toObject() | object | Plain object |
beforeSave() | void | Sets timestamps (called automatically) |
Static Helpers
Entity.forUser(address: string, filename: string): WormEntity;
Entity.forCollection(address: string, collection: string): WormEntity;
Entity.parse(key: string): WormEntity;
Repository
Class-based CRUD repository for hand-written Entity types.
const repo = worm.getRepository(BlogPost);
| Method | Signature | Description |
|---|---|---|
findById | (id: string) => Promise<T | null> | Find entity by ID |
findAll | (options?: FindAllOptions<T>) => Promise<T[]> | Find all with filter/sort/pagination |
save | (entity: T) => Promise<T> | Save entity (auto-generates ID) |
delete | (entityOrId: T | string) => Promise<boolean> | Delete entity |
create | (data?: Partial<T>) => T | Create instance without saving |
interface FindAllOptions<T> {
filter?: (item: T) => boolean;
sort?: (a: T, b: T) => number;
limit?: number;
offset?: number;
}
SchemaRepository
Schema-driven repository returned by worm.model(). Provides typed CRUD, validation, filtering, aggregation, entity links, and more.
const customers = worm.model("Customer");
CRUD
// Create an entity instance (does not persist)
customers.create(data: Record<string, unknown>): SchemaEntity;
// Save (create or update)
await customers.save(entity: SchemaEntity, options?: { actor?: string }): Promise<SchemaEntity>;
// Find by ID
await customers.findById(id: string, options?: {
select?: string[];
populate?: PopulateSpec;
}): Promise<SchemaEntity | null>;
// Find all with query options
await customers.findAll(options?: {
filter?: Record<string, unknown>;
sort?: { field: string; order: "asc" | "desc" };
limit?: number;
offset?: number;
select?: string[];
populate?: PopulateSpec;
}): Promise<SchemaEntity[]>;
// Count entities
await customers.count(filter?: Record<string, unknown>): Promise<number>;
// Check existence
await customers.exists(id: string): Promise<boolean>;
// Delete
await customers.delete(id: string, options?: { actor?: string }): Promise<boolean>;
Soft Delete
await customers.listTrashed(): Promise<SchemaEntity[]>;
await customers.restore(id: string): Promise<SchemaEntity | null>;
await customers.purge(id: string): Promise<boolean>;
await customers.purgeExpired(): Promise<number>;
Oplog
await customers.getHistory(id: string): Promise<OplogEntry[]>;
await customers.rollback(id: string, options: { toSeq: number }): Promise<SchemaEntity | null>;
Snapshots
await customers.snapshot(id: string): Promise<void>;
await customers.listSnapshots(id: string): Promise<{ ts: string; size: number }[]>;
await customers.restoreSnapshot(id: string, ts: string): Promise<SchemaEntity | null>;
Entity Links
await customers.findRelated(id: string, refName: string, options?: FindRelatedOptions): Promise<SchemaEntity[]>;
await customers.populate(entity: SchemaEntity, spec: PopulateSpec): Promise<SchemaEntity>;
Aggregation
await customers.aggregate(options: AggregateOptions): Promise<AggregateResult>;
Properties
| Property | Type | Description |
|---|---|---|
mode | AccessMode | "readonly" | "readwrite" | "append" |
schema | ModelDefinition | The model definition from schema.json |
Core Types
WormListEntry
interface WormListEntry {
key: string;
size: number;
contentType: string;
lastModifiedIso: string;
}
PutBytesOptions
interface PutBytesOptions {
onProgress?: (percentage: number) => void;
}
S3WormOptions
interface S3WormOptions {
bucketName: string;
region?: string;
credentials?: any;
endpoint?: string;
}
Schema Types
WormSchemaConfig
interface WormSchemaConfig {
schemaVersion: string;
sourceOfTruth: "local" | "remote" | "bidirectional" | string;
symbols?: Record<string, string>;
dynamicTypes?: Record<string, DynamicTypeDefinition>;
operators?: Record<string, OperatorDefinition>;
storage?: StorageConfig;
paths?: string[];
models?: Record<string, ModelDefinition>;
views?: Record<string, ViewDefinition>;
rules?: Record<string, WormRule>;
acl?: BucketAcl;
}
ModelDefinition
interface ModelDefinition {
path: string;
idType?: string;
fields: Record<string, FieldDefinition>;
file: string;
mode?: AccessMode; // "readonly" | "readwrite" | "append"
singleton?: boolean;
oplog?: boolean;
softDelete?: boolean;
snapshots?: SnapshotConfig;
refs?: Record<string, RefDefinition>;
integrity?: IntegrityConfig;
manifest?: ManifestConfig;
indexes?: Record<string, IndexDefinition>;
acl?: ModelAcl;
}
FieldDefinition
interface FieldDefinition {
type: FieldType; // "string" | "number" | "boolean" | "datetime" | "object" | "string[]" | "number[]" | "object[]"
required?: boolean;
enum?: string[];
default?: unknown;
ref?: string;
auto?: boolean;
embedded?: boolean;
encrypted?: boolean;
acl?: string[];
}
WormRule
interface WormRule {
applyTo?: string;
acl?: string | ModelAcl;
scope?: string;
validator?: string;
onWrite?: string;
[key: string]: unknown;
}
ACL Types
Principal Types
interface Principal {
id: string;
name?: string;
type: "user" | "service" | "anonymous";
roles?: string[];
}
interface UserPrincipal extends Principal {
type: "user";
identity:
| { method: "evm"; address: string }
| { method: "solana"; address: string }
| { method: "email"; email: string };
}
interface ServicePrincipal extends Principal {
type: "service";
keyId: string;
}
interface AnonymousPrincipal extends Principal {
type: "anonymous";
id: "anonymous";
}
BucketAcl
interface BucketAcl {
defaultPolicy: "deny" | "allow";
principals?: Record<string, PrincipalDefinition>;
grants?: BucketGrant[];
accessLog?: AccessLogConfig;
}
ModelAcl
interface ModelAcl {
read?: string[];
write?: string[];
delete?: string[];
list?: string[];
}
AclDenyReason
type AclDenyReason =
| { layer: "mode"; model: string; mode: AccessMode; operation: string }
| { layer: "bucket"; principal: string; operation: string; policy: string }
| { layer: "model"; principal: string; model: string; operation: string }
| { layer: "entity"; principal: string; rule: string; scope: string }
| { layer: "token"; principal: string; operation: string; reason: string };
AccessTokenData
interface AccessTokenData {
id: string;
issuer: string;
subject: string;
permissions: TokenPermission[];
issuedAt: string;
expiresAt: string;
signature: string;
}
interface TokenPermission {
model: string;
operations: AclOperation[];
ids?: string[];
filter?: Record<string, unknown>;
}
Link Types
RefDefinition
interface RefDefinition {
field?: string;
model: string;
foreignKey?: string;
type: "belongsTo" | "hasMany" | "hasOne";
onDelete?: "cascade" | "nullify" | "restrict" | "none";
through?: ThroughConfig;
index?: boolean;
eager?: boolean;
}
PopulateSpec
type PopulateSpec = string[] | Record<string, true | PopulateRefOptions>;
interface PopulateRefOptions {
populate?: PopulateSpec;
select?: string[];
}
Manifest Types
ManifestConfig
interface ManifestConfig {
enabled: boolean;
fields?: string[];
autoUpdate?: boolean;
partitionThreshold?: number;
maxPartitions?: number;
}
IndexDefinition
interface IndexDefinition {
field: string;
unique?: boolean;
type?: "standard" | "multiValue";
}
AggregateOptions
interface AggregateOptions {
groupBy?: string;
count?: boolean;
sum?: string;
avg?: string;
min?: string;
max?: string;
filter?: Record<string, unknown>;
}
@decoperations/bucket-sync
Exports from main entry
import {
LocalBucket,
BlobStore,
ManifestDB,
SyncEngine,
CacheManager,
TabCoordinator,
CryptoManager,
hashBlob,
hashBuffer,
} from "@decoperations/bucket-sync";
Exports from service-worker entry
import {
registerBucketSW,
unregisterBucketSW,
} from "@decoperations/bucket-sync/service-worker";
@decoperations/s3worm-gateway
Exports from main entry
import {
Gateway,
GatewayError,
resolveAuth,
AuthError,
} from "@decoperations/s3worm-gateway";
import type {
GatewayConfig,
CorsConfig,
OperationContext,
ParsedQuery,
GatewayRequest,
GatewayResponse,
AuthConfig,
JwtAuthConfig,
ApiKeyAuthConfig,
AuthResult,
JwtClaims,
} from "@decoperations/s3worm-gateway";
Exports from nextjs entry
import {
createWormHandler,
createModelHandlers,
createEntityHandlers,
} from "@decoperations/s3worm-gateway/nextjs";
import type {
NextRouteHandler,
WormHandlerOptions,
} from "@decoperations/s3worm-gateway/nextjs";
Export Paths
| Package | Entry | Description |
|---|---|---|
@decoperations/s3worm | main | Core ORM client, entities, types |
@decoperations/s3worm/server | /server | Server-only utilities |
@decoperations/s3worm/edge | /edge | Edge runtime utilities |
@decoperations/bucket-sync | main | LocalBucket, SyncEngine, CryptoManager |
@decoperations/bucket-sync/service-worker | /service-worker | SW registration and bucket SW |
@decoperations/s3worm-gateway | main | Gateway, auth resolvers |
@decoperations/s3worm-gateway/nextjs | /nextjs | Next.js App Router adapter |