UNPKG

express-multitenancy

Version:

Express middleware for managing multi-tenant applications with configurable tenant resolution strategies

230 lines (229 loc) 7.96 kB
import { Request } from 'express'; /** * Interface for tenant identification strategies. * * Implement this interface to create custom strategies for identifying * the current tenant from an incoming request. This allows for * flexible tenant resolution based on different parts of the request. */ export interface Strategy { /** * Resolves the tenant ID from the request. * * @param req - Express request object to analyze for tenant information * @returns A Promise resolving to the tenant ID string if found, or null if no tenant could be identified */ resolveTenantId(req: Request): Promise<string | null>; } /** * Strategy for identifying tenants based on HTTP headers. * * This strategy extracts the tenant ID from a specified HTTP header. * It's a common approach for API-based multi-tenant applications. * * @example * ``` * // Create a strategy that looks for tenant ID in x-tenant-id header * const headerStrategy = new HeaderStrategy('x-tenant-id'); * ``` */ export declare class HeaderStrategy implements Strategy { private headerName; /** * Creates a new HeaderStrategy instance. * * @param headerName - The name of the HTTP header containing the tenant ID (case insensitive) * Defaults to 'x-tenant-id' if not provided. */ constructor(headerName?: string); /** * Extracts tenant ID from the specified HTTP header. * * @param req - Express request object * @returns The tenant ID from the header, or null if header is not present */ resolveTenantId(req: Request): Promise<string | null>; } /** * Strategy for identifying tenants based on hostname. * * This strategy extracts the tenant ID from the hostname using a regular expression pattern. * It's useful for subdomain-based multi-tenancy (e.g., tenant1.example.com). * * @example * ``` * // Create a strategy that extracts tenant ID from subdomain * const hostStrategy = new HostStrategy(/^([^.]+)/); // matches "tenant1" from "tenant1.example.com" * ``` */ export declare class HostStrategy implements Strategy { private pattern; /** * Creates a new HostStrategy instance. * * @param pattern - Regular expression pattern with a capture group for the tenant ID */ constructor(pattern: RegExp); /** * Extracts tenant ID from the hostname using the provided regex pattern. * * @param req - Express request object * @returns The tenant ID extracted from hostname, or null if no match */ resolveTenantId(req: Request): Promise<string | null>; } /** * Strategy for identifying tenants based on route parameters. * * This strategy extracts the tenant ID from route parameters. * It's useful for route-based multi-tenancy (e.g., /api/:tenantId/resources). * * @example * ``` * // Define a route with tenant parameter * app.get('/api/:tenantId/resources', (req, res) => { ... }); * * // Create a strategy that extracts tenant ID from route parameter * const routeStrategy = new RouteStrategy('tenantId'); * * // For Express 5 compatibility, mount the middleware on specific routes * app.use(['/api/:tenantId', '/api/:tenantId/*'], multitenancy({ * strategies: [routeStrategy], * store: myStore * })); * ``` */ export declare class RouteStrategy implements Strategy { private paramName; /** * Creates a new RouteStrategy instance. * * @param paramName - Name of the route parameter to extract as tenant ID (default: 'tenantId') */ constructor(paramName?: string); /** * Extracts tenant ID from the route parameter specified in constructor. * * @param req - Express request object * @returns The tenant ID from route parameter, or null if not present */ resolveTenantId(req: Request): Promise<string | null>; } /** * Options for the BasePathStrategy. */ export interface BasePathOptions { /** * If true, the tenant path segment will be removed from req.path after tenant resolution, * making the rest of the application unaware of the tenant segment in the URL. * For example, "/tenant1/api/resources" becomes "/api/resources". */ rebasePath?: boolean; /** * The position of the path segment to use as tenant ID (1-based index). * For example, if the URL is "/tenant1/api/resources", and position is 1, * the tenant ID will be "tenant1". */ position: number; } /** * Strategy for identifying tenants based on URL path segments. * * This strategy extracts the tenant ID from a specific segment of the URL path. * It's useful for path-based multi-tenancy (e.g., /tenant1/api/resources). * * @example * ``` * // Create a strategy that uses the first path segment as tenant ID * const basePathStrategy = new BasePathStrategy({ position: 1 }); // extracts "tenant1" from "/tenant1/api/resources" * * // Create a strategy that also rebases the path (removes the tenant segment) * const basePathStrategy = new BasePathStrategy({ rebasePath: true }); * // After tenant resolution, "/tenant1/api/resources" becomes "/api/resources" * ``` */ export declare class BasePathStrategy implements Strategy { private options; /** * Creates a new BasePathStrategy instance. * * @param options - Configuration options for the strategy */ constructor(options?: Partial<BasePathOptions>); /** * Extracts tenant ID from the specified position in the URL path. * * @param req - Express request object * @returns The tenant ID from the path segment, or null if not present */ resolveTenantId(req: Request): Promise<string | null>; } /** * Represents a JWT or authentication payload with flexible structure */ export interface AuthPayload { [key: string]: unknown; } /** * Options for the ClaimStrategy. */ export interface ClaimStrategyOptions { /** * Optional function to extract the auth payload from the request * If not provided, the strategy will try to extract from Authorization header */ authExtractor?: (req: Request) => AuthPayload | null; /** * Whether to enable debug logging for claim extraction * Default: false */ debug?: boolean; } /** * Strategy for identifying tenants based on authentication claims. * * This strategy extracts the tenant ID from JWT claims or other auth tokens. * It's useful for applications where tenant context is tied to user authentication. * * @example * ``` * // Create a strategy that extracts tenant ID from a specific claim * const claimStrategy = new ClaimStrategy('tenantId'); * * // Extract from nested claim property * const nestedClaimStrategy = new ClaimStrategy('app_metadata.tenant_id'); * * // With custom auth extractor * const customStrategy = new ClaimStrategy('tenant', { * authExtractor: (req) => req.user // For passport or similar auth middleware * }); * ``` */ export declare class ClaimStrategy implements Strategy { private claimPath; private authExtractor; private debug; /** * Creates a new ClaimStrategy instance. * * @param claimPath - Path to the claim containing tenant ID (dot notation for nested properties) * @param options - Configuration options for the strategy */ constructor(claimPath: string, options?: ClaimStrategyOptions); /** * Extracts tenant ID from the authentication claims. * * @param req - Express request object * @returns The tenant ID from the claims, or null if not found */ resolveTenantId(req: Request): Promise<string | null>; /** * Default extractor that looks for JWT in Authorization header. * This handles "Bearer <token>" format and attempts to decode the JWT. */ private defaultAuthExtractor; /** * Gets a nested property from an object using dot notation. */ private getNestedProperty; }