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

@statewalker/vcs-store-mem

v0.3.2

Published

In-memory storage backend for StateWalker VCS

Readme

@statewalker/vcs-store-mem

In-memory implementations of the StateWalker VCS store interfaces: Git objects (blobs, trees, commits, tags), refs, the staging area (index), and raw/delta binary storage. Everything lives in JavaScript Maps and arrays and disappears with the instance.

Why it exists

Code built on @statewalker/vcs-core and @statewalker/vcs-working-tree takes stores as interfaces. Tests, examples and short-lived operations need an implementation of those interfaces with no disk, no database and no setup. This package is that implementation. It is also the reference behavior: the shared conformance suites in @statewalker/vcs-testing run against it and against the persistent backends, so a difference between them points to a bug.

How to use

pnpm add @statewalker/vcs-store-mem

No peer dependencies. Runs anywhere modern JavaScript runs (browser, Node, workers).

| Entry point | Gives | | --- | --- | | @statewalker/vcs-store-mem | Everything listed below |

| Export | What it is | | --- | --- | | createMemoryObjectStores(options?) | { objects, blobs, trees, commits, tags } with Git-compatible SHA-1 ids, backed by a MemoryRawStorage. Pass { storage } to reuse an existing one. | | MemoryStagingStore | In-memory Staging (the index): entries, conflict stages, builder/editor, readTree/writeTree. | | MemoryRefStore | In-memory Refs (re-exported from @statewalker/vcs-core). | | MemoryRawStorage | In-memory RawStorage key/bytes map (re-exported from @statewalker/vcs-core). | | MemoryCommitStore, MemoryTreeStore, MemoryTagStore | Object-map Commits / Trees / Tags. Ids are not Git ids (see Internals). | | MemBinStore, createMemBinStore() | BinStore combining a MemoryRawStorage and a MemDeltaStore. | | MemDeltaStore | DeltaStore that records base/target delta relationships. |

Use createMemoryObjectStores() when ids must match what git produces (interop, transport, pack tests). Use the Memory*Store classes only where any stable, content-derived id is enough.

Examples

Git-compatible object stores, refs and staging

import { FileMode } from "@statewalker/vcs-core";
import {
  createMemoryObjectStores,
  MemoryRefStore,
  MemoryStagingStore,
} from "@statewalker/vcs-store-mem";

const stores = createMemoryObjectStores();
const refs = new MemoryRefStore();
const staging = new MemoryStagingStore();

// The real Git SHA-1 of "hello\n"
const blobId = await stores.blobs.store([new TextEncoder().encode("hello\n")]);
// -> "ce013625030ba8dba906f756967f9e9ca394464a"

await staging.setEntry({ path: "README.md", mode: FileMode.REGULAR_FILE, objectId: blobId });
const treeId = await staging.writeTree(stores.trees);

const who = { name: "Ada", email: "[email protected]", timestamp: 1700000000, tzOffset: "+0000" };
const commitId = await stores.commits.store({
  tree: treeId,
  parents: [],
  author: who,
  committer: who,
  message: "init\n",
});

await refs.set("refs/heads/main", commitId);
await refs.setSymbolic("HEAD", "refs/heads/main");
const head = await refs.resolve("HEAD"); // { name: "refs/heads/main", objectId: commitId, ... }

Fresh, isolated stores per test

import { beforeEach, expect, it } from "vitest";
import { createMemoryObjectStores, type MemoryObjectStores } from "@statewalker/vcs-store-mem";

let stores: MemoryObjectStores;
beforeEach(() => {
  stores = createMemoryObjectStores(); // nothing is shared between instances
});

it("stores a blob", async () => {
  const id = await stores.blobs.store([new TextEncoder().encode("test")]);
  expect(await stores.blobs.has(id)).toBe(true);
});

Object-map stores (fast, non-Git ids)

import { MemoryCommitStore, MemoryTreeStore } from "@statewalker/vcs-store-mem";

const trees = new MemoryTreeStore();
const commits = new MemoryCommitStore();

