Configuration
S3WormOptions
The S3Worm constructor accepts a configuration object that tells the client how to connect to your S3-compatible storage:
import { S3Worm } from "@decoperations/s3worm";
const worm = new S3Worm({
bucket: "my-bucket",
endpoint: "https://gateway.storjshare.io",
region: "us-east-1",
credentials: {
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
},
});
Option Reference
| Option | Type | Required | Description |
|---|---|---|---|
bucket | string | Yes | The S3 bucket name to use as the database. |
endpoint | string | No | Custom S3 endpoint URL. Required for non-AWS providers (Storj, MinIO, R2, etc.). Protocol is auto-added if missing. Trailing slashes are stripped. |
region | string | No | AWS region. Defaults to "us-east-1". |
credentials | object | No | Access credentials with accessKeyId and secretAccessKey. Omit to use the default AWS credential chain. |
keychain | Keychain | No | Optional keychain instance for identity and credential management. |
signingKey | string | No | Signing key for access token creation. Defaults to the bucket name if not provided. |
S3ClientConfig Interface
interface S3ClientConfig {
bucket: string;
endpoint?: string;
region?: string;
credentials?: {
accessKeyId: string;
secretAccessKey: string;
};
}
The underlying AWS SDK client is configured with forcePathStyle: true for maximum compatibility across providers, along with followRegionRedirects: true and retryMode: "standard".
Environment Variables
You can source configuration from environment variables. S3WORM does not read these automatically -- you pass them to the constructor:
const worm = new S3Worm({
bucket: process.env.S3WORM_BUCKET!,
endpoint: process.env.S3WORM_ENDPOINT!,
region: process.env.S3WORM_REGION || "us-east-1",
credentials: {
accessKeyId: process.env.S3WORM_ACCESS_KEY!,
secretAccessKey: process.env.S3WORM_SECRET_KEY!,
},
});
Example .env file:
S3WORM_BUCKET=my-app-data
S3WORM_ENDPOINT=https://gateway.storjshare.io
S3WORM_REGION=us-east-1
S3WORM_ACCESS_KEY=jx7...
S3WORM_SECRET_KEY=jy8...
Provider-Specific Configurations
AWS S3
const worm = new S3Worm({
bucket: "my-bucket",
region: "us-west-2",
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
},
// No endpoint needed -- defaults to AWS S3
});
For AWS, you can also omit credentials entirely and rely on the default credential provider chain (IAM roles, environment variables, ~/.aws/credentials, etc.).
Storj Gateway (S3-Compatible)
const worm = new S3Worm({
bucket: "my-bucket",
endpoint: "https://gateway.storjshare.io",
region: "us-east-1",
credentials: {
accessKeyId: process.env.STORJ_ACCESS_KEY!,
secretAccessKey: process.env.STORJ_SECRET_KEY!,
},
});
Generate S3 credentials from the Storj dashboard under Access > S3 Credentials. The endpoint is always https://gateway.storjshare.io for the Storj DCS gateway.
MinIO
const worm = new S3Worm({
bucket: "my-bucket",
endpoint: "http://localhost:9000",
region: "us-east-1",
credentials: {
accessKeyId: "minioadmin",
secretAccessKey: "minioadmin",
},
});
MinIO uses http:// by default in development. The default credentials are minioadmin / minioadmin. For production, use TLS and proper credentials.
Cloudflare R2
const worm = new S3Worm({
bucket: "my-bucket",
endpoint: `https://${process.env.CF_ACCOUNT_ID}.r2.cloudflarestorage.com`,
region: "auto",
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY!,
secretAccessKey: process.env.R2_SECRET_KEY!,
},
});
R2 endpoints follow the pattern https://<account-id>.r2.cloudflarestorage.com. Create API tokens in the Cloudflare dashboard under R2 > Manage R2 API Tokens.
DigitalOcean Spaces
const worm = new S3Worm({
bucket: "my-bucket",
endpoint: "https://nyc3.digitaloceanspaces.com",
region: "nyc3",
credentials: {
accessKeyId: process.env.DO_SPACES_KEY!,
secretAccessKey: process.env.DO_SPACES_SECRET!,
},
});
Replace nyc3 with your Spaces region. Generate keys in the DigitalOcean dashboard under API > Spaces Keys.
CORS Configuration
If you access S3WORM from a browser (e.g., direct uploads with putBytes()), you need to configure CORS on your bucket.
AWS S3
Apply via the S3 console under Bucket > Permissions > CORS:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "HEAD", "DELETE"],
"AllowedOrigins": ["https://your-app.com"],
"ExposeHeaders": ["ETag", "Content-Length", "Content-Type"],
"MaxAgeSeconds": 3600
}
]
Storj
CORS is configured per bucket in the Storj dashboard. Navigate to Buckets > your-bucket > CORS and add:
[
{
"AllowedOrigins": ["https://your-app.com"],
"AllowedMethods": ["GET", "PUT", "HEAD", "DELETE"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
MinIO
Use the mc CLI tool:
mc admin config set local cors <<EOF
{
"cors": {
"allow_origin": ["https://your-app.com"],
"allow_methods": ["GET", "PUT", "HEAD", "DELETE"],
"allow_headers": ["*"],
"expose_headers": ["ETag"],
"max_age_seconds": 3600
}
}
EOF
mc admin service restart local
Or set CORS at the bucket level via the MinIO Console UI.
Cloudflare R2
R2 CORS is configured in the Cloudflare dashboard under R2 > your-bucket > Settings > CORS Policy:
[
{
"AllowedOrigins": ["https://your-app.com"],
"AllowedMethods": ["GET", "PUT", "HEAD", "DELETE"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
DigitalOcean Spaces
Configure via the DigitalOcean dashboard under Spaces > your-space > Settings > CORS Configurations, or use the s3cmd CLI:
s3cmd setcors cors.xml s3://my-bucket
<!-- cors.xml -->
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>https://your-app.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<ExposeHeader>ETag</ExposeHeader>
<MaxAgeSeconds>3600</MaxAgeSeconds>
</CORSRule>
</CORSConfiguration>
Schema Configuration
Beyond the client connection, S3WORM supports a JSON schema that defines models, storage layout, views, and access control. Load it with loadSchema():
worm.loadSchema(".worm/schema.json");
// Or pass the schema object directly
worm.loadSchema({
schemaVersion: "1.0",
sourceOfTruth: "local",
storage: { layout: "root" },
models: {
Customer: {
path: "#org/@customers/(id:uuid)",
fields: { name: { type: "string", required: true } },
file: "[profile].json",
},
},
});
See the Entity & Repository and Path DSL docs for schema model and path definitions.