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

astriveone-db

v1.2.0

Published

Universal Database Engine For Everything. Install once. Use everywhere.

Readme

astriveone-db

Universal Database Engine. One package, installed once.

npm version npm downloads license

npm install astriveone-db

Quick start

import { AstriveOne } from "astriveone-db";

const db = new AstriveOne();   // in-memory, zero config
await db.connect();

await db.set("users", { id: "001", username: "bayu" });
const user = await db.get("users", "001");
// { id: "001", username: "bayu" }

await db.close();

Drivers — what actually works where

Each driver has its own platform requirements. Choose the right one for your runtime.

memory — all platforms ✅

const db = new AstriveOne({ driver: "memory" });

| Platform | Works | |---|---| | Node.js ≥ 18 | ✅ | | Bun | ✅ | | Deno | ✅ | | Browser | ✅ | | Cloudflare Workers | ✅ | | Vercel Edge | ✅ | | React Native | ✅ |

Data lives only in process memory. Zero persistence — use remote or pair with a server for shared/persistent access.


json — Node / Bun / Deno only ⚠️

const db = new AstriveOne({ driver: "json", path: "./data.json" });

| Platform | Works | |---|---| | Node.js ≥ 18 | ✅ | | Bun | ✅ | | Deno (with --allow-write) | ✅ | | Browser | ❌ No filesystem | | Cloudflare Workers | ❌ No filesystem | | Vercel Edge | ❌ No filesystem | | AWS Lambda /tmp | ⚠️ Ephemeral only — data lost on cold start | | React Native | ❌ No Node fs module |

Calling db.connect() on a platform without a filesystem throws immediately with a clear error message rather than failing silently later.

Writes are crash-safe: data is written to a tmp file and atomically renamed, so a power loss mid-write cannot corrupt the database.


sqlite — Node 22+ / Bun ⚠️

const db = new AstriveOne({ driver: "sqlite", path: "./app.db" });
// or in-memory:
const db = new AstriveOne({ driver: "sqlite", path: ":memory:" });

| Platform | Works | |---|---| | Node.js ≥ 22 | ✅ Uses built-in node:sqlite — no extra packages | | Bun | ✅ | | Node.js < 22 | ❌ node:sqlite not available | | Browser / Edge / RN | ❌ No SQLite runtime |

Uses Node 22's built-in node:sqlite module — zero extra npm dependencies. Native SQL transactions are fully supported (not a snapshot/rollback workaround):

await db.transaction(async (tx) => {
  await tx.update("accounts", "a1", { balance: 50 });
  await tx.update("accounts", "a2", { balance: 150 });
  // if anything throws → full ROLLBACK, no partial writes
});

// Direct SQL for complex queries:
const storage = new SQLiteStorage("./app.db");
const rows = storage.exec("SELECT COUNT(*) as c FROM __documents WHERE collection = ?", ["users"]);

remote — all platforms ✅

const db = new AstriveOne({
  mode: "remote",
  url: "https://db.example.com",
  apiKey: process.env.ASTRIVEONE_KEY,
});

An HTTP client over the AstriveOne-DB REST+WebSocket wire protocol. Works anywhere fetch is available (all modern JS runtimes). Start a server with await db.start() on your Node/Bun backend and point this at it from any other language or platform.


Planned — not yet implemented 🚧

| Driver | Status | |---|---| | postgres | 🚧 Planned | | mysql | 🚧 Planned | | mongo | 🚧 Planned | | redis | 🚧 Planned |

Calling connect() with any of these drivers throws a clear error that says exactly what is and isn't implemented. There is no driver that pretends to work but fails silently.


CRUD

// Insert — auto-generates id if omitted
await db.set("posts", { id: "p1", title: "Hello", views: 0 });
await db.set("posts", { title: "Auto ID" }); // id generated

// Read — returns null (not undefined, not an error) if missing
const post = await db.get("posts", "p1");

// Find with operators
const results = await db.find("posts", {
  where: {
    views: { $gte: 100 },                    // range
    category: { $in: ["tech", "design"] },   // in list
    title: { $contains: "guide" },           // string match
    draft: { $ne: true },                    // not equal
    published: true,                          // exact match
  },
  sort: { views: -1 },  // -1 desc, 1 asc
  limit: 20,
  offset: 0,
});

// Partial update — keeps fields not in patch
await db.update("posts", "p1", { views: 1 });

// Delete — returns false if document didn't exist
const deleted = await db.delete("posts", "p1");

Transactions

await db.transaction(async (tx) => {
  const sender = await tx.get("accounts", "alice");
  if (sender.balance < 100) throw new Error("insufficient funds");
  await tx.update("accounts", "alice", { balance: sender.balance - 100 });
  await tx.update("accounts", "bob",   { balance: bob.balance + 100 });
  // if anything throws, all writes are rolled back
});

Memory/JSON drivers use snapshot-and-rollback. SQLite driver uses native SQL BEGIN/COMMIT/ROLLBACK — guaranteed atomic by the database engine.


Realtime

// Watch a collection — fires on insert, update, delete
const stop = db.watch("messages", (event) => {
  console.log(event.type);       // "insert" | "update" | "delete"
  console.log(event.id);         // document id
  console.log(event.doc);        // new/updated document
  console.log(event.before);     // previous state (update/delete)
});

