PouchdbStore — embedded document database

Read this page in the documentation

PouchdbStore — embedded document database Overview PouchDB is an embedded, in-process document database (it can run purely in Node against a filesystem-backed adapter, with no server). Unlike the plain key-value engines, PouchDB is document-style: documents are addressed by an id and versioned by a rev, and the API is promise-based (put/get/remove/allDocs/bulkDocs). It has no SQL-shaped surface (query(sql), identifier escaping, DDL). Because none of that fits the SQL-shaped Dialect interface, PouchdbStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch. It maps a common KV surface (put/get/del keyed on id) onto PouchDB's document API, alongside the native insert/allDocs. Identity: Property | Value | --------- | ------------ | name | 'pouchdb' | library | 'pouchdb' | The store is built on the pouchdb npm driver, which is promise-based. Lazy loading — not a hard dependency The pouchdb driver is not a hard dependency of this package. It is loaded lazily via require('pouchdb') inside connect(), rather than a top-level import. Importing this module therefore does not require the driver to be installed — it is only needed when a PouchDB store is actually connected without an injected client. On load, connect() constructs new PouchDB(name, config). Injected client PouchdbStoreOptions accepts a pre-built client (any object matching PouchClientLike). When provided, connect() uses it directly and skips require('pouchdb') entirely. This is how the test suite injects a promise-based mock database (no driver, no filesystem), and how callers can supply a custom-configured database. Connection Build a store from connection options and call connect(): Connection options (PouchdbStoreOptions): Option | Type | Purpose | -------- | --------------------------- | --------------------------------------------------------------------------------------------------------- | name | string | Database name / path passed to new PouchDB(name). Defaults to './data/pouchdb'. | config | Record<string, unknown> | Escape hatch for any other PouchDB constructor option (adapter, auth, …). Passed as the second argument to new PouchDB(name, config). | client | PouchClientLike | A pre-built database to use directly (mock or custom). When set, the driver is not required. | Injected-client form Supply your own database (or a mock) to bypass driver-based construction: Methods Every operation resolves the client via a private guard: using any method before connect() (or after disconnect()) throws a ConnectionError. Driver failures are wrapped in a DatabaseError (preserving the original error) with a PouchDB <action> failed: … message. Lifecycle Method | Signature | Behavior | ------------ | -------------------------------- | ---------------------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise lazy-requires pouchdb and constructs new PouchDB(name, config). Idempotent when already connected. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void> | Best-effort client.close(), then clears connection state. | isConnected| isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): PouchClientLike | Returns the underlying database for operations not wrapped here. Throws ConnectionError if not connected. | Key-value surface (keyed on id) Method | Signature | Behavior | ------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | put | put(key: string, value: Record<string, unknown>): Promise<PouchWriteResult> | Writes a document keyed by id = key, mapping onto client.put({ id: key, ...value }). | get | get(key: string): Promise<PouchDoc> | Reads a document by id via client.get(key). | del | del(key: string): Promise<PouchWriteResult> | Deletes a document by id. PouchDB needs the current rev, so this first gets the doc, then removes it. | batch | batch(ops: PouchBatchOp[]): Promise<void> | Puts are collected as { id, ...value } and sent through a single bulkDocs call; deletes are resolved individually via del(). | list | list(prefix?: string): Promise<string[]> | Lists document ids via client.allDocs(). With no prefix, calls allDocs({}). With prefix, restricts to { startkey: prefix, endkey: prefix + '￿' }. Returns each row's id. | Native document operation Method | Signature | Behavior | -------- | ----------------------------------------------- | --------------------------------------------------------------------------- | insert | insert(doc: PouchDoc): Promise<PouchWriteResult> | Stores a document as-is (must carry its own id). Routes to client.put(doc). | PouchBatchOp is the entry type for a batch(): Example Verification status Unit / mock-verified only. The tests in tests/nosql/pouchdb.test.ts are fully mock-driven: a promise-based fake database whose methods are jest spies returning canned values is injected via PouchdbStoreOptions.client. The real pouchdb driver is not installed, and there is no filesystem and no network in the test run — because a client is injected, connect() never reaches require('pouchdb'). What this proves: put() merges key into id and calls put({ id, ...value }); insert() passes the doc straight through to put; get() calls get(id). del() first gets the doc (for its rev) then removes it; batch() sends puts through a single bulkDocs call and resolves deletes individually; list() returns ids from allDocs, and list(prefix) builds the { startkey, endkey } range. Lifecycle: connecting via an injected client without loading the driver, disconnect() closing the database, idempotent re-connect, and ConnectionError before connect() / via getClient() when not connected. Error handling: put/get rejections wrapped in DatabaseError. What this does not prove: live execution against a real PouchDB database (file-backed or otherwise). The call/response shapes are verified against the driver's documented contract, but end-to-end execution against the real engine has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories