Skip to content
Files SDK
Esc
↑↓navigate↵open⌘Jpreview
On this page

PocketBase

PocketBase via the official JS SDK. Maps the unified key/blob API onto a dedicated collection with a unique key field and a single-file body field.

Installation

pocketbase is an optional peer dependency of files-sdk - install alongside the SDK so the adapter’s imports resolve at runtime.

npm install files-sdk pocketbase
pnpm add files-sdk pocketbase
yarn add files-sdk pocketbase
bun add files-sdk pocketbase
nub add files-sdk pocketbase
aube add files-sdk pocketbase

Usage

PocketBase via the official pocketbase JS SDK. PocketBase has no object-store primitive - files live as field values on records inside collections. The adapter maps the unified key/blob API onto a dedicated collection: each upload becomes (or updates) a record whose configurable key field holds the user-facing string key and whose configurable file field holds the body.

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

const files = new Files({
  adapter: pocketbase({
    collection: "files",
    // Auto-loads url + auth from POCKETBASE_URL,
    // POCKETBASE_ADMIN_EMAIL + POCKETBASE_ADMIN_PASSWORD, or
    // POCKETBASE_AUTH_TOKEN. Or pass an existing PocketBase client.
    //
    // Collection must already exist with a unique-indexed text `key`
    // field and a single-value `file` field. Field names are
    // configurable via `keyField` / `fileField`.
  }),
});

Options

PropType
collectionstring

Collection name (or id) that holds the file records. Must already exist with the configured `keyField` (unique-indexed text) and `fileField` (single-value file). The adapter does not create or migrate the collection — set it up via the PocketBase admin UI or migrations first.

Typestring
client?PocketBaseClient

Existing PocketBase client. Highest precedence — when passed, all auth options below are ignored. Useful when the host app already shares one client across auth, realtime, and storage.

TypePocketBaseClient
url?string

PocketBase backend URL (e.g. `https://pb.example.com`). Falls back to `POCKETBASE_URL`.

Typestring
adminEmail?string

Superuser email. Combined with `adminPassword` to auth as a superuser before each session. Falls back to `POCKETBASE_ADMIN_EMAIL`.

Typestring
adminPassword?string

Superuser password. Falls back to `POCKETBASE_ADMIN_PASSWORD`.

Typestring
authToken?string

Pre-issued auth token. Saved into the client's `authStore` directly — use this when you already have a token from elsewhere (e.g. an OAuth2 exchange or a custom user auth flow). Falls back to `POCKETBASE_AUTH_TOKEN`. Mutually exclusive with the admin email/password pair; if both are provided, the explicit token wins.

Typestring
keyField?string

Name of the text field on the collection holding the user-facing key. Must be unique-indexed. Defaults to `"key"`.

Typestring
fileField?string

Name of the single-file field on the collection holding the body. Defaults to `"file"`.

Typestring
publicBaseUrl?string

Origin used to build URLs from `url()`. When set, `url(key)` returns `${publicBaseUrl}/${key}` and skips PocketBase's file URL entirely — appropriate when a CDN sits in front of the PB instance. When unset, `url()` falls back to `pb.files.getURL(record, filename)`.

Typestring

Compatibility

Method Status Notes
upload ⚠️ Stream bodies are buffered up-front - the SDK uploads via multipart FormData with a Blob, which has no streaming form. User metadata and cacheControl throw - PocketBase has no per-file HTTP cache headers and no arbitrary-metadata field on the file; add extra typed columns to the collection and write via raw if you need them. Existing keys are updated in place (no duplicate-key error); new keys create a new record. Resumable uploads (control) are not supported — PocketBase uploads in a single multipart request.
download ⚠️ No streaming primitive - PocketBase’s JS SDK has no binary download API, so the adapter resolves the record, mints a short-lived file token via pb.files.getToken() when authenticated, and fetches the file URL with fetch(). Size and content-type come back from the HTTP response, not the record - PB doesn’t store them on the record itself.
delete ✅
list ⚠️ PocketBase’s stable list API is offset/limit (page/perPage), not cursor-based. The adapter encodes the next page number as a numeric cursor string so the unified API works unchanged. prefix is pre-filtered server-side with the ~ (SQL LIKE) operator on the configured keyField, then matched exactly (case-sensitive, _/% literal) client-side, so a page can hold fewer than limit items when the prefix contains _/% or other keys differ only in letter case. List items expose lazy bodies (one fetch per .text()/.arrayBuffer() call) — PocketBase records don’t carry size or content-type, so list entries always report size: 0 and type: 'application/octet-stream'; read the body (.arrayBuffer()) to get the real size, or download() the key for both.
search ⚠️ Built on listAll — inherits this adapter’s list behavior above. Client-side key match (glob, regex, substring, exact).
head ⚠️ PocketBase records don’t carry size, content-type, or etag for their file fields, so head() always reports size: 0 and type: 'application/octet-stream'; read the body (.arrayBuffer()) to get the real size, or download() the key for both. lastModified is sourced from the record’s updated field. The filename PocketBase generated on upload is exposed under metadata.filename.
exists ✅
copy ⚠️ Read-then-write — PocketBase has no server-side copy primitive, so the source record’s file is downloaded and written under the destination key: a new record, or the existing record’s file replaced in place (like upload). Costs an egress + an ingest; not atomic.
url ⚠️ Default returns pb.files.getURL(record, filename) — permanent for public collections, threaded with a short-lived file token from pb.files.getToken() when the client is authenticated. With publicBaseUrl, returns <publicBaseUrl>/<key>. expiresIn is silently ignored — PocketBase fixes the file-token TTL server-side. responseContentDisposition always throws — PB has no per-URL Content-Disposition override; use raw and the ?download=true query string instead.
signedUploadUrl ❌ Throws — PocketBase has no presigned upload primitive. Writes always go through the authenticated API; mint a short-lived auth token for the client and call create/update directly, or proxy uploads through your application.

Was this page helpful?