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

resource-machine

v0.5.0

Published

ResourceMachine - WebMachine for NodeJS

Readme

ResourceMachine

HTTP decision machine for API gateways and microservices — Node.js port of Webmachine

npm version


HTTP is not just if (req.method === 'GET'). A production API has to get dozens of things right: content negotiation, conditional requests, ETags, caching headers, authorization, correct 4xx/5xx codes for every edge case. Most frameworks leave all of that to you, and most implementations get it quietly wrong.

ResourceMachine implements the full Webmachine v3 HTTP decision diagram — roughly 40 decision points that correctly model HTTP semantics. You describe your resource; the machine handles the protocol.

Who it's for

ResourceMachine is designed for engineers building API gateways and microservices — backends where HTTP correctness matters and separation of concerns reduces bugs. It is not a web application framework and does not try to be.

If your service needs to:

  • Return different representations based on Accept headers
  • Respect If-None-Match / If-Modified-Since for cache validation
  • Handle PUT / DELETE / PATCH with correct precondition checking
  • Enforce authorization and permission rules per endpoint
  • Do all of the above correctly, every time, without repeating yourself

…ResourceMachine handles the HTTP layer so you handle the business logic.

How it works

You define a Resource class per endpoint. Override only the methods relevant to that endpoint — everything else falls back to safe HTTP defaults. The decision machine instantiates your class per request and walks the diagram, calling your methods at the right moment.

import { createServer, Resource } from "resource-machine";

class ArticleResource extends Resource {
  private article: Article | null = null;

  // Which HTTP methods are allowed?
  override async allowedMethods() {
    return ["GET", "HEAD", "PUT", "DELETE"];
  }

  // Does this resource exist? Fetch it once, cache on `this`.
  override async resourceExists() {
    this.article = await db.find(this.req.params.id);
    return this.article !== null;
  }

  // Serve it — article already fetched above, no second DB call.
  override async contentTypesProvided() {
    return {
      "application/json": () => JSON.stringify(this.article),
    };
  }

  // Accept a PUT body.
  override async contentTypesAccepted() {
    return {
      "application/json": async () => {
        const body = JSON.parse((await this.req.getBody()).toString());
        this.article = await db.update(this.req.params.id, body);
        return true;
      },
    };
  }
}

const server = createServer({ name: "articles-api" });
server.addRoute("/articles/:id", ArticleResource);
await server.listen(3000);

The machine takes care of: 404 when resourceExists() is false, 405 for disallowed methods, 406 when no content type matches, 412 on failed preconditions, 304 for unmodified resources — all without you touching a status code.

Requirements

  • Node.js 22.0.0 or later
  • TypeScript (optional but strongly recommended)

Installation

npm install resource-machine

Documentation

Full documentation at jongretar.github.io/ResourceMachine.

Examples are in examples/.

License

MIT — Copyright © 2026 Jón Grétar Borgþórsson