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

@ticatec/common-express-server

v0.5.5

Published

Enterprise-grade TypeScript framework for Express.js with built-in multi-tenant support, CRUD controllers, validation, authentication, and API gateway integration. Simplifies building scalable REST APIs with boilerplate-free routing, automatic error handl

Readme

@ticatec/common-express-server

npm version License: MIT

A comprehensive TypeScript library providing common classes, controllers, and middleware for building scalable Express.js applications with multi-tenant support.

中文 | English

Features

  • 🚀 Express.js Foundation: Built on Express.js 5.x with full TypeScript support
  • 🏢 Multi-tenant Architecture: Built-in support for multi-tenant applications
  • 🔐 Authentication & Authorization: User authentication and role-based access control
  • 🎯 Controller Patterns: Pre-built base controllers for common CRUD operations
  • 📝 Validation: Integrated data validation using bean-validator
  • 🔄 Error Handling: Centralized error handling and logging
  • 🌐 Internationalization: Built-in language support via headers
  • 📊 Logging: Structured logging with log4js integration
  • 🎨 TypeScript First: Full TypeScript support with comprehensive type definitions

Documentation

  • Controller Guide - Comprehensive guide on using controllers for CRUD and search operations

Installation

npm install @ticatec/common-express-server

Peer Dependencies

npm install express@^5.1.0

Quick Start

1. Create a Basic Server

import { BaseServer } from '@ticatec/common-express-server';

class MyServer extends BaseServer {
    protected async loadConfigFile(): Promise<void> {
        // Load your configuration here
        console.log('Loading configuration...');
    }

    protected getWebConf() {
        return {
            port: 3000,
            ip: '0.0.0.0',
            contextRoot: '/api'
        };
    }

    protected async setupRoutes(): Promise<void> {
        // Set up your routes here
        await this.bindRoutes('/users', () => import('./routes/UserRoutes'));
    }
}

// Start the server
const server = new MyServer();
BaseServer.startup(server);

2. Create Routes

import { CommonRoutes, routerHelper } from '@ticatec/common-express-server';

class UserRoutes extends CommonRoutes {

    // Load additional user data
    protected getUserHook(): ((user: any) => any) | null {
        return async (user) => {
            // Load user preferences
            user.preferences = await loadPreferences(user.accountCode);
            return user;
        };
    }

    protected bindRoutes() {
        this.get('/profile', routerHelper.invokeRestfulAction(this.getProfile));
        this.post('/update', routerHelper.invokeRestfulAction(this.updateProfile));
    }

    private getProfile = async (req: Request) => {
        // Your logic here
        return { message: 'User profile' };
    };

    private updateProfile = async (req: Request) => {
        // Your logic here
        return { message: 'Profile updated' };
    };
}

export default UserRoutes;

Custom User Hook

The getUserHook() method allows you to process and enrich user data after authentication:

import { CommonRoutes } from '@ticatec/common-express-server';

class AdminRoutes extends CommonRoutes {

    // Process and enrich user data
    protected getUserHook(): ((user: any) => any) | null {
        return async (user) => {
            if (user) {
                // Load admin-specific data
                user.adminData = await loadAdminData(user.accountCode);
                user.permissions = await loadPermissions(user.accountCode);
                user.settings = await loadSettings(user.accountCode);
            }
            return user;
        };
    }

    protected bindRoutes() {
        this.get('/dashboard', routerHelper.invokeRestfulAction(this.getDashboard));
    }

    private getDashboard = async (req: Request) => {
        // User data is already enriched here
        return {
            dashboard: req['user'].adminData,
            permissions: req['user'].permissions
        };
    };
}

Custom User Validation

The isValidUser() method allows you to implement custom validation logic beyond authentication:

import { CommonRoutes } from '@ticatec/common-express-server';

class VerifiedUserRoutes extends CommonRoutes {

    // Validate user account status
    protected async isValidUser(user: any): Promise<boolean> {
        if (!user) {
            return false;
        }
        // Check if user account is active
        const account = await database.getAccount(user.accountCode);
        return account && account.status === 'active';
    }

    protected bindRoutes() {
        this.get('/profile', routerHelper.invokeRestfulAction(this.getProfile));
    }

    private getProfile = async (req: Request) => {
        return req['user'];
    };
}

More examples:

// Check user roles
class AdminRoutes extends CommonRoutes {
    protected isValidUser(user: any): boolean {
        return user && user.roles && user.roles.includes('admin');
    }
}

// Tenant validation
class TenantRoutes extends CommonRoutes {
    protected async isValidUser(user: any): Promise<boolean> {
        if (!user || !user.tenant) {
            return false;
        }
        const tenant = await database.getTenant(user.tenant.code);
        return tenant && tenant.isActive;
    }
}

