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

@hearthforge/plugin-sdk

v0.2.0

Published

Adapter interfaces, descriptor types and compliance tests every HearthForge game plugin implements

Readme

@hearthforge/plugin-sdk

The contract every HearthForge game plugin is written against. A plugin is one npm package that implements GamePlugin: seven adapters (compose, monitor, bootstrap, backup, auth, command, data), a manifest, optional modules and optional React UI. The panel and the agent know nothing about any specific game — everything game-specific lives in the plugin, and this package defines the seam. It also ships the compliance runner that checks a plugin against that seam, the build presets that produce the dist/ layout the panel loads, and the safe-command helpers (composeShell, execShell, envArg, …) that keep operator config out of shell text.

Install

pnpm add -D @hearthforge/plugin-sdk @hearthforge/shared zod

Node >= 22. Most of the package is types and pure functions, so a backend-only plugin needs no React.

Usage

Implement each adapter interface directly — the SDK ships interfaces, not base classes:

import type {
  ComposeAdapter,
  DockerComposeConfig,
  InstanceContext,
  PortRequirement,
  ResolvedModule,
  ValidationResult,
} from "@hearthforge/plugin-sdk";

export class MyGameComposeAdapter implements ComposeAdapter {
  constructor(private readonly ctx: InstanceContext) {}

  generateCompose(_config: unknown, _modules: ResolvedModule[]): DockerComposeConfig {
    return { services: { server: { image: "example/my-game:1.0", init: true } } };
  }

  getRequiredEnvVars() {
    return [];
  }

  validateConfig(_config: unknown): ValidationResult {
    return { valid: true };
  }

  getPortRequirements(): PortRequirement[] {
    return [{ containerRole: "server", port: 7777, protocol: "tcp", description: "my-game:ports.game" }];
  }
}

Then hold the whole plugin to the contract in your own test suite:

import { runAdapterComplianceTests } from "@hearthforge/plugin-sdk";
import MyGamePlugin from "./index";

const result = runAdapterComplianceTests(new MyGamePlugin(), mockCtx);
if (!result.passed) {
  throw new Error(result.checks.filter((c) => !c.passed).map((c) => `${c.id}: ${c.errors.join("; ")}`).join("\n"));
}

mockCtx is an InstanceContext whose config your validateConfig accepts. Pass { messages, packageJson, ui } as the third argument to switch on the i18n, package-manifest and UI-registration checks.

Subpath entries: @hearthforge/plugin-sdk/schemas (zod schemas for the package manifest and registry index), @hearthforge/plugin-sdk/build (the backendConfig / uiConfig vite presets), @hearthforge/plugin-sdk/relay-channel (the browser-safe relay frame policy).

The full walkthrough — package layout, every adapter, building, modules — is the plugin-authoring guide. Start a new plugin from the plugin-template repository; @hearthforge/plugin-reference is a complete plugin to read alongside it.

Peer dependencies

| peer | range | | |---|---|---| | @hearthforge/shared | the matching 0.x line | required | | zod | ^4.0.0 | required | | react | ^18.0.0 \|\| ^19.0.0 | optional — only for a plugin that ships UI | | @tanstack/react-query | >=5.0.0 <6 | optional — only for a plugin that ships UI |

A plugin's UI bundle never bundles React: the panel supplies its own copy through the host share scope (HOST_SHARED_MODULES), so the plugin's components run on the panel's one React. HOST_API_VERSION names the generation of that host API a bundle's register(host) is written against.

Versioning

Pre-1.0: a minor release may break the contract; a patch never does. Declare hearthforge.sdk in your package manifest as the range your plugin was built against, and the panel refuses to load a plugin outside it. Maintenance lines publish from release/X.Y branches under the release-X.Y npm dist-tag and never move latest — see Maintenance releases. Every release is listed in CHANGELOG.md.

License

Apache-2.0 — a plugin built against this contract does not inherit the panel's licence.

Links