Read-only
Lock a Files instance to reads only with the readonly option or files.readonly(), so every write surface fails consistently with a ReadOnly FilesError.
When a caller should be able to inspect storage but never mutate it, lock the client at construction:
const files = new Files({
adapter: s3({ bucket: "uploads" }),
readonly: true,
});Or derive a read-only view from an existing configured client:
const files = new Files({
adapter: s3({ bucket: "uploads" }),
prefix: "users",
timeout: 10_000,
});
const readOnlyFiles = files.readonly();The derived view reuses the same adapter, prefix, timeout, retries, and hooks. It does not clone storage state or create a second provider client.
What is still allowed
Read-only instances still support every read surface:
downloadheadexistslistlistAllurlfile(key)for a key-scoped read handle
What is blocked
Every write surface throws FilesError with code: "ReadOnly":
uploaddeletecopymovesignedUploadUrl- The equivalent
file(key)helpers:upload,delete,copyTo,copyFrom,moveTo,moveFrom,signedUploadUrl
try {
await readOnlyFiles.upload("avatars/123.png", file);
} catch (err) {
if (err instanceof FilesError && err.code === "ReadOnly") {
// switch to a writable Files instance
}
}What it does not lock down
Read-only applies to the unified Files API only. The raw escape hatch still exposes the underlying provider client unchanged, so code that writes through files.raw bypasses the guard by design.
Cancellation
An AbortSignal always fails the call fast at the Files layer; whether the underlying provider request is also cancelled depends on the adapter.
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.