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 pocketbasepnpm add files-sdk pocketbaseyarn add files-sdk pocketbasebun add files-sdk pocketbasenub add files-sdk pocketbaseaube add files-sdk pocketbaseUsage
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
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.
stringclient?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.
PocketBaseClienturl?string
PocketBase backend URL (e.g. `https://pb.example.com`). Falls back to `POCKETBASE_URL`.
stringadminEmail?string
Superuser email. Combined with `adminPassword` to auth as a superuser before each session. Falls back to `POCKETBASE_ADMIN_EMAIL`.
stringadminPassword?string
Superuser password. Falls back to `POCKETBASE_ADMIN_PASSWORD`.
stringauthToken?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.
stringkeyField?string
Name of the text field on the collection holding the user-facing key. Must be unique-indexed. Defaults to `"key"`.
stringfileField?string
Name of the single-file field on the collection holding the body. Defaults to `"file"`.
stringpublicBaseUrl?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)`.
stringCompatibility
| 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. |