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/webrun-files-mem

v0.10.3

Published

In-memory FilesApi implementation

Readme

@statewalker/webrun-files-mem

What it is

MemFilesApi, an implementation of FilesApi from @statewalker/webrun-files that keeps every file and directory in a Map in memory. Nothing persists after the instance is dropped.

Why it exists

Tests, prototypes and short-lived caches need a file system that starts empty (or pre-filled), needs no disk, no cleanup and no permissions, and behaves like every other backend. Because it passes the same shared test suites as the Node, browser, S3 and SQLite backends, code tested against it behaves the same when the backend is swapped.

How to use

pnpm add @statewalker/webrun-files-mem @statewalker/webrun-files

One entry point, @statewalker/webrun-files-mem: ESM (dist/esm/index.js), CommonJS (dist/cjs/index.cjs), types (dist/index.d.ts); sources in src/. Runs anywhere: browsers, workers, Node.js.

import { MemFilesApi, type MemFilesApiOptions } from '@statewalker/webrun-files-mem';

const files = new MemFilesApi(); // or new MemFilesApi({ initialFiles: { ... } })

MemFilesApiOptions has one field, initialFiles?: Record<string, string | Uint8Array>: paths mapped to content. Strings are encoded as UTF-8; parent directories are created.

Examples

Write, read, list

import { MemFilesApi } from '@statewalker/webrun-files-mem';
import { readText, writeText } from '@statewalker/webrun-files';

const files = new MemFilesApi();
await writeText(files, '/config.json', '{"debug": true}');
console.log(await readText(files, '/config.json')); // {"debug": true}

for await (const entry of files.list('/')) {
  if (entry.kind === 'file') console.log(entry.name, entry.size, entry.lastModified);
  else console.log(entry.name, 'directory'); // directories carry no size or time
}

Start with files

const files = new MemFilesApi({
  initialFiles: {
    '/config.json': '{"theme": "dark"}',
    '/data/users.json': '[{"id": 1, "name": "Alice"}]',
    '/data/binary.bin': new Uint8Array([0x00, 0x01, 0x02, 0x03]),
  },
});

A fresh file system per test

import { beforeEach, expect, it } from 'vitest';
import { MemFilesApi } from '@statewalker/webrun-files-mem';
import { readText, writeText } from '@statewalker/webrun-files';

let files: MemFilesApi;
beforeEach(() => {
  files = new MemFilesApi({ initialFiles: { '/config.json': '{"version": 1}' } });
});

it('updates the config', async () => {
  await writeText(files, '/config.json', '{"version": 2}');
  expect(JSON.parse(await readText(files, '/config.json')).version).toBe(2);
});

Internals

One map of normalized paths

Each entry is keyed by its normalized path and is either a file (its bytes and a timestamp) or a directory. write collects all chunks and stores one Uint8Array; read yields one chunk, a subarray of the stored bytes clipped to start/length.

What it costs, and what to watch

  • list() scans every entry. Each call walks the whole map, keeps the entries under the directory, sorts them with comparePaths and then applies after. Cost grows with the total number of entries, not with the size of the listed directory.
  • Shared buffers. A Uint8Array passed in initialFiles is stored as is, and the chunk read() yields is a view of the stored bytes. Mutating either changes the stored file. Copy first if you need to modify them.
  • move is copy then remove, in memory, so it is cheap but not atomic against concurrent calls on the same instance.
  • Everything lives in the JavaScript heap; a large file costs its size in memory.

Dependencies

@statewalker/webrun-files only, for the types, normalizePath, basename and comparePaths.

License

MIT