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

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

Prop

Type

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

MethodStatusNotes
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 without urlBaseUrl - the fs adapter has no built-in upload server, so there's nothing to sign against. With urlBaseUrl set, returns a PUT URL with ?expires=, ?content-type=, and ?max-size= query params for a dev upload-handler to validate. The fs adapter does not enforce the params itself.

On this page