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

routerling

v0.1.1

Published

Routerling is a simple and fast router for Node.js

Readme

Routerling

Documentation

A simple, fast, and powerful web framework for Node.js with built-in WebSocket support, lifecycle hooks, and daemon processes.

📚 Read the Documentation

Features

  • 🚀 Fast HTTP Routing - Efficient route matching and handling
  • 🔌 WebSocket Support - Built-in WebSocket server with route-based handlers
  • 🎯 Lifecycle Hooks - STARTUP and SHUTDOWN hooks for initialization and cleanup
  • ⚙️ Daemon Processes - Register background tasks that run on server startup
  • 📦 Context Object - Store and share values across request handlers and middleware
  • 🌐 Subdomain Routing - Route requests based on subdomains
  • 📦 Router Mounting - Compose applications from multiple routers
  • 🎨 Template Rendering - Built-in Nunjucks template support
  • 📁 Static Files - Serve static assets with automatic MIME type detection
  • 🍪 Cookie Parsing - Built-in cookie support
  • 📤 File Uploads - Handle multipart form data and file uploads

Installation

npm install routerling

Quick Start

import { Router, STARTUP, SHUTDOWN } from 'routerling';

const app = new Router();

// Startup hook - runs when server starts
app.ONCE(STARTUP, async () => {
  console.log('Server initializing...');
  // Connect to database, load config, etc.
});

// Shutdown hook - runs when server stops
app.ONCE(SHUTDOWN, async () => {
  console.log('Cleaning up...');
  // Close connections, save state, etc.
});

// HTTP routes - handlers receive (req, res, ctx)
app.GET('/', (req, res, ctx) => {
  res.json({ message: 'Hello from Routerling!' });
});

app.POST('/api/users', (req, res, ctx) => {
  const user = req.body;
  res.status = 201;
  res.json({ id: 1, ...user });
});

// WebSocket endpoint
app.WS('/chat', (ws, request) => {
  ws.on('message', (data) => {
    ws.send(`Echo: ${data}`);
  });
});

// Start server
app.listen(3000, 'localhost', () => {
  console.log('Server running on http://localhost:3000');
});

API Reference

Router Methods

HTTP Methods

  • GET(route, handler, subdomain?) - Handle GET requests
  • POST(route, handler, subdomain?) - Handle POST requests
  • PUT(route, handler, subdomain?) - Handle PUT requests
  • PATCH(route, handler, subdomain?) - Handle PATCH requests
  • DELETE(route, handler, subdomain?) - Handle DELETE requests
  • HEAD(route, handler, subdomain?) - Handle HEAD requests
  • OPTIONS(route, handler, subdomain?) - Handle OPTIONS requests
  • HTTP(route, handler, subdomain?) - Handle all HTTP methods

Route Parameters with Type Coercion:

  • :id - String parameter (default)
  • :id:int - Integer parameter (auto-converted to number)
  • :price:float - Float parameter (auto-converted to number)
  • :active:bool - Boolean parameter (auto-converted to boolean)

Examples:

app.GET('/users/:id:int', (req, res, ctx) => {
  // req.params.id is a number, not a string
  console.log(typeof req.params.id); // 'number'
});

app.GET('/products/:id:int/reviews/:rating:float', (req, res, ctx) => {
  // Both params are auto-converted to numbers
});

WebSocket

  • WS(route, handler, subdomain?) - Handle WebSocket connections

Lifecycle

  • ONCE(event, handler) - Register startup/shutdown hooks
    • STARTUP - Runs when server starts
    • SHUTDOWN - Runs when server stops

Daemons

  • DAEMON(handler) - Register background process

Middleware

  • BEFORE(route, handler, subdomain?) - Add before middleware
  • AFTER(route, handler, subdomain?) - Add after middleware

Wildcard Middleware: Middleware supports wildcard patterns to match multiple routes:

// Matches /api/users, /api/products, etc.
app.BEFORE('/api/*', (req, res, ctx) => {
  ctx.startTime = Date.now();
});

app.AFTER('/api/*', (req, res, ctx) => {
  console.log(`Request took ${Date.now() - ctx.startTime}ms`);
});

Routing

  • subdomain(name) - Register a subdomain
  • mount(router, isolated?) - Mount another router

Static Assets & Templates

  • ASSETS(path) - Serve static files from directory
  • TEMPLATES(path, options?) - Enable template rendering

State Management

  • keep(key, value) - Store value in global state
  • peek(key) - Retrieve value from global state
  • unkeep(key) - Remove and return value from global state

Server

  • listen(port, hostname, callback?) - Start HTTP server
  • close() - Stop server gracefully

Request Object

app.GET('/user/:id', (req, res, ctx) => {
  req.params.id      // Route parameters
  req.query          // Query string parameters
  req.body           // Parsed request body
  req.headers        // Request headers
  req.cookies        // Parsed cookies
  req.files          // Uploaded files
  req.method         // HTTP method
  req.url            // Request URL
  req.path           // URL path
});

Response Object

app.GET('/example', (req, res, ctx) => {
  res.status = 200;                    // Set status code
  res.body = 'Hello';                  // Set response body
  res.json({ key: 'value' });          // Send JSON
  res.html('<h1>Hello</h1>');          // Send HTML
  res.redirect('/other');              // Redirect
  res.cookie('name', 'value', opts);   // Set cookie
  res.header('X-Custom', 'value');     // Set header
});

Context Object

The context object allows you to store and retrieve values across request handlers, middleware, and the request lifecycle.

// Store values in context
app.BEFORE('/api/*', (req, res, ctx) => {
  ctx.keep('startTime', Date.now());
  ctx.user = { id: 1, name: 'John' };  // Proxy syntax
});

app.GET('/api/data', (req, res, ctx) => {
  // Retrieve values from context
  const user = ctx.user;                // Proxy syntax
  const startTime = ctx._data.get('startTime');
  
  res.json({ user, processingTime: Date.now() - startTime });
});

// Context methods
ctx.keep(key, value)       // Store a value
ctx.has(key)               // Check if key exists
ctx.delete(key)            // Remove a key
ctx.keys()                 // Get all keys
ctx.values()               // Get all values
ctx.entries()              // Get all entries
ctx.clear()                // Clear all data
ctx.size                   // Number of stored values

Examples

Daemon Process

app.DAEMON(async (router) => {
  // Background task that runs on startup
  setInterval(() => {
    console.log('Health check...');
  }, 60000);
});

Subdomain Routing

app.subdomain('api');

const handler = (req, res, ctx) => {
  res.json({ subdomain: 'api' });
};

app.GET('/users', handler, 'api');  // api.example.com/users
app.GET('/users', handler);         // www.example.com/users

Router Mounting

const apiRouter = new Router();

const getUsers = (req, res, ctx) => res.json({ users: [] });
const createUser = (req, res, ctx) => res.json({ created: true });

apiRouter.GET('/users', getUsers);
apiRouter.POST('/users', createUser);

app.mount(apiRouter);

Template Rendering

await app.TEMPLATES('./views');

app.GET('/page', (req, res, ctx) => {
  res.render('template.html', { data: 'value' });
});

Static Files

await app.ASSETS('./public');
// Serves files from ./public directory

Testing

npm test

License

MIT

Author

Tersoo Ortserga