const treeId = await trees.store([]); // empty tree: "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
const who = { name: "Ada", email: "[email protected]", timestamp: 1700000000, tzOffset: "+0000" };
const c1 = await commits.store({ tree: treeId, parents: [], author: who, committer: who, message: "a" });
const c2 = await commits.store({ tree: treeId, parents: [c1], author: who, committer: who, message: "b" });

await commits.isAncestor(c1, c2); // true
for await (const id of commits.walkAncestry(c2)) console.log(id); // c2, then c1

Binary storage with deltas

import { createMemBinStore } from "@statewalker/vcs-store-mem";

const bin = createMemBinStore();
await bin.raw.store("base", (async function* () {
  yield new TextEncoder().encode("hello world");
})());

const update = bin.delta.startUpdate();
await update.storeDelta({ baseKey: "base", targetKey: "target" }, [
  { type: "start", targetLen: 5 },
  { type: "copy", start: 0, len: 5 },
  { type: "finish", checksum: 0 },
]);
await update.close(); // deltas become visible only after close()

await bin.delta.isDelta("target"); // true
bin.clear();

Internals

Two kinds of object stores, and why their ids differ

createMemoryObjectStores() serializes every object in Git format into a MemoryRawStorage and hashes it with SHA-1. It uses the same createGitObjectStore / createBlobs / createTrees / createCommits / createTags code as the persistent backends, so its ids match native Git.

MemoryCommitStore, MemoryTreeStore and MemoryTagStore keep plain JavaScript objects and skip serialization. Their ids come from computeCommitHash / computeTreeHash / computeTagHash in @statewalker/vcs-core: a 32-bit FNV-1a hash with a type prefix, zero-padded to 40 characters (commit2814e9b0000…, tree84b15896000…, tag…). They are deterministic and content-derived, but they are not Git ids. Do not mix them with ids from a Git-format store. The one exception is the empty tree, which MemoryTreeStore always reports as Git's 4b825dc642cb6eb9a060e54bf8d69288fbee4904. gpgSignature is stored but not hashed.

Copies in, copies out

The object-map stores deep-copy on store and on load, so mutating a returned commit, tree entry or tag never changes stored state. Tree entries are sorted in Git canonical order (directories compare as name/) before hashing.

Staging keeps entries sorted

MemoryStagingStore keeps entries in one array sorted by (path, stage) and looks them up by binary search. read(), write() and isOutdated() exist for interface compatibility; nothing is persisted.

What breaks

| Situation | Error | | --- | --- | | staging.writeTree() with conflict stages present | Cannot write tree with unresolved conflicts | | Builder add() without a mode | FileMode not set for path <path> | | Builder finish() with the same path and stage twice | Duplicate entry: <path> stage <n> | | Builder finish() with stage 0 next to stages 1-3 | Invalid stages for <path>: stage 0 cannot coexist with other stages | | resolveConflict() with an unknown resolution | Invalid resolution: <value> | | MemoryCommitStore.getParents() on a missing id | Commit <id> not found | | MemoryTagStore.getTarget(id, true) over more than 100 nested tags | Tag chain too deep (> 100) | | storeDelta() on an update after its close() | Update already closed |

Delta store limits

MemDeltaStore records which key is a delta of which base and keeps the delta instructions. The update's storeObject() does nothing: full objects belong in the raw store. Chain walks stop at depth 50. getDeltaChainInfo() always reports originalSize: 0, compressedSize is an estimate from the instruction list, and the stored ratio is 1 or 0. Do not use these numbers for packing decisions.

Dependencies

  • @statewalker/vcs-core: store interfaces, Git object codecs, MemoryRefStore, MemoryRawStorage, and the ancestry algorithms (walkAncestry, findMergeBase, isAncestor) that MemoryCommitStore delegates to.
  • @statewalker/vcs-working-tree: the Staging interface and merge-stage constants.
  • @statewalker/vcs-utils: the Delta type.

License

MIT