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

lunadb-client

v0.0.11

Published

Official Node.js client library for LunaDB - A high-performance, disk-first document and key-value database.

Readme

LunaDB Node.js Client 🐈

An asynchronous, connection-pooled Node.js client for interacting with the LunaDB database via its secure, TLS-based BSON binary protocol. This library is designed to be highly concurrent, robust, and ergonomically friendly for TypeScript and JavaScript developers.


📖 Getting Started

Installation

npm install lunadb-client

Connection and Basic Operations

The LunaDBClient class automatically manages a Connection Pool (default: 100 sockets) under the hood to handle massive concurrency without blocking the Node.js event loop.

import { LunaDBClient } from "lunadb-client";

// Server Configuration
const DB_HOST = "127.0.0.1";
const DB_PORT = 5876;
const DB_USER = "admin";
const DB_PASS = "adminpass";

// Initialize the client
// Parameters: host, port, user, pass, certPath, rejectUnauthorized, poolSize
const client = new LunaDBClient(
  DB_HOST,
  DB_PORT,
  DB_USER,
  DB_PASS,
  null,  // serverCertPath (Provide your CA cert in production)
  false, // rejectUnauthorized (Set to true in production)
  100    // poolSize (Number of concurrent TLS sockets)
);

async function runExample() {
  try {
    // 1. Establish the connection pool
    await client.connect();
    console.log(`✔ Connected and authenticated as: ${client.authenticatedUser}`);

    const collName = "users";
    await client.collectionCreate(collName);
    console.log(`✔ Collection '${collName}' created.`);

    // 2. Set an item (Auto-generates UUID if key is omitted)
    const userValue = { name: "Elena", city: "Madrid", active: true };
    const savedUser = await client.collectionItemSet(collName, userValue);
    console.log(`✔ User set successfully with ID: ${savedUser._id}`);

    // 3. Set an item with a specific explicit key
    const specificKey = "user_marcos";
    await client.collectionItemSet(
      collName,
      { name: "Marcos", city: "Bogota", active: true },
      specificKey
    );
    console.log(`✔ User '${specificKey}' set successfully.`);

    // 4. Retrieve the item back
    const result = await client.collectionItemGet(collName, specificKey);
    if (result.found) {
      console.log("✔ Item retrieved:", result.value);
    }
  } catch (error) {
    console.error("✖ Connection or operation error:", error.message);
  } finally {
    // Always close the pool when the application shuts down
    client.close();
    console.log("Connection pool closed.");
  }
}

runExample();

Stateful ACID Transactions

For operations that must either all succeed or all fail, LunaDB supports strict ACID transactions. Calling begin() locks a dedicated connection from the pool for your transaction block.

async function transactionExample() {
  await client.connect();

  // Start a transaction (returns a dedicated Tx object)
  const tx = await client.begin();
  
  try {
    // Perform operations using the 'tx' instance, NOT the 'client' instance
    await tx.collectionItemUpdate("accounts", "acc1", { balance: 50 });
    await tx.collectionItemUpdate("accounts", "acc2", { balance: 150 });

    // If all operations succeed, commit the changes to disk
    await tx.commit();
    console.log("✔ Transaction committed successfully.");
  } catch (error) {
    // If any operation fails, roll back all changes safely
    await tx.rollback();
    console.error("✖ Transaction failed, changes were rolled back.");
  } finally {
    client.close();
  }
}

🎯 Massive Server-Side Mutations

Update or delete thousands of records instantly using a query filter. The data never travels over the network; the LunaDB engine handles the B-Tree lookups and physical batching entirely internally.

// Update Where: Set status to 'Shipped' for all 'Pending' orders
const updateQuery = {
  filter: { field: "status", op: "=", value: "Pending" }
};
const patch = { status: "Shipped" };
await client.collectionUpdateWhere("orders", updateQuery, patch);
console.log("✔ All pending orders updated to shipped.");

// Delete Where: Delete all 'Cancelled' orders
const deleteQuery = {
  filter: { field: "status", op: "=", value: "Cancelled" }
};
await client.collectionDeleteWhere("orders", deleteQuery);
console.log("✔ All cancelled orders purged.");

(Note: These methods are also fully supported within the tx Transaction object).


🔬 Advanced Queries with the Query Object

The Query interface is the most powerful feature of the client, allowing you to build complex, server-side queries. LunaDB executes these using in-memory B-Trees and Zero-Copy BSON streams, making them incredibly fast.

Query Parameters

  • filter (object): Defines conditions to select items (like a WHERE clause).

  • order_by (array): Sorts the results based on one or more fields ([{"field": "age", "direction": "desc"}]).

  • limit (number): Restricts the maximum number of results returned.

  • offset (number): Skips a specified number of results. Highly optimized for Deep Pagination.

  • count (boolean): If true, returns a raw count of matching items.

  • distinct (string): Returns a list of unique values for the specified field.

  • group_by (array): Groups results by one or more fields to perform aggregations.

  • aggregations (object): Defines math functions to run on groups (e.g., sum, avg, min, max, count).

  • having (object): Filters the results after grouping and aggregation (like a HAVING clause).

  • projection (array of strings): Selects strictly which fields to return, reducing network traffic.

  • lookups (array of objects): Enriches documents by performing server-side Hash Joins with other collections.

Building Filters

The filter object is the core of your query. It can be a single condition or a nested structure using logical operators like and, or, and not.

