import * as plugins from './plugins.js'; import type { IDomainConfig, IPortProxySettings } from './classes.pp.interfaces.js'; /** * Manages domain configurations and target selection */ export class DomainConfigManager { // Track round-robin indices for domain configs private domainTargetIndices: Map = new Map(); constructor(private settings: IPortProxySettings) {} /** * Updates the domain configurations */ public updateDomainConfigs(newDomainConfigs: IDomainConfig[]): void { this.settings.domainConfigs = newDomainConfigs; // Reset target indices for removed configs const currentConfigSet = new Set(newDomainConfigs); for (const [config] of this.domainTargetIndices) { if (!currentConfigSet.has(config)) { this.domainTargetIndices.delete(config); } } } /** * Get all domain configurations */ public getDomainConfigs(): IDomainConfig[] { return this.settings.domainConfigs; } /** * Find domain config matching a server name */ public findDomainConfig(serverName: string): IDomainConfig | undefined { if (!serverName) return undefined; return this.settings.domainConfigs.find((config) => config.domains.some((d) => plugins.minimatch(serverName, d)) ); } /** * Find domain config for a specific port */ public findDomainConfigForPort(port: number): IDomainConfig | undefined { return this.settings.domainConfigs.find( (domain) => domain.portRanges && domain.portRanges.length > 0 && this.isPortInRanges(port, domain.portRanges) ); } /** * Check if a port is within any of the given ranges */ public isPortInRanges(port: number, ranges: Array<{ from: number; to: number }>): boolean { return ranges.some((range) => port >= range.from && port <= range.to); } /** * Get target IP with round-robin support */ public getTargetIP(domainConfig: IDomainConfig): string { if (domainConfig.targetIPs && domainConfig.targetIPs.length > 0) { const currentIndex = this.domainTargetIndices.get(domainConfig) || 0; const ip = domainConfig.targetIPs[currentIndex % domainConfig.targetIPs.length]; this.domainTargetIndices.set(domainConfig, currentIndex + 1); return ip; } return this.settings.targetIP || 'localhost'; } /** * Checks if a domain should use NetworkProxy */ public shouldUseNetworkProxy(domainConfig: IDomainConfig): boolean { return !!domainConfig.useNetworkProxy; } /** * Gets the NetworkProxy port for a domain */ public getNetworkProxyPort(domainConfig: IDomainConfig): number | undefined { return domainConfig.useNetworkProxy ? (domainConfig.networkProxyPort || this.settings.networkProxyPort) : undefined; } /** * Get effective allowed and blocked IPs for a domain */ public getEffectiveIPRules(domainConfig: IDomainConfig): { allowedIPs: string[], blockedIPs: string[] } { return { allowedIPs: [ ...domainConfig.allowedIPs, ...(this.settings.defaultAllowedIPs || []) ], blockedIPs: [ ...(domainConfig.blockedIPs || []), ...(this.settings.defaultBlockedIPs || []) ] }; } /** * Get connection timeout for a domain */ public getConnectionTimeout(domainConfig?: IDomainConfig): number { if (domainConfig?.connectionTimeout) { return domainConfig.connectionTimeout; } return this.settings.maxConnectionLifetime || 86400000; // 24 hours default } }