Background
`S3Client` constructor today: `(region?: string, profile?: string)`. The endpoint is implicitly `s3..amazonaws.com`. Every S3-API-compatible store needs a custom endpoint:
| Provider |
Endpoint format |
| Cloudflare R2 |
`https://.r2.cloudflarestorage.com` |
| MinIO |
self-hosted, arbitrary URL |
| DigitalOcean Spaces |
`https://.digitaloceanspaces.com` |
| Backblaze B2 |
`https://s3..backblazeb2.com` |
| Wasabi |
`https://s3..wasabisys.com` |
Without a way to override the endpoint, downstream packages can't ship adapters for any of these — they're all S3-API-compatible but the request URL needs to point elsewhere.
This blocks stacksjs/stacks#1896 (R2 driver). The framework's per-tenant scoping wrapper (`ScopedStorageAdapter`) already works with any S3-shaped adapter — only the endpoint config is missing.
Proposed API
new S3Client({ region: 'auto', endpoint: 'https://<account-id>.r2.cloudflarestorage.com', credentials })
// Or as a third positional arg if the constructor must stay positional-compatible:
new S3Client(region, profile, { endpoint })
The signing logic stays unchanged — SigV4 against the configured endpoint host. Apps using the default AWS endpoint see no behavior change.
Acceptance
Once this lands, the Stacks-side R2 driver is ~30 lines extending S3StorageAdapter with the right config defaults.
Background
`S3Client` constructor today: `(region?: string, profile?: string)`. The endpoint is implicitly `s3..amazonaws.com`. Every S3-API-compatible store needs a custom endpoint:
Without a way to override the endpoint, downstream packages can't ship adapters for any of these — they're all S3-API-compatible but the request URL needs to point elsewhere.
This blocks stacksjs/stacks#1896 (R2 driver). The framework's per-tenant scoping wrapper (`ScopedStorageAdapter`) already works with any S3-shaped adapter — only the endpoint config is missing.
Proposed API
The signing logic stays unchanged — SigV4 against the configured endpoint host. Apps using the default AWS endpoint see no behavior change.
Acceptance
S3Clientaccepts a customendpointfield (constructor or options)Once this lands, the Stacks-side R2 driver is ~30 lines extending
S3StorageAdapterwith the right config defaults.