Custom Authentication Middleware

Use getGlobalHandler() to add custom middleware:

import { CommonRoutes, routerHelper } from '@ticatec/common-express-server';

class ApiRoutes extends CommonRoutes {

    // Add custom global middleware
    protected getGlobalHandler(): RequestHandler | null {
        return async (req, res, next) => {
            // Check API version
            const version = req.headers['api-version'];
            if (!version) {
                throw new Error('API version is required');
            }
            next();
        };
    }

    protected bindRoutes() {
        this.get('/data', routerHelper.invokeRestfulAction(this.getData));
    }

    private getData = async (req: Request) => {
        return { data: [] };
    };
}

Public Routes (No Authentication)

import { CommonRoutes, routerHelper } from '@ticatec/common-express-server';

class PublicRoutes extends CommonRoutes {

    // Override isValidUser to allow public access (no authentication required)
    protected isValidUser(user: any): boolean {
        return true; // Allow access without authentication
    }

    protected bindRoutes() {
        this.get('/info', routerHelper.invokeRestfulAction(this.getInfo));
    }

    private getInfo = async (req: Request) => {
        return { message: 'Public information' };
    };
}

3. Create Controllers

import { TenantBaseController } from '@ticatec/common-express-server';
import { ValidationRules, StringValidator } from '@ticatec/bean-validator';

interface UserService {
    createNew(user: any, data: any): Promise<any>;
    update(user: any, data: any): Promise<any>;
    search(user: any, query: any): Promise<any>;
}

const userValidationRules: ValidationRules = [
    new StringValidator('name', { required: true, minLen: 2 }),
    new StringValidator('email', {
        required: true,
        format: {
            regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
            message: 'Invalid email format'
        }
    })
];

class UserController extends TenantBaseController<UserService> {
    constructor(userService: UserService) {
        super(userService, userValidationRules);
    }

    // CRUD methods are inherited and automatically validated
    // createNew(), update(), del() are available

    // Add custom methods
    search() {
        return async (req: Request): Promise<any> => {
            const query = req.query;
            this.checkInterface('search');
            return await this.invokeServiceInterface('search', [
                this.getLoggedUser(req),
                query
            ]);
        };
    }
}

Core Classes

BaseServer

Abstract base server class that provides:

  • Express application setup
  • Configuration loading
  • Route binding
  • Error handling
  • Health check endpoint
  • Static file serving
  • Global user parsing (non-invasive, for all requests)

Global Middleware Order:

1. SetNoCache              - Disable caching
2. HealthCheck             - /health-check endpoint
3. RetrieveUser (Global)   - Parse user from headers (non-invasive)
4. Routes                  - All route definitions
5. ActionNotFound          - 404 handler
6. Error Handler           - Error handling

RouterHelper (Singleton)

Middleware utilities for:

  • JSON response formatting
  • Cache control
  • User authentication
  • Error handling
  • Request logging

Usage:

import { routerHelper } from '@ticatec/common-express-server';

// Use middleware
routerHelper.setNoCache           // Disable caching
routerHelper.checkLoggedUser()    // Require authentication
routerHelper.retrieveUser()       // Parse user (non-invasive)
routerHelper.actionNotFound()     // 404 handler
routerHelper.invokeRestfulAction() // Wrap async handlers
routerHelper.invokeController()    // Wrap controller handlers

CommonRoutes

Base class for route definitions with:

  • Express router integration
  • Flexible authentication control
  • Custom user validation checks
  • User hook support
  • Global middleware support
  • Logging capabilities
  • Built-in HTTP method helpers

Middleware Order:

1. getUserHook()           - Process and enrich user data
2. isValidUser()             - Custom user validation
3. getGlobalHandler()      - Custom middleware
4. bindRoutes()            - Route definitions

Key Methods:

  • getUserHook(): ((user: any) => any) | null - Process user data
  • isValidUser(user: any): boolean | Promise<boolean> - Custom user validation
  • getGlobalHandler(): RequestHandler | null - Custom middleware
  • bindRoutes() - Define your routes

Controllers Hierarchy

  • BaseController: Basic controller with logging and user context
  • CommonController: CRUD operations with validation
  • AdminBaseController: Admin-specific operations (tenant-independent)
  • TenantBaseController: Tenant-specific operations
  • AdminSearchController: Admin search operations
  • TenantSearchController: Tenant search operations

📚 Complete Controller Guide →

Architecture Overview

Request Processing Flow

