npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

levelplane

v0.1.1

Published

Tiny isomorphic LevelDB wrapper with sublevels, msgpack encoding, async iterators, and browser-ready builds

Readme

levelplane

npm version npm downloads license CI

Tiny isomorphic LevelDB wrapper with sublevels, msgpack encoding, async iterators, and browser-ready builds.

levelplane is a small convenience layer over level that provides the same basic database pattern in Node and the browser. In Node it stores data in a filesystem-backed Level database. In the browser it uses the browser-backed Level implementation through the package/browser build path.

Install

npm i levelplane

Runtime usage supports Node 16 or newer.

Node usage

const Levelplane = require('levelplane')

async function main() {
  const db = await Levelplane.init({ dir: '.data', name: 'main' })

  await db.put('hello', { text: 'world' })
  console.log(await db.get('hello'))

  await db.close()
}

main().catch(console.error)

In Node, a string argument is treated as the filesystem database location.

const db = await Levelplane.init('.data/main')

Browser usage with a bundler

const Levelplane = require('levelplane/browser')

async function main() {
  const db = await Levelplane.init('my-browser-db')

  await db.put('hello', { text: 'world' })
  console.log(await db.get('hello'))
}

main().catch(console.error)

In the browser, a string argument is treated as the browser database name.

Browser usage from CDN

The browser bundle can be loaded from UNPKG or jsDelivr.

<script src="https://unpkg.com/levelplane"></script>
<script>
  async function main() {
    const db = await Levelplane.init('my-browser-db')

    await db.put('hello', { text: 'world' })
    console.log(await db.get('hello'))
  }

  main().catch(console.error)
</script>

The unpkg and jsdelivr package fields point to dist/levelplane.min.js.

Examples

node examples/node.js

examples/browser.html loads ../dist/levelplane.js, so run npm run build before opening it locally.

Options

const db = await Levelplane.init({
  dir: '.data',
  name: 'main',
  reset: false,
  keyEncoding: 'utf8',
  valueEncoding: 'msgpack',
  cache: false,
  createIfMissing: true,
  errorIfExists: false
})

Core options

dir is the parent directory for Node database files. It defaults to .data.

name is the database name. In Node, it is joined with dir when location is not provided. In the browser, it is the database name.

location is an explicit database location. In Node, it is resolved as a filesystem path. In the browser, it is used as the database name.

reset clears the database during Levelplane.init().

keyEncoding defaults to utf8.

valueEncoding defaults to msgpack, backed by notepack.io.

cache enables cached sublevel instances for repeated sub() calls with the same arguments.

createIfMissing and errorIfExists are passed through to the underlying Level database.

Basic API

await db.put('a', 1)
await db.get('a')
await db.has('a')
await db.del('a')
await db.clear()
await db.close()

Missing keys return null instead of throwing.

put(), del(), clear(), and close() return the database instance where appropriate so they are easy to use in small flows.

Sublevels

const users = db.sub('users')
const posts = db.sub('posts')

await users.put('a', { name: 'Aaron' })
await posts.put('a', { title: 'Hello' })

console.log(await users.get('a'))
console.log(await posts.get('a'))

Sublevels are isolated from each other and from the root database.

Nested sublevels can be created with strings or arrays.

const one = db.sub('app', 'settings')
const two = db.sub(['app', 'settings'])

Cached sublevels can be enabled per call.

const one = db.sub('app', 'settings', { cache: true })
const two = db.sub(['app', 'settings'], { cache: true })

console.log(one === two)

Iteration and collection

await db.put('a', 1)
await db.put('b', 2)

console.log(await db.entries())
console.log(await db.keys())
console.log(await db.values())

entries() returns pairs:

[
  ['a', 1],
  ['b', 2]
]

collect() is a small convenience wrapper.

await db.collect()
await db.collect('entries')
await db.collect('keys')
await db.collect('values')
await db.collect('records')

First and last helpers

await db.first()
await db.last()
await db.firstKey()
await db.lastKey()

These use the underlying iterator order and return null when no matching item exists.

Async iterable helpers

iterator(), pairIterator(), entryIterator(), keyIterator(), and valueIterator() return async iterables with a few small chain helpers.

const items = await db.iterator()
  .filter(([key]) => key !== 'b')
  .map(([key, value]) => [key.toUpperCase(), value * 10])
  .take(2)
  .toArray()
const total = await db.valueIterator()
  .reduce((sum, value) => sum + value, 0)

Supported helpers:

map(fn) maps each item.

filter(fn) keeps matching items.

take(n) stops after n items.

reduce(fn, initial) reduces the iterable.

toArray() collects the iterable into an array.

Batch writes

Array batch:

await db.batch([
  { type: 'put', key: 'a', value: 1 },
  { type: 'put', key: 'b', value: 2 },
  { type: 'del', key: 'c' }
])

Chain batch:

await db.batch()
  .put('a', 1)
  .put('b', 2)
  .del('c')
  .write()

Events

levelplane exposes small write events for convenience.

db.on('put', event => console.log(event))
db.on('del', event => console.log(event))
db.once('batch', event => console.log(event))

await db.put('a', 1)
await db.del('a')
await db.batch([{ type: 'put', key: 'b', value: 2 }])

Write events are emitted after the underlying write succeeds.

Transform hooks

Transform hooks make it possible to wrap keys and values without changing calling code. This can be used for encoding, encryption, namespacing, or custom read/write behavior.

const coded = db.sub('coded', {
  writeKey: key => `key:${key}`,
  readKey: key => key.replace(/^key:/, ''),
  write: value => ({ wrapped: value }),
  read: value => value.wrapped
})

await coded.put('a', { ok: true })
console.log(await coded.get('a'))
console.log(await coded.keys())

Hooks:

writeKey(key) runs before keys are written or queried.

readKey(key) runs when keys are read from iterators.

write(value, key) runs before values are stored.

read(value, key) runs after values are loaded.

Utility methods

await db.length()
await db.size()
db.debug()
db.toString()

length() counts keys by iterating.

size() returns an approximate logical size summary based on iterated keys and decoded values.

debug() returns the current location, sublevel path, status, and encoding options.

toString() returns a readable label such as [Levelplane] or [Levelplane:users].

Package entry points

Default Node entry:

const Levelplane = require('levelplane')

Browser-safe entry:

const Levelplane = require('levelplane/browser')

Explicit Node entry:

const Levelplane = require('levelplane/node')

The shared browser-safe core lives in levelplane.js. The Node entry lives in levelplane-node.js and injects the Node filesystem/path platform adapter. browser.js and node.js are small compatibility shims for older bundlers that do not read package exports.

Scripts

npm test
npm run build
npm run pack:dry
npm run check

npm test runs the Mocha test suite.

npm run build creates dist/levelplane.js with Rollup and dist/levelplane.min.js with Terser.

npm run pack:dry inspects the current package contents with npm pack --dry-run.

npm run check runs tests, builds the browser bundles, and dry-runs the package contents.

npm run prepack runs tests and builds before packing or publishing.

The package runtime supports Node 16+. The Rollup 4 browser build toolchain requires Node 18+.

License

MIT