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

@versioned-store/core

v0.1.0-alpha.0

Published

Embedded-first, storage-portable, immutable-versioned config primitive with an eval-gate coupled to promote. Arbitrary payload T; SQLite/File/InMemory/Postgres/Mongo/Redis backends.

Downloads

120

Readme

@versioned-store/core

An embedded-first, storage-portable, immutable-versioned config primitive with an eval-gate coupled to promote. One small core (createVersionedStore<T>) sits over an eight-method backend contract, with SQLite as the zero-config default plus InMemory, File, Postgres, Redis, and Mongo adapters.

npm install @versioned-store/core

What it is

A production override layer for any payload T, not a version-control toy:

  • Immutable versions. addVersion never overwrites; the new version is max + 1.
  • A movable label pointer. promote flips active (also staging, canary, shadow); rollback flips it back.
  • A code-default fallback. An in-code sentinel (version 0) is served when the label or version is missing, or when the backend is unreachable, under a per-domain null-vs-throw policy, so the store is never a hard dependency.
  • An eval-gate coupled to promote. A failing candidate is refused at the pointer flip, so a bad edit sits inactive and never goes live.
  • Observability. A versioned event schema (fallback, gate-outcome, promote-accepted, promote-refused) with a per-type counter.
  • Domain-agnostic. The payload T maps via toDoc / fromDoc; hash, validate, and the missing-policy are injected. The core has no if (domain === ...) branch.

The defensible thing is the runtime pairing, not any single piece. See Honest positioning.

Quickstart on SQLite (under five minutes)

import { createVersionedStore } from "@versioned-store/core";
import { createSqliteBackend } from "@versioned-store/core/backends/sqlite";

const store = createVersionedStore<{ text: string }>(
  {
    domain: "greeting",
    defaults: { hello: { text: "Hello!" } },
    hash: (v) => v.text,
    toDoc: (v) => ({ text: v.text }),
    fromDoc: (d) => (typeof d.text === "string" ? { text: d.text } : null),
  },
  createSqliteBackend("./greetings.db"),
);

const v1 = await store.addVersion("hello", { text: "Hi there!" });
await store.promote("hello", v1);
const active = await store.resolve("hello"); // { version: 1, value: { text: "Hi there!" } }

The backend is always injected: the store never constructs one, so it carries no backend-specific dependency.

Entry points

The main entry is dependency-free and works on Node 18. Anything that needs a driver is a subpath, so importing the core never loads node:sqlite, pg, or mongodb:

| Import | Requires | |---|---| | @versioned-store/core | nothing (Node 18+) | | @versioned-store/core/backends/sqlite | node:sqlite (Node 22+) | | @versioned-store/core/backends/postgres | pg | | @versioned-store/core/backends/mongo | mongodb | | @versioned-store/core/conformance | nothing | | @versioned-store/core/cli | node:sqlite (Node 22+) |

InMemory, File, and Redis (an injected client) are driver-free and export from the main entry.

Consuming the store: the rule of one construction site

Wire the store ONCE at a composition root and export a typed façade. Every other file in your app imports from that façade, never from @versioned-store/core directly:

// src/config/prompts.ts — the one construction site
import { createVersionedStore, setStoreLogger } from "@versioned-store/core";
import { createPostgresBackend } from "@versioned-store/core/backends/postgres";
import { logger, pool } from "../infra.js";

setStoreLogger(logger); // inject your pino-compatible logger once
const prompts = createVersionedStore<Prompt>(promptCfg, createPostgresBackend(pool));

// the typed façade the rest of your app imports
export const resolvePrompt = (key: string) => prompts.resolve(key);
export const promotePrompt = prompts.promote;

This makes every future upgrade (additive or BREAKING) a one-file change on your side: fifty call sites become one file to touch. Do not leak the backend's internal shapes across the façade; expose only the intent-revealing verbs (resolve / addVersion / promote / listVersions).

Backends

| Backend | Factory | Notes | |---|---|---| | InMemory | createInMemoryBackend() | reference implementation; tests and backend-less runs | | SQLite | createSqliteBackend(path) | built-in node:sqlite (Node 22+); subpath import | | File | createFileBackend(dir) | zero-dependency, durable; wx-flag immutability | | Postgres | createPostgresBackend(pool) | inject a pg Pool; subpath import | | Redis | createRedisBackend(client, prefix) | inject an ioredis-like client; atomic Lua insert | | Mongo | createMongoBackend(getDb, vColl, lColl) | inject a () => Promise<Db>; subpath import |

Every backend passes the same conformance suite: the immutability and compare-and-swap contract is identical across all of them.

Eval-gate ladder (three tiers)

  • Tier 1 deterministic: render, parse, and schema checks, fully offline. The domain supplies the predicate.
  • Tier 2 golden-output (goldenOutputGate): render the candidate over golden inputs, then run promptfoo-style assertions on the output. Offline.
  • Tier 3 LLM-judge (llmJudgeGate): score the output through an injected judge; skipped gracefully when no provider is configured. Pin the judge model version (calibration note in evalGate.ts).

buildGate(config) composes any subset of the three; promote({ gate }) awaits it.

Portability and rollout

  • Migration (migrate): a portable bundle moves between any two backends, verified by content hash.
  • Sealed bundles (bundle): a single-object, content-addressed, optionally HMAC-signed export; tampering is detected on import.
  • Canary and shadow (canary): weighted resolution plus gate-driven auto-rollback. A failing canary is demoted to the last-known-good and alarmed, embedded, with no hosted service.
  • CLI (npx versioned-store <verb> ...): keys, versions, get, label, promote, rollback, export, import, migrate.

Certifying a new backend

Implement the VersionedStoreBackend contract (backend.ts, eight methods), then run the same suite this repo runs against its own adapters:

import { runConformance } from "@versioned-store/core/conformance";

runConformance("MyBackend", () => makeMyBackend());

If it is green, the adapter honours immutability, compare-and-swap, version ordering, and labels.

Honest positioning

Several properties here are not novel, and the positioning concedes each:

  • Immutable versions of an arbitrary payload: AWS AppConfig already has this.
  • A movable pointer: SSM labels, Dolt branches, and MLflow aliases already have this.
  • A deploy-time gate: AppConfig validators, Langfuse eval-before-production, and LaunchDarkly approvals already have this; the schema-registry compatibility checks (Buf, Confluent) even run offline.

The claim is only the runtime bundle: the eval-gate coupled to promote so bad edits cannot go live, plus the code-default or offline fallback so the store is never a hard dependency, both over arbitrary T, embedded-first with SQLite by default. A reviewer should not be able to point to a single over-claim.

Domain packages

@versioned-store/prompt-store and @versioned-store/scaffold-store are batteries-included domain stores built on this core. They are worked examples of the pattern: payload shape, rendering, and a domain gate on top; policy and storage below.

MIT.