This document describes breaking changes and how to upgrade. For a complete list of changes including minor and patch releases, please refer to the changelog.
Introducing many-level
: a fork of multileveldown
that removes the need for levelup
, encoding-down
and more. It implements the abstract-level
interface - which merged abstract-leveldown
with levelup
. For many-level
that means it has the same familiar API including encodings, promises and events but excluding streams. In addition, you can now choose to use Uint8Array instead of Buffer. Sublevels are builtin.
We've put together several upgrade guides for different modules. See the FAQ to find the best upgrade guide for you. This one describes how to replace multileveldown
with many-level
.
Support of Node.js 10 has been dropped.
- Throughput of iterators has doubled
- Reverse iterators have been fixed to support retry
- Supports
iterator.seek()
(across retries too).
If you are using any of the following, please also read the upgrade guide of abstract-level@1
which goes into more detail about these:
- Not-found errors on
db.get()
(replaced by error codes) - Sublevels created with
subleveldown
(now built-in) - The
db.iterator().end()
method (renamed toclose()
, withend()
as an alias) - Zero-length keys and range options (now valid)
- Chained batches (must now be closed if not committed).
We started using classes, which means using new
is now required. The server / client roles are now called host / guest. If you previously did:
// Server
const multileveldown = require('multileveldown')
const stream = multileveldown.server(db, options)
// Client
const multileveldown = require('multileveldown')
const db = multileveldown.client(encodingOptions)
const stream = db.connect(options)
You should now do:
// Host
const { ManyLevelHost } = require('many-level')
const host = new ManyLevelHost(db, options)
const stream = host.createRpcStream()
// Guest
const { ManyLevelGuest } = require('many-level')
const db = new ManyLevelGuest(encodingOptions)
const stream = db.createRpcStream(options)
Arguments and options are the same. The previous exports (server
and client
) are still available but log a deprecation warning.
A many-level
guest cannot talk to a multileveldown
server due to breaking protocol changes. This means both ends must be upgraded to many-level
.
Node.js readable streams must now be created with a new standalone module called level-read-stream
rather than database methods like db.createReadStream()
. To offer an alternative to db.createKeyStream()
and db.createValueStream()
, two new types of iterators have been added: db.keys()
and db.values()
.
Encodings have a new home in abstract-level
and are now powered by level-transcoder
. The main change is that logic from the existing public API has been expanded down into the storage layer. There are however a few differences from encoding-down
. Some breaking:
- The lesser-used
'id'
,'ascii'
,'ucs2'
and'utf16le'
encodings are not supported - The undocumented
encoding
option (as an alias forvalueEncoding
) is not supported.
And some non-breaking:
- The
'binary'
encoding has been renamed to'buffer'
, with'binary'
as an alias - The
'utf8'
encoding previously did not touch Buffers. Now it will callbuffer.toString('utf8')
for consistency. Consumers can use the'buffer'
encoding to avoid this conversion.
Uint8Array data is now supported too, although many-level
internally uses Buffers. It's a separate encoding called 'view'
that can be used interchangeably:
const db = new ManyLevelGuest({ valueEncoding: 'view' })
await db.put('elena', new Uint8Array([97, 98, 99]))
await db.get('elena') // Uint8Array
await db.get('elena', { valueEncoding: 'utf8' }) // 'abc'
await db.get('elena', { valueEncoding: 'buffer' }) // Buffer
Like abstract-level@1
, many-level
started using error codes. The specific error messages that multileveldown
had did not change, but it is a breaking change in the sense that going forward, the semver contract will be on codes instead of messages (which, in other words, may change at any time). If you previously did:
try {
await db.get('abc')
} catch (err) {
if (err.message === 'Connection to leader lost') {
// ..
}
}
You should now do:
try {
await db.get('abc')
} catch (err) {
if (err.code === 'LEVEL_CONNECTION_LOST') {
// ..
}
}
Previously, the Connection to leader lost
error was also used upon a db.close()
(in addition to upon loss of connection). Closing the database while it has pending operations now results in a LEVEL_DATABASE_NOT_OPEN
error on those operations. This is the same code that abstract-level
(and therefore many-level
) uses on operations made after a db.close()
.
The error codes are also used in communication between host and guest, instead of exposing arbitrary error messages. If the host encounters an unexpected error, the code received by a guest will be LEVEL_REMOTE_ERROR
.
All together, here are the errors to be expected from many-level
:
Previous message | New code |
---|---|
Connection to leader lost |
LEVEL_CONNECTION_LOST or LEVEL_DATABASE_NOT_OPEN |
Database is readonly |
LEVEL_READONLY |
Any other message | LEVEL_REMOTE_ERROR or an abstract-level code |
The following properties are now read-only getters.
Object | Property | Original module | New module |
---|---|---|---|
db | status |
abstract-leveldown |
abstract-level |
chained batch | length |
levelup |
abstract-level |
Semi-private properties like _clearRequests()
and _ended
(that's not an exhaustive list) have been replaced with symbols and are no longer accessible.
For earlier releases, before many-level
was forked from multileveldown
(v5.0.1), please see the upgrade guide of multileveldown
.