Abstract Key-Value Database Class

raw JSON →
3.1.1 verified Wed Apr 22 auth: no javascript

abstract-level provides an abstract interface for building lexicographically sorted key-value databases, serving as the foundation for the entire LevelDB ecosystem in JavaScript/TypeScript. It defines the core API, including operations like `put`, `get`, `del`, `batch`, and iterators, along with support for encodings, sublevels, events, and hooks. The current stable version is `3.1.1`, with active development reflected in regular minor and patch releases, and major versions introducing significant breaking changes (e.g., v2 to v3). Its key differentiator is being a specification rather than an implementation, allowing concrete database modules like `level` or `classic-level` to adhere to a common, well-defined API. It ships with comprehensive TypeScript types and leverages modern JavaScript features.

error TypeError: db.get is not a function
cause Attempting to use callback-style `db.get('key', callback)` after upgrading to `abstract-level` v2.0.0 or later, which switched to Promises.
fix
Change to promise-based API: const value = await db.get('key'); or db.get('key').then(value => ...);.
error Error: Iterator.seek() is not implemented
cause Your chosen LevelDB implementation does not support the mandatory `iterator.seek()` method, which became required in `abstract-level` v3.0.0.
fix
Upgrade your concrete LevelDB implementation (e.g., level, classic-level) to a version that satisfies abstract-level v3.0.0 requirements, or downgrade abstract-level if you cannot upgrade the implementation.
error RangeError: Invalid or unsupported Node.js version
cause `abstract-level` v3.0.0 and above requires Node.js version 18 or higher due to new language features.
fix
Update your Node.js environment to version 18.x or later.
error Property 'value' does not exist on type 'unknown'.
cause TypeScript error indicating that the generic type parameters for keys and values were not specified, leading to `unknown` types when interacting with the database.
fix
When creating your database instance, specify the generic types for keys and values, e.g., const db = new Level<string, MyDataType>('./db', { valueEncoding: 'json' });.
breaking Version 3.0.0 made `iterator.seek()` a mandatory feature. Implementations must now provide this method, and consumers relying on `abstract-level`'s interface will expect its presence.
fix Ensure your `AbstractLevel` implementation fully supports `iterator.seek()`. If you are an implementer, add the `seek` method to your iterator. If you are a consumer, verify your chosen database implementation adheres to the v3 specification.
breaking Version 3.0.0 introduced new language features, requiring Node.js >=18. Older Node.js versions are no longer supported.
fix Upgrade your Node.js environment to version 18 or higher.
breaking Version 2.0.0 removed callbacks in favor of Promises for all asynchronous operations. Methods like `put`, `get`, `del`, `batch`, and `close` now return Promises.
fix Update your code to use `await` or `.then()` syntax for all asynchronous database operations. For example, `db.get('key', callback)` becomes `await db.get('key')`.
breaking Version 2.0.0 changed the behavior for non-existent entries: `get()` now returns `undefined` instead of throwing a `NotFoundError` (or similar error) when a key is not found.
fix Adjust error handling logic to check for `undefined` return values instead of catching specific 'not found' errors. For example, `try { await db.get('key') } catch (err)` becomes `const value = await db.get('key'); if (value === undefined) { /* not found */ }`.
gotcha `abstract-level` is an abstract class, not a concrete database implementation. Direct instantiation of `AbstractLevel` is not intended for end-user applications.
fix Always use a concrete implementation that extends `AbstractLevel`, such as `level`, `classic-level`, or `memory-level`, for your database instances. `import { Level } from 'level'; const db = new Level('./db');`.
gotcha TypeScript users must correctly specify generic type parameters for keys and values when instantiating `AbstractLevel` implementations and sublevels, e.g., `Level<string, MyDataType>`. Failing to do so can lead to `any` types or incorrect type inference.
fix Explicitly define key and value types: `const db = new Level<string, MyValue>('./db', { valueEncoding: 'json' });`.
npm install abstract-level
yarn add abstract-level
pnpm add abstract-level

This quickstart demonstrates basic database operations (put, get, batch, iterate) using a `level` implementation conforming to `abstract-level`, highlighting type safety with generics and modern async/await patterns.

import { Level } from 'level';
import type { AbstractLevel, AbstractBatchOperation } from 'abstract-level';

interface MyValue { x: number; name: string; }

async function runDbExample() {
  // In a real application, replace 'level' with your chosen LevelDB implementation.
  // The generic types specify key and value types.
  const db: AbstractLevel<string, MyValue> = new Level<string, MyValue>('./my-db-path', {
    valueEncoding: 'json' // This will automatically JSON.stringify/parse values
  });

  try {
    console.log('Opening database...');
    await db.open();

    await db.put('item1', { x: 1, name: 'First Item' });
    await db.put('item2', { x: 2, name: 'Second Item' });

    const value1 = await db.get('item1');
    console.log(`Value for item1: ${JSON.stringify(value1)}`);

    // Batch operations
    const batchOperations: AbstractBatchOperation<string, MyValue>[] = [
      { type: 'put', key: 'item3', value: { x: 3, name: 'Third Item' } },
      { type: 'del', key: 'item1' }
    ];
    await db.batch(batchOperations);

    const value3 = await db.get('item3');
    console.log(`Value for item3: ${JSON.stringify(value3)}`);

    const deletedValue = await db.get('item1');
    console.log(`Value for item1 after delete (should be undefined): ${deletedValue}`);

    console.log('Iterating through remaining items:');
    for await (const [key, value] of db.iterator()) {
      console.log(`Key: ${key}, Value: ${JSON.stringify(value)}`);
    }

  } catch (error) {
    console.error('Database operation failed:', error);
  } finally {
    console.log('Closing database...');
    await db.close();
  }
}

runDbExample();