import { Server as HTTPServer } from 'http'; import express from 'express'; import { z } from 'zod'; import { CacheConfig } from '../Cache/types.js'; import { HttpMethod } from '../API/Request.js'; import { ResponseErrorType } from '../API/Response.js'; import Transaction, { TransactionConfig, TransactionExecution, StringMap } from '../BaseEvent/Transaction.js'; /** * Configuration options for rate limiting on a specific route. * @property {number} [windowMs] - Time window in milliseconds for rate limiting (default: 60000 - 1 minute) * @property {number} [limit] - Maximum number of requests allowed per window (default: 60) * @property {string} [message] - Custom error message for rate limit exceeded * @property {'ip' | 'userId' | ((req: express.Request) => string)} [keyGenerator] - Strategy for generating rate limit keys */ export interface RateLimitConfig { windowMs?: number; limit?: number; message?: string; keyGenerator?: 'ip' | 'userId' | ((req: express.Request) => string); skip?: (req: express.Request) => boolean; } /** * Global rate limiting configuration for the router. * @property {boolean} [enabled] - Whether rate limiting is enabled (default: true if config provided) * @property {number} [windowMs] - Time window in milliseconds (default: 60000 - 1 minute) * @property {number} [limit] - Maximum requests per window per key (default: 60) * @property {(req: express.Request) => string} [keyGenerator] - Function to generate rate limit key (default: IP-based) * @property {(req: express.Request, res: express.Response) => void} [handler] - Custom handler for rate limit exceeded * @property {(req: express.Request) => boolean} [skip] - Function to skip rate limiting for certain requests * @property {'memory' | 'redis'} [store] - Storage backend for rate limit data * @property {object} [redis] - Redis rate limit options when using Redis store */ export interface GlobalRateLimitConfig { enabled?: boolean; windowMs?: number; limit?: number; keyGenerator?: (req: express.Request) => string; handler?: (req: express.Request, res: express.Response) => void; skip?: (req: express.Request) => boolean; store?: 'memory' | 'redis'; redis?: { prefix?: string; }; } /** * Represents a route in an API. * @template InputType - The type of the input data for the route. * @template OutputType - The type of the output data for the route. * @property {string} path - The path of the route. * @property {string} method - The HTTP method of the route. * @property {TransactionExecution, OutputType | ResponseErrorType>} handler - The handler function for the route. * @property {?z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects}[inputSchema] - The input schema for validating the input data. ZodEffects is supported so schemas using .refine/.superRefine/.transform can be passed directly. * @property {?z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects}[pathSchema] - The path schema for validating the path data. * @property {?z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects}[querySchema] - The query schema for validating the query data. */ export interface Route { /** * Represents a file path as a string. * @param {string} path - The file path. * @returns None */ path: string | string[]; /** * Represents the method used in an API request. * @type {string} */ method: HttpMethod; /** * Represents a handler for executing a transaction with the given input type and output type. * @param {Transaction} transaction - The transaction to execute. * @param {OutputType | ResponseErrorType} - The output type or response error type of the transaction. */ handler: TransactionExecution, OutputType | ResponseErrorType>; /** * An optional input schema for validating the structure of the input data. * ZodEffects is supported so schemas wrapped with .refine/.superRefine/.transform can be used directly. * * @type {?z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects} */ inputSchema?: z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects; /** * An optional input schema for validating the structure of the path params. * * @type {?z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects} */ pathSchema?: z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects; /** * An optional input schema for validating the structure of the query params. * * @type {?z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects} */ querySchema?: z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodEffects; /** * An optional openApi object with extra metadata for docs generation. */ openApi?: { summary: string; description: string; tags?: string[]; outputSchema?: z.ZodObject | z.ZodUnion | z.ZodIntersection | z.ZodType; successCode?: number; security?: { [key: string]: string[] | never[]; }[]; }; /** * Optional rate limiting configuration for this specific route. * Set to `false` to disable global rate limiting for this route. * @type {RateLimitConfig | false} */ rateLimit?: RateLimitConfig | false; } export type AnyRoute = Route; /** * Represents the configuration options for a router. * @typedef {TransactionConfig & { * routes: Route[] * port?: number * timeout?: number * cors?: { * origin?: string | string[] * headers?: string[] * allowCredentials?: boolean * } * healthCheckRoute?: string * }} RouterConfig * @property {Route[]} routes - The routes to be configured in the router. * @property {number} [port] - The port number to listen on. If not specified, a default port will be used. * @property {number} [timeout] - The timeout duration for requests in milliseconds. If not specified, a default timeout will be */ export type RouterConfig = TransactionConfig & { /** * An array of route objects representing the available routes in the application. * @type {Route[]} */ routes: AnyRoute[]; /** * The port number for the server to listen on. * @type {number | undefined} */ port?: number; /** * Optional timeout value in milliseconds. * @type {number | undefined} */ timeout?: number; /** * Configuration options for Cross-Origin Resource Sharing (CORS). * @property {string | string[]} [origin] - The allowed origin(s) for CORS requests. * @property {string[]} [headers] - The allowed headers for CORS requests. * @property {boolean} [allowCredentials] - Whether to allow credentials (cookies, HTTP authentication, and client-side SSL certificates) to be sent in CORS requests. */ cors?: { origin?: string | string[]; headers?: string[]; allowCredentials?: boolean; }; /** * Shared cache configuration used by WAPI-managed Redis integrations. * Required when rateLimit.store is set to 'redis'. * @type {CacheConfig<'redis'> | undefined} */ cache?: CacheConfig<'redis'>; /** * The route for the health check endpoint. * @type {string | undefined} */ healthCheckRoute?: string; /** * Paths that should not be logged (e.g., health checks, metrics). * These requests will still be processed but won't create verbose logs. * @type {string[] | undefined} */ noLogPaths?: string[]; /** * Global rate limiting configuration for all routes. * Individual routes can override this with their own rateLimit config. * @type {GlobalRateLimitConfig | undefined} */ rateLimit?: GlobalRateLimitConfig; containerSetupHook?: (server: HTTPServer, app: express.Express) => Promise; }; /** * Represents a router that handles routing logic for a web application. */ export default class Router { /** * The configuration object for the router. */ private readonly config; /** * The private readonly server instance. */ private readonly server; /** * Constructs a new instance of the Router class. * @param {RouterConfig} config - The configuration object for the router. * @returns None */ constructor(config: RouterConfig); /** * Retrieves the export function from the server. * @returns {CallableFunction} The export function from the server. */ getExport(): CallableFunction; /** * Checks if the current element is a container. * @returns {boolean} - True if the element is a container, false otherwise. */ private isContainer; }