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

@react-text-game/devtools

v0.1.0

Published

Development-time CLI for React Text Game: detects whether a save migration is needed by diffing your game's save schema against a committed baseline

Readme

@react-text-game/devtools

Development-time CLI for React Text Game. It answers one question you cannot reliably answer by hand: does this release need a save migration?

bun add -d @react-text-game/devtools

The binary is rtg, and it runs under both Bun and Node:

bunx @react-text-game/devtools saves check
npx @react-text-game/devtools saves check

Why

A save stores the state of every registered entity, so changing that state's shape can break saves your players already have. Which changes are dangerous is not obvious:

| Change | What happens to an old save | Migration | | --- | --- | --- | | New field on an existing entity | Keeps its default, because loading merges over defaults | Not needed | | Removed field | Comes back as an unused variable | Not needed | | Renamed field | Value stranded under the old name | Needed | | A whole new entity | Variables are cleared, not defaulted | Needed | | Changed type | The game gets a value of the old type | Needed | | Removed or renamed passage | The save points at a passage that no longer resolves | Needed |

It also catches two failures that are invisible in a diff:

  • a shape change whose gameVersion was not bumped — migrations only run when a save's version differs from the current one, so nothing would migrate;
  • a deleted passage, which leaves old saves resolving to no passage at all, silently.

Usage

Export the version from the module you point the CLI at, so the tool and the running game read one value:

// src/game/registry.ts
export * from "./entities";
export * from "./stories";

export const gameVersion = "0.2.0";

Record a baseline once per release, and commit the file it writes:

rtg saves snapshot --entry src/game/registry.ts   # -> save-schemas/0.2.0.json

Then check on every commit:

rtg saves check --entry src/game/registry.ts

Exit codes make it a CI gate: 0 nothing to do (or a registered migration already covers the change), 1 a migration is required, 2 bad usage or an unreadable file.

Point --entry at a module that only registers entities and passages. The React entry point imports stylesheets and components, which cannot be loaded outside a browser.

Already shipped without a baseline?

The baseline is recoverable: every Game.init() writes a pristine copy of the default state into the browser under __SYSTEM_INITIAL_STATE__. Capture it from the production origin before deploying the new version, which overwrites it.

# from an IndexedDB row copied out of DevTools
rtg saves snapshot --from-dump system-save.json

# or from any exported save file
rtg saves snapshot --from-save backup.sx --game-id my-game

Both work under plain Node with no loader.

Limits

check is the thing that stops you forgetting, not proof of compatibility. It cannot see element types inside collections that were empty when captured, meaning changes at an identical shape (gold switching to minor units), or the difference between a field that was unset and one that was retyped. And it verifies only that a migration exists — never that it is correct.

Documentation

License

MIT