hyperdb: P2P Indexable Database

6.6.0 · active · verified Wed Apr 22

Hyperdb is a JavaScript library providing a database layer designed for both peer-to-peer (P2P) and local-only data storage, leveraging the Holepunch (formerly Hypercore Protocol) ecosystem. As of version 6.6.0, it offers a schema-driven approach to defining data structures, collections, and indexes using the `Hyperschema` and `hyperdb/builder` tools. It differentiates itself by allowing developers to choose between a P2P backend (Hyperbee) for distributed, eventually consistent data, or a local, embedded database backend (RocksDB) for high-performance, single-instance storage. The project appears to be actively maintained, aligning with the broader Holepunch initiative, though a strict release cadence isn't published. Key features include declarative schema and index definitions, streaming queries, and both synchronous (`await db.get`) and asynchronous (`db.find().toArray()`) data access patterns.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates initializing a local Hyperdb instance (using RocksDB), inserting data into a defined collection, querying by exact match and using an index, and properly closing the database. It assumes database schemas and collections have already been defined and built into './spec/hyperdb/index.js'.

// This quickstart assumes you have already run a builder script (like the one in the README)
// to generate your database definition files in './spec/hyperdb/index.js'.

import HyperDB from 'hyperdb';
import def from './spec/hyperdb/index.js'; // The generated database definition

async function run() {
  // Choose your engine: .rocks for local-only, .bee for P2P
  // For this example, we'll use RocksDB locally.
  // Replace './my-local-db' with a suitable path for your database files.
  const db = HyperDB.rocks('./my-local-db', def, { writable: true });

  await db.ready(); // Ensure the database is initialized and ready for operations

  // Add some entries
  console.log('Inserting members...');
  await db.insert('@example/members', { name: 'Alice', age: 30 });
  await db.insert('@example/members', { name: 'Bob', age: 25 });
  await db.insert('@example/members', { name: 'Charlie', age: 30 });
  await db.flush(); // Commit changes to the database

  console.log('Querying for Alice by name...');
  const alice = await db.get('@example/members', { name: 'Alice' });
  console.log('Found Alice:', alice);

  console.log('Querying for members with names starting C or later (via index)...');
  // The example index 'members-by-name' has a 'mapNameToLowerCase' helper.
  const olderMembersStream = db.find('@example/members-by-name', { gte: { key: 'c' } });
  const olderMembers = await olderMembersStream.toArray();
  console.log('Members with names starting C or later:', olderMembers.map(m => m.name));

  console.log('Getting one specific member by name using findOne...');
  const bob = await db.findOne('@example/members', { name: 'Bob' });
  console.log('Found Bob:', bob);

  await db.close(); // Close the database connection to release resources
  console.log('Database closed.');
}

run().catch(console.error);

view raw JSON →