// Watch everything
const stopAll = db.watchAll((event) => {
  console.log(`${event.collection}/${event.id}: ${event.type}`);
});

// Custom pub/sub
db.subscribe("notifications", (payload) => console.log(payload));
db.emit("notifications", { text: "New message" });

// Stop watching
stop();

The realtime bus is a zero-dependency in-process event system (plain Map<string, Set<fn>>). No node:events, no EventEmitter — runs identically on Node, Bun, Deno, browsers, Cloudflare Workers, and React Native.


Authentication

// Register and login
await db.auth.register("bayu", "password123", ["admin"]);
const session = await db.auth.login("bayu", "password123");
console.log(session.token); // secure random token

// Verify and check roles
const verified = await db.auth.verify(session.token);
const isAdmin = db.auth.hasRole(verified, "admin");

// Logout (invalidates the token server-side)
await db.auth.logout(session.token);

// API keys for service-to-service auth
const key = await db.auth.createApiKey("my-bot", ["service"]);
await db.auth.verifyApiKey(key);
await db.auth.revokeApiKey(key);

External identity (OAuth integration)

This package does not perform OAuth flows (redirects, code exchange, provider API calls). That is your responsibility. Once you have verified an external identity, call:

// After YOU have verified the Google/GitHub/etc token and obtained the user's external id:
const session = await db.auth.createSessionFromExternalIdentity(
  "google",
  verifiedGoogleUserId,  // from Google's verified token payload
  { email: "[email protected]", name: "Bayu" }
);

If the user does not exist yet, a local record is created automatically. If they do, a new session is issued for the existing record.


Encryption at rest

// Requires an explicit, non-empty secret. encrypt: true alone is rejected.
const db = new AstriveOne({
  driver: "json",
  path: "./data.json",
  encrypt: { secret: process.env.DB_SECRET },  // must be explicit
});

Uses AES-256-GCM. The file on disk is completely unreadable without the secret. There is no hardcoded fallback key — passing an empty or whitespace-only secret throws immediately at connect().


Validation

db.defineSchema("users", {
  username: { type: "string", required: true, min: 3, max: 32 },
  email:    { type: "string", required: true, pattern: "^[^@]+@[^@]+$" },
  age:      { type: "number", min: 0, max: 120 },
  active:   { type: "boolean" },
});

// This throws before touching storage:
await db.set("users", { username: "ab" });
// AstriveOne-DB: validation failed for "users": "username" min length is 3

Built-in cache

await db.useCache({ ttl: 30_000, maxEntries: 1000 });

// Reads are cached — identical object reference on cache hit:
const a = await db.get("users", "u1");
const b = await db.get("users", "u1"); // same reference, from cache

// Cache is invalidated automatically on any write to the same collection
await db.update("users", "u1", { name: "Updated" });
const c = await db.get("users", "u1"); // fresh from storage

Security

// Rate limiting (token bucket per collection)
db.enableRateLimit(100, 60_000); // 100 ops per minute

// Audit log — every mutation recorded
const db = new AstriveOne({ audit: true });

// Backup / restore
await db.backup("./backups/2026-06-25.json");
await db.restore("./backups/2026-06-25.json");

Studio (visual admin dashboard)

const studio = await db.start({ port: 4848 });
// Prints:
// ╔══════════════════════════════════════════════╗
// ║           AstriveOne-DB v1.0.0               ║
// ╠══════════════════════════════════════════════╣
// ║  Status:   ONLINE                            ║
// ║  REST:     http://localhost:4848/api/db      ║
// ║  Studio:   http://localhost:4848/studio      ║
// ╠══════════════════════════════════════════════╣
// ║  Access Token:                               ║
// ║  astro_root_xxxxxxxxxxxxxxxxxxxxxxxxxxxx     ║
// ╚══════════════════════════════════════════════╝

// Tokens for sharing access:
const viewToken = await db.createToken("viewer", "read-only client", { expire: "24h" });
const editToken = await db.createToken("editor", "CI bot");
const list = await db.listTokens();
await db.revokeToken(list[0].id);
const rotated = await db.rotateToken(oldToken);

Examples

Discord bot

import { Client, GatewayIntentBits } from "discord.js";
import { AstriveOne } from "astriveone-db";

const db = new AstriveOne({ driver: "json", path: "./bot.json" });
await db.connect();

const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.on("interactionCreate", async (interaction) => {
  if (!interaction.isChatInputCommand()) return;
  if (interaction.commandName === "save") {
    await db.set("notes", { id: crypto.randomUUID(), userId: interaction.user.id, text: interaction.options.getString("text") });
    await interaction.reply({ content: "Saved ✓", ephemeral: true });
  }
});
client.login(process.env.DISCORD_TOKEN);

WhatsApp bot

import { Client } from "whatsapp-web.js";
import { AstriveOne } from "astriveone-db";

const db = new AstriveOne({ driver: "json", path: "./wa.json" });
await db.connect();
const client = new Client();
client.on("message", async (msg) => {
  if (msg.body.startsWith("!save ")) {
    await db.set("notes", { id: crypto.randomUUID(), from: msg.from, text: msg.body.slice(6) });
    msg.reply("Saved ✓");
  }
});
client.initialize();

License

MIT © althericoffcv — follow on GitHub