Level Universal Database
The `level` package provides a universal, `abstract-level`-compliant key-value database interface for both Node.js and browser environments. It acts as a convenience wrapper, dynamically exporting `classic-level` for Node.js and `browser-level` for browsers. This design allows developers to write platform-agnostic code for lexicographically sorted key-value stores. The current stable version is 10.0.0, which incorporates `abstract-level` v3, enhancing its foundational API. The project maintains a frequent release cadence, often introducing breaking changes with major version bumps to align with upstream `abstract-level`, `classic-level`, or `browser-level` updates, emphasizing modernization and API consistency across its ecosystem. It is designed to be highly extensible and supports various encoding options, including `json` for complex data structures and `utf8` for strings.
Common errors
-
TypeError: Level is not a constructor
cause Attempting to instantiate `level` with `new require('level')()` instead of `new Level()` after destructuring.fixEnsure you are destructuring the `Level` class from the `level` module: `const { Level } = require('level')` or `import { Level } from 'level'`. -
Error: Database is not open
cause Attempting database operations (like `put`, `get`, `iterator`) before the database has been successfully opened.fixAlways call `await db.open()` before performing any operations. Check `db.status` to ensure it's `open`. -
Property 'put' does not exist on type 'Level<string, string>'
cause In TypeScript, the `Level` instance was inferred or explicitly typed as `Level<string, string>`, but you are attempting to store values that are not strings (e.g., objects with `valueEncoding: 'json'`).fixExplicitly define the value type when creating the `Level` instance: `new Level<string, any>('./db', { valueEncoding: 'json' })` if storing objects, or `new Level<string, Buffer>('./db', { valueEncoding: 'binary' })` for binary data.
Warnings
- breaking Version 10.0.0 introduced a breaking change by upgrading to `abstract-level` v3. This may require changes to code interacting directly with the `abstract-level` API or relying on specific behaviors of earlier versions.
- breaking Version 9.0.0 included a breaking change by upgrading to `abstract-level` v2. This involved significant API changes in how `abstract-level` databases operate and are instantiated.
- breaking Version 8.0.0 fundamentally changed `level` to use `classic-level` in Node.js and `browser-level` in browsers. If your application previously relied on specific `leveldown` behaviors or direct `leveldown` imports, this will be a breaking change.
- breaking Version 7.0.0 included multiple breaking changes, including bumps to `leveldown` and `level-packager`, and a major upgrade of `level-js` from 5.x to 6.x. It also modernized syntax, potentially affecting older Node.js environments.
- gotcha Incorrectly using `require('level')` without destructuring `Level` can lead to runtime errors, as `level` exports `Level` as a named property.
- gotcha When using TypeScript, omitting generic type parameters for `Level` or `sublevel` will default to `Level<string, string>`, leading to type errors if you store or retrieve non-string values (e.g., objects with `valueEncoding: 'json'`).
Install
-
npm install level -
yarn add level -
pnpm add level
Imports
- Level
import Level from 'level'
import { Level } from 'level' - Level (CommonJS)
const Level = require('level')const { Level } = require('level') - AbstractLevel (type)
import { AbstractLevel } from 'level'import type { AbstractLevel } from 'abstract-level'
Quickstart
import { Level } from 'level';
// Specify types of keys and values for better type safety.
// The generic type parameters default to Level<string, string>.
// Use { valueEncoding: 'json' } for objects, otherwise 'utf8' is common.
const db = new Level<string, any>('./my-database', { valueEncoding: 'json' });
async function runExample() {
try {
// Ensure the database is open before operations
if (db.status === 'closed') {
await db.open();
}
// Add an entry with key 'user:1' and a JSON object value
await db.put('user:1', { name: 'Alice', age: 30 });
console.log('Added user:1');
// Add multiple entries using batch operation
await db.batch([
{ type: 'put', key: 'user:2', value: { name: 'Bob', age: 24 } },
{ type: 'put', key: 'user:3', value: { name: 'Charlie', age: 35 } }
]);
console.log('Added user:2 and user:3');
// Get value of key 'user:1'
const user1 = await db.get('user:1');
console.log('Value of user:1:', user1);
// Iterate entries with keys greater than 'user:1'
console.log('Users greater than user:1:');
for await (const [key, value] of db.iterator({ gt: 'user:1' })) {
console.log(` Key: ${key}, Value:`, value);
}
// Example of a sublevel
const userEmails = db.sublevel<string, string>('emails', { valueEncoding: 'utf8' });
await userEmails.put('alice', 'alice@example.com');
const aliceEmail = await userEmails.get('alice');
console.log('Alice email:', aliceEmail);
} catch (error) {
console.error('Database operation failed:', error);
} finally {
// Always close the database when done
if (db.status === 'open') {
await db.close();
console.log('Database closed.');
}
}
}
runExample();