┌─────────────────────────────────────────────────────────────┐
│                    BaseServer Middleware                    │
├─────────────────────────────────────────────────────────────┤
│ 1. SetNoCache              - Disable caching                │
│ 2. HealthCheck             - /health-check endpoint         │
│ 3. RetrieveUser (Global)   - Parse user from headers        │
│ 4. Routes                  - All route definitions          │
│ 5. ActionNotFound          - 404 handler                    │
│ 6. Error Handler           - Error handling                 │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│              CommonRoutes Middleware Order                   │
├─────────────────────────────────────────────────────────────┤
│ 1. getUserHook()           - Process user data             │
│ 2. isValidUser()             - Custom user validation         │
│ 3. getGlobalHandler()      - Custom middleware              │
│ 4. bindRoutes()            - Route definitions              │
└─────────────────────────────────────────────────────────────┘

Configuration

Application Configuration

import { AppConf } from '@ticatec/common-express-server';

// Initialize configuration
AppConf.init({
    database: {
        host: 'localhost',
        port: 5432
    },
    server: {
        port: 3000
    }
});

// Use configuration
const config = AppConf.getInstance();
const dbHost = config.get('database.host');
const serverPort = config.get('server.port');

Gateway Architecture

This application is designed to work behind an API Gateway. The gateway handles JWT tokens or session-based authentication and forwards the authenticated user information to the Express application via HTTP headers.

Architecture Flow
Client Request (JWT/Session) → API Gateway → Express Application
                                    ↓
                            User Info Headers
Gateway Responsibilities

The API Gateway should:

  1. Authenticate requests using JWT tokens, session cookies, or other authentication mechanisms
  2. Extract user information from the authentication token/session
  3. Forward user data as HTTP headers to the Express application
  4. Handle authorization and rate limiting as needed
User Authentication Headers

The library expects user information in the request headers:

// Headers forwarded by the gateway
{
    'user': encodeURIComponent(JSON.stringify({
        accountCode: 'user123',
        name: 'John Doe',
        tenant: { code: 'tenant1', name: 'Tenant One' }
    })),
    'x-language': 'en'
}

User Impersonation

The library supports user impersonation for debugging and troubleshooting:

// Headers with user impersonation
{
    'user': encodeURIComponent(JSON.stringify({
        // Original privileged user
        accountCode: 'admin123',
        name: 'System Admin',
        tenant: { code: 'system', name: 'System Tenant' },

        // User being impersonated
        actAs: {
            accountCode: 'user456',
            name: 'Target User',
            tenant: { code: 'client-a', name: 'Client A' }
        }
    })),
    'x-language': 'en'
}

Multi-tenant Support

The library provides built-in multi-tenant support:

// Tenant-specific controller
class ProductController extends TenantBaseController<ProductService> {
    // Automatically receives logged user context
    // All operations are tenant-scoped
}

// Admin controller (cross-tenant)
class SystemController extends AdminBaseController<SystemService> {
    // Operations across all tenants
}

Validation

Built-in validation using @ticatec/bean-validator:

import { ValidationRules, StringValidator, NumberValidator } from '@ticatec/bean-validator';

const rules: ValidationRules = [
    new StringValidator('name', { required: true, minLen: 2, maxLen: 50 }),
    new StringValidator('email', {
        required: true,
        format: {
            regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
            message: 'Invalid email format'
        }
    }),
    new NumberValidator('age', { required: false, minValue: 18, maxValue: 120 })
];

class UserController extends CommonController<UserService> {
    constructor(service: UserService) {
        super(service, rules); // Validation applied automatically
    }
}

Error Handling

Centralized error handling with @ticatec/express-exception:

import {
    ActionNotFoundError,
    UnauthenticatedError,
    IllegalParameterError
} from '@ticatec/express-exception';

// Errors are automatically handled and formatted
throw new ActionNotFoundError('Resource not found');
throw new UnauthenticatedError('User not authenticated');
throw new IllegalParameterError('Invalid input data');

API Reference

Types

// Function signatures
export type RestfulFunction = (req: Request) => any;
export type ControlFunction = (req: Request, res: Response) => any;
export type moduleLoader = () => Promise<any>;

// User interfaces
export interface CommonUser {
    accountCode: string;
    name: string;
    tenant?: { // Optional, may not be present for platform admins
        code: string;
        name: string;
    };
    [key: string]: any;
}

export interface LoggedUser extends CommonUser {
    isPlatform?: boolean; // Platform admin flag
    actAs?: CommonUser; // For user impersonation
}

Development

Build

npm run build         # Build the project
npm run dev           # Development mode with watch

Requirements

  • Node.js >= 18.0.0
  • Express.js ^5.1.0
  • TypeScript ^5.0.0

Dependencies

  • @ticatec/bean-validator: Data validation
  • @ticatec/express-exception: Error handling
  • @ticatec/node-common-library: Common utilities
  • log4js: Logging framework

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support and questions:


Made with ❤️ by TicaTec