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

@prism.engineer/router

v0.0.1

Published

A type-safe router library that provides Express.js integration with automatic API client code generation. This library serves as a wrapper around Express.js that adds:

Readme

@prism/router

A type-safe router library that provides Express.js integration with automatic API client code generation. This library serves as a wrapper around Express.js that adds:

  1. Dynamic route loading from file patterns
  2. Automatic TypeScript API client generation
  3. Type-safe API consumption for frontends and backends

Table of Contents

Installation

# Install the router
npm install @prism/router

# Install required peer dependency
npm install @sinclair/typebox

Note: TypeBox is a required dependency for defining route schemas with runtime validation and type safety.

Quick Start

1. Import and Initialize

import { router } from '@prism/router';

// Access the Express app instance
const app = router.app;

// Add middleware as needed
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

2. Create Route Files

Create route files using the createApiRoute helper. TypeBox is required for defining type-safe schemas:

// api/hello.ts - Simple GET route
import { createApiRoute } from '@prism/router';
import { Type } from '@sinclair/typebox';

export const helloRoute = createApiRoute({
  path: '/api/hello',
  method: 'GET',
  outputs: {
    body: Type.Object({
      message: Type.String()
    })
  },
  handler: (req, res) => {
    res.json({ message: 'Hello, World!' });
  }
});
// api/users.ts - POST route with request body
import { createApiRoute } from '@prism/router';
import { Type } from '@sinclair/typebox';

export const createUserRoute = createApiRoute({
  path: '/api/users',
  method: 'POST',
  inputs: {
    body: Type.Object({
      name: Type.String(),
      email: Type.String()
    })
  },
  outputs: {
    body: Type.Object({
      id: Type.Number(),
      name: Type.String(),
      email: Type.String()
    })
  },
  handler: (req, res) => {
    const { name, email } = req.body;
    res.json({ id: 1, name, email });
  }
});

3. Load Routes Dynamically

// Load all API routes
await router.loadRoutes(/api\/.*\.ts$/);

// Load specific route patterns
await router.loadRoutes(/api\/v1\/.*\.ts$/);
await router.loadRoutes('api/**/*.ts'); // glob pattern

// Load multiple patterns
const patterns = [
  /api\/v1\/.*\.ts$/,
  /api\/v2\/.*\.ts$/,
  /admin\/.*\.ts$/
];

for (const pattern of patterns) {
  await router.loadRoutes(pattern);
}

4. Start the Server

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

API Client Generation

Configuration File

Create config.prism.router.ts in your project root:

export default {
  outputDir: './generated',
  clientName: 'ApiClient',
  format: 'typescript', // or 'javascript'
  baseUrl: 'http://localhost:3000',
  includeTypes: true,
};

Programmatic Compilation

import { router } from '@prism/router';

// Compile with custom config
await router.compile({
  outputDir: './src/generated',
  clientName: 'MyApiClient',
  format: 'typescript',
  baseUrl: 'http://localhost:3000',
  includeTypes: true,
});

CLI Usage

# Generate API client using config file
npx router compile

# The generated client will be type-safe:
# ./generated/ApiClient.ts

Using Generated Client

The generated client mirrors your API structure using actual paths:

import { ApiClient } from './generated/ApiClient';

const client = new ApiClient('http://localhost:3000');

// GET /api/hello -> client.api.hello.get()
const hello = await client.api.hello.get();

// POST /api/users -> client.api.users.post({ body: {...} })
const newUser = await client.api.users.post({ 
  body: { name: 'John', email: '[email protected]' } 
});

Query Parameters

Add query parameters to GET requests for filtering, pagination, etc:

// Route definition
export const getUsersRoute = createApiRoute({
  path: '/api/users',
  method: 'GET',
  inputs: {
    query: Type.Object({
      page: Type.Optional(Type.Number()),
      limit: Type.Optional(Type.Number()),
      search: Type.Optional(Type.String())
    })
  },
  outputs: {
    body: Type.Array(Type.Object({
      id: Type.Number(),
      name: Type.String(),
      email: Type.String()
    }))
  },
  handler: (req, res) => {
    const { page = 1, limit = 10, search } = req.query;
    res.json([{ id: 1, name: 'John', email: '[email protected]' }]);
  }
});
// Client usage
const users = await client.api.users.get({ 
  query: { page: 1, limit: 10, search: 'john' } 
});

Path Parameters

