many-level

2.0.0 · active · verified Wed Apr 22

many-level is a JavaScript library designed to share an abstract-level compatible database over network streams, acting as the spiritual successor to `multileveldown`. Currently at version 2.0.0, it allows a 'host' to expose a LevelDB-like database over any binary stream (e.g., TCP), while 'guests' can connect and interact with it as if it were a local `abstract-level` database instance. It leverages compact Protocol Buffers for efficient message encoding. The project follows a steady release cadence with significant updates marked by major version bumps addressing underlying stream mechanisms and protocol versions. A key differentiator is its optional seamless retry mechanism for guests, which helps maintain connectivity and resume operations, though it comes with a trade-off regarding snapshot guarantees. It ships with TypeScript types, providing a robust development experience.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates setting up a `ManyLevelHost` server and connecting a `ManyLevelGuest` client, performing basic put/get/del operations, and ensuring proper shutdown.

import { ManyLevelHost, ManyLevelGuest } from 'many-level';
import { Level } from 'level';
import { pipeline } from 'readable-stream';
import { createServer, connect } from 'net';
import { rmSync } from 'fs';

// Clean up previous test database if it exists
try {
  rmSync('./db', { recursive: true, force: true });
} catch (e) {
  // ignore
}

const dbPath = './db';
const hostDb = new Level(dbPath);
const host = new ManyLevelHost(hostDb);

const PORT = 9001;

const server = createServer(function (socket) {
  pipeline(socket, host.createRpcStream(), socket, (err) => {
    if (err) console.error('Host pipeline error:', err.message);
    console.log('Host: Client disconnected.');
  });
});

server.listen(PORT, async () => {
  console.log(`Host server listening on port ${PORT}`);

  const guestDb = new ManyLevelGuest();
  const guestSocket = connect(PORT);

  pipeline(guestSocket, guestDb.createRpcStream(), guestSocket, (err) => {
    if (err) console.error('Guest pipeline error:', err.message);
    console.log('Guest: Disconnected from host.');
  });

  try {
    await guestDb.put('hello', 'world');
    console.log(`Guest: Successfully put 'hello': 'world'`);
    const value = await guestDb.get('hello');
    console.log(`Guest: Retrieved 'hello': '${value}'`);

    await guestDb.del('hello');
    console.log(`Guest: Successfully deleted 'hello'.`);

    const hostValue = await hostDb.get('hello');
    console.log(`Host: Value after guest operation: '${hostValue}'`);
  } catch (error) {
    console.error('Guest operation failed:', error.message);
  } finally {
    server.close(() => console.log('Host server closed.'));
    await hostDb.close();
    console.log('Host database closed.');
    try {
        rmSync(dbPath, { recursive: true, force: true });
        console.log('Cleaned up database files.');
    } catch (e) {
        console.warn('Failed to clean up database files:', e.message);
    }
  }
});

view raw JSON →