import type { IRouteConfig, IRouteMatch, IRouteAction, IRouteTarget, IRouteTls, IRouteRedirect, IRouteSecurity, IRouteAdvanced, TPortRange } from './models/route-types.js'; /** * Basic helper function to create a route configuration */ export function createRoute( match: IRouteMatch, action: IRouteAction, metadata?: { name?: string; description?: string; priority?: number; tags?: string[]; } ): IRouteConfig { return { match, action, ...metadata }; } /** * Create a basic HTTP route configuration */ export function createHttpRoute( options: { ports?: number | number[]; // Default: 80 domains?: string | string[]; path?: string; target: IRouteTarget; headers?: Record; security?: IRouteSecurity; name?: string; description?: string; priority?: number; tags?: string[]; } ): IRouteConfig { return createRoute( { ports: options.ports || 80, ...(options.domains ? { domains: options.domains } : {}), ...(options.path ? { path: options.path } : {}) }, { type: 'forward', target: options.target, ...(options.headers || options.security ? { advanced: { ...(options.headers ? { headers: options.headers } : {}) }, ...(options.security ? { security: options.security } : {}) } : {}) }, { name: options.name || 'HTTP Route', description: options.description, priority: options.priority, tags: options.tags } ); } /** * Create an HTTPS route configuration with TLS termination */ export function createHttpsRoute( options: { ports?: number | number[]; // Default: 443 domains: string | string[]; path?: string; target: IRouteTarget; tlsMode?: 'terminate' | 'terminate-and-reencrypt'; certificate?: 'auto' | { key: string; cert: string }; headers?: Record; security?: IRouteSecurity; name?: string; description?: string; priority?: number; tags?: string[]; } ): IRouteConfig { return createRoute( { ports: options.ports || 443, domains: options.domains, ...(options.path ? { path: options.path } : {}) }, { type: 'forward', target: options.target, tls: { mode: options.tlsMode || 'terminate', certificate: options.certificate || 'auto' }, ...(options.headers || options.security ? { advanced: { ...(options.headers ? { headers: options.headers } : {}) }, ...(options.security ? { security: options.security } : {}) } : {}) }, { name: options.name || 'HTTPS Route', description: options.description, priority: options.priority, tags: options.tags } ); } /** * Create an HTTPS passthrough route configuration */ export function createPassthroughRoute( options: { ports?: number | number[]; // Default: 443 domains?: string | string[]; target: IRouteTarget; security?: IRouteSecurity; name?: string; description?: string; priority?: number; tags?: string[]; } ): IRouteConfig { return createRoute( { ports: options.ports || 443, ...(options.domains ? { domains: options.domains } : {}) }, { type: 'forward', target: options.target, tls: { mode: 'passthrough' }, ...(options.security ? { security: options.security } : {}) }, { name: options.name || 'HTTPS Passthrough Route', description: options.description, priority: options.priority, tags: options.tags } ); } /** * Create a redirect route configuration */ export function createRedirectRoute( options: { ports?: number | number[]; // Default: 80 domains?: string | string[]; path?: string; redirectTo: string; statusCode?: 301 | 302 | 307 | 308; name?: string; description?: string; priority?: number; tags?: string[]; } ): IRouteConfig { return createRoute( { ports: options.ports || 80, ...(options.domains ? { domains: options.domains } : {}), ...(options.path ? { path: options.path } : {}) }, { type: 'redirect', redirect: { to: options.redirectTo, status: options.statusCode || 301 } }, { name: options.name || 'Redirect Route', description: options.description, priority: options.priority, tags: options.tags } ); } /** * Create an HTTP to HTTPS redirect route configuration */ export function createHttpToHttpsRedirect( options: { domains: string | string[]; statusCode?: 301 | 302 | 307 | 308; name?: string; priority?: number; } ): IRouteConfig { const domainArray = Array.isArray(options.domains) ? options.domains : [options.domains]; return createRedirectRoute({ ports: 80, domains: options.domains, redirectTo: 'https://{domain}{path}', statusCode: options.statusCode || 301, name: options.name || `HTTP to HTTPS Redirect for ${domainArray.join(', ')}`, priority: options.priority || 100 // High priority for redirects }); } /** * Create a block route configuration */ export function createBlockRoute( options: { ports: number | number[]; domains?: string | string[]; clientIp?: string[]; name?: string; description?: string; priority?: number; tags?: string[]; } ): IRouteConfig { return createRoute( { ports: options.ports, ...(options.domains ? { domains: options.domains } : {}), ...(options.clientIp ? { clientIp: options.clientIp } : {}) }, { type: 'block' }, { name: options.name || 'Block Route', description: options.description, priority: options.priority || 1000, // Very high priority for blocks tags: options.tags } ); } /** * Create a load balancer route configuration */ export function createLoadBalancerRoute( options: { ports?: number | number[]; // Default: 443 domains: string | string[]; path?: string; targets: string[]; // Array of host names/IPs for load balancing targetPort: number; tlsMode?: 'passthrough' | 'terminate' | 'terminate-and-reencrypt'; certificate?: 'auto' | { key: string; cert: string }; headers?: Record; security?: IRouteSecurity; name?: string; description?: string; tags?: string[]; } ): IRouteConfig { const useTls = options.tlsMode !== undefined; const defaultPort = useTls ? 443 : 80; return createRoute( { ports: options.ports || defaultPort, domains: options.domains, ...(options.path ? { path: options.path } : {}) }, { type: 'forward', target: { host: options.targets, port: options.targetPort }, ...(useTls ? { tls: { mode: options.tlsMode!, ...(options.tlsMode !== 'passthrough' && options.certificate ? { certificate: options.certificate } : {}) } } : {}), ...(options.headers || options.security ? { advanced: { ...(options.headers ? { headers: options.headers } : {}) }, ...(options.security ? { security: options.security } : {}) } : {}) }, { name: options.name || 'Load Balanced Route', description: options.description || `Load balancing across ${options.targets.length} backends`, tags: options.tags } ); } /** * Create a complete HTTPS server configuration with HTTP redirect */ export function createHttpsServer( options: { domains: string | string[]; target: IRouteTarget; certificate?: 'auto' | { key: string; cert: string }; security?: IRouteSecurity; addHttpRedirect?: boolean; name?: string; } ): IRouteConfig[] { const routes: IRouteConfig[] = []; const domainArray = Array.isArray(options.domains) ? options.domains : [options.domains]; // Add HTTPS route routes.push(createHttpsRoute({ domains: options.domains, target: options.target, certificate: options.certificate || 'auto', security: options.security, name: options.name || `HTTPS Server for ${domainArray.join(', ')}` })); // Add HTTP to HTTPS redirect if requested if (options.addHttpRedirect !== false) { routes.push(createHttpToHttpsRedirect({ domains: options.domains, name: `HTTP to HTTPS Redirect for ${domainArray.join(', ')}`, priority: 100 })); } return routes; } /** * Create a port range configuration from various input formats */ export function createPortRange( ports: number | number[] | string | Array<{ from: number; to: number }> ): TPortRange { // If it's a string like "80,443" or "8000-9000", parse it if (typeof ports === 'string') { if (ports.includes('-')) { // Handle range like "8000-9000" const [start, end] = ports.split('-').map(p => parseInt(p.trim(), 10)); return [{ from: start, to: end }]; } else if (ports.includes(',')) { // Handle comma-separated list like "80,443,8080" return ports.split(',').map(p => parseInt(p.trim(), 10)); } else { // Handle single port as string return parseInt(ports.trim(), 10); } } // Otherwise return as is return ports; } /** * Create a security configuration object */ export function createSecurityConfig( options: { allowedIps?: string[]; blockedIps?: string[]; maxConnections?: number; authentication?: { type: 'basic' | 'digest' | 'oauth'; // Auth-specific options [key: string]: any; }; } ): IRouteSecurity { return { ...(options.allowedIps ? { allowedIps: options.allowedIps } : {}), ...(options.blockedIps ? { blockedIps: options.blockedIps } : {}), ...(options.maxConnections ? { maxConnections: options.maxConnections } : {}), ...(options.authentication ? { authentication: options.authentication } : {}) }; } /** * Create a static file server route */ export function createStaticFileRoute( options: { ports?: number | number[]; // Default: 80 domains: string | string[]; path?: string; targetDirectory: string; tlsMode?: 'terminate' | 'terminate-and-reencrypt'; certificate?: 'auto' | { key: string; cert: string }; headers?: Record; security?: IRouteSecurity; name?: string; description?: string; priority?: number; tags?: string[]; } ): IRouteConfig { const useTls = options.tlsMode !== undefined; const defaultPort = useTls ? 443 : 80; return createRoute( { ports: options.ports || defaultPort, domains: options.domains, ...(options.path ? { path: options.path } : {}) }, { type: 'forward', target: { host: 'localhost', // Static file serving is typically handled locally port: 0, // Special value indicating a static file server preservePort: false }, ...(useTls ? { tls: { mode: options.tlsMode!, certificate: options.certificate || 'auto' } } : {}), advanced: { ...(options.headers ? { headers: options.headers } : {}), staticFiles: { directory: options.targetDirectory, indexFiles: ['index.html', 'index.htm'] } }, ...(options.security ? { security: options.security } : {}) }, { name: options.name || 'Static File Server', description: options.description || `Serving static files from ${options.targetDirectory}`, priority: options.priority, tags: options.tags } ); } /** * Create a test route for debugging purposes */ export function createTestRoute( options: { ports?: number | number[]; // Default: 8000 domains?: string | string[]; path?: string; response?: { status?: number; headers?: Record; body?: string; }; name?: string; } ): IRouteConfig { return createRoute( { ports: options.ports || 8000, ...(options.domains ? { domains: options.domains } : {}), ...(options.path ? { path: options.path } : {}) }, { type: 'forward', target: { host: 'test', // Special value indicating a test route port: 0 }, advanced: { testResponse: { status: options.response?.status || 200, headers: options.response?.headers || { 'Content-Type': 'text/plain' }, body: options.response?.body || 'Test route is working!' } } }, { name: options.name || 'Test Route', description: 'Route for testing and debugging', priority: 500, tags: ['test', 'debug'] } ); }