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

@openapi-typescript-infra/cluster-proxy

v1.6.0

Published

Configurable cluster-aware HTTP/S proxy for local development with DNS, TLS, service registry, and TUI

Readme

@openapi-typescript-infra/cluster-proxy

A configurable local development proxy that routes traffic to Kubernetes-style services. It combines an HTTP/HTTPS proxy, a DNS server, a service registry, and a terminal UI into a single tool so you can develop against multiple services locally without editing /etc/hosts or managing individual DNS entries.

Features

  • DNS server that resolves your configured zones to the proxy
  • Service registry where local services announce themselves on startup
  • TLS termination with automatic certificate generation via mkcert
  • Cluster fallback — unregistered hostnames are forwarded to the real cluster
  • WebSocket support with full upgrade handling
  • Auth token exchange — optionally extracts auth cookies and forwards them as headers
  • Terminal UI with live request log, service registry view, filtering, and request inspection
  • macOS resolver integration — automatically creates /etc/resolver/* files when running with sudo

Quick start

With a config file

Create a cluster-proxy.json:

{
  "zones": ["local.dev.mycompany.com", "mc"],
  "clusterSuffix": ".mc.svc.cluster.local"
}
npx @openapi-typescript-infra/cluster-proxy --config cluster-proxy.json

With CLI args only

npx @openapi-typescript-infra/cluster-proxy \
  --zone local.dev.mycompany.com \
  --zone mc \
  --clusterSuffix .mc.svc.cluster.local

On standard ports (requires sudo)

sudo npx @openapi-typescript-infra/cluster-proxy \
  --config cluster-proxy.json \
  --host 127.0.0.2 --httpPort 80 --httpsPort 443

How it works

                        ┌──────────────┐
   Browser request      │  DNS Server  │  Resolves *.zone → proxy IP
   *.local.dev.myco.com │  (port 5533) │
          │              └──────────────┘
          ▼
   ┌──────────────────┐
   │   HTTP / HTTPS    │
   │   Proxy Server    │
   └────────┬─────────┘
            │
    ┌───────┴────────┐
    ▼                ▼
 Registered?     Not registered
    │                │
    ▼                ▼
 localhost:PORT   hostname.clusterSuffix
 (from registry) (e.g. api.mc.svc.cluster.local)
  1. The DNS server resolves any hostname under your configured zones to the proxy's IP address.
  2. When a request arrives, the proxy extracts the first subdomain (e.g. api from api.local.dev.mycompany.com).
  3. If that name is in the local registry, the request routes to localhost:<registered port>.
  4. Otherwise it forwards to the cluster at <hostname>.<clusterSuffix>.

Configuration

Config file

All options can be set in a JSON config file passed via --config:

{
  "name": "My Proxy",
  "zones": ["local.dev.mycompany.com", "mc"],
  "clusterSuffix": ".mc.svc.cluster.local",
  "primaryZone": "local.dev.mycompany.com",
  "certs": {
    "keyFile": "~/.certs/my.keyfile.pem",
    "certFile": "~/.certs/my.certfile.pem",
    "mkcertDomains": ["local.dev.mycompany.com", "*.local.dev.mycompany.com"]
  },
  "auth": {
    "cookieName": "session_token",
    "endpoint": "http://auth.mc.svc.cluster.local/token-check",
    "headerNames": ["x-auth-token"]
  },
  "host": "127.0.0.1",
  "httpPort": 9080,
  "httpsPort": 9443,
  "dnsPort": 5533
}

| Field | Required | Default | Description | |-------|----------|---------|-------------| | zones | yes | — | DNS zones the proxy handles. Requests to *.zone are resolved and routed by the proxy. | | clusterSuffix | yes | — | Suffix appended to single-word hostnames for cluster routing (e.g. .mc.svc.cluster.local). | | name | no | "Cluster Proxy" | Display name for the TUI logo and error pages. | | primaryZone | no | zones[0] | The zone used for registry URLs and default certificate paths. | | certs.keyFile | no | ~/.certs/_wildcard.<primaryZone>.keyfile.pem | Path to TLS key file. | | certs.certFile | no | ~/.certs/_wildcard.<primaryZone>.certfile.pem | Path to TLS cert file. | | certs.mkcertDomains | no | [primaryZone, "*.primaryZone"] | Domains passed to mkcert when auto-generating certificates. | | auth.cookieName | no | — | Cookie to look for on incoming requests. Auth is disabled if auth is not set. | | auth.endpoint | no | — | URL to call for token exchange when the cookie is present. | | auth.headerNames | no | — | Response headers to extract from the auth endpoint and forward upstream. | | host | no | 127.0.0.1 | Bind address. | | httpPort | no | 9080 | HTTP listen port. | | httpsPort | no | 9443 | HTTPS listen port. | | dnsPort | no | 5533 | DNS listen port. Set to 0 to disable DNS. | | logLevel | no | debug | Pino log level. |

CLI arguments

CLI arguments override config file values.

--config <path>       Path to JSON config file
--zone <domain>       DNS zone (repeatable, e.g. --zone foo.com --zone bar)
--clusterSuffix <s>   Cluster service suffix
--name <name>         Display name
--host <ip>           Bind address              (default: 127.0.0.1)
--httpPort <port>     HTTP listen port          (default: 9080)
--httpsPort <port>    HTTPS listen port         (default: 9443)
--dnsPort <port>      DNS listen port, 0=off    (default: 5533)
--key <path>          TLS key file path
--cert <path>         TLS cert file path
--logLevel <level>    Pino log level            (default: debug)
--no-pretty           Disable pretty-printed logs
--tui false           Disable the terminal UI

Service registration

Services register themselves by sending a POST to the proxy's registry endpoint:

curl http://registry.local.dev.mycompany.com/register \
  -H "Content-Type: application/json" \
  -d '{"name": "my-api", "port": 8080, "protocol": "http"}'

After registration, my-api.local.dev.mycompany.com routes to localhost:8080.

  • Services ending in -web automatically get a base name alias (e.g. registering my-api-web also creates a my-api route).
  • If a new service registers on the same port as an existing one, the old registration is replaced.
  • If the proxy gets ECONNREFUSED when forwarding to a registered service, it automatically unregisters and falls back to cluster routing.

Auth token exchange

When auth is configured, the proxy checks each HTTPS request for the specified cookie. If found, it calls the auth endpoint with the cookie and extracts the configured header from the response, forwarding it upstream. This is useful for reproducing the behavior of an auth sidecar (like Envoy) in local development.

Terminal UI

When running in an interactive terminal, the proxy displays a TUI with:

  • ASCII art logo and connection info
  • Live list of registered services and cluster hosts
  • Merged activity timeline (logs + requests)
  • Request inspector with full headers and body

Keyboard shortcuts:

| Key | Action | |-----|--------| | f | Open filter (by hostname or path, supports * wildcards) | | c | Clear request history | | q | Quit | | Enter | Inspect selected request | | Esc / b | Back to dashboard | | Up / Down | Scroll / navigate |

DNS and macOS resolver

When dnsPort is non-zero, the proxy starts a DNS server that resolves all configured zones to the bind address. On macOS with sudo, it automatically creates resolver files at /etc/resolver/<zone> so lookups work without any manual DNS configuration. These files are cleaned up on exit.

Without sudo, a warning is logged with the manual commands to run.

Programmatic usage

The proxy can also be used as a library:

import { createMainProxy, type ClusterProxyConfig } from '@openapi-typescript-infra/cluster-proxy';

const config: ClusterProxyConfig = {
  zones: ['local.dev.mycompany.com'],
  clusterSuffix: '.mc.svc.cluster.local',
};

const { proxy, httpsServer, httpServer, dnsServer } = await createMainProxy({
  key: '...pem contents...',
  cert: '...pem contents...',
  httpPort: 9080,
  httpsPort: 9443,
  logger,
  config,
});

License

MIT