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 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 matched server-side via the ~ operator on the configured keyField. List items expose lazy bodies (one fetch per .text()/.arrayBuffer() call) — PocketBase records don’t carry size or content-type, so list entries return size: 0 and type: 'application/octet-stream' until the body is read. |
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() returns size: 0 and type: 'application/octet-stream' until the body is read via the lazy body factory. 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 uploaded as a new record under the destination key. 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. |