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

@raven-js/wings

v0.4.48

Published

Zero-dependency isomorphic routing library for modern JavaScript - Server and CLI routing

Readme

🦅 Wings: Zero-Dependency Isomorphic Routing

Your app's flight control. Same routes work everywhere - server, CLI, wherever. No dependencies, no framework lock-in, no bullshit.

Website Documentation Zero Dependencies ESM Node.js

Wings gives you isomorphic routing that actually works. Define routes once, use them everywhere. Server, CLI, doesn't matter. Each route is a Feather - light, movable, composable.

Zero dependencies. Modern JavaScript. Ship it.

Why Wings Works

Same routes everywhere. Your route definitions work on server and CLI without modification. No more rewriting logic for different environments.

Zero bloat. No transitive dependencies to rot or break. Just pure JavaScript that does what you need.

Modern by default. ESNext features without transpilation. If your environment can't handle modern JS, it's time to upgrade.

Framework agnostic. Works with anything or nothing. No lock-in, no special configuration.

Quick Start

npm install @raven-js/wings
import { Router } from "@raven-js/wings/core";
import {
  DevServer,
  ClusteredServer,
  Logger,
  generateSSLCert,
} from "@raven-js/wings/server";

// Define routes once
const router = new Router();

// Add logging middleware (use with server adapters)
router.useEarly(new Logger());

router.get("/", (ctx) => ctx.html("<h1>Hello World!</h1>"));
router.get("/api/users/:id", (ctx) => ctx.json({ id: ctx.params.id }));

// Use DevServer for development
const devServer = new DevServer(router);
await devServer.listen(3000);

// Use ClusteredServer for production
const server = new ClusteredServer(router);
await server.listen(3000);

Server Implementations

DevServer - Development with live-reload and HTTPS support. WebSocket-based browser reload that actually works. For file watching: node --watch-path=./src boot.js. Server restart triggers browser reload automatically. Built-in HTTPS support for testing real-world scenarios.

ClusteredServer - Production scaling without the complexity. Uses all CPU cores for horizontal scaling. Automatically restarts crashed workers (no PM2 needed). Zero logging by default to prevent disk filling. HTTPS support with same simple API as HTTP.

NodeHttp - Base class that gets out of your way. NOT meant for direct use (extend for custom implementations). Lightweight with zero dependencies. HTTP/HTTPS detection built-in, no special configuration.

HTTPS Support

Every server supports HTTPS with two simple options. No certificates? Generate them in one line. Need custom certificates? Just pass them in. It's that simple.

import {
  DevServer,
  ClusteredServer,
  generateSSLCert,
} from "@raven-js/wings/server";

// Generate certificates (development)
const { privateKey, certificate } = await generateSSLCert();
const server = new DevServer(router, {
  sslCertificate: certificate,
  sslPrivateKey: privateKey,
});
await server.listen(3000); // https://localhost:3000

// Production with your certificates
const prodServer = new ClusteredServer(router, {
  sslCertificate: fs.readFileSync("cert.pem", "utf8"),
  sslPrivateKey: fs.readFileSync("key.pem", "utf8"),
});
await prodServer.listen(443);

Terminal Runtime

Transform CLI commands into URL patterns, then leverage the blazing-fast HTTP router for command dispatch. COMMAND routes are separate from HTTP routes but use the same O(1) Trie matching.

import { Router } from "@raven-js/wings/core";
import { Terminal, success, table } from "@raven-js/wings/terminal";

const router = new Router();

// CLI commands use router.cmd() (COMMAND method)
router.cmd("/users/list", async (ctx) => {
  const active = ctx.queryParams.get("active") === "true";
  const users = await getUsers({ active });
  table(users); // Built-in terminal table renderer
});

router.cmd("/deploy/:env", async (ctx) => {
  const env = ctx.pathParams.env;
  await deployToEnvironment(env);
  success(`Deployed to ${env}`);
});

// CLI execution: args → URL pattern → fast router matching
const terminal = new Terminal(router);
await terminal.run(process.argv.slice(2));

// Usage: node app.js users list --active
//        node app.js deploy production

Environment-Specific Setup

const isDev = process.env.NODE_ENV === "development";
const server = isDev ? new DevServer(router) : new ClusteredServer(router);
await server.listen(3000);

RAVENJS_ORIGIN Auto-Detection

Wings automatically sets RAVENJS_ORIGIN environment variable for SSR components. This enables relative URLs to resolve correctly during server-side rendering.

// Wings automatically sets based on server configuration:
// RAVENJS_ORIGIN = "http://localhost:3000"   (development)
// RAVENJS_ORIGIN = "https://your-domain.com" (production)

// Your SSR components can use relative URLs:
const response = await fetch("/api/data"); // Works in SSR!

Manual Override (containers, reverse proxies):

// Set before server starts - Wings respects explicit values
process.env.RAVENJS_ORIGIN = "https://api.example.com";
await server.listen(3000);
// Wings will NOT override your explicit setting

