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

@michaelthielemann/kestrel-redirects-default

v5.8.1

Published

Steps redirects.validate/lookup/export/render: admin-managed redirect rules, honoured in site resolution and exported as redirects.json for an edge proxy.

Readme

redirects/default

Admin-managed redirects: the redirects singleton (rules: json, list of { from, to, status }, order = priority) is compiled into anchored regex rules. from uses * (one segment) / ** (one or more), to is a path or an http(s) URL with $1…; status 301 (default) | 302 | 307 | 308. Config: type (redirects), field (rules), prefix (blobstore prefix, same as delivery-static), key (redirects.json). Steps: redirects.validate before content.set (VALIDATION, details.row, message Row N: …); redirects.lookup in the site pipeline before site.resolve – on a hit the pipeline ends with { redirect: { to, status } }; redirects.export after save and in publish-all writes <prefix>redirects.json ([{ pattern, target, status }], [] when empty; broken legacy rows are skipped and logged); redirects.render serves the same list from the DB. Not included: query matching/forwarding, regex authoring, the edge handler itself (see ../../examples/nginx-njs).

How a rule compiles

Editors never write a regex. from is a path with * (one segment) or ** (one or more) wildcards, and to references them positionally as $1, $2, … in authored order; the translation into the anchored regex happens here, so the edge only matches and substitutes. The exported list is { pattern, target, status } for every rule and nothing else, so a consumer such as the njs handler needs no per-item shape check.

${1} is rejected: it compiles clean and then ships verbatim in every Location, a rule that silently 404s. A bare $ is left alone — it is a legal path character, only $ followed by digits is reserved. Two ** with only a separator between them are rejected as well: they match the same thing through every split point, which is quadratic on a long path.

Security of a capture

A capture comes from the request, not from the editor, so the checks that ran over the authored literal say nothing about what it holds; the capture class is the guard instead. It excludes a backslash, because every browser resolves Location: /\host as a host.

A $n placeholder inside an absolute target's host is rejected outright: with https://neu.example.com$1, a request for /blog/.evil.com would produce https://neu.example.com.evil.com. The capture classes cannot prevent that — the hazard is where $n sits, not what it holds.

A stored rules field that is neither absent nor a list is a broken container, not a bad row: redirects.lookup fails open on it, so a live site keeps resolving pages instead of answering 500 on every request.

Generated from the manifest

@michaelthielemann/kestrel-redirects-default – module redirects/default: provides no contract; requires content@1, blobstore@1.

| Config | Type | Required | Default | |---|---|---|---| | type | string | no | "redirects" | | field | string | no | "rules" | | prefix | string | no | "" | | key | string | no | "redirects.json" |

| Step | Summary | Reads | Writes | Input | Output | Errors | |---|---|---|---|---|---|---| | redirects.validate | Compile the redirect rules of the payload; VALIDATION names the offending row | – | – | { rules?: object[] } | – | 400 Row N: | | redirects.lookup | Answer { redirect: { to, status } } and end the pipeline when the request path matches a rule | params.path | result? | – | – | – | | redirects.export | Write redirects.json to the blobstore (adds redirects: { rules, skipped } to the result) | – | result.redirects | – | { redirects: object, … } | – | | redirects.render | The compiled redirect list (same content as redirects.json) | – | result | – | object[] | – |

Pipelines in examples/minimal using these steps:

  • publishAllPages (POST /admin/publish-all/pages): authn.requireUser → authz.require:pages.manage → delivery.publishAll:pages → redirects.export → delivery.exportLlms
  • renderRedirects (GET /redirects.json): redirects.render
  • resolvePage (GET /site/*path): authn.identifyUser → authz.require:pages.read → redirects.lookup → site.resolve:pages?home=home&status=published&fallback=true → site.resolveLinks:pages?home=home&status=published&fallback=true
  • setRedirects (PUT /redirects): authn.requireUser → authz.require:redirects.write → validate.check:redirects.rules → redirects.validate → content.set:redirects → redirects.export