Use {paramName} syntax in routes. Client uses underscore notation _paramName_:

// Route definition
export const getUserByIdRoute = createApiRoute({
  path: '/api/users/{userId}',
  method: 'GET',
  outputs: {
    body: Type.Object({
      id: Type.Number(),
      name: Type.String(),
      email: Type.String()
    })
  },
  handler: (req, res) => {
    const { userId } = req.params;
    res.json({ id: Number(userId), name: 'John', email: '[email protected]' });
  }
});
// Client usage
const user = await client.api.users._userId_.get('123');

// Multiple path parameters (passed in order)
const comment = await client.api.users._userId_.posts._postId_.get('123', '456');

Headers

Define expected headers for validation and typing:

// Route definition
export const protectedRoute = createApiRoute({
  path: '/api/protected',
  method: 'GET',
  inputs: {
    headers: Type.Object({
      authorization: Type.String(),
      'x-api-version': Type.Optional(Type.String())
    })
  },
  outputs: {
    body: Type.Object({
      message: Type.String()
    })
  },
  handler: (req, res) => {
    const { authorization } = req.headers;
    res.json({ message: 'Access granted' });
  }
});
// Client usage
const result = await client.api.protected.get({
  headers: { 
    authorization: 'Bearer token123',
    'x-api-version': 'v1' 
  }
});

Authentication

Add authentication requirements to routes:

// Route definition
export const secureRoute = createApiRoute({
  path: '/api/secure',
  method: 'GET',
  outputs: {
    body: Type.Object({
      data: Type.String()
    })
  },
  auth: { required: true, type: 'bearer' },
  handler: (req, res) => {
    // req.user is available when auth is configured
    res.json({ data: 'Secret information' });
  }
});

Request Options

All HTTP methods support the same options structure:

interface RequestOptions {
  query?: Record<string, any>;
  body?: any;
  headers?: Record<string, string>;
}

// Example with query parameters
await client.api.users.get({ 
  query: { page: 1, limit: 10 }
});

// Example with request body and headers
await client.api.users.post({ 
  body: { name: 'John', email: '[email protected]' },
  headers: { 'content-type': 'application/json' }
});

Key Features

Core Benefits

  • Runtime Validation: Automatic request/response validation using TypeBox schemas
  • Type Safety: TypeScript types automatically inferred from schemas
  • Path-Based Client: Generated client mirrors your API structure (client.api.users.get())
  • JSON Schema Output: Generate OpenAPI/Swagger documentation automatically

Authentication Support

// No auth required (default)
// auth property can be omitted

// Bearer token
auth: { required: true, type: 'bearer' }

// API key in header
auth: { required: true, type: 'apikey', location: 'header', name: 'x-api-key' }

// Basic auth
auth: { required: true, type: 'basic' }

// Custom validation
auth: { required: true, type: 'custom', validator: (req) => boolean }

Complete Example

import express from 'express';
import { router } from '@prism/router';
import { loadConfig } from '@prism/router';

async function main() {
  // Get the Express app
  const app = router.app;
  
  // Add middleware
  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));
  
  // Load routes from multiple patterns
  await router.loadRoutes(/api\/.*\.ts$/);
  await router.loadRoutes(/admin\/.*\.ts$/);
  
  // Start server
  app.listen(3000, () => {
    console.log('🚀 Server running on port 3000');
  });
  
  // Generate API client
  const config = await loadConfig();
  await router.compile(config);
  console.log('✅ API client generated');
}

main().catch(console.error);

Configuration Options

The config.prism.router.ts file supports these options:

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | outputDir | string | ✅ | - | Output directory for generated client | | clientName | string | ✅ | - | Name of the generated client class | | format | 'typescript' \| 'javascript' | ❌ | 'typescript' | Output format | | baseUrl | string | ❌ | '' | Base URL for API calls | | includeTypes | boolean | ❌ | true | Include TypeScript type definitions |

export default {
  outputDir: './generated',
  clientName: 'ApiClient',
  format: 'typescript',
  baseUrl: 'http://localhost:3000',
  includeTypes: true,
};

Development

Dependencies

  • Use npm install {package} to add dependencies
  • Compatible with any Node.js project

Testing

  • Run tests: npm test
  • Watch mode: npm run test:watch
  • Coverage: npm run test:coverage

Package Info

  • Package name: @prism/router
  • Type: Library package for Express.js applications
  • Current version: 0.0.1
  • Node.js compatibility: >= 16.0.0