RouterWrapper

Custom express-router-wrapper of expresso-macchiato

Description

The RouterWrapper class is used to define and standardize your Express routes within the expresso-macchiato framework.

It enables:

  • A clean, structured API definition using a consistent return format.

  • Swagger 3.0 documentation generation for all declared routes and models.

  • The ability to auto-generate CRUD routes for a database entity, with optional security and filtering.

  • Middleware support and full control over route logic and parameters.

import { Response as ExpressResponse, Request, RequestHandler } from "express";
import { BaseEntity } from "typeorm";
import { Parameter, Reference, SchemaV3, Response as SwaggerResponse } from "./swagger.sptypes";
// Check the github type file for swagger v3

export type Methods = "GET" | "POST" | "PUT" | "DELETE"
export type ExpressReturn = { isOk:boolean, result:any, status:number, contentType?:string }
export interface RouterWrapperInterface<T extends typeof BaseEntity = typeof BaseEntity> {
    basePath:string;
    tag:string,
    swaggerNewSchemas?:{ [schema:string]: SchemaV3 },
    dbRouting?:{
        entity:T,
        primaryKey?:string,
        getParameters?:Array<Parameter>
        bodyParameters?:SchemaV3,
        avoid?:Array<Methods | 'LIST'>,
        secure?:SecureTokenConfig,
        returningProps?:string[]
    }
    apis?: Record<string, {
        'GET'?:MethodPathHandling
        'POST'?:MethodPathHandling
        'PUT'?:MethodPathHandling
        'DELETE'?:MethodPathHandling
    }>
}

export type MethodPathHandling = {
    swaggerMultipartForm?:boolean,
    swaggerBody?:{
        schema:string,
        required?:boolean,
        description?:string,
        comType?:'application/json' | 'multipart/form-data',
    },
    swaggerResponses?:Record<string, Reference | SwaggerResponse>,
    swaggerParameters?:Array<Parameter>
    middlewares?: RequestHandler[];
    handler: (req:Request, res:ExpressResponse) => Promise<ExpressReturn>
}

export type SecureTokenConfig = boolean | { 
[columnName:string]:{
    tokenKey:string,
    methods:"*" | Array<Methods | "LIST">
} }

Properties

basePath: string

The base path for all the routes defined inside this wrapper. Example: /user, /auth

tag: string

Used to group the routes inside the Swagger UI. Each router has its own tag.

swaggerNewSchemas?: { [schema: string]: SchemaV3 }

Optional. Define any custom Swagger schemas required for the documentation.

You can use those new schemas in the apis creation.

DbRouting

dbRouting?: {
  entity: T,
  primaryKey?: string,
  getParameters?: Array<Parameter>, // Check Swagger Types on this doc
  bodyParameters?: SchemaV3, // Check Swagger Types on this doc
  avoid?: Array<Methods | 'LIST'>,
  secure?: SecureTokenConfig,
  returningProps?: string[]
}

export type SecureTokenConfig = boolean | { 
[columnName:string]:{
    tokenKey:string,
    methods:"*" | Array<Methods | "LIST">
} }

This property enables you to automatically generate a standard set of RESTful routes for a given entity, following the conventional pattern:

  • LIST → paginated list with query params (e.g., ?limit=10&page=2)

  • GET → retrieve a single entity by ID

  • POST → create a new entity

  • PUT → update an existing entity

  • DELETE → delete an entity

If dbRouting is not defined, no dynamic routes will be created. When defined, you can customize route behavior, schemas, parameters, and even token-based access control.

  • entity: the TypeORM entity.

  • primaryKey: override the default primary key (default: "id").

  • getParameters: list of Parameter (swagger types) for the list and getendpoint.

  • bodyParameters: this is used if you want to override the default schema for POST and PUT bodies.

  • avoid: exclude some routes from being generated (e.g., ['DELETE']).

  • returningProps: select specific entity properties to return in the response (if undefined every prop will be returned)

  • secure: Enables token-based protection for the generated routes.

    You can either:

    • Set it to true to simply require a valid token for all routes. The token will be decrypted and its validity checked.

    • Provide a configuration object to enforce column-level authorization.

    In the object form, the key should match the column name in the database entity.

    Its value is an object like:

    • tokenKey (string)

    • methods (list of methods or "*")

    This setup will:

    • Decrypt the token,

    • Extract the tokenKey from the payload,

    • Match it against the specified column in the entity before allowing access.

    secure: { userId: { tokenKey: 'sub' } }
    
    /*
        This will check if entity.userId === tokenPayload.sub
    */ 

    For the methods, if you put "*" this secure rule will be valid for every method, otherwise pass an array of methods you want.

If you want to use the dbRouting with some custom defined apis, the routes defined in apis property will override the default routes by the dbRouting.

Api

apis?: Record<string, {
  GET?: MethodPathHandling,
  POST?: MethodPathHandling,
  PUT?: MethodPathHandling,
  DELETE?: MethodPathHandling
}>

MethodPathHandling = {
  swaggerBody?: {
    schema: string,
    required?: boolean,
    description?: string,
    comType?: 'application/json' | 'multipart/form-data',
  },
  swaggerResponses?: Record<string, Reference | SwaggerResponse>, // Check Swagger sections in this doc
  swaggerParameters?: Array<Parameter>, // Check Swagger sections in this doc
  middlewares?: RequestHandler[],
  handler: (req: Request, res: ExpressResponse) => Promise<ExpressReturn>
}

export type ExpressReturn = { isOk:boolean, result:any, status:number, contentType?:string }

The apis property allows you to define custom API endpoints that will be automatically registered under the router’s basePath. It is structured as a record where each key represents a relative subpath (e.g. /custom-endpoint) and its value contains a set of supported HTTP methods (GET, POST, PUT, DELETE), each configured via a MethodPathHandling object.

If one of the routes defined here matches an HTTP method and path already generated via dbRouting, this definition will override the default dynamic one, allowing full customization of the behavior or response structure.

These APIs are powerful in that they integrate with the Swagger documentation system and offer fine-grained control over routing logic, validation, and authentication.

MethodPathHandling

Each method defined under an apis entry is built using a MethodPathHandling object, which includes:

  • swaggerBody (optional): An object that defines the request body schema used for Swagger generation. It includes:

    • schema: the name of the registered schema,

    • required (optional): whether the body is required,

    • description (optional): a textual description of the body,

    • comType (optional): the content type, which can be either 'multipart/form-data' or 'application/json' if nothing is specified.

  • swaggerResponses (optional): A map of HTTP status codes to either Swagger $ref definitions or full SwaggerResponse objects. This controls the structure and description of responses in Swagger UI.

  • swaggerParameters (optional): A list of query/path/header parameters, used to populate Swagger documentation.

  • middlewares (optional): An array of Express-compatible middlewares that will be executed before the final handler.

  • handler (required): An asynchronous function of the form (req: Request, res: ExpressResponse) => Promise<ExpressReturn>. This is the actual logic of the API endpoint, and it must return a response following the ExpressReturn structure:

Check the related utils section on this doc to look at the apiOk/apiNok usage.

Last updated