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

@seahax/espresso

v0.3.2

Published

A lightweight, type-safe Node.js HTTP server framework with routing, filtering, and error handling.

Downloads

23

Readme

@seahax/espresso

A lightweight, type-safe Node.js HTTP server framework with routing, filtering, and error handling.

Installation

npm install @seahax/espresso

Quick Start

import { createApplication } from '@seahax/espresso';

const app = createApplication();

app.addRoute('GET', '/', (request, response) => {
  response.sendJson({ message: 'Hello, World!' });
});

app.listen({ port: 3000 });

Core Concepts

Application

The main entry point for creating HTTP servers with routing, filtering, and error handling.

import { createApplication } from '@seahax/espresso';

const app = createApplication({
  headers: { 'x-powered-by': 'espresso' },
  compression: true
});

Routes

Define how HTTP requests are handled based on method and path patterns.

import { createRoute } from '@seahax/espresso';

// Inline route definition
app.addRoute('GET', '/users/{id}', async (request, response) => {
  const { id } = await request.pathParameters();
  response.sendJson({ userId: id });
});

// Pre-defined route
const userRoute = createRoute('GET', '/users/{id}', async (request, response) => {
  const { id } = await request.pathParameters();
  response.sendJson({ userId: id });
});
app.addRoute(userRoute);

// Multiple methods and paths
app.addRoute(['GET', 'POST'], ['/api/users/{id}', '/users/{id}'], (request, response) => {
  const { id } = await request.pathParameters();
  response.sendJson({ userId: id });
});

// Multi-segment route parameter
app.addRoute('GET', '/files/{path+}', async (request, response) => {
  const { path } = await request.pathParameters();
  response.sendJson({ filePath: path });
});

Controllers

Group related routes, filters, and error handlers with optional path prefixes.

import { createController } from '@seahax/espresso';

const apiController = createController('/api');

apiController.addRoute('GET', '/users', (request, response) => {
  response.sendJson({ users: [] });
});

apiController.addRoute('POST', '/users', async (request, response) => {
  const userData = await request.body();
  response.sendJson({ created: true });
});

app.addController(apiController);
// Routes are now available at /api/users

Request Handling

Access request data with built-in validation support.

app.addRoute('POST', '/users/{id}', async (request, response) => {
  // Path parameters (from route like /users/{id})
  const pathParams = await request.pathParameters();
  // With schema validation (requires @standard-schema compatible schema)
  // const validatedPathParams = await request.pathParameters(pathParamsSchema);
  
  // Query parameters
  const queryParams = await request.queryParameters();
  // With schema validation
  // const validatedQueryParams = await request.queryParameters(queryParamsSchema);
  
  // Headers
  const headers = await request.headers();
  // With schema validation
  // const validatedHeaders = await request.headers(headersSchema);
  
  // Cookies
  const cookies = await request.cookies();
  // With schema validation
  // const validatedCookies = await request.cookies(cookiesSchema);
  
  // Request body (parsed based on content-type)
  const body = await request.body();
  // With schema validation
  // const validatedBody = await request.body(bodySchema);
  
  response.sendJson({ success: true });
});

Response Handling

Send different types of responses with built-in compression and caching support.

app.addRoute('GET', '/api/data', async (request, response) => {
  // Text/HTML response
  response.send('Hello, World!');

  // JSON response
  response.sendJson({ data: 'value' });
  
  // File response
  response.sendFile('/public', 'index.html');
  
  // Set status code
  response.setStatus(201).sendJson({ created: true });
  
  // Set headers
  response
    .setHeader('cache-control', 'max-age=3600')
    .sendJson({ data: 'cached' });
});

Filters

Apply middleware-like logic to requests before they reach route handlers.

import { createFilter } from '@seahax/espresso';

// Authentication filter
const authFilter = createFilter(async (request, response) => {
  const { authorization } = await request.headers();

  if (!authorization) {
    response.setStatus(401).sendJson({ error: 'Unauthorized' });
    // Response sent, route handler won't be called
  }
});

app.addFilter(authFilter);

Error Handlers

Handle errors thrown by filters or route handlers.

import { createErrorHandler, RequestValidationError } from '@seahax/espresso';

const errorHandler = createErrorHandler(async ({ error, request, response }) => {
  console.error('Request error:', error);
  
  if (!response.sent) {
    response.setStatus(500).sendJson({ 
      error: 'Internal Server Error',
      message: error.message 
    });
  }
});

// Error handler that skips remaining handlers for specific errors
const validationErrorHandler = createErrorHandler(async ({ error, request, response, skipRemainingHandlers }) => {
  if (error instanceof RequestValidationError) {
    response.setStatus(400).sendJson({ 
      error: 'Request Validation Error',
      issues: error.issues 
    });
    
    // Skip remaining error handlers since we've handled this error
    skipRemainingHandlers();
  }
});

app.addErrorHandler(validationErrorHandler);
app.addErrorHandler(errorHandler); // This won't run for RequestValidationErrors

Body Parsers

Handle different content types in request bodies. By default, espresso includes parsers for:

  • application/json and default - JSON parsing
  • application/x-www-form-urlencoded - URL-encoded form data
  • text/plain - Plain text
