Escape hatch
Drop down to the native, per-adapter client for any feature outside the unified surface — versioning, lifecycle rules, ACLs, object tags, and more.
The unified surface is deliberately small — the methods every adapter can implement. When you need a provider feature that isn't part of it (S3 versioning, lifecycle rules, ACLs, object tags, anything), drop down to the native client instead of waiting for it to be wrapped.
files.raw
raw is the underlying provider client, typed per adapter — S3Client for s3(), VercelBlobClient for vercelBlob(), an R2Bucket (or S3Client in HTTP mode) for r2(), and so on. The type flows through from the adapter, so you keep full autocomplete on it.
const files = new Files({ adapter: s3({ bucket: "uploads" }) });
// `files.raw` is typed as S3Client — no cast needed.
await files.raw.send(
new PutObjectAclCommand({
Bucket: "uploads",
Key: "a.png",
ACL: "public-read",
})
);files.adapter is the adapter itself, if you need its name or want to pass it around; files.adapter.raw is the same client as files.raw.
What raw bypasses
The native client talks to the provider directly, so none of the Files wrapper's behavior applies to calls you make through it:
- No prefix scoping. You pass the provider's full key yourself, including any
prefixtheFilesinstance was constructed with —files.rawdoesn't know about it. - No normalized errors. A failure throws the provider's own error type, not a
FilesError; catch and classify accordingly. - No hooks, retries, timeouts, or cancellation. Hooks don't fire, and
signal/timeout/retriesaren't applied. Use the provider client's own equivalents.
In short, raw is an unmanaged door straight to the provider. Reach for it for the one feature you need, and keep using the unified methods for everything else.
Keeping the type
The raw type is inferred from the adapter you pass in, so it stays typed as long as the instance keeps its concrete type. Widening to the bare Files (whose adapter is the default Adapter) erases it:
const files = new Files({ adapter: s3({ bucket: "uploads" }) });
files.raw; // S3Client
const widened: Files = files;
widened.raw; // unknownIf you store a Files instance on a typed field, annotate it with the adapter's type (for example Files<S3Adapter>) rather than the bare Files, and raw stays typed.
See the Compatibility section on each adapter's docs page for what it supports through the unified surface before reaching for the escape hatch.
Cancellation
An AbortSignal always fails the call fast at the Files layer; whether the underlying provider request is also cancelled depends on the adapter.
Multipart uploads
Upload a large body in parallel parts instead of a single request — the robust path past the single-request size limit and for streams of unknown length. A per-call option on upload only.