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

@12-apps/wiring

v1.16.0

Published

The package-to-host wiring contract: a producer half for packages (capability manifests — HTTP routes, job blueprints, MCP tools with annotations, permissions, notification blueprints, mailers, Prisma partials, web surfaces) and a consumer half for hosts

Readme

@12-apps/wiring

The package-to-host wiring contract. A producer half for packages — declare what you provide and what you require, per capability — and a consumer half for hosts — adopt the declarations, bind each one against shared ports, and get one ordered, conflict-checked, reported aggregate back.

Zero dependencies. Every capability shape is a structural twin of a seam a package in this repo already ships, so adopting the contract is declaring what already exists, not rewriting it.

The problem

Every @12-apps/* package already follows the same implicit plugin shape — createApi*(config) → { routes }, createWeb*(config) → { page, … }, a ./hono adapter, a Prisma partial, sometimes ./mcp or job blueprints. But the shape lives in TypeScript conventions and per-package ADOPTING.md files, so:

  • every host rediscovers each package's contract by reading it;
  • the origin host wires ~24 packages through hand-written surface files, route files, nav files, icon files, badge files and policy tables;
  • shapes that must stay identical across packages (JobBlueprint vs PaymentsJobBlueprint) are kept identical by convention, with no compile check anywhere;
  • a version bump that adds a capability arrives silently: report-builder 5.x shipped three working-copy endpoints its own client calls, and the origin host never mounted them — the editor's autosave 404s and nothing is red;
  • packages that should notify or mail cannot say so: there is no notify port at all, and the only email port lives inside another package's server entry.

The model

        PRODUCER (the package)                CONSUMER (the host)
  ┌──────────────────────────────┐      ┌────────────────────────────────┐
  │ <pkg>/manifest               │      │ createWiringHost({name, kind,  │
  │   defineManifest({           │      │                   ports})      │
  │     name, contract: 1,       │      │                                │
  │     permissions, mcp,        │──────▶ .adoptServer({manifest,        │
  │     notifications, db, e2e,  │      │    server, bindings})          │
  │     server: ['http','jobs'], │      │ .adoptWeb({manifest, web,      │
  │     web: ['surface','areas'] │      │    bindings})                  │
  │   })                         │      │                                │
  │ <pkg>/manifest/server        │      │ .assemble() ──▶ routes, jobs,  │
  │   defineServerManifest(...)  │      │    mailers, surfaces,          │
  │ <pkg>/manifest/web           │      │    permissions, notifications, │
  │   defineWebManifest(...)     │      │    mcpEndpoints, db, areas,    │
  └──────────────────────────────┘      │    report                      │
                                        └────────────────────────────────┘

Three manifests per package because bundles are physics: the shared manifest is data every runtime can hold; the server manifest carries the createApi* factory and job blueprints; the web manifest carries the createWeb* factory. The shared manifest inventories the other two, and that inventory is the integrity mechanism: the producer refuses a runtime manifest that drifts from it, and a host that adopts a manifest without answering an inventoried capability gets a red assemble() naming the package and the capability.

Every declared capability must be bound or declined with a written reason. Declining is legitimate — a harness with no worker declines jobs — but silence is not: assemble() throws while anything is unanswered. That is what turns "the bump shipped a capability the host never wired" from a silent 404 into a build failure.

Capabilities

| kind | producer declares | consumer binds with | aggregate | |---|---|---|---| | http | create(config) → { routes } — the existing createApi* factory | { mountPath, config } | routes, specificity-ordered, conflict-checked | | jobs | namespace + dep-free blueprints (twin of @12-apps/jobs' JobBlueprint) | { deps } | jobsJobDefinition twins; jobs.map(defineJob) and done | | email | createMailer(port) → mailer (the createAuthMailer pattern) | { port? } (defaults to the host port) | mailers[pkg] | | mcp | WireMcpTool[]McpEndpoint plus annotations | collected; host-built vocabulary tools join via mcpEndpoints | mcpEndpoints, uniqueness-checked | | permissions | an rbac-shaped contribution (source, ids, permissions, labels) | collected | permissions — feed composePermissions | | notifications | blueprints: type, suggested category, generate | collected | notifications — feed the notifications mount | | db | the Prisma partial + migrations paths | collected | db — feed the sync tooling | | surface | create(config) → surface — the existing createWeb* factory | { config } | surfaces[pkg], built once (the memoisation rule, held in one place) | | areas | route/nav/gate suggestions per host area | collected | areas — project nav from data | | e2e | the journeys' entry subpath | collected | in the report |

Ports (@12-apps/wiring/ports)

What a host provides once, for every package to require: EmailPort (the EmailDriver shape, verbatim), NotifyPort (new — emit a typed notification event; never throws), LoggerPort, JobsEnqueuePort (never throws), ClockPort. Memory reference implementations ship for tests.

What stays host-owned

The contract deliberately moves no decision that is host vocabulary today: every user-facing sentence (pt-BR copy arrives as config, exactly as report-builder 4.0 inverted it), guards and actor resolution, plan gates, nav placement/labels/icons, MCP operation ids and summaries for vocabulary-driven tools, the RBAC catalog assembly, and the database itself. The contract makes each of those a named, typed, refusable argument instead of a convention.

Example

See src/__tests__/fixture-package.ts for a complete producer, and src/__tests__/consumer.test.ts for both host kinds. The short version:

// host (API server)
import { createWiringHost } from "@12-apps/wiring/consumer";
import { defineJob } from "@12-apps/jobs";

const host = createWiringHost({ name: "web", kind: "server", ports: { email } });
host.adoptServer({
  manifest: notesManifest,
  server: notesServerManifest,
  bindings: {
    http: { mountPath: "/api/admin/:tenantSlug", config: { store } },
    jobs: { deps: { store, ran } },
    email: {},
  },
});
const wired = host.assemble();          // throws while anything is unanswered
wired.jobs.map((job) => defineJob(job)); // every adopted package's jobs, one line
console.log(renderWiringReport(wired.report));

Hosts that must keep one route file per endpoint (coverage gates read guards out of route files) still adopt: they mount by hand and pin unclaimedRoutes(wired.routes, claimedKeys) to [] in a unit test, which is the test that would have caught the working-copy 404.

Status

Released: the package is in release-packages.txt (first — it has no dependencies) and @12-apps/report-builder is the first producer, adopted by the consumer harness. The RFC and the per-package adaptation report live in docs/wiring/.