Skip to content
Files SDK
Esc
navigateopen⌘Jpreview
On this page

Filesystem

Local filesystem - the dev/test adapter. Uses node:fs/promises with a sidecar .meta.json per file. Not for production.

Installation

This adapter has no extra peer dependencies - the runtime (Node or Bun) provides everything it needs.

npm install files-sdk
pnpm add files-sdk
yarn add files-sdk
bun add files-sdk

Usage

Local filesystem. The dev/test adapter - point it at a directory and it implements the same Adapter contract as the cloud adapters using node:fs/promises. Each upload writes the body and a sidecar .meta.json file alongside it (Content-Type, ETag, user metadata) so reads round-trip cleanly. Not for production: there’s no replication, no signing, no auth.

import { Files } from "files-sdk";
import { fs } from "files-sdk/fs";

// Writes objects under `./.uploads` with a sidecar `.meta.json`
// per file for Content-Type, ETag, and user metadata. Designed for
// dev and CI - same Adapter contract as the cloud adapters, so swap
// it in via env without changing call sites.
const files = new Files({
  adapter: fs({
    root: "./.uploads",
    // Optional: configure if a dev server exposes the same root over
    // HTTP, so url() returns a browser-friendly URL instead of file://.
    // urlBaseUrl: "http://localhost:3000/files",
  }),
});

Options

PropType
rootstring

Absolute or relative directory the adapter manages. Created on first upload if it doesn't exist. All operations are scoped to this root — keys that resolve outside it (e.g. `../etc/passwd`) throw `Provider`.

Typestring
urlBaseUrl?string

Optional URL prefix for `url()`. When set, `url(key)` returns `${urlBaseUrl}/${key}` — useful when a dev server (Next.js `/public` mount, `serve-static`, etc.) is exposing the same root. When unset, `url()` returns a `file://` URL — appropriate for CLIs/tests, not for browsers.

Typestring
defaultUrlExpiresIn?number

Accepted for backward compatibility but ignored. `url()` returns a `file://` or static-server URL, and `signedUploadUrl()` fails closed because the fs adapter has no built-in upload signer or verifier.

Typenumber

Storage layout

Body at `${root}/${key}`; sidecar at `${root}/${key}.meta.json`. Sidecars survive cp -r / git mv / partial-tree deletion. list() hides them. ETag is a SHA-1-derived stable hash computed at upload time. Files written into root by hand without a sidecar are still readable - contentType falls back to application/octet-stream and etag is absent.

Compatibility

Method Status Notes
upload
download
delete
list
search
head
exists
copy
url ⚠️ Returns a file:// URL by default - fine for CLIs and tests, not browsers. With urlBaseUrl set, returns <urlBaseUrl>/<key> so a dev server (Next.js /public mount, serve-static, etc.) can deliver the body. responseContentDisposition throws because neither file:// nor static-server URLs have a signature mechanism in which to bind the override.
signedUploadUrl Throws - the fs adapter has no built-in upload server, signer, or verifier, so it cannot bind expiry, content type, or size limits into an upload capability. Upload through files.upload() or an application route that enforces those controls server-side.

Was this page helpful?