import { parseJson, parseText, parseUrlEncoded } from '@seahax/espresso';

// Add custom parser for XML
app.addParser('application/xml', async (body) => {
  // Parse XML string to object
  return parseXml(body);
});

// Disable JSON parsing (including as the default)
app.addParser(['application/json', 'default'], false);

Health Check Routes

Create health check endpoints with automatic status monitoring.

import { createHealthRoute } from '@seahax/espresso';

const healthRoute = createHealthRoute({
  database: async () => {
    // Return true if database is healthy
    return await checkDatabaseConnection();
  },
  redis: {
    check: async () => await checkRedisConnection(),
    intervalSeconds: 60,
    initialDelaySeconds: 10
  }
}, {
  path: '/health',
  onCheck: (name, result, error) => {
    if (!result) {
      console.error(`Health check ${name} failed:`, error);
    }
  }
});

app.addRoute(healthRoute);

Info Routes

Create application info endpoints with caching and conditional responses.

import { createInfoRoute } from '@seahax/espresso';

// Custom path and options
const apiInfoRoute = createInfoRoute({
  name: 'My API',
  version: '1.0.0',
  build: process.env.BUILD_ID
}, {
  // defaults to /_info
  path: '/api/info',
});

app.addRoute(apiInfoRoute);
// Available at GET /api/info

SPA Routes

Create routes for serving single-page applications with fallback handling.

import { createSpaRoute } from '@seahax/espresso';

// Basic SPA route
const spaRoute = createSpaRoute('/public');
app.addRoute(spaRoute);

// SPA with custom path and options
const spaRoute = createSpaRoute('/admin-dist', {
  path: '/app',
  index: 'index.html',
  headers: (filename) => ({
    'cache-control': filename.startsWith('assets/') ? 'max-age=86400' : 'no-cache'
  })
});
app.addRoute(spaRoute);

Connect Middleware

Use existing Connect middleware.

import { createMiddlewareFilter } from '@seahax/espresso';
import helmet from 'helmet';
import morgan from 'morgan';

const helmetFilter = createMiddlewareFilter(helmet());
const morganFilter = createMiddlewareFilter(morgan('combined'));

app.addFilter(helmetFilter);
app.addFilter(morganFilter);

Server Lifecycle

Control server startup and shutdown.

const app = createApplication();

// Basic listen
const server = app.listen({ port: 3000 });

// Listen with custom server
import { createServer } from 'https';
const httpsServer = createServer(sslOptions);
app.listen({ 
  server: httpsServer, 
  port: 443,
  onListening: (url, server) => {
    console.log(`Server running at ${url}`);
  }
});

// Graceful shutdown
process.on('SIGTERM', () => {
  app.close();
});

// Listen for events
app.on('listening', (url, server) => {
  console.log(`Server started at ${url}`);
});

app.on('closing', () => {
  console.log('Server close method called');
});

app.on('close', () => {
  console.log('Server closed');
});

API Reference

Application

  • createApplication(options?) - Create a new application instance
  • app.addRoute(route) - Add a pre-defined route
  • app.addRoute(method, path, handler) - Add a route inline
  • app.addController(controller) - Add a controller
  • app.addFilter(filter) - Add a request filter
  • app.addErrorHandler(handler) - Add an error handler
  • app.addParser(contentType, parser) - Add a body parser
  • app.addDefaultHandler(handler) - Add a fallback handler
  • app.listen(options?) - Start the server
  • app.close() - Stop the server

Controller

  • createController(prefix?) - Create a controller with optional path prefix
  • controller.addRoute(...) - Add routes (same API as application)
  • controller.addController(controller) - Add nested controllers
  • controller.addFilter(filter) - Add controller-scoped filters
  • controller.addErrorHandler(handler) - Add controller-scoped error handlers

Route

  • createRoute(method, path, handler) - Create a route definition
  • createHealthRoute(checks, options?) - Create health check route
  • createInfoRoute(info, options?) - Create info endpoint route
  • createSpaRoute(root, options?) - Create single-page application route

Request

  • request.pathParameters(schema?) - Get path parameters
  • request.queryParameters(schema?) - Get query parameters
  • request.headers(schema?) - Get headers
  • request.cookies(schema?) - Get cookies
  • request.body(schema?) - Get parsed body
  • request.method - HTTP method
  • request.path - Request path
  • request.url - Full URL
  • request.protocol - 'http' or 'https'

Response

  • response.send(body?, options?) - Send response
  • response.sendJson(body, options?) - Send JSON response
  • response.sendFile(root, filename, options?) - Send file
  • response.setStatus(code) - Set status code
  • response.setHeader(name, value) - Set header
  • response.setHeaders(headers) - Set multiple headers
  • response.sent - Whether response has been sent
  • response.finished - Whether response is finished

Utilities

  • createFilter(fn) - Create a filter function
  • createMiddlewareFilter(middleware) - Create a filter function from Connect middleware
  • createErrorHandler(fn) - Create an error handler function
  • createMiddlewareErrorHandler(middleware) - Create an error handler function from connect middleware
  • parseJson(body) - Parse JSON body
  • parseText(body) - Parse text body
  • parseUrlEncoded(body) - Parse URL encoded body