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

@openlfcp/storage-idb

v0.2.2

Published

Durable portable storage for LFCP clients on IndexedDB (browsers, Electron, mobile WebViews).

Readme

@openlfcp/storage-idb

Durable portable storage for LFCP clients (LFCP-059): IdbLfcpStorage, the LfcpStorage interface of @openlfcp/storage on IndexedDB. It runs in browsers, Electron (Obsidian desktop) and mobile WebViews. It uses no Node built-ins (scripts/check-boundaries.mjs), and it passes the shared contract suite (runStorageContract from @openlfcp/storage/contract).

const storage = await IdbLfcpStorage.open(`openlfcp-v1-${installId}`, {
  onReserved: ({ kind, key, value }) => mirrorHighWater(kind, key, value),
});
// ... storage.commit([...]), storage.dataUnits.get(id), ...
storage.close();

The application names the database. Use one per client install: an IndexedDB origin is often shared (all Obsidian vaults share app://obsidian.md), and two installs must never share sequence counters.

Scope

Part of the OpenLFCP TypeScript SDK, which implements the OpenLFCP MVP 0.1 subset of LFCP-WIRE-01 at mvp-0.1-baseline.9, not every deferred WIRE-01 feature. It does not claim full LFCP-WIRE-01 conformance. This is the MVP 0.1 release (0.1.3, npm dist-tag latest). Until 1.0, minor versions may change APIs.

Guarantees

  • Atomicity. One commit() is one readwrite transaction over every object store. The Control Head compare-and-set is read inside it, and any failure aborts the whole transaction: every write or none.
  • Durability. Every readwrite transaction asks for durability: "strict" (Chromium's default is relaxed), and every promise resolves only on the transaction's complete event.
  • Sequences. A reservation reads its counter, checks it against this Principal's own stored units or Snapshots, and writes it, all in one strict transaction. A counter behind them fails closed with SEQUENCE_REUSE. A value is returned only after its transaction completed, and only after onReserved returned. If onReserved throws, the value is abandoned and never reissued.
  • Exact bytes. Control Records, Data Units, Key Packages and Snapshots are stored as their exact bytes; the other fields are indexes. Storing an ID again with other bytes fails the batch. Values come out as frozen copies.
  • No foreign awaits. A transaction awaits only IndexedDB requests, so it cannot auto-commit half way.

counters() lists the reservation counters (actor:<resource>:<principal>, snapshot:<resource>:<epoch>:<publisher>). meta.get/meta.put keep small, durable application metadata, such as an install marker. Never put secrets there: secrets belong in a SecretStore.

Limits

  • Strict durability is the runtime's promise, not ours. The tests run on fake-indexeddb (6.2.5, a test dependency only). The tests check that every readwrite transaction asks for strict, but they cannot show that a real browser flushed to disk. How durable the data is depends on the browser's IndexedDB implementation and the device's storage.
  • Eviction. Browsers may evict IndexedDB under storage pressure unless the origin's storage is persistent. Applications should call navigator.storage.persist() and tell the user when it is denied. An evicted database loses the sequence counters, so the application must not keep writing as the same Principal (for example, check an install marker kept elsewhere).
  • One writer. IndexedDB transactions serialize the reservations, but two application instances writing the same database is not a supported configuration. Hold a Web Lock (navigator.locks) for the lifetime of the writer.
  • Plaintext. Profile checkpoints are plaintext CRDT state. They are protected at rest only by the runtime's profile directory.

Links

License

Apache-2.0. See LICENSE.