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.