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

@youneed/server-plugin-devtools

v0.1.0

Published

@youneed/server plugin: dev-time topology, OWASP security audit, OpenAPI generation and microbenchmarks — mounts a devtools UI on a live app.

Readme

@youneed/server-plugin-devtools

The analysis core behind the server devtools — a renderer-agnostic, serializable topology model plus the tools that operate on it: an OWASP-aligned security audit, an OpenAPI generator, and a microbenchmark. The browser UI (panels on @youneed/dom-ui-shad) builds on this; this package is the pure, testable data + analysis layer.

import { topology, externalServer, securityAudit, toOpenApi, microbench } from "@youneed/server-plugin-devtools";

const t = topology([
  { name: "api", middleware: ["cors", "helmet", "rate-limit"], routes: [/* … */] },
  externalServer({ name: "billing", url: "https://billing.acme.dev" }), // not behind our API
]);

securityAudit(t.servers[0]); // OWASP API Top 10 findings
toOpenApi(t.servers[0]);      // OpenAPI 3.1 document from route schemas
microbench(() => serialize(payload)); // ops/sec + p50/p99

| API | meaning | | --- | --- | | topology(servers) / mergeTopologies(...) | assemble / combine the topology model | | externalServer(info) | declare a server not served through our API | | securityAudit(server) | OWASP API-Security-Top-10 heuristics (auth, validation, rate-limit, BOLA, misconfig) | | auditGrade(findings) | roll findings up to pass / warning / error | | toOpenApi(server, opts?) | OpenAPI 3.1 document from routes + JSON schemas | | microbench(fn, opts?) / microbenchAsync | quick perf measurement (ops/sec, mean, p50, p99) |

Security audit (OWASP API Security Top 10, 2023)

Heuristics over the topology + the mounted @youneed/server-middleware-*:

  • API1 (BOLA) — an :id route with no guard → object-level-authorization hint.
  • API2 (broken auth) — a mutating route (POST/PUT/PATCH/DELETE) with no guard or auth middleware → error.
  • API3 (tampering) — a body-carrying route with no validation schema.
  • API4 (resource consumption) — no rate-limit / body-limit middleware.
  • API8 (misconfiguration) — no helmet / cors / https-redirect.

It's a fast first pass, not a substitute for a real review.

UI (@youneed/server-plugin-devtools/ui)

A <server-devtools> web component built on @youneed/dom-ui-shad renders the analysis core as tabs — Topology, Security, OpenAPI, Bench — using shad cards, tabs, badges, data-tables, inputs and buttons. Feed it a topology; add external servers from the UI; run the microbench on demand.

import "@youneed/server-plugin-devtools/ui";       // registers <server-devtools>
import { registerTailwind } from "@youneed/dom-ui-shad";
registerTailwind(tailwindCss);              // shad needs Tailwind + theme.css (document level)

const el = document.querySelector("server-devtools");
el.topology = myTopology;                   // ServerTopology
el.benchmarks = [{ name: "serialize", run: () => serialize(payload) }]; // optional

@youneed/dom + @youneed/dom-ui-shad are optional peers (only needed for /ui).

Plugin + programmatic API (@youneed/server-plugin-devtools/serve)

Point it at a live @youneed/server app and it mounts a devtools endpoint that serves the web UI wired to the app's real app.topology() — no hand-declared data. This is the easiest way to see your own server.

Preferred — register it as a first-class server plugin via app.plugin(...):

import { Application } from "@youneed/server";
import { devtools } from "@youneed/server-plugin-devtools/serve"; // or from the package index

const app = Application(UsersController)
  .use(cors()).use(helmet()).use(rateLimit())
  .plugin(devtools({ name: "demo-api", url: "http://localhost:3000", path: "/__devtools", middleware: ["cors", "helmet", "rate-limit"] }));
app.listen(3000, () => {}); // open http://localhost:3000/__devtools

devtools(opts?) returns a ServerPlugin (name: "devtools"); its setup(app) mounts the endpoints below onto the AppBuilder. DevtoolsPluginOptions carries the same knobs as serveDevtools (path, name, url, middleware).

Or imperatively, on a live app — serveDevtools(app, opts?):

import { serveDevtools } from "@youneed/server-plugin-devtools/serve";

const app = Application(UsersController).use(cors()).use(helmet()).use(rateLimit());
serveDevtools(app, { name: "demo-api", url: "http://localhost:3000", middleware: ["cors", "helmet", "rate-limit"] });
app.listen(3000, () => {}); // open http://localhost:3000/__devtools

Dev-only. The devtools endpoint exposes your full route topology + schemas. Register it only in development (e.g. guard the app.plugin(devtools()) call behind process.env.NODE_ENV !== "production") or put it behind auth.

It registers, under path (default /__devtools): the UI page, /topology.json (the live topology), and /client.js (the prebuilt UI bundle, shipped in dist/web, built via pnpm --filter @youneed/server-plugin-devtools build:web).

fromApp(app, meta) is also exported if you want the ServerInfo directly. The live topology is produced by @youneed/server's app.topology() (route registry: methods, paths, controllers, guard/interceptor counts, JSON schemas, ws/sse). Because mounted middleware are anonymous functions, pass meta.middleware (the security-relevant names) so the audit is accurate.

Runnable demo: pnpm examples:serve:server-devtools → real server at http://localhost:3000/__devtools.

Roadmap

Done: analysis core, live app.topology() introspection, the shad UI, and the serveDevtools programmatic API. Planned next, on confirmation: AsyncAPI for ws/sse routes, and extracting a shared renderer-agnostic devtools shell so the DOM and server panels share chrome.