Skip to content

An abstract-level database for browsers, backed by IndexedDB.

License

Notifications You must be signed in to change notification settings

Level/browser-level

Repository files navigation

browser-level

An abstract-level database for browsers, backed by IndexedDB. The successor to level-js. If you are upgrading, please see UPGRADING.md.

📌 Which module should I use? What is abstract-level? Head over to the FAQ.

level badge npm Test Coverage Standard Common Changelog Donate

Table of Contents

Click to expand

Usage

const { BrowserLevel } = require('browser-level')

// Create a database called 'example'
const db = new BrowserLevel('example', { valueEncoding: 'json' })

// Add an entry with key 'a' and value 1
await db.put('a', 1)

// Add multiple entries
await db.batch([{ type: 'put', key: 'b', value: 2 }])

// Get value of key 'a': 1
const value = await db.get('a')

// Iterate entries with keys that are greater than 'a'
for await (const [key, value] of db.iterator({ gt: 'a' })) {
  console.log(value) // 2
}

API

The API of browser-level follows that of abstract-level with just two additional constructor options (see below) and one additional method (see below). As such, the majority of the API is documented in abstract-level. The createIfMissing and errorIfExists options of abstract-level are not supported here.

Like other implementations of abstract-level, browser-level has first-class support of binary keys and values, using either Uint8Array or Buffer. In order to sort string and binary keys the same way as other databases, browser-level internally converts data to a Uint8Array before passing them to IndexedDB. If you have no need to work with Buffer keys or values, you can choose to omit the buffer shim from a JavaScript bundle (through configuration of Webpack, Browserify or other bundlers).

Due to limitations of IndexedDB, browser-level does not offer snapshot guarantees. Such a guarantee would mean that an iterator does not see the data of simultaneous writes - it would be reading from a snapshot in time. In contrast, a browser-level iterator reads a few entries ahead and then opens a new IndexedDB transaction on the next read. A "few" means all entries for iterator.all(), size amount of entries for iterator.nextv(size) and a hardcoded 100 entries for iterator.next(). Individual calls to those methods have snapshot guarantees but repeated calls do not.

The result is that an iterator will include the data of simultaneous writes, if db.put(), db.del() or db.batch() are called in between creating the iterator and consuming the iterator, or in between calls to iterator.next() or iterator.nextv(). For example:

const iterator = db.iterator()
await db.put('abc', '123')

for await (const [key, value] of iterator) {
  // This might be 'abc'
  console.log(key)
}

If snapshot guarantees are a must for your application then use iterator.all() and call it immediately after creating the iterator:

const entries = await db.iterator({ limit: 50 }).all()

// Synchronously iterate the result
for (const [key, value] of entries) {
  console.log(key)
}

db = new BrowserLevel(location[, options])

Create a new database or open an existing one. The required location argument is the string name of the IDBDatabase to be opened, as well as the name of the object store within that database. The name of the IDBDatabase will be prefixed with options.prefix.

Besides abstract-level options, the optional options argument may contain:

  • prefix (string, default: 'level-js-'): Prefix for the IDBDatabase name. Can be set to an empty string. The default is compatible with level-js.
  • version (string or number, default: 1): The version to open the IDBDatabase with.

See IDBFactory#open() for more details about database name and version.

BrowserLevel.destroy(location[, prefix][, callback])

Delete the IndexedDB database at the given location. If prefix is not given, it defaults to the same value as the BrowserLevel constructor does. The callback function will be called when the destroy operation is complete, with a possible error argument. If no callback is provided, a promise is returned. This method is an additional method that is not part of the abstract-level interface.

Before calling destroy(), close a database if it's using the same location and prefix:

const db = new BrowserLevel('example')
await db.close()
await BrowserLevel.destroy('example')

Install

With npm do:

npm install browser-level

This module is best used with browserify or similar bundlers.

Contributing

Level/browser-level is an OPEN Open Source Project. This means that:

Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.

See the Contribution Guide for more details.

Donate

Support us with a monthly donation on Open Collective and help us continue our work.

License

MIT