Common use cases:

  • Containers: RAVENJS_ORIGIN=https://your-domain.com
  • Reverse proxies: RAVENJS_ORIGIN=https://api.internal:8080
  • Development: Auto-detected as http://localhost:3000
  • Testing: Set explicit value for consistent test URLs

Migration from Express

// Before (Express.js)
const express = require("express");
const app = express();
app.get("/api/users", (req, res) => res.json({ users: [] }));
app.listen(3000);

// After (Wings)
import { Router } from "@raven-js/wings/core";
import { DevServer } from "@raven-js/wings/server";

const router = new Router();
router.get("/api/users", (ctx) => ctx.json({ users: [] }));

const server = new DevServer(router);
await server.listen(3000);

Installation

npm install @raven-js/wings

API Reference

Core Module

import { Router } from "@raven-js/wings/core";

const router = new Router();
router.get("/", (ctx) => ctx.html("<h1>Home</h1>"));
router.get("/api/users/:id", (ctx) => ctx.json({ id: ctx.params.id }));

Server Module

import { Router } from "@raven-js/wings/core";
import {
  DevServer,
  ClusteredServer,
  Logger,
  generateSSLCert,
} from "@raven-js/wings/server";

const router = new Router();

// Add logging middleware (use with server adapters)
router.useEarly(new Logger());

router.get("/api/users", (ctx) => ctx.json({ users: [] }));

// Development (HTTP)
const devServer = new DevServer(router);
await devServer.listen(3000);

// Development (HTTPS)
const { privateKey, certificate } = await generateSSLCert();
const httpsServer = new DevServer(router, {
  sslCertificate: certificate,
  sslPrivateKey: privateKey,
});
await httpsServer.listen(3000);

// Production
const server = new ClusteredServer(router);
await server.listen(3000);

Logger Middleware: Request logging with colored terminal output (development) or structured JSON (production). Includes performance indicators (⚡🚀🐌), request tracing, and compliance standards (SOC2, ISO 27001, GDPR).

ClusteredServer Helpers: isMainProcess and isWorkerProcess getters for process identification in clustered environments.

Terminal Module

import { Router } from "@raven-js/wings/core";
import {
  Terminal,
  ask,
  confirm,
  success,
  error,
  table,
  bold,
} from "@raven-js/wings/terminal";

const router = new Router();

// Interactive CLI commands
router.cmd("/setup", async (ctx) => {
  const name = await ask("Project name: ");
  const confirmed = await confirm(`Create ${bold(name)}?`);

  if (confirmed) {
    await createProject(name);
    success("Project created!");
  }
});

// Data display
router.cmd("/users", async (ctx) => {
  const users = await getUsers();
  table(users); // ASCII table output
});

const terminal = new Terminal(router);
await terminal.run(process.argv.slice(2));

Available actions: ask(), confirm() (async input) • success(), error(), warning(), info(), print() (colored output) • bold(), italic(), dim(), underline() (text formatting) • table() (structured data display)

Combined Runtimes

Your app becomes multi-purpose. Starts as CLI tool but can boot into web server mode using the same router. Single deliverable handles both operational commands and web serving.

import { Router } from "@raven-js/wings/core";
import { ClusteredServer } from "@raven-js/wings/server";
import { Terminal, success, info } from "@raven-js/wings/terminal";

const router = new Router();

// HTTP routes for web traffic
router.get("/", (ctx) => ctx.html("<h1>Hello, World!</h1>"));
router.get("/api/users", (ctx) => ctx.json({ users: [] }));
router.get("/health", (ctx) => ctx.json({ status: "ok" }));

// CLI operational commands
router.cmd("/migrate", async (ctx) => {
  info("Running database migrations...");
  await runMigrations();
  success("Migrations completed");
});

router.cmd("/seed", async (ctx) => {
  await seedDatabase();
  success("Database seeded");
});

router.cmd("/backup", async (ctx) => {
  const filename = await backupDatabase();
  success(`Backup created: ${filename}`);
});

// CLI command that boots web server
router.cmd("/boot", async (ctx) => {
  info("Starting web server...");
  const server = new ClusteredServer(router);
  await server.listen(3000);
  success("Server running on port 3000");
  // Server now handles HTTP routes while CLI commands remain available
});

// Start in CLI mode
const terminal = new Terminal(router);
await terminal.run(process.argv.slice(2));

Usage patterns:

# Operational commands
node app.js migrate
node app.js seed
node app.js backup

# Boot web server (uses same router for HTTP routes)
node app.js boot

# In another terminal, operational commands still work
node app.js health-check

Deployment advantages: Your final application handles its own operational needs. No separate migration scripts, backup tools, or health check utilities needed. One deliverable, multiple operational modes.

License

MIT License - see LICENSE for details.


Built with ❤️ by Anonyfox

GitHub Sponsors