---
changelog:
  category: Release
  version: files-sdk@1.1.0
date: '2026-05-09T19:59:05Z'
seo:
  description: >-
    Add Akamai Cloud Object Storage adapter (files-sdk/akamai), formerly Linode
    Object Storage. Thin wrapper over the S3 adapter with Akamai defaults:
    endpoint…
title: files-sdk@1.1.0
type: changelog
---
### Minor Changes

-   510cde5: Add Akamai Cloud Object Storage adapter (`files-sdk/akamai`), formerly Linode Object Storage. Thin wrapper over the S3 adapter with Akamai defaults: endpoint derived from the `region` cluster code (`us-iad-1`, `nl-ams-1`, `fr-par-1`, the older `us-east-1`/`eu-central-1`/`ap-south-1` clusters, etc.) as `https://<region>.linodeobjects.com` and overridable, virtual-hosted-style addressing, `"Akamai error"` provider label, and `AKAMAI_ACCESS_KEY_ID` / `AKAMAI_SECRET_ACCESS_KEY` env-var fallbacks. `publicBaseUrl` accepts a public-bucket origin (`https://<bucket>.<region>.linodeobjects.com`) or a custom CNAME for unsigned URLs; otherwise `url()` returns a presigned GetObject (1-hour default).
-   f40e0d3: Add Box adapter (`files-sdk/box`) for personal Box and Box Enterprise via the official `box-typescript-sdk-gen` SDK. Box files live by ID rather than by path, so the adapter walks `rootFolderId` and translates virtual keys (`docs/a.txt`) into nested Box subfolders, auto-creating intermediate folders on `upload()` and racing-recovering on `item_name_in_use`. Five auth shapes (pre-built `client`, `developerToken`, `oauth` with refresh-token seeding, `ccg` with `enterpriseId` or `userId`, and `jwt` with `configJsonString` or `configFilePath`) cover scripts, user apps, and enterprise installs; env-var fallback via `BOX_DEVELOPER_TOKEN`. Token lifecycle is handled by the SDK's built-in `Authentication` classes — no manual refresh bookkeeping. Direct `upload()` uses single-call `uploads.uploadFile` up to 50 MB and switches to `chunkedUploads.uploadBigFile` automatically; existing leaf names route through `uploadFileVersion` (overwrite). `url()` mints a signed download URL via `getDownloadFileUrl` by default; with `publicByDefault: true`, `upload()` also calls `addShareLinkToFile` (open access) and `url()` returns the link's `download_url`; `responseContentDisposition` always throws (no override on Box URLs). `signedUploadUrl()` throws — Box uploads require a multipart POST with both an `attributes` JSON part and the file bytes part, which fits neither the SDK's PUT-with-headers nor POST-with-form-fields shape; use `upload()` server-side or Box's UI Elements / Content Uploader for browser flows. `list()` returns immediate-children files only at `rootFolderId` (no recursion, subfolders filtered out, prefix matched client-side, offset encoded as a numeric cursor). User `metadata` and `cacheControl` throw (Box exposes file metadata via classifications and metadata templates — drop to `raw.fileMetadata.*` if you need it).
-   54edb1b: Add DigitalOcean Spaces adapter (`files-sdk/digitalocean-spaces`). Thin wrapper over the S3 adapter with Spaces defaults: endpoint derived from `region` (`https://${region}.digitaloceanspaces.com`), virtual-hosted addressing, `"Spaces error"` provider label, and `DO_SPACES_KEY` / `DO_SPACES_SECRET` env-var fallbacks. `publicBaseUrl` accepts a Spaces CDN host (`https://${bucket}.${region}.cdn.digitaloceanspaces.com`) or a custom CNAME.
-   c841bbb: Add Dropbox adapter (`files-sdk/dropbox`) for personal Dropbox and Dropbox Business via the official `dropbox` SDK. Path-addressable like OneDrive, so virtual keys map directly to Dropbox paths — no virtual-key cache. Four auth shapes (pre-built `client`, static or callable `accessToken`, OAuth refresh-token flow with `refreshToken` + `appKey` (+ optional `appSecret`), and env-var fallback via `DROPBOX_ACCESS_TOKEN` or `DROPBOX_REFRESH_TOKEN` + `DROPBOX_APP_KEY` (+ `DROPBOX_APP_SECRET`)). Refresh tokens are exchanged at `api.dropboxapi.com/oauth2/token` and cached until ~60s before expiry. `url()` mints a 4-hour temporary link via `filesGetTemporaryLink` by default; with `publicByDefault: true`, `upload()` also creates a public shared link and `url()` returns it (rewritten to `?dl=1` for direct download); `expiresIn` is capped at Dropbox's 14400s (4h) maximum and `responseContentDisposition` always throws (no override on Dropbox links). `signedUploadUrl()` throws — Dropbox's temporary upload link expects POST with a raw body, which fits neither the SDK's PUT-with-headers nor POST-with-form-fields shape; use `upload()` or drop to `raw.filesGetTemporaryUploadLink(...)`. Direct `upload()` uses single-call `filesUpload` up to 150 MB and switches to `filesUploadSession*` (chunked, up to 350 GB) automatically; user `metadata` and `cacheControl` throw (Dropbox files have no native arbitrary-metadata field — use `raw` with `property_groups` if you need it).
-   5ff9d79: Add Google Drive adapter (`files-sdk/google-drive`) via the official `@googleapis/drive` v3 client. Drive has no native key field, so the adapter maps virtual keys onto `appProperties.fsdkKey` and amortizes lookups with a per-instance LRU cache (configurable via `fileIdCacheSize`, defaults to 1024). Three auth shapes: inline service-account `credentials`, a `keyFilename` JSON path, or 3-legged `oauth` refresh tokens — plus a pre-built `client` escape hatch (note: `signedUploadUrl()` requires an auth handle and throws when constructed via `client`). `signedUploadUrl()` initiates a Drive resumable session and returns the session URL as a one-shot PUT (`maxSize` is forwarded as `X-Upload-Content-Length` advisory only; `minSize` is ignored). `url()` requires `publicByDefault: true` (grants `anyone, reader` on upload and returns the permanent Drive download URL); `expiresIn` ignored, `responseContentDisposition` always throws. Service-account workloads should target a Shared Drive via `driveId` to avoid the 15 GB personal quota. Caller `metadata` keys starting with `fsdk` are reserved.
-   2a84ef2: Add Hetzner Object Storage adapter (`files-sdk/hetzner`). Thin wrapper over the S3 adapter with Hetzner defaults: endpoint derived from the `region` location code (`fsn1`, `nbg1`, `hel1`) as `https://<region>.your-objectstorage.com` and overridable, virtual-hosted-style addressing, `"Hetzner error"` provider label, and `HCLOUD_ACCESS_KEY_ID` / `HCLOUD_SECRET_ACCESS_KEY` env-var fallbacks. `publicBaseUrl` accepts a custom CNAME or proxy host for unsigned URLs; otherwise `url()` returns a presigned GetObject (1-hour default).
-   b4fd387: Add Netlify Blobs adapter (`files-sdk/netlify-blobs`). Wraps the `@netlify/blobs` SDK with site-scoped or deploy-scoped stores, configurable consistency, and a metadata round-trip that packs `contentType`/`size`/`lastModified`/`cacheControl` plus user metadata into Netlify's metadata map so `head()`/`download()` return rich fields. Auto-detects credentials from Netlify's runtime context (`NETLIFY_BLOBS_CONTEXT`) when available, with explicit `siteID`/`token` overrides falling back to `NETLIFY_SITE_ID` / `NETLIFY_API_TOKEN` / `NETLIFY_BLOBS_TOKEN`. `copy()` is read-then-write since Netlify has no native copy primitive; `list()` returns key + etag (rich metadata requires a per-item `head()`); `url()` and `signedUploadUrl()` throw because Netlify Blobs has no public URL or presigned-upload primitive.
-   0d5af66: Add OneDrive adapter (`files-sdk/onedrive`) for OneDrive personal, OneDrive for Business, and SharePoint document libraries via Microsoft Graph (`@microsoft/microsoft-graph-client` + `@azure/identity`). Path-addressable like the underlying API, so virtual keys map onto real OneDrive paths — no virtual-key cache, no reserved-metadata namespace. Four auth shapes (`clientCredentials` for app-only, `oauth` for delegated refresh-token flow, `accessToken` for caller-managed tokens, and a pre-built `client` escape hatch) and four drive targets (`/me/drive`, `driveId`, `siteId`, `userId`). `signedUploadUrl()` returns a Graph upload-session URL (one-shot PUT, advisory `maxSize`/`minSize`); `url()` requires `publicByDefault: true` and creates an anonymous-view share link (Graph has no signed URL primitive, `expiresIn` ignored). `copy()` polls Graph's async copy monitor with a configurable `copyTimeoutMs`. Direct `upload()` is capped at OneDrive's 250 MB simple-upload limit; user `metadata` and `cacheControl` throw (Graph drive items have no native arbitrary-metadata field — use `raw` for Open Extensions).
-   7251d42: Add Storj adapter (`files-sdk/storj`). Thin wrapper over the S3 adapter with Storj defaults: `endpoint` defaults to `https://gateway.storjshare.io` (Gateway MT, the hosted multi-tenant gateway) and is overridable for self-hosted Gateway ST, path-style addressing on, region defaulted to `us-east-1` (the gateway ignores it for routing), `"Storj error"` provider label, and `STORJ_ACCESS_KEY_ID` / `STORJ_SECRET_ACCESS_KEY` env-var fallbacks. `publicBaseUrl` accepts a linksharing prefix like `https://link.storjshare.io/raw/<accessGrant>/<bucket>` for unsigned URLs.
-   37be6fc: Add UploadThing adapter (`files-sdk/uploadthing`). Maps the user-supplied key onto UploadThing's `customId`, supports public-read and private ACLs, signs UFS presigned PUT URLs via Web Crypto HMAC-SHA256, and falls back to HEAD-on-URL for `head()` and read-then-write for `copy()` since UploadThing has no native primitives for those.

