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

@blite/client

v1.0.1

Published

TypeScript/Node.js client for BLite database server

Readme

@blite/client

TypeScript/Node.js client for BLite — the embedded document database server.

Install

npm install @blite/client

Quick start

import { BLiteClient, BsonId } from '@blite/client';

const client = new BLiteClient({
  host:   'localhost',
  port:   2626,          // default gRPC port
  apiKey: 'your-api-key',
  useTls: true,          // set false only for local dev
});

const users = client.getCollection('users');

// Insert
const id = await users.insert({ name: 'Alice', age: 30, active: true });
console.log(id.toString()); // hex ObjectId or string, etc.

// Find by ID
const doc = await users.findById(id);

// Query (fluent builder)
const results = await users.query()
  .whereEq('active', true)
  .whereGte('age', 18)
  .orderBy('name')
  .skip(0).take(20)
  .toArray();

// Stream large result sets
for await (const doc of users.query().whereEq('status', 'pending').execute()) {
  console.log(doc);
}

// Update
await users.update(id, { ...doc, age: 31 });

// Delete
await users.delete(id);

Typed collection

Use a CollectionMapper<T> to map between a TypeScript type and BsonDocument. This gives you compile-time safety on read/write paths.

import { BLiteClient, CollectionMapper, BsonId, BsonDocument } from '@blite/client';

interface User {
  id?: BsonId;
  name: string;
  email: string;
  age: number;
}

const userMapper: CollectionMapper<User> = {
  collectionName: 'users',
  getId(u) { return u.id!; },
  toDocument(u): BsonDocument {
    return { _id: u.id?.toString(), name: u.name, email: u.email, age: u.age };
  },
  fromDocument(doc): User {
    return {
      id:    doc._id ? BsonId.fromString(String(doc._id)) : undefined,
      name:  String(doc.name),
      email: String(doc.email),
      age:   Number(doc.age),
    };
  },
};

const client = new BLiteClient({ host: 'localhost', apiKey: 'key' });
const users  = client.getTypedCollection(userMapper);

const id    = await users.insert({ name: 'Bob', email: '[email protected]', age: 25 });
const user  = await users.findById(id);            // → User | null
const list  = await users.query().whereGt('age', 20).toArray(); // → User[]

Transactions

const tx = await client.beginTransaction();
try {
  await col.insert({ key: 'a' }, tx);
  await col.insert({ key: 'b' }, tx);
  await tx.commit();
} catch {
  await tx.rollback();
}

// Or with AsyncDisposable (Node.js 18.2+, TypeScript 5.2+):
await using tx = await client.beginTransaction();
await col.insert({ key: 'a' }, tx);
await col.insert({ key: 'b' }, tx);
await tx.commit();

Indexes

// BTree index (supports range queries)
await users.createIndex('email', { unique: true });

// Vector index (HNSW)
await products.createVectorIndex('embedding', 1536, { metric: 'Cosine' });

// Vector similarity search
for await (const doc of products.vectorSearch(queryEmbedding, { k: 10 })) {
  console.log(doc);
}

// Spatial index
await locations.createSpatialIndex('coordinates');

Change Data Capture (CDC)

// Stream all write events for a collection
for await (const event of users.watch(true /* capture payload */)) {
  console.log(event.operation, event.documentId.toString(), event.payload);
}

Key-Value store

const kv = client.kv;

await kv.set('session:abc', Buffer.from(JSON.stringify({ userId: 1 })), 3_600_000); // 1 h TTL
const buf = await kv.get('session:abc');
const keys = await kv.scanKeys('session:');

// Batch
await kv.batch((b) => {
  b.set('k1', Buffer.from('v1'));
  b.set('k2', Buffer.from('v2'), 60_000);
  b.delete('k3');
});

Admin API

import { BLiteOperation } from '@blite/client';

const admin = client.admin;

// Create a user with scoped permissions
const apiKey = await admin.createUser('bob', {
  permissions: [
    { collection: 'orders', ops: BLiteOperation.Query | BLiteOperation.Insert },
  ],
});

// Rotate key
const newKey = await admin.rotateKey('bob');

// Tenant provisioning (multi-tenant mode)
await admin.provisionTenant('tenant-acme');
await admin.deprovisionTenant('tenant-old', /* deleteFiles */ true);

Schema management

// Define a schema (enforced on write)
await users.setSchema([
  { name: 'name',  typeCode: 0x02 /* String */,  nullable: false },
  { name: 'age',   typeCode: 0x10 /* Int32 */,   nullable: true  },
  { name: 'email', typeCode: 0x02 /* String */,  nullable: false },
], 'UserSchema');

const info = await users.getSchema();
console.log(info.title, info.version, info.fields);

Time series

await metrics.configureTimeSeries('timestamp', 7 * 24 * 3_600_000); // 7-day retention
const info = await metrics.getTimeSeriesInfo();
await metrics.forcePrune(); // prune expired documents on demand

Configuration reference

| Option | Type | Default | Description | |--------|------|---------|-------------| | host | string | 'localhost' | Server hostname | | port | number | 2626 | gRPC port | | apiKey | string | required | API key sent as x-api-key | | useTls | boolean | true | Enable TLS | | address | string | — | Full address override; skips host/port/useTls |

Key-map refresh

BLite uses a compact binary format (C-BSON) where field names are replaced by 2-byte IDs.
The client keeps a local cache of fieldName ↔ ID mappings and registers new fields automatically on every write.

If you need to read documents written by other clients before making any writes yourself, pre-populate the cache:

await client.refreshKeyMap('users');  // any collection you have Query access to

Notes

  • Node.js 18+ required (AsyncDisposable, Buffer.writeBigInt64LE, ES2020 target).
  • int64 values in filter predicates: pass as bigint for values outside [-2^53, 2^53].
  • Decimal128 fields are decoded as a raw string representation for lossless round-trip; no arithmetic support.
  • The TypeScript client uses DynamicService only; DocumentService (typed BSON path with CLR type hints) is a C#-only concept.

License

AGPL-3.0 © EntglDb