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

opendbs

v1.0.1

Published

Official Node.js client for OpenDBS: documents, SQL, aggregation, transactions, cluster failover

Readme

opendbs

The official Node.js client for OpenDBS, a document and SQL database server.

  • No dependencies. It uses Node's built-in fetch, with connections kept alive.
  • Works with one server or a whole cluster. Give several URLs and the client moves to another member when one fails, including during a failover election.
  • Retries are safe. Every write carries an Idempotency-Key, so a retry after a network error is never applied twice.
  • TypeScript types are included.

Requires Node.js 18 or newer and an OpenDBS 1.0 server.

npm install opendbs

Connect

const { OpenDBS } = require('opendbs');

// With an API key (admin panel → API keys; can be limited to databases and IPs)
const client = new OpenDBS({ url: 'http://localhost:4402', apiKey: process.env.OPENDBS_KEY });

// Or with a user. The client signs in on the first call and again when the session expires.
const client2 = new OpenDBS({ url: 'http://localhost:4402', username: 'app', password: process.env.OPENDBS_PASSWORD });

// A cluster: list the members
const client3 = new OpenDBS({ url: 'http://10.0.0.5:4402,http://10.0.0.6:4402,http://10.0.0.7:4402', apiKey: process.env.OPENDBS_KEY });

Options: url (string, comma-separated list or array), apiKey, username, password, totp (2FA code), token, timeoutMs (default 30000), failoverMs (how long to keep trying other members, default 20000).

Documents

const shop = client.database('shop');
await client.createDatabase('shop');
await shop.createRack('events');                       // NoSQL rack: any JSON
await shop.createTable('customers', {                  // SQL table: typed columns
  name:  { type: 'string', required: true },
  email: { type: 'string', required: true, unique: true },
  age:   { type: 'integer' },
});

const customers = shop.table('customers');
const id  = await customers.insert({ name: 'Asha', email: '[email protected]', age: 31 });
const ids = await customers.insertMany([{ name: 'Ravi', email: '[email protected]', age: 45 }]);   // all or nothing

const { results, total } = await customers.find(
  { age: { $gte: 18 }, $or: [{ name: 'Asha' }, { name: 'Ravi' }] },
  { limit: 20, skip: 0, sort: { field: 'age', order: 'desc' } },
);
const one = await customers.get(id);                   // null when missing
await customers.patch(id, { age: 32 });                // merge fields
await customers.update(id, { name: 'Asha', email: '[email protected]', age: 33 });   // replace
await customers.delete(id);
await customers.createIndex(['name', 'age']);          // compound index

SQL

// ? (or $1) placeholders are never parsed as SQL: use them for any user input.
const { result } = await shop.sql(
  `SELECT c.name, COUNT(*) AS orders, SUM(o.total) AS spent
     FROM customers c JOIN orders o ON o.customer_id = c.id
    WHERE o.total > ?
    GROUP BY c.name HAVING COUNT(*) > 1 ORDER BY spent DESC`,
  [20],
);

Aggregation, search, transactions

const byCity = await shop.rack('events').aggregate([
  { $match: { type: 'purchase' } },
  { $group: { _id: '$city', revenue: { $sum: '$amount' } } },
  { $sort: { revenue: -1 } },
]);

await shop.rack('products').fuzzySearch('name', 'lapptop');
await shop.rack('products').vectorSearch('embedding', [0.12, 0.4, 0.9], 10);

// Atomic across racks. tx.insert() returns a reference to the new id.
await client.transaction((tx) => {
  const order = tx.insert('shop', 'orders', { customer_id: '1', total: 40 });
  tx.insert('shop', 'order_items', { order_id: order, sku: 'LAMP-1', qty: 1 });
  tx.patch('shop', 'stock', '7', { qty: 11 });
});

Errors

Failed requests throw an OpenDBSError with status (the HTTP status) and body (the server's response).

const { OpenDBSError } = require('opendbs');
try { await customers.insert({ name: 'Dup', email: '[email protected]' }); }
catch (e) { if (e instanceof OpenDBSError && e.status === 400) console.log(e.message); }

Upgrading from 1.0.0

Code written for 1.0.0 keeps working. The 1.0.0 methods that take the database and rack as arguments are still there: login(username, password), insert(db, rack, doc), find(db, rack, query), findOne, update, delete, sql(db, query), search, fuzzySearch, vectorSearch, rangeSearch, patternSearch, listRacks, createRack(db, { name, type, schema }), deleteRack, clearRack, deleteDatabase, register, regenerateApiKey, getSqlCredentials, and the backup methods. They return the same values as before. The baseURL option is accepted as another name for url.

Two differences:

  • axios is no longer a dependency. Errors are OpenDBSError (with status and body) instead of axios errors (with response.status).
  • ignoreSSL is no longer supported. To trust a self-signed certificate, start Node with NODE_EXTRA_CA_CERTS=/path/to/cert.pem.

License

CC BY-NC 4.0. Non-commercial use is free with attribution.