### Patch Changes

-   0ec97d0: Extract shared adapter helpers into `src/internal/core.ts` so authoring a new adapter is less boilerplate. The new module exports `DEFAULT_URL_EXPIRES_IN`, `joinPublicUrl`, `resolveUrlStrategy` (the two-state public-vs-sign decision, with `responseContentDisposition` always forcing signing), `normalizeBody` (Body → `Uint8Array | ReadableStream<Uint8Array>` + content-type/length), and `makeErrorMapper` (factory for the per-provider `mapXError` scaffold — code-set lookup, HTTP-status fallback, `FilesError` pass-through). The s3, azure, gcs, supabase, r2, fs, and uploadthing adapters now consume these helpers; supabase keeps its own `normalizeBody` because Blob pass-through is required for multipart uploads, and r2's `url()` keeps its three-state hybrid logic. `mapS3Error` retains its 2-arg legacy signature for the S3-compatible wrappers (R2 HTTP, MinIO, DigitalOcean Spaces, Storj, Hetzner, Akamai). No public-API changes.
-   30d3634: Improve test coverage and remove dead code in the fs adapter. Adds tests for r2's HTTP-path delegation (copy/delete/download/head/list/signedUploadUrl proxies to the lazy-loaded inner s3 adapter, plus the `raw` getter's pre/post-init behavior) and for fs uploads with `ArrayBuffer` and `ArrayBufferView` bodies plus rejection of keys that resolve to the adapter root. Drops the unreachable `ReadableStream` branch in `fs/bodyToBytes` — stream uploads route through `writeStreamToTempThenRename`, so the parameter type is narrowed to `Exclude<Body, ReadableStream<Uint8Array>>` to enforce that at the type level.

    Further hardens coverage of edge paths across the fs, azure, supabase, r2, and stored-file modules: corrupt/partial sidecar JSON handling, lazy-body errors when an underlying file is removed, atomic upload cleanup when rename fails (buffer + stream paths), non-ENOENT delete errors, Azure stream downloads with missing `readableStreamBody`, anonymous Azure copy source URLs, Supabase numeric `statusCode` fallback and Date/number `lastModified` parsing, R2 binding copy with put failure, and concurrent reads on a lazy `StoredFile` sharing the in-flight cache promise.
