NedbStore — embedded document database (MongoDB-like)
Read this page in the documentation
NedbStore — embedded document database (MongoDB-like) Overview NeDB is an embedded, in-process document database with a MongoDB-like API, backed by an append-only file or purely in-memory. Unlike the plain key-value engines, NeDB is document-style: it stores documents addressed by an id field and exposes insert/findOne/find/remove. It has no SQL-shaped surface (query(sql), identifier escaping, DDL). Because none of that fits the SQL-shaped Dialect interface, NedbStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch. It maps a common key-value surface (put/get/del keyed on id) onto NeDB's document API, alongside the native insert/find. Identity: Property | Value | --------- | ---------- | name | 'nedb' | library | 'nedb' | The store is built on the nedb npm driver, which is callback-based. The store wraps each callback call into a Promise via a private promisify helper. Lazy loading — not a hard dependency The nedb driver is not a hard dependency of this package. It is loaded lazily via require('nedb') 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 NeDB store is actually connected without an injected client. On load, connect() constructs new Datastore({ filename, autoload: true }) when a filename is given, or new Datastore({}) for a purely in-memory store. Injected client NedbStoreOptions accepts a pre-built client (any object matching NedbClientLike, i.e. a NeDB Datastore). When provided, connect() uses it directly and skips require('nedb') entirely. This is how the test suite injects a callback-based mock datastore (no driver, no filesystem), and how callers can supply a custom-configured datastore. Connection Build a store from connection options and call connect(): Connection options (NedbStoreOptions): Option | Type | Purpose | ---------- | ----------------- | ------------------------------------------------------------------------------------------- | filename | string | Filesystem path for the NeDB datafile. Omit for a purely in-memory store. When set, the datastore is opened with autoload: true. | client | NedbClientLike | A pre-built Datastore to use directly (mock or custom). When set, the driver is not required. | Injected-client form Supply your own datastore (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 NeDB <action> failed: … message. Lifecycle Method | Signature | Behavior | ------------ | -------------------------------- | ---------------------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise lazy-requires nedb and constructs a Datastore. Idempotent when already connected. Wraps failures in ConnectionError. | disconnect | disconnect(): Promise<void> | NeDB has no explicit close — drops the client reference and clears connection state so callers can't keep using it. | isConnected| isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): NedbClientLike | Returns the underlying Datastore 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<NedbDoc> | Writes a document keyed by id = key, mapping onto insert({ id: key, ...value }). Returns the inserted doc. | get | get(key: string): Promise<NedbDoc \| null> | Reads a document by id via findOne({ id: key }). Returns null if absent. | del | del(key: string): Promise<number> | Deletes a document by id via remove({ id: key }, {}). Returns the number removed. | batch | batch(ops: NedbBatchOp[]): Promise<void> | Applies a list of put/del operations sequentially, routing put to put() (insert) and del to del() (remove). | list | list(): Promise<string[]> | Lists all document ids via find({}), mapping each doc's id to a string. (No prefix argument.) | Native document operations Method | Signature | Behavior | -------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------- | insert | insert(doc: NedbDoc): Promise<NedbDoc> | Adds a document as-is (NeDB assigns an id if omitted). Routes to client.insert. | find | find(query: Record<string, unknown> = {}): Promise<NedbDoc[]> | Returns every document matching the Mongo-style query. Routes to client.find. | NedbBatchOp is the entry type for a batch(): Example Verification status Unit / mock-verified only. The tests in tests/nosql/nedb.test.ts are fully mock-driven: a callback-based fake Datastore whose methods are jest spies (each invoking its callback with canned results) is injected via NedbStoreOptions.client. The real nedb 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('nedb'). What this proves: put() merges key into id and calls insert({ id, ...value }); get() calls findOne({ id }); del() calls remove({ id }, {}) and returns the count. Native insert() and find() pass their arguments straight through; batch() maps put/del onto insert/remove; list() returns the ids from find({}). Lifecycle: connecting via an injected client without loading the driver, disconnect() reporting disconnected, idempotent re-connect, and ConnectionError before connect() / via getClient() when not connected. Error handling: put/get callback errors wrapped in DatabaseError. What this does not prove: live execution against a real NeDB datastore (file-backed or in-memory). The callback/result 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