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

@moltendb-web/query

v0.4.0

Published

Type-safe query builder for MoltenDB — chainable API for get, set, update and delete operations.

Readme

@moltendb-web/query

Type-safe, chainable query builder for MoltenDB.

Works in vanilla JavaScript and TypeScript. Compiles as an npm module (CJS + ESM + .d.ts).

🌋 Explore the Full Functionality

The best way to experience the MoltenDB query builder is through our Interactive Demo on StackBlitz. It contains a complete, live environment where you can test query builder expressions, perform mutations, and see real-time events without any local setup.


Installation

npm install @moltendb-web/query

Quick start

import { MoltenDB } from '@moltendb-web/core';
import { MoltenDBClient, WorkerTransport } from '@moltendb-web/query';

// 1. Initialize the Core Engine (boots WASM worker)
const workerUrl = new URL('@moltendb-web/core/worker', import.meta.url).href;
const db = new MoltenDB('moltendb_demo', { syncEnabled: false, workerUrl });
await db.init();

// 2. Connect the Query Builder to the worker
const client = new MoltenDBClient(new WorkerTransport(db.worker, 10000));
// SET — insert / upsert
await client.collection('laptops')
    .set({
        lp1: { brand: 'Lenovo', model: 'ThinkPad X1', price: 1499, in_stock: true },
        lp2: { brand: 'Apple',  model: 'MacBook Pro',  price: 3499, in_stock: true },
    })
    .exec();

// GET — query with WHERE, field projection, sort and pagination
const results = await client.collection('laptops')
  .get()
  .where({ brand: 'Apple' })
  .fields(['brand', 'model', 'price'])
  .sort([{ field: 'price', order: 'asc' }])
  .count(5)
  .exec();

// UPDATE — partial patch (only listed fields are changed)
await client.collection('laptops')
  .update({ lp1: { price: 1749, in_stock: false } })
  .exec();

// DELETE — single key
await client.collection('laptops').delete().keys('lp1').exec();

// DELETE — batch
await client.collection('laptops').delete().keys(['lp1', 'lp2']).exec();

// DELETE — drop entire collection
await client.collection('laptops').delete().drop().exec();

Operations & allowed fields

Each operation only exposes the methods that are valid for it — invalid combinations are caught at compile time by TypeScript.

get() — read / query

| Method | Description | |---|---| | .keys(key \| key[]) | Fetch one or more documents by key | | .where(clause) | Filter with operators: $eq $ne $gt $gte $lt $lte $in $nin $contains (and aliases) | | .fields(string[]) | Return only these fields (dot-notation supported) | | .excludedFields(string[]) | Return everything except these fields | | .joins(JoinSpec[]) | Embed related documents from other collections | | .sort(SortSpec[]) | Sort results (multi-field, asc/desc) | | .count(n) | Limit results to N documents | | .offset(n) | Skip first N results (pagination) | | .build() | Return the raw JSON payload without sending | | .exec() | Send the query and return the result |

set(data) — insert / upsert

| Method | Description | |---|---| | .extends(map) | Embed snapshots from other collections at insert time | | .build() | Return the raw JSON payload without sending | | .exec() | Send and return { count, status } |

data can be a { key: document } map or a Document[] array (UUIDv7 keys are auto-assigned for arrays).

update(data) — partial patch

| Method | Description | |---|---| | .build() | Return the raw JSON payload without sending | | .exec() | Send and return { count, status } |

Only the fields present in each patch object are updated — all other fields are left unchanged.

delete() — delete documents or drop collection

| Method | Description | |---|---| | .keys(key \| key[]) | Delete one or more documents by key | | .drop() | Drop the entire collection | | .build() | Return the raw JSON payload without sending | | .exec() | Send and return { count, status } |


WHERE operators

// Exact equality (implicit or explicit)
.where({ brand: 'Apple' })
.where({ brand: { $eq: 'Apple' } })
.where({ brand: { $equals: 'Apple' } }) // alias

// Comparison
.where({ price: { $gt: 1000, $lt: 3000 } })
.where({ price: { $greaterThan: 1000, $lessThan: 3000 } }) // aliases
.where({ 'specs.cpu.cores': { $gte: 12 } })

// Not equal
.where({ 'specs.cpu.brand': { $ne: 'Intel' } })
.where({ 'specs.cpu.brand': { $notEquals: 'Intel' } }) // alias

// In / not-in list
.where({ brand: { $in: ['Apple', 'Dell'] } })
.where({ brand: { $oneOf: ['Apple', 'Dell'] } }) // alias
.where({ brand: { $nin: ['Framework'] } })
.where({ brand: { $notIn: ['Framework'] } }) // alias

// Contains (string substring or array element)
.where({ model: { $contains: 'Pro' } })
.where({ model: { $ct: 'Pro' } }) // alias
.where({ tags:  { $contains: 'gaming' } })

// Multiple conditions (implicit AND)
.where({ in_stock: true, 'specs.cpu.brand': 'Intel' })

Joins

const results = await client.collection('laptops')
  .get()
  .fields(['brand', 'model', 'price'])
  .joins([
    { alias: 'ram',    from: 'memory',  on: 'memory_id',  fields: ['capacity_gb', 'type'] },
    { alias: 'screen', from: 'display', on: 'display_id', fields: ['refresh_hz', 'panel'] },
  ])
  .exec();
// Each result: { brand, model, price, ram: { capacity_gb, type }, screen: { refresh_hz, panel } }

Extends (snapshot embedding at insert time)

await client.collection('laptops')
  .set({
    lp7: {
      brand: 'MSI', model: 'Titan GT77', price: 3299,
      specs: { cpu: { brand: 'Intel', cores: 16, ghz: 5.0 } },
    },
  })
  .extends({ ram: 'memory.mem4', screen: 'display.dsp3' })
  .exec();
// lp7 is stored with the full mem4 and dsp3 documents embedded inline.

When to use extends vs joins:

| | extends | joins | |---|---|---| | Resolved at | Insert time (once) | Query time (every request) | | Data freshness | Snapshot — may become stale | Always live | | Read cost | O(1) — data already embedded | O(1) per join per document | | Use when | Data rarely changes, fast reads matter | Data changes frequently, freshness matters |


Custom transport

Implement MoltenTransport to connect to any backend:

import { MoltenTransport, MoltenDBClient, Document, JsonValue } from '@moltendb-web/query';

class FetchTransport implements MoltenTransport {
  constructor(private baseUrl: string, private token: string) {}

  async send(action: 'get' | 'set' | 'update' | 'delete', payload: Document): Promise<JsonValue> {
    const res = await fetch(`${this.baseUrl}/${action}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`,
      },
      body: JSON.stringify(payload),
    });
    return res.json();
  }
}

const db = new MoltenDBClient(new FetchTransport('https://localhost:1538', myToken));

Build

npm run typecheck  # type-check without emitting

License

MIT OR Apache-2.0