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

@tpgames/sdk-dev-kit

v0.3.0

Published

Local authoring tools for games built with `@tpgames/game-kit` and `@tpgames/sdk`.

Readme

@tpgames/sdk-dev-kit

Local authoring tools for games built with @tpgames/game-kit and @tpgames/sdk.

The package includes:

  • a standalone multi-surface browser workbench for normal npm run dev use
  • an in-memory harness for focused unit tests
  • deterministic network-fault helpers for repeatable latency and reconnect tests
  • the tpgames CLI for project initialization, physical-device development, source-boundary checks, registry bundle assembly, authentication, and publication

Author delivery CLI

Detached game repositories describe delivery inputs in tpgames.json and use the package binary directly:

{
  "game": {
    "id": "signal-rally",
    "version": "1.0.0",
    "title": "Signal Rally"
  },
  "bundle": {
    "manifest": "bundle/manifest.template.json",
    "output": "dist",
    "clean": false,
    "copies": []
  }
}
tpgames init signal-rally
tpgames check-boundaries
tpgames dev --devices
tpgames bundle
tpgames login
tpgames whoami
tpgames register

tpgames init <target-dir> creates the same renderer-neutral canonical starter as npm create @tpgames/game@latest. A kebab-case directory name becomes the default game ID and display title; explicit identity flags are also available. The command requires a target path that does not already exist. The project includes local and physical-device workflows, CI, and a standalone TP Games development skill.

The bundle command renders the configured manifest, applies any explicit copy rules for framework or engine assets, and writes dist/<game-id>-<version>.zip. The CLI defaults to the production registry at https://tpg-registry.tp-games.workers.dev and accepts --registry-url or TPG_REGISTRY_URL for an explicit staging or loopback registry. Registration uploads a game version; it does not register a developer account. It defaults to the safe upload mode. Use --mode submit, or use --mode publish --yes when publication is the intended result.

For interactive development, run tpgames login. The CLI prints a short code, opens the TP Games approval page, and saves an origin-scoped session in the operating system's user configuration directory only after you explicitly approve it. Use tpgames whoami to verify the saved session and tpgames logout to revoke it remotely and remove the local copy. Pass --no-open to login when you want to open the printed URL yourself.

Production and loopback approval pages open automatically after strict URL and code validation. For a custom HTTPS registry, the CLI prints the URL without opening it unless you explicitly trust its shell with --approval-origin https://shell.example.com or TPG_APPROVAL_ORIGIN. The configured origin must exactly match the registry response.

tpgames register uses TPG_API_KEY first when it is set, then the saved session for the exact registry origin. Keep TPG_API_KEY for CI and other non-interactive environments; secrets are deliberately not accepted as command arguments or project configuration. Use tpgames logout --local-only only when the registry is unreachable and you intentionally cannot revoke the remote session. Browser-created CLI sessions expire after 90 days and can be revoked earlier from the CLI or creator portal.

Routine values have command-line flags, so local use does not require temporary environment variables:

tpgames bundle \
  --game-id signal-rally \
  --game-version 1.1.0 \
  --game-title "Signal Rally" \
  --output-dir dist

tpgames register \
  --game-id signal-rally \
  --game-version 1.1.0 \
  --mode submit

Flags override matching TPG_* environment variables, which override tpgames.json. Run tpgames help bundle or tpgames help register for the complete option list.

Saved sessions are isolated by normalized registry origin. Signing in to a loopback or staging registry does not expose that credential to production, and changing --registry-url requires a separate login.

Multi-surface workbench

Add the public Vite plugin to your game repository:

import { tpgWorkbench } from "@tpgames/sdk-dev-kit/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    tpgWorkbench({
      title: "Signal Rally",
      surfaces: {
        host: "/host.html",
        controller: "/controller.html",
        spectator: "/spectator.html",
      },
      controllers: 2,
      spectator: true,
    }),
  ],
});

Then run:

npm run dev

Vite opens /__tpg/workbench. The workbench mounts one host display, one to sixteen configurable controllers, and an optional spectator. It provides:

  • lifecycle, readiness, settings, join/leave, reconnect, and authority controls
  • canonical shared state, per-player state, and transient message inspection
  • a searchable, pausable, exportable bridge log capped at 500 entries
  • seeded latency, jitter, packet-loss, and reconnect simulation
  • responsive surface previews with the same public iframe/runtime bridge used by packaged games
  • independent 50–125% zoom controls for seeing more or less of each surface
  • live pop-out windows that stay synchronized with the embedded workbench session

The browser workbench renders its visible interface with React. Session orchestration, iframe messaging, pop-out lifecycle, and other browser effects remain behind focused adapters, so author projects continue to use the same Vite plugin and mount API.

Physical devices without an upload

With the Vite plugin configured, start a real shell room backed by the current local source:

tpgames dev --devices

The command starts Vite on loopback, creates a temporary Cloudflare Quick Tunnel, and opens a host URL on https://play.tp.games. Scan the room QR from one or more phones; controllers and spectators receive the same validated development manifest through the host-authoritative room snapshot. No registry upload, API key, or package build is involved.

Install cloudflared first, or provide a tunnel you manage:

cloudflared tunnel --url http://127.0.0.1:5173
tpgames dev --devices --port 5173 --public-url https://random-name.trycloudflare.com

For a named tunnel, configure its public hostname to forward to http://127.0.0.1:5173, run cloudflared tunnel run <name>, then pass that hostname with --port 5173 --public-url https://game-dev.example.com. The port must match the tunnel origin. When --public-url is present, tpgames does not start, own, or stop that tunnel.

Use --shell-url for a local or preview shell, --port to choose the Vite port, and --no-open in headless environments. Each room's development selection expires eight hours after launch, uses an unguessable one-run manifest descriptor, and runs with the unreviewed iframe capability policy. Treat the generated host link as private because it contains that descriptor. Quick Tunnel URLs expose the Vite server and source modules publicly, so share only the shell's room QR or controller invite, keep .env files, credentials, and private assets outside Vite's served root, and stop the command and tunnel when testing is finished. By default the host link opens automatically. With --no-open, open the printed host link; the QR and device invite appear after that host connects and creates the room.

Controller definitions can supply stable IDs and names:

tpgWorkbench({
  title: "Signal Rally",
  surfaces: { host: "/host.html", controller: "/controller.html" },
  controllers: [
    { id: "blue-team", screenName: "Blue Team" },
    { id: "gold-team", screenName: "Gold Team" },
  ],
  networkProfile: {
    latencyMs: 80,
    jitterMs: 20,
    lossRate: 0.02,
    reconnectDelayMs: 1500,
    seed: 42,
  },
});

The simulator is host-authoritative and exercises public bridge contracts, but it does not replace final packaged-bundle verification. Use it for the fast author loop, use dev --devices for real transport and device input, then verify the uploaded bundle paths and reviewed permissions before publishing.

In-memory harness

Use the root export for lifecycle and state unit tests without a browser:

import {
  createFakeParticipants,
  createGameDevHarness,
} from "@tpgames/sdk-dev-kit";
import game from "./game";

const harness = createGameDevHarness({ game });
harness.pushParticipants(createFakeParticipants(["Casey", "Riley"]));
harness.pushLifecycle("started");
harness.pushSharedState({ round: 1 });

The lower-level createWorkbenchSession export is also available for tooling that needs to orchestrate several public bridge adapters without mounting the built-in interface.