Single Condition Structure: { field: "field_name", op: "operator", value: ... }

|Operator (op)|Description|Example value| |---|---|---| |=|Equal to|"some_string" or 123| |!=|Not equal to|"some_string" or 123| |>|Greater than|100| |>=|Greater than or equal to|100| |<|Less than|50| |<=|Less than or equal to|50| |like|Regex-backed pattern matching (% is wildcard)|"start%" or "%middle%"| |in|Value is in a list of possibilities|["value1", "value2"]| |between|Value is between two values (inclusive)|[10, 20]| |is null|The field does not exist or is null|true (or any value)| |is not null|The field exists and is not null|true (or any value)|

Example: Complex Filter

This query finds all users who are active and older than 30.

const query = {
  filter: {
    and: [
      { field: "active", op: "=", value: true },
      { field: "age", op: ">", value: 30 },
    ],
  },
};
const results = await client.collectionQuery("users", query);

Joins and Data Enrichment with lookups

The lookups parameter allows you to perform powerful, zero-copy server-side joins.

// Enriches 'profiles' with data from 'users'
const lookupQuery = {
  lookups: [
    {
      from: "users",
      localField: "user_id", // Field from the 'profiles' collection
      foreignField: "_id",   // Field from the 'users' collection
      as: "user_info",       // New field to store the joined user document
    },
  ],
};

const enrichedProfiles = await client.collectionQuery("profiles", lookupQuery);

Deep Query Example: Aggregations & Grouping

const analyticsQuery = {
  // 1. Group documents by the 'active' field
  group_by: ["active"],

  // 2. Define the aggregations to perform on each group
  aggregations: {
    userCount: { func: "count", field: "_id" }, // Count documents
    maxAge: { func: "max", field: "age" },      // Find max age
  },
};

const report = await client.collectionQuery("users", analyticsQuery);

⚡ API Reference

Connection and Session

  • constructor(host, port, username?, password?, serverCertPath?, rejectUnauthorized?, poolSize?): Creates a new client instance.

  • connect(): Promise<void>: Establishes the TLS connection pool and authenticates.

  • close(): void: Closes all underlying socket connections.

  • isAuthenticatedSession: Boolean indicating if the client is authenticated.

  • authenticatedUser: String containing the username of the authenticated user.

Transaction Operations (Tx Object)

  • client.begin(): Promise<Tx>: Starts a new transaction and locks a connection.

  • tx.commit(): Promise<string>: Commits the transaction to disk.

  • tx.rollback(): Promise<string>: Discards changes and releases the connection.

  • tx.collectionItemUpdate(...): (And other mutation methods) Execute operations within the transaction scope.

Collection & Index Operations

  • collectionCreate(name: string): Promise<string>: Creates a new bucket on disk.

  • collectionDelete(name: string): Promise<string>: Deletes a collection and its indexes.

  • collectionList(): Promise<string[]>: Lists all accessible collections.

  • collectionIndexCreate(coll: string, field: string): Promise<string>: Builds a B-Tree index in RAM.

  • collectionIndexDelete(coll: string, field: string): Promise<string>: Removes an index.

  • collectionIndexList(coll: string): Promise<string[]>: Lists all indexed fields for a collection.

Item (CRUD) Operations

  • collectionItemSet<T>(coll: string, value: T, key?: string): Promise<T>: Stores an item. Returns the saved BSON document.

  • collectionItemSetMany<T>(coll: string, items: T[]): Promise<string>: Stores multiple items via Group Commit.

  • collectionItemUpdate<T>(coll: string, key: string, patchValue: Partial<T>): Promise<string>: Partially updates a document using BSON patching.

  • collectionItemUpdateMany<T>(coll: string, items: { _id: string, patch: Partial<T> }[]): Promise<string>: Partially updates multiple items in a batch.

  • collectionItemGet<T>(coll: string, key: string): Promise<GetResult<T>>: Retrieves an item.

  • collectionItemDelete(coll: string, key: string): Promise<string>: Deletes a document.

  • collectionItemDeleteMany(coll: string, keys: string[]): Promise<string>: Deletes multiple items by key.

Mass Mutation Operations

  • collectionUpdateWhere<T>(coll: string, query: Query, patchValue: Partial<T>): Promise<string>: Mass updates all documents matching the query condition using a BSON patch.

  • collectionDeleteWhere(coll: string, query: Query): Promise<string>: Mass deletes all documents matching the query condition.

Query Operations

  • collectionQuery<T>(coll: string, query: Query): Promise<T>: Executes a complex query returning an array of documents, aggregations, or distinct values.

🔒 Security Considerations

  • TLS is Mandatory: LunaDB enforces TLS to encrypt data in transit.

  • Certificate Verification: For production, always set rejectUnauthorized to true (the default) and provide a serverCertPath to prevent man-in-the-middle attacks.


❤️ Support the Project

Hello! I'm Adonay Boscán, the developer behind LunaDB. This is a passionate open-source effort to build a modern, high-performance database engine from scratch.

If this project has helped you scale your applications, consider supporting its continued development. Your contributions allow me to maintain the codebase, implement new features, and keep the project thriving.

How You Can Help

Every contribution, no matter the size, is a great help and is enormously appreciated.

Click here to donate via PayPal

Other Ways to Contribute

  • Star the project on GitHub.

  • Share it with your engineering team.

  • Report bugs or request features by opening an issue.