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

@app-studio/qa-core

v0.5.0

Published

The bindings contract every other @app-studio/qa package reads: schema, loader, cross-process lock, command runner and the default layer stack.

Readme

@app-studio/qa-core

The contract every other @app-studio/qa package reads.

A host repository declares its QA facts once, in qa.bindings.json at its root: which commands exist, which layers the test suite is made of, where the tests and seeds live, which ports the apps bind, which accounts the seeds create. The runner, the hooks and the doctor read that file at execution time. Nothing is copied into the host and left to go stale.

That rule is not stylistic. A QA system copied from one repository into another without its bindings rewritten produces a guard whose patterns match no file — it denies nothing while looking exactly like a guard with nothing to complain about. @app-studio/qa-doctor exists to make that state impossible; this package is the contract it checks against.

What is here

| Export | Purpose | | --- | --- | | bindingsSchema, QaBindings | The zod schema and its types. strict() throughout: an unknown key is an error, because a typo that silently does nothing is how a binding becomes a lie. | | loadBindings, findBindingsFile | Walk up from any directory to the repository root and validate. Returns failure as data so the doctor can report it instead of crashing. | | acquireLock, withLock | A cross-process lock keyed by checkout. Atomic creation; a stale lock is reported, never auto-deleted. | | runCommand, startBackground | Command execution with signal forwarding and SIGTERM→SIGKILL shutdown. | | waitForUrl, ensurePortFree, isPortFree | Readiness and port hygiene for orchestrating servers. | | DEFAULT_LAYERS, selectLayers, runLayers, describeLayers | The layered walk: bottom-up, stop at the first break, say what was not run and why. | | Rule, Finding, DoctorContext | The doctor's plugin contract, here so packages can contribute rules without depending on the doctor. |

The bindings file

{
  "$schema": "./node_modules/@app-studio/qa-core/schema/qa.bindings.schema.json",
  "version": "2",
  "repo": { "name": "my-app" },

  // The canonical registry. Layers, gates and docs reference the KEYS, never
  // the shell strings, so "what this repository runs" is written down once.
  "commands": {
    "typecheck": "pnpm typecheck",
    "test.unit": "pnpm vitest run --project unit",
    "test.integration": "pnpm vitest run --project integration",
    "test.e2e": "pnpm playwright test",
    "seed.apply": "pnpm seed",
    "seed.check": "pnpm seed:check"
  },

  // Bottom-up. `qa run` stops at the first break.
  "layers": [
    {
      "key": "logic",
      "title": "Pure logic",
      "restsOn": "nothing — no database, no application",
      "means": "a sanitiser or a validator is wrong. Nothing above can be trusted.",
      "commands": ["test.unit"]
    }
  ],

  "paths": { "seeds": "src/features/*/seed/index.ts", "tests.e2e": "tests/e2e" },
  "ports": { "api": { "port": 3000, "boundBy": "playwright.config.ts" } },
  "seedAccounts": [
    { "role": "ADMIN", "email": "[email protected]", "password": { "kind": "seeded-constant", "value": "password123456" } }
  ]
}

restsOn and means are not decoration. qa run --list prints them, and a broken layer prints its own means next to the list of layers it did not run — so a red run says which floor is broken and why the floors above it were skipped, instead of five hundred failures that are one bug wearing different names.

The lock, in three decisions

  1. Keyed by checkout, hashing the repository root into the lock filename, so two worktrees of the same project seed concurrently and two shells in the same checkout do not.
  2. Atomic creation (open(path, 'wx')). Check-then-create leaves a window in which both contenders believe they won.
  3. A stale lock is reported, never removed automatically. Two waiters can both observe a dead holder and both delete the file — and the second delete evicts a lock the first has just legitimately taken. The error names the holder and prints the rm command; a human decides.

Requirements

Node.js 20 or newer.