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

@isais-logic/isha-vector-db-web

v0.1.0

Published

vdb for the web: the same engine, compiled to WebAssembly, storing in OPFS.

Readme

@isais-logic/isha-vector-db-web

The same engine, compiled to WebAssembly, storing in the Origin Private File System.

import { load, Metric } from '@isais-logic/isha-vector-db-web';
import { opfsAdapter } from '@isais-logic/isha-vector-db-web/adapters/opfs.js';

const adapter = await opfsAdapter('my-app');
const vdb = await load(fetch('/vdb.wasm'), adapter);

const db = vdb.open('/notes');
const notes = db.collection('notes', 384, Metric.Cosine);

notes.upsert('note-1', embedding);
notes.flush();

for (const { id, score } of notes.search(query, 10)) {
  console.log(id, score);
}

How this is built

There is no wasm-bindgen and no bundler step. This SDK drives include/vdb.h — the identical C ABI the iOS, Android and Node SDKs use — so the whole toolchain is cargo build --target wasm32-unknown-unknown. scripts/build-web.sh does it.

Two functions exist that the C header does not declare, vdb_wasm_alloc and vdb_wasm_free. JavaScript cannot allocate inside the module's linear memory, so the module has to hand it a region; a C caller has its own allocator and never needs them. They are a calling convention, not database functionality, and vdb_abi_version() does not cover them.

Storage adapters

The engine calls storage synchronously. OPFS can do synchronous I/O through FileSystemSyncAccessHandle, but obtaining one is asynchronous, so a file cannot be opened at the moment the engine asks for it. opfsAdapter therefore opens a pool of handles at start-up and assigns them to paths on demand, with each slot carrying a header naming the path it holds so the mapping is recovered on reload without a separate index to keep consistent.

Set slots to comfortably exceed the number of files your database will hold; running out raises an error naming the pool rather than failing obscurely.

adapters/indexeddb.js is the fallback for browsers where OPFS is unavailable — older Safari, and private browsing modes where the origin private filesystem is restricted. IndexedDB has no synchronous API at all, not even inside a Worker, so there is no arrangement of handles that makes it answer a synchronous read. Instead the whole database is held in memory and IndexedDB is where it is kept: 64 KiB blocks written back in the background, so a small change to a large segment rewrites one block rather than the file.

Two consequences worth knowing before choosing it. The database must fit in memory — bytesResident() reports where you are against that. And durability is weaker again than OPFS: a write the engine considers flushed is in memory and queued, and flush() returns a promise that resolves only once the queue has drained. The adapter also drains on pagehide and when the page becomes hidden, which covers the ways a tab normally goes away, but not a crash.

adapters/node.js is a third adapter over node:fs, used to test this stack without a browser. It is not a supported way to run isha-vector-db on a server — use the native addon in sdk/node, which has no WebAssembly boundary.

Run it in a Worker

OPFS synchronous access handles are only available in a Worker, and a search is a blocking call: running the engine on the main thread would block rendering for its duration. Put this SDK in a dedicated Worker and post messages to it.

What is tested, and what is not

test/wasm.test.js and test/opfs.test.js run the real WebAssembly module — 7 tests covering writes, search, deletes, reopening from persisted bytes, structured errors, slot-mapping recovery across a remount, and pool exhaustion. The Rust side adds the 25-check storage conformance suite and a full engine test against the same backend.

Both browser backends are verified in a headless Chromium. test/browser.html runs the engine in a Worker against genuine OPFS sync access handles, and test/browser-idb.html does the same against real IndexedDB; each writes twenty documents, searches, deletes, then reloads the page and finds the data still there. Serve this directory over HTTP and open them — OPFS needs a secure context. CI does not run these; they need a browser, and the Node job does not have one.

That check earned its keep immediately. The first version ran on the main thread and failed with handle.createSyncAccessHandle is not a function, because that method exists only on a Worker. Nothing in the Node suite could have found it: test/opfs.test.js runs against a stand-in, and a stand-in written from the same assumptions as the adapter agrees with them by construction — including the assumption that the method is there at all.

Durability

OPFS flush() is best-effort — it is not a barrier against power loss the way fsync is. The storage backend reports durable_sync: false and the engine downgrades what it promises rather than claiming a guarantee the platform cannot keep. The write-ahead log still protects against the failure that actually happens in a browser: the tab going away.