From f8647516b5ba65cfea0259d973aea009303033fc Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Fri, 9 May 2025 22:46:53 +0000 Subject: [PATCH] fix(typescript): Refactor types and interfaces to use consistent I prefix and update related tests --- changelog.md | 8 +++ test/test.certprovisioner.unit.ts | 27 ++++---- test/test.forwarding.examples.ts | 12 ++-- test/test.forwarding.ts | 18 ++--- test/test.forwarding.unit.ts | 14 ++-- test/test.smartproxy.ts | 14 +++- ts/00_commitinfo_data.ts | 2 +- ts/certificate/acme/acme-factory.ts | 6 +- ts/certificate/acme/challenge-handler.ts | 6 +- ts/certificate/index.ts | 8 +-- ts/certificate/models/certificate-types.ts | 3 +- ts/certificate/providers/cert-provisioner.ts | 46 ++++++------- ts/certificate/storage/file-storage.ts | 8 +-- ts/certificate/utils/certificate-helpers.ts | 4 +- ts/common/port80-adapter.ts | 2 +- ts/forwarding/config/domain-config.ts | 15 ++--- ts/forwarding/config/domain-manager.ts | 18 ++--- ts/forwarding/config/forwarding-types.ts | 65 ++++++++----------- ts/forwarding/factory/forwarding-factory.ts | 22 +++---- ts/forwarding/handlers/base-handler.ts | 4 +- ts/forwarding/handlers/http-handler.ts | 15 ++++- .../handlers/https-passthrough-handler.ts | 15 ++++- .../https-terminate-to-http-handler.ts | 4 +- .../https-terminate-to-https-handler.ts | 4 +- ts/http/models/http-types.ts | 19 +++--- ts/http/port80/acme-interfaces.ts | 16 ++--- ts/http/port80/challenge-responder.ts | 32 ++++----- ts/http/port80/port80-handler.ts | 40 ++++++------ ts/http/router/proxy-router.ts | 22 +++---- .../network-proxy/certificate-manager.ts | 20 +++--- ts/proxies/network-proxy/connection-pool.ts | 8 +-- ts/proxies/network-proxy/models/types.ts | 34 ++++------ ts/proxies/network-proxy/network-proxy.ts | 22 +++---- ts/proxies/network-proxy/request-handler.ts | 12 ++-- ts/proxies/network-proxy/websocket-handler.ts | 16 ++--- ts/proxies/smart-proxy/connection-handler.ts | 22 +++---- ts/proxies/smart-proxy/connection-manager.ts | 28 ++++---- .../smart-proxy/domain-config-manager.ts | 58 ++++++++--------- ts/proxies/smart-proxy/models/interfaces.ts | 32 ++++----- .../smart-proxy/network-proxy-bridge.ts | 22 +++---- ts/proxies/smart-proxy/port-range-manager.ts | 4 +- ts/proxies/smart-proxy/security-manager.ts | 4 +- ts/proxies/smart-proxy/smart-proxy.ts | 20 +++--- ts/proxies/smart-proxy/timeout-manager.ts | 20 +++--- ts/proxies/smart-proxy/tls-manager.ts | 4 +- 45 files changed, 403 insertions(+), 392 deletions(-) diff --git a/changelog.md b/changelog.md index 3cca057..71d8b7b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2025-05-09 - 13.1.1 - fix(typescript) +Refactor types and interfaces to use consistent 'I' prefix and update related tests + +- Replaced DomainConfig with IDomainConfig and SmartProxyOptions with ISmartProxyOptions in various modules +- Renamed SmartProxyCertProvisionObject to TSmartProxyCertProvisionObject for clarity +- Standardized type names (e.g. ForwardConfig → IForwardConfig, Logger → ILogger) across proxy, forwarding, and certificate modules +- Updated tests and helper functions to reflect new type names and ensure compatibility + ## 2025-05-09 - 13.1.0 - feat(docs) Update README to reflect new modular architecture and expanded core utilities: add Project Architecture Overview, update export paths and API references, and mark plan tasks as completed diff --git a/test/test.certprovisioner.unit.ts b/test/test.certprovisioner.unit.ts index daa6cd2..defcdc3 100644 --- a/test/test.certprovisioner.unit.ts +++ b/test/test.certprovisioner.unit.ts @@ -1,9 +1,10 @@ import { tap, expect } from '@push.rocks/tapbundle'; import * as plugins from '../ts/plugins.js'; import { CertProvisioner } from '../ts/certificate/providers/cert-provisioner.js'; -import type { DomainConfig } from '../ts/forwarding/config/forwarding-types.js'; -import type { SmartProxyCertProvisionObject } from '../ts/certificate/models/certificate-types.js'; -import type { CertificateData } from '../ts/certificate/models/certificate-types.js'; +import type { IDomainConfig } from '../ts/forwarding/config/domain-config.js'; +import type { ICertificateData } from '../ts/certificate/models/certificate-types.js'; +// Import SmartProxyCertProvisionObject type alias +import type { TSmartProxyCertProvisionObject } from '../ts/certificate/providers/cert-provisioner.js'; // Fake Port80Handler stub class FakePort80Handler extends plugins.EventEmitter { @@ -19,15 +20,15 @@ class FakePort80Handler extends plugins.EventEmitter { // Fake NetworkProxyBridge stub class FakeNetworkProxyBridge { - public appliedCerts: CertificateData[] = []; - applyExternalCertificate(cert: CertificateData) { + public appliedCerts: ICertificateData[] = []; + applyExternalCertificate(cert: ICertificateData) { this.appliedCerts.push(cert); } } tap.test('CertProvisioner handles static provisioning', async () => { const domain = 'static.com'; - const domainConfigs: DomainConfig[] = [{ + const domainConfigs: IDomainConfig[] = [{ domains: [domain], forwarding: { type: 'https-terminate-to-https', @@ -37,7 +38,7 @@ tap.test('CertProvisioner handles static provisioning', async () => { const fakePort80 = new FakePort80Handler(); const fakeBridge = new FakeNetworkProxyBridge(); // certProvider returns static certificate - const certProvider = async (d: string): Promise => { + const certProvider = async (d: string): Promise => { expect(d).toEqual(domain); return { domainName: domain, @@ -75,7 +76,7 @@ tap.test('CertProvisioner handles static provisioning', async () => { tap.test('CertProvisioner handles http01 provisioning', async () => { const domain = 'http01.com'; - const domainConfigs: DomainConfig[] = [{ + const domainConfigs: IDomainConfig[] = [{ domains: [domain], forwarding: { type: 'https-terminate-to-http', @@ -85,7 +86,7 @@ tap.test('CertProvisioner handles http01 provisioning', async () => { const fakePort80 = new FakePort80Handler(); const fakeBridge = new FakeNetworkProxyBridge(); // certProvider returns http01 directive - const certProvider = async (): Promise => 'http01'; + const certProvider = async (): Promise => 'http01'; const prov = new CertProvisioner( domainConfigs, fakePort80 as any, @@ -106,7 +107,7 @@ tap.test('CertProvisioner handles http01 provisioning', async () => { tap.test('CertProvisioner on-demand http01 renewal', async () => { const domain = 'renew.com'; - const domainConfigs: DomainConfig[] = [{ + const domainConfigs: IDomainConfig[] = [{ domains: [domain], forwarding: { type: 'https-terminate-to-http', @@ -115,7 +116,7 @@ tap.test('CertProvisioner on-demand http01 renewal', async () => { }]; const fakePort80 = new FakePort80Handler(); const fakeBridge = new FakeNetworkProxyBridge(); - const certProvider = async (): Promise => 'http01'; + const certProvider = async (): Promise => 'http01'; const prov = new CertProvisioner( domainConfigs, fakePort80 as any, @@ -132,7 +133,7 @@ tap.test('CertProvisioner on-demand http01 renewal', async () => { tap.test('CertProvisioner on-demand static provisioning', async () => { const domain = 'ondemand.com'; - const domainConfigs: DomainConfig[] = [{ + const domainConfigs: IDomainConfig[] = [{ domains: [domain], forwarding: { type: 'https-terminate-to-https', @@ -141,7 +142,7 @@ tap.test('CertProvisioner on-demand static provisioning', async () => { }]; const fakePort80 = new FakePort80Handler(); const fakeBridge = new FakeNetworkProxyBridge(); - const certProvider = async (): Promise => ({ + const certProvider = async (): Promise => ({ domainName: domain, publicKey: 'PKEY', privateKey: 'PRIV', diff --git a/test/test.forwarding.examples.ts b/test/test.forwarding.examples.ts index b10a0e9..439b8b9 100644 --- a/test/test.forwarding.examples.ts +++ b/test/test.forwarding.examples.ts @@ -2,8 +2,8 @@ import * as plugins from '../ts/plugins.js'; import { tap, expect } from '@push.rocks/tapbundle'; import { SmartProxy } from '../ts/proxies/smart-proxy/index.js'; -import type { DomainConfig } from '../ts/forwarding/config/forwarding-types.js'; -import type { ForwardingType } from '../ts/forwarding/config/forwarding-types.js'; +import type { TForwardingType } from '../ts/forwarding/config/forwarding-types.js'; +import type { IDomainConfig } from '../ts/forwarding/config/domain-config.js'; import { httpOnly, httpsPassthrough, @@ -14,7 +14,7 @@ import { // Test to demonstrate various forwarding configurations tap.test('Forwarding configuration examples', async (tools) => { // Example 1: HTTP-only configuration - const httpOnlyConfig: DomainConfig = { + const httpOnlyConfig: IDomainConfig = { domains: ['http.example.com'], forwarding: httpOnly({ target: { @@ -30,7 +30,7 @@ tap.test('Forwarding configuration examples', async (tools) => { expect(httpOnlyConfig.forwarding.type).toEqual('http-only'); // Example 2: HTTPS Passthrough (SNI) - const httpsPassthroughConfig: DomainConfig = { + const httpsPassthroughConfig: IDomainConfig = { domains: ['pass.example.com'], forwarding: httpsPassthrough({ target: { @@ -47,7 +47,7 @@ tap.test('Forwarding configuration examples', async (tools) => { expect(Array.isArray(httpsPassthroughConfig.forwarding.target.host)).toBeTrue(); // Example 3: HTTPS Termination to HTTP Backend - const terminateToHttpConfig: DomainConfig = { + const terminateToHttpConfig: IDomainConfig = { domains: ['secure.example.com'], forwarding: tlsTerminateToHttp({ target: { @@ -75,7 +75,7 @@ tap.test('Forwarding configuration examples', async (tools) => { expect(terminateToHttpConfig.forwarding.http?.redirectToHttps).toBeTrue(); // Example 4: HTTPS Termination to HTTPS Backend - const terminateToHttpsConfig: DomainConfig = { + const terminateToHttpsConfig: IDomainConfig = { domains: ['proxy.example.com'], forwarding: tlsTerminateToHttps({ target: { diff --git a/test/test.forwarding.ts b/test/test.forwarding.ts index 2aacae5..6364cb2 100644 --- a/test/test.forwarding.ts +++ b/test/test.forwarding.ts @@ -1,6 +1,6 @@ import { tap, expect } from '@push.rocks/tapbundle'; import * as plugins from '../ts/plugins.js'; -import type { ForwardConfig, ForwardingType } from '../ts/forwarding/config/forwarding-types.js'; +import type { IForwardConfig, TForwardingType } from '../ts/forwarding/config/forwarding-types.js'; // First, import the components directly to avoid issues with compiled modules import { ForwardingHandlerFactory } from '../ts/forwarding/factory/forwarding-factory.js'; @@ -17,7 +17,7 @@ const helpers = { tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => { // HTTP-only defaults - const httpConfig: ForwardConfig = { + const httpConfig: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 } }; @@ -26,7 +26,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => expect(expandedHttpConfig.http?.enabled).toEqual(true); // HTTPS-passthrough defaults - const passthroughConfig: ForwardConfig = { + const passthroughConfig: IForwardConfig = { type: 'https-passthrough', target: { host: 'localhost', port: 443 } }; @@ -36,7 +36,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => expect(expandedPassthroughConfig.http?.enabled).toEqual(false); // HTTPS-terminate-to-http defaults - const terminateToHttpConfig: ForwardConfig = { + const terminateToHttpConfig: IForwardConfig = { type: 'https-terminate-to-http', target: { host: 'localhost', port: 3000 } }; @@ -48,7 +48,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => expect(expandedTerminateToHttpConfig.acme?.maintenance).toEqual(true); // HTTPS-terminate-to-https defaults - const terminateToHttpsConfig: ForwardConfig = { + const terminateToHttpsConfig: IForwardConfig = { type: 'https-terminate-to-https', target: { host: 'localhost', port: 8443 } }; @@ -62,7 +62,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => tap.test('ForwardingHandlerFactory - validate configuration', async () => { // Valid configuration - const validConfig: ForwardConfig = { + const validConfig: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 } }; @@ -77,7 +77,7 @@ tap.test('ForwardingHandlerFactory - validate configuration', async () => { expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig1)).toThrow(); // Invalid configuration - invalid port - const invalidConfig2: ForwardConfig = { + const invalidConfig2: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 0 } }; @@ -85,7 +85,7 @@ tap.test('ForwardingHandlerFactory - validate configuration', async () => { expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig2)).toThrow(); // Invalid configuration - HTTP disabled for HTTP-only - const invalidConfig3: ForwardConfig = { + const invalidConfig3: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 }, http: { enabled: false } @@ -94,7 +94,7 @@ tap.test('ForwardingHandlerFactory - validate configuration', async () => { expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig3)).toThrow(); // Invalid configuration - HTTP enabled for HTTPS passthrough - const invalidConfig4: ForwardConfig = { + const invalidConfig4: IForwardConfig = { type: 'https-passthrough', target: { host: 'localhost', port: 443 }, http: { enabled: true } diff --git a/test/test.forwarding.unit.ts b/test/test.forwarding.unit.ts index 657d9bf..8f1274a 100644 --- a/test/test.forwarding.unit.ts +++ b/test/test.forwarding.unit.ts @@ -1,6 +1,6 @@ import { tap, expect } from '@push.rocks/tapbundle'; import * as plugins from '../ts/plugins.js'; -import type { ForwardConfig } from '../ts/forwarding/config/forwarding-types.js'; +import type { IForwardConfig } from '../ts/forwarding/config/forwarding-types.js'; // First, import the components directly to avoid issues with compiled modules import { ForwardingHandlerFactory } from '../ts/forwarding/factory/forwarding-factory.js'; @@ -17,7 +17,7 @@ const helpers = { tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => { // HTTP-only defaults - const httpConfig: ForwardConfig = { + const httpConfig: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 } }; @@ -26,7 +26,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => expect(expandedHttpConfig.http?.enabled).toEqual(true); // HTTPS-passthrough defaults - const passthroughConfig: ForwardConfig = { + const passthroughConfig: IForwardConfig = { type: 'https-passthrough', target: { host: 'localhost', port: 443 } }; @@ -36,7 +36,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => expect(expandedPassthroughConfig.http?.enabled).toEqual(false); // HTTPS-terminate-to-http defaults - const terminateToHttpConfig: ForwardConfig = { + const terminateToHttpConfig: IForwardConfig = { type: 'https-terminate-to-http', target: { host: 'localhost', port: 3000 } }; @@ -48,7 +48,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => expect(expandedTerminateToHttpConfig.acme?.maintenance).toEqual(true); // HTTPS-terminate-to-https defaults - const terminateToHttpsConfig: ForwardConfig = { + const terminateToHttpsConfig: IForwardConfig = { type: 'https-terminate-to-https', target: { host: 'localhost', port: 8443 } }; @@ -62,7 +62,7 @@ tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => tap.test('ForwardingHandlerFactory - validate configuration', async () => { // Valid configuration - const validConfig: ForwardConfig = { + const validConfig: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 } }; @@ -77,7 +77,7 @@ tap.test('ForwardingHandlerFactory - validate configuration', async () => { expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig1)).toThrow(); // Invalid configuration - invalid port - const invalidConfig2: ForwardConfig = { + const invalidConfig2: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 0 } }; diff --git a/test/test.smartproxy.ts b/test/test.smartproxy.ts index bba3053..ba1234b 100644 --- a/test/test.smartproxy.ts +++ b/test/test.smartproxy.ts @@ -282,10 +282,20 @@ tap.test('should support optional source IP preservation in chained proxies', as // Test round-robin behavior for multiple target hosts in a domain config. tap.test('should use round robin for multiple target hosts in domain config', async () => { // Create a domain config with multiple hosts in the target - const domainConfig = { + const domainConfig: { + domains: string[]; + forwarding: { + type: 'http-only'; + target: { + host: string[]; + port: number; + }; + http: { enabled: boolean }; + } + } = { domains: ['rr.test'], forwarding: { - type: 'http-only', + type: 'http-only' as const, target: { host: ['hostA', 'hostB'], // Array of hosts for round-robin port: 80 diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index b5d6767..84bcb1d 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartproxy', - version: '13.1.0', + version: '13.1.1', description: 'A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, dynamic routing with authentication options, and automatic ACME certificate management.' } diff --git a/ts/certificate/acme/acme-factory.ts b/ts/certificate/acme/acme-factory.ts index feffb55..3ebb58e 100644 --- a/ts/certificate/acme/acme-factory.ts +++ b/ts/certificate/acme/acme-factory.ts @@ -1,6 +1,6 @@ import * as fs from 'fs'; import * as path from 'path'; -import type { AcmeOptions } from '../models/certificate-types.js'; +import type { IAcmeOptions } from '../models/certificate-types.js'; import { ensureCertificateDirectory } from '../utils/certificate-helpers.js'; // We'll need to update this import when we move the Port80Handler import { Port80Handler } from '../../http/port80/port80-handler.js'; @@ -12,7 +12,7 @@ import { Port80Handler } from '../../http/port80/port80-handler.js'; * @returns A new Port80Handler instance */ export function buildPort80Handler( - options: AcmeOptions + options: IAcmeOptions ): Port80Handler { if (options.certificateStore) { ensureCertificateDirectory(options.certificateStore); @@ -32,7 +32,7 @@ export function createDefaultAcmeOptions( email: string, certificateStore: string, useProduction: boolean = false -): AcmeOptions { +): IAcmeOptions { return { accountEmail: email, enabled: true, diff --git a/ts/certificate/acme/challenge-handler.ts b/ts/certificate/acme/challenge-handler.ts index 249a322..751d710 100644 --- a/ts/certificate/acme/challenge-handler.ts +++ b/ts/certificate/acme/challenge-handler.ts @@ -1,12 +1,12 @@ import * as plugins from '../../plugins.js'; -import type { AcmeOptions, CertificateData } from '../models/certificate-types.js'; +import type { IAcmeOptions, ICertificateData } from '../models/certificate-types.js'; import { CertificateEvents } from '../events/certificate-events.js'; /** * Manages ACME challenges and certificate validation */ export class AcmeChallengeHandler extends plugins.EventEmitter { - private options: AcmeOptions; + private options: IAcmeOptions; private client: any; // ACME client from plugins private pendingChallenges: Map; @@ -14,7 +14,7 @@ export class AcmeChallengeHandler extends plugins.EventEmitter { * Creates a new ACME challenge handler * @param options ACME configuration options */ - constructor(options: AcmeOptions) { + constructor(options: IAcmeOptions) { super(); this.options = options; this.pendingChallenges = new Map(); diff --git a/ts/certificate/index.ts b/ts/certificate/index.ts index 661b0c3..3176dca 100644 --- a/ts/certificate/index.ts +++ b/ts/certificate/index.ts @@ -25,8 +25,8 @@ export * from './storage/file-storage.js'; // Convenience function to create a certificate provisioner with common settings import { CertProvisioner } from './providers/cert-provisioner.js'; import { buildPort80Handler } from './acme/acme-factory.js'; -import type { AcmeOptions, DomainForwardConfig } from './models/certificate-types.js'; -import type { DomainConfig } from '../forwarding/config/domain-config.js'; +import type { IAcmeOptions, IDomainForwardConfig } from './models/certificate-types.js'; +import type { IDomainConfig } from '../forwarding/config/domain-config.js'; /** * Creates a complete certificate provisioning system with default settings @@ -37,8 +37,8 @@ import type { DomainConfig } from '../forwarding/config/domain-config.js'; * @returns Configured CertProvisioner */ export function createCertificateProvisioner( - domainConfigs: DomainConfig[], - acmeOptions: AcmeOptions, + domainConfigs: IDomainConfig[], + acmeOptions: IAcmeOptions, networkProxyBridge: any, // Placeholder until NetworkProxyBridge is migrated certProvider?: any // Placeholder until cert provider type is properly defined ): CertProvisioner { diff --git a/ts/certificate/models/certificate-types.ts b/ts/certificate/models/certificate-types.ts index b187c5f..b4622b3 100644 --- a/ts/certificate/models/certificate-types.ts +++ b/ts/certificate/models/certificate-types.ts @@ -84,4 +84,5 @@ export interface IAcmeOptions { certificateStore?: string; // Directory to store certificates skipConfiguredCerts?: boolean; // Skip domains with existing certificates domainForwards?: IDomainForwardConfig[]; // Domain-specific forwarding configs -} \ No newline at end of file +} + diff --git a/ts/certificate/providers/cert-provisioner.ts b/ts/certificate/providers/cert-provisioner.ts index f36b96e..4ade972 100644 --- a/ts/certificate/providers/cert-provisioner.ts +++ b/ts/certificate/providers/cert-provisioner.ts @@ -1,34 +1,34 @@ import * as plugins from '../../plugins.js'; -import type { DomainConfig } from '../../forwarding/config/domain-config.js'; -import type { CertificateData, DomainForwardConfig, DomainOptions } from '../models/certificate-types.js'; +import type { IDomainConfig } from '../../forwarding/config/domain-config.js'; +import type { ICertificateData, IDomainForwardConfig, IDomainOptions } from '../models/certificate-types.js'; import { Port80HandlerEvents, CertProvisionerEvents } from '../events/certificate-events.js'; import { Port80Handler } from '../../http/port80/port80-handler.js'; // We need to define this interface until we migrate NetworkProxyBridge -interface NetworkProxyBridge { - applyExternalCertificate(certData: CertificateData): void; +interface INetworkProxyBridge { + applyExternalCertificate(certData: ICertificateData): void; } // This will be imported after NetworkProxyBridge is migrated // import type { NetworkProxyBridge } from '../../proxies/smart-proxy/network-proxy-bridge.js'; // For backward compatibility -export type ISmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01'; +export type TSmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01'; /** * Type for static certificate provisioning */ -export type CertProvisionObject = plugins.tsclass.network.ICert | 'http01' | 'dns01'; +export type TCertProvisionObject = plugins.tsclass.network.ICert | 'http01' | 'dns01'; /** * CertProvisioner manages certificate provisioning and renewal workflows, * unifying static certificates and HTTP-01 challenges via Port80Handler. */ export class CertProvisioner extends plugins.EventEmitter { - private domainConfigs: DomainConfig[]; + private domainConfigs: IDomainConfig[]; private port80Handler: Port80Handler; - private networkProxyBridge: NetworkProxyBridge; - private certProvisionFunction?: (domain: string) => Promise; - private forwardConfigs: DomainForwardConfig[]; + private networkProxyBridge: INetworkProxyBridge; + private certProvisionFunction?: (domain: string) => Promise; + private forwardConfigs: IDomainForwardConfig[]; private renewThresholdDays: number; private renewCheckIntervalHours: number; private autoRenew: boolean; @@ -47,14 +47,14 @@ export class CertProvisioner extends plugins.EventEmitter { * @param forwardConfigs Domain forwarding configurations for ACME challenges */ constructor( - domainConfigs: DomainConfig[], + domainConfigs: IDomainConfig[], port80Handler: Port80Handler, - networkProxyBridge: NetworkProxyBridge, - certProvider?: (domain: string) => Promise, + networkProxyBridge: INetworkProxyBridge, + certProvider?: (domain: string) => Promise, renewThresholdDays: number = 30, renewCheckIntervalHours: number = 24, autoRenew: boolean = true, - forwardConfigs: DomainForwardConfig[] = [] + forwardConfigs: IDomainForwardConfig[] = [] ) { super(); this.domainConfigs = domainConfigs; @@ -92,11 +92,11 @@ export class CertProvisioner extends plugins.EventEmitter { */ private setupEventSubscriptions(): void { // We need to reimplement subscribeToPort80Handler here - this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_ISSUED, (data: CertificateData) => { + this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_ISSUED, (data: ICertificateData) => { this.emit(CertProvisionerEvents.CERTIFICATE_ISSUED, { ...data, source: 'http01', isRenewal: false }); }); - this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_RENEWED, (data: CertificateData) => { + this.port80Handler.on(Port80HandlerEvents.CERTIFICATE_RENEWED, (data: ICertificateData) => { this.emit(CertProvisionerEvents.CERTIFICATE_RENEWED, { ...data, source: 'http01', isRenewal: true }); }); @@ -110,7 +110,7 @@ export class CertProvisioner extends plugins.EventEmitter { */ private setupForwardingConfigs(): void { for (const config of this.forwardConfigs) { - const domainOptions: DomainOptions = { + const domainOptions: IDomainOptions = { domainName: config.domain, sslRedirect: config.sslRedirect || false, acmeMaintenance: false, @@ -138,7 +138,7 @@ export class CertProvisioner extends plugins.EventEmitter { */ private async provisionDomain(domain: string): Promise { const isWildcard = domain.includes('*'); - let provision: CertProvisionObject = 'http01'; + let provision: TCertProvisionObject = 'http01'; // Try to get a certificate from the provision function if (this.certProvisionFunction) { @@ -174,7 +174,7 @@ export class CertProvisioner extends plugins.EventEmitter { // Static certificate (e.g., DNS-01 provisioned or user-provided) this.provisionMap.set(domain, 'static'); const certObj = provision as plugins.tsclass.network.ICert; - const certData: CertificateData = { + const certData: ICertificateData = { domain: certObj.domainName, certificate: certObj.publicKey, privateKey: certObj.privateKey, @@ -235,7 +235,7 @@ export class CertProvisioner extends plugins.EventEmitter { if (provision !== 'http01' && provision !== 'dns01') { const certObj = provision as plugins.tsclass.network.ICert; - const certData: CertificateData = { + const certData: ICertificateData = { domain: certObj.domainName, certificate: certObj.publicKey, privateKey: certObj.privateKey, @@ -267,7 +267,7 @@ export class CertProvisioner extends plugins.EventEmitter { const isWildcard = domain.includes('*'); // Determine provisioning method - let provision: CertProvisionObject = 'http01'; + let provision: TCertProvisionObject = 'http01'; if (this.certProvisionFunction) { provision = await this.certProvisionFunction(domain); @@ -288,7 +288,7 @@ export class CertProvisioner extends plugins.EventEmitter { } else { // Static certificate (e.g., DNS-01 provisioned) supports wildcards const certObj = provision as plugins.tsclass.network.ICert; - const certData: CertificateData = { + const certData: ICertificateData = { domain: certObj.domainName, certificate: certObj.publicKey, privateKey: certObj.privateKey, @@ -311,7 +311,7 @@ export class CertProvisioner extends plugins.EventEmitter { sslRedirect?: boolean; acmeMaintenance?: boolean; }): Promise { - const domainOptions: DomainOptions = { + const domainOptions: IDomainOptions = { domainName: domain, sslRedirect: options?.sslRedirect || true, acmeMaintenance: options?.acmeMaintenance || true diff --git a/ts/certificate/storage/file-storage.ts b/ts/certificate/storage/file-storage.ts index 8309ace..65ece3e 100644 --- a/ts/certificate/storage/file-storage.ts +++ b/ts/certificate/storage/file-storage.ts @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as plugins from '../../plugins.js'; -import type { CertificateData, Certificates } from '../models/certificate-types.js'; +import type { ICertificateData, ICertificates } from '../models/certificate-types.js'; import { ensureCertificateDirectory } from '../utils/certificate-helpers.js'; /** @@ -21,10 +21,10 @@ export class FileStorage { /** * Save a certificate to the file system - * @param domain Domain name + * @param domain Domain name * @param certData Certificate data to save */ - public async saveCertificate(domain: string, certData: CertificateData): Promise { + public async saveCertificate(domain: string, certData: ICertificateData): Promise { const sanitizedDomain = this.sanitizeDomain(domain); const certDir = path.join(this.storageDir, sanitizedDomain); ensureCertificateDirectory(certDir); @@ -57,7 +57,7 @@ export class FileStorage { * @param domain Domain name * @returns Certificate data if found, null otherwise */ - public async loadCertificate(domain: string): Promise { + public async loadCertificate(domain: string): Promise { const sanitizedDomain = this.sanitizeDomain(domain); const certDir = path.join(this.storageDir, sanitizedDomain); diff --git a/ts/certificate/utils/certificate-helpers.ts b/ts/certificate/utils/certificate-helpers.ts index 21dcab6..21d9a60 100644 --- a/ts/certificate/utils/certificate-helpers.ts +++ b/ts/certificate/utils/certificate-helpers.ts @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { fileURLToPath } from 'url'; -import type { Certificates } from '../models/certificate-types.js'; +import type { ICertificates } from '../models/certificate-types.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -9,7 +9,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); * Loads the default SSL certificates from the assets directory * @returns The certificate key pair */ -export function loadDefaultCertificates(): Certificates { +export function loadDefaultCertificates(): ICertificates { try { // Need to adjust path from /ts/certificate/utils to /assets/certs const certPath = path.join(__dirname, '..', '..', '..', 'assets', 'certs'); diff --git a/ts/common/port80-adapter.ts b/ts/common/port80-adapter.ts index 4eb7380..996cdf5 100644 --- a/ts/common/port80-adapter.ts +++ b/ts/common/port80-adapter.ts @@ -6,7 +6,7 @@ import type { } from './types.js'; import type { - ForwardConfig as IForwardConfig + IForwardConfig } from '../forwarding/config/forwarding-types.js'; /** diff --git a/ts/forwarding/config/domain-config.ts b/ts/forwarding/config/domain-config.ts index d55f5a7..fa30b8b 100644 --- a/ts/forwarding/config/domain-config.ts +++ b/ts/forwarding/config/domain-config.ts @@ -1,14 +1,14 @@ -import type { ForwardConfig } from './forwarding-types.js'; +import type { IForwardConfig } from './forwarding-types.js'; /** * Domain configuration with unified forwarding configuration */ -export interface DomainConfig { +export interface IDomainConfig { // Core properties - domain patterns domains: string[]; // Unified forwarding configuration - forwarding: ForwardConfig; + forwarding: IForwardConfig; } /** @@ -16,8 +16,8 @@ export interface DomainConfig { */ export function createDomainConfig( domains: string | string[], - forwarding: ForwardConfig -): DomainConfig { + forwarding: IForwardConfig +): IDomainConfig { // Normalize domains to an array const domainArray = Array.isArray(domains) ? domains : [domains]; @@ -25,7 +25,4 @@ export function createDomainConfig( domains: domainArray, forwarding }; -} - -// Backwards compatibility -export interface IDomainConfig extends DomainConfig {} \ No newline at end of file +} \ No newline at end of file diff --git a/ts/forwarding/config/domain-manager.ts b/ts/forwarding/config/domain-manager.ts index 37c0b96..ba53bff 100644 --- a/ts/forwarding/config/domain-manager.ts +++ b/ts/forwarding/config/domain-manager.ts @@ -1,5 +1,5 @@ import * as plugins from '../../plugins.js'; -import type { DomainConfig } from './domain-config.js'; +import type { IDomainConfig } from './domain-config.js'; import { ForwardingHandler } from '../handlers/base-handler.js'; import { ForwardingHandlerEvents } from './forwarding-types.js'; import { ForwardingHandlerFactory } from '../factory/forwarding-factory.js'; @@ -21,14 +21,14 @@ export enum DomainManagerEvents { * Manages domains and their forwarding handlers */ export class DomainManager extends plugins.EventEmitter { - private domainConfigs: DomainConfig[] = []; + private domainConfigs: IDomainConfig[] = []; private domainHandlers: Map = new Map(); - + /** * Create a new DomainManager * @param initialDomains Optional initial domain configurations */ - constructor(initialDomains?: DomainConfig[]) { + constructor(initialDomains?: IDomainConfig[]) { super(); if (initialDomains) { @@ -40,7 +40,7 @@ export class DomainManager extends plugins.EventEmitter { * Set or replace all domain configurations * @param configs Array of domain configurations */ - public async setDomainConfigs(configs: DomainConfig[]): Promise { + public async setDomainConfigs(configs: IDomainConfig[]): Promise { // Clear existing handlers this.domainHandlers.clear(); @@ -57,7 +57,7 @@ export class DomainManager extends plugins.EventEmitter { * Add a new domain configuration * @param config The domain configuration to add */ - public async addDomainConfig(config: DomainConfig): Promise { + public async addDomainConfig(config: IDomainConfig): Promise { // Check if any of these domains already exist for (const domain of config.domains) { if (this.domainHandlers.has(domain)) { @@ -193,7 +193,7 @@ export class DomainManager extends plugins.EventEmitter { * Create handlers for a domain configuration * @param config The domain configuration */ - private async createHandlersForDomain(config: DomainConfig): Promise { + private async createHandlersForDomain(config: IDomainConfig): Promise { try { // Create a handler for this forwarding configuration const handler = ForwardingHandlerFactory.createHandler(config.forwarding); @@ -221,7 +221,7 @@ export class DomainManager extends plugins.EventEmitter { * @param handler The handler * @param config The domain configuration for this handler */ - private setupHandlerEvents(handler: ForwardingHandler, config: DomainConfig): void { + private setupHandlerEvents(handler: ForwardingHandler, config: IDomainConfig): void { // Forward relevant events handler.on(ForwardingHandlerEvents.CERTIFICATE_NEEDED, (data) => { this.emit(DomainManagerEvents.CERTIFICATE_NEEDED, { @@ -277,7 +277,7 @@ export class DomainManager extends plugins.EventEmitter { * Get all domain configurations * @returns Array of domain configurations */ - public getDomainConfigs(): DomainConfig[] { + public getDomainConfigs(): IDomainConfig[] { return [...this.domainConfigs]; } } \ No newline at end of file diff --git a/ts/forwarding/config/forwarding-types.ts b/ts/forwarding/config/forwarding-types.ts index 139eb9c..18376c5 100644 --- a/ts/forwarding/config/forwarding-types.ts +++ b/ts/forwarding/config/forwarding-types.ts @@ -3,7 +3,7 @@ import type * as plugins from '../../plugins.js'; /** * The primary forwarding types supported by SmartProxy */ -export type ForwardingType = +export type TForwardingType = | 'http-only' // HTTP forwarding only (no HTTPS) | 'https-passthrough' // Pass-through TLS traffic (SNI forwarding) | 'https-terminate-to-http' // Terminate TLS and forward to HTTP backend @@ -12,7 +12,7 @@ export type ForwardingType = /** * Target configuration for forwarding */ -export interface TargetConfig { +export interface ITargetConfig { host: string | string[]; // Support single host or round-robin port: number; } @@ -20,7 +20,7 @@ export interface TargetConfig { /** * HTTP-specific options for forwarding */ -export interface HttpOptions { +export interface IHttpOptions { enabled?: boolean; // Whether HTTP is enabled redirectToHttps?: boolean; // Redirect HTTP to HTTPS headers?: Record; // Custom headers for HTTP responses @@ -29,7 +29,7 @@ export interface HttpOptions { /** * HTTPS-specific options for forwarding */ -export interface HttpsOptions { +export interface IHttpsOptions { customCert?: { // Use custom cert instead of auto-provisioned key: string; cert: string; @@ -40,8 +40,8 @@ export interface HttpsOptions { /** * ACME certificate handling options */ -export interface AcmeForwardingOptions { - enabled?: boolean; // Enable ACME certificate provisioning +export interface IAcmeForwardingOptions { + enabled?: boolean; // Enable ACME certificate provisioning maintenance?: boolean; // Auto-renew certificates production?: boolean; // Use production ACME servers forwardChallenges?: { // Forward ACME challenges @@ -54,7 +54,7 @@ export interface AcmeForwardingOptions { /** * Security options for forwarding */ -export interface SecurityOptions { +export interface ISecurityOptions { allowedIps?: string[]; // IPs allowed to connect blockedIps?: string[]; // IPs blocked from connecting maxConnections?: number; // Max simultaneous connections @@ -63,7 +63,7 @@ export interface SecurityOptions { /** * Advanced options for forwarding */ -export interface AdvancedOptions { +export interface IAdvancedOptions { portRanges?: Array<{ from: number; to: number }>; // Allowed port ranges networkProxyPort?: number; // Custom NetworkProxy port if using terminate mode keepAlive?: boolean; // Enable TCP keepalive @@ -74,21 +74,21 @@ export interface AdvancedOptions { /** * Unified forwarding configuration interface */ -export interface ForwardConfig { +export interface IForwardConfig { // Define the primary forwarding type - use-case driven approach - type: ForwardingType; - + type: TForwardingType; + // Target configuration - target: TargetConfig; - + target: ITargetConfig; + // Protocol options - http?: HttpOptions; - https?: HttpsOptions; - acme?: AcmeForwardingOptions; - + http?: IHttpOptions; + https?: IHttpsOptions; + acme?: IAcmeForwardingOptions; + // Security and advanced options - security?: SecurityOptions; - advanced?: AdvancedOptions; + security?: ISecurityOptions; + advanced?: IAdvancedOptions; } /** @@ -118,8 +118,8 @@ export interface IForwardingHandler extends plugins.EventEmitter { * Helper function types for common forwarding patterns */ export const httpOnly = ( - partialConfig: Partial & Pick -): ForwardConfig => ({ + partialConfig: Partial & Pick +): IForwardConfig => ({ type: 'http-only', target: partialConfig.target, http: { enabled: true, ...(partialConfig.http || {}) }, @@ -128,8 +128,8 @@ export const httpOnly = ( }); export const tlsTerminateToHttp = ( - partialConfig: Partial & Pick -): ForwardConfig => ({ + partialConfig: Partial & Pick +): IForwardConfig => ({ type: 'https-terminate-to-http', target: partialConfig.target, https: { ...(partialConfig.https || {}) }, @@ -140,8 +140,8 @@ export const tlsTerminateToHttp = ( }); export const tlsTerminateToHttps = ( - partialConfig: Partial & Pick -): ForwardConfig => ({ + partialConfig: Partial & Pick +): IForwardConfig => ({ type: 'https-terminate-to-https', target: partialConfig.target, https: { ...(partialConfig.https || {}) }, @@ -152,20 +152,11 @@ export const tlsTerminateToHttps = ( }); export const httpsPassthrough = ( - partialConfig: Partial & Pick -): ForwardConfig => ({ + partialConfig: Partial & Pick +): IForwardConfig => ({ type: 'https-passthrough', target: partialConfig.target, https: { forwardSni: true, ...(partialConfig.https || {}) }, ...(partialConfig.security ? { security: partialConfig.security } : {}), ...(partialConfig.advanced ? { advanced: partialConfig.advanced } : {}) -}); - -// Backwards compatibility interfaces with 'I' prefix -export interface ITargetConfig extends TargetConfig {} -export interface IHttpOptions extends HttpOptions {} -export interface IHttpsOptions extends HttpsOptions {} -export interface IAcmeForwardingOptions extends AcmeForwardingOptions {} -export interface ISecurityOptions extends SecurityOptions {} -export interface IAdvancedOptions extends AdvancedOptions {} -export interface IForwardConfig extends ForwardConfig {} \ No newline at end of file +}); \ No newline at end of file diff --git a/ts/forwarding/factory/forwarding-factory.ts b/ts/forwarding/factory/forwarding-factory.ts index ca791d1..a03304c 100644 --- a/ts/forwarding/factory/forwarding-factory.ts +++ b/ts/forwarding/factory/forwarding-factory.ts @@ -1,5 +1,5 @@ -import type { ForwardConfig } from '../config/forwarding-types.js'; -import type { ForwardingHandler } from '../handlers/base-handler.js'; +import type { IForwardConfig } from '../config/forwarding-types.js'; +import { ForwardingHandler } from '../handlers/base-handler.js'; import { HttpForwardingHandler } from '../handlers/http-handler.js'; import { HttpsPassthroughHandler } from '../handlers/https-passthrough-handler.js'; import { HttpsTerminateToHttpHandler } from '../handlers/https-terminate-to-http-handler.js'; @@ -14,35 +14,35 @@ export class ForwardingHandlerFactory { * @param config The forwarding configuration * @returns The appropriate forwarding handler */ - public static createHandler(config: ForwardConfig): ForwardingHandler { + public static createHandler(config: IForwardConfig): ForwardingHandler { // Create the appropriate handler based on the forwarding type switch (config.type) { case 'http-only': return new HttpForwardingHandler(config); - + case 'https-passthrough': return new HttpsPassthroughHandler(config); - + case 'https-terminate-to-http': return new HttpsTerminateToHttpHandler(config); - + case 'https-terminate-to-https': return new HttpsTerminateToHttpsHandler(config); - + default: // Type system should prevent this, but just in case: throw new Error(`Unknown forwarding type: ${(config as any).type}`); } } - + /** * Apply default values to a forwarding configuration based on its type * @param config The original forwarding configuration * @returns A configuration with defaults applied */ - public static applyDefaults(config: ForwardConfig): ForwardConfig { + public static applyDefaults(config: IForwardConfig): IForwardConfig { // Create a deep copy of the configuration - const result: ForwardConfig = JSON.parse(JSON.stringify(config)); + const result: IForwardConfig = JSON.parse(JSON.stringify(config)); // Apply defaults based on forwarding type switch (config.type) { @@ -112,7 +112,7 @@ export class ForwardingHandlerFactory { * @param config The configuration to validate * @throws Error if the configuration is invalid */ - public static validateConfig(config: ForwardConfig): void { + public static validateConfig(config: IForwardConfig): void { // Validate common properties if (!config.target) { throw new Error('Forwarding configuration must include a target'); diff --git a/ts/forwarding/handlers/base-handler.ts b/ts/forwarding/handlers/base-handler.ts index 324f2fe..9be0054 100644 --- a/ts/forwarding/handlers/base-handler.ts +++ b/ts/forwarding/handlers/base-handler.ts @@ -1,6 +1,6 @@ import * as plugins from '../../plugins.js'; import type { - ForwardConfig, + IForwardConfig, IForwardingHandler } from '../config/forwarding-types.js'; import { ForwardingHandlerEvents } from '../config/forwarding-types.js'; @@ -13,7 +13,7 @@ export abstract class ForwardingHandler extends plugins.EventEmitter implements * Create a new ForwardingHandler * @param config The forwarding configuration */ - constructor(protected config: ForwardConfig) { + constructor(protected config: IForwardConfig) { super(); } diff --git a/ts/forwarding/handlers/http-handler.ts b/ts/forwarding/handlers/http-handler.ts index e041b0f..b93442d 100644 --- a/ts/forwarding/handlers/http-handler.ts +++ b/ts/forwarding/handlers/http-handler.ts @@ -1,6 +1,6 @@ import * as plugins from '../../plugins.js'; import { ForwardingHandler } from './base-handler.js'; -import type { ForwardConfig } from '../config/forwarding-types.js'; +import type { IForwardConfig } from '../config/forwarding-types.js'; import { ForwardingHandlerEvents } from '../config/forwarding-types.js'; /** @@ -11,14 +11,23 @@ export class HttpForwardingHandler extends ForwardingHandler { * Create a new HTTP forwarding handler * @param config The forwarding configuration */ - constructor(config: ForwardConfig) { + constructor(config: IForwardConfig) { super(config); - + // Validate that this is an HTTP-only configuration if (config.type !== 'http-only') { throw new Error(`Invalid configuration type for HttpForwardingHandler: ${config.type}`); } } + + /** + * Initialize the handler + * HTTP handler doesn't need special initialization + */ + public async initialize(): Promise { + // Basic initialization from parent class + await super.initialize(); + } /** * Handle a raw socket connection diff --git a/ts/forwarding/handlers/https-passthrough-handler.ts b/ts/forwarding/handlers/https-passthrough-handler.ts index 028a0d4..c4ba40e 100644 --- a/ts/forwarding/handlers/https-passthrough-handler.ts +++ b/ts/forwarding/handlers/https-passthrough-handler.ts @@ -1,6 +1,6 @@ import * as plugins from '../../plugins.js'; import { ForwardingHandler } from './base-handler.js'; -import type { ForwardConfig } from '../config/forwarding-types.js'; +import type { IForwardConfig } from '../config/forwarding-types.js'; import { ForwardingHandlerEvents } from '../config/forwarding-types.js'; /** @@ -11,14 +11,23 @@ export class HttpsPassthroughHandler extends ForwardingHandler { * Create a new HTTPS passthrough handler * @param config The forwarding configuration */ - constructor(config: ForwardConfig) { + constructor(config: IForwardConfig) { super(config); - + // Validate that this is an HTTPS passthrough configuration if (config.type !== 'https-passthrough') { throw new Error(`Invalid configuration type for HttpsPassthroughHandler: ${config.type}`); } } + + /** + * Initialize the handler + * HTTPS passthrough handler doesn't need special initialization + */ + public async initialize(): Promise { + // Basic initialization from parent class + await super.initialize(); + } /** * Handle a TLS/SSL socket connection by forwarding it without termination diff --git a/ts/forwarding/handlers/https-terminate-to-http-handler.ts b/ts/forwarding/handlers/https-terminate-to-http-handler.ts index 27d6976..4f68e61 100644 --- a/ts/forwarding/handlers/https-terminate-to-http-handler.ts +++ b/ts/forwarding/handlers/https-terminate-to-http-handler.ts @@ -1,6 +1,6 @@ import * as plugins from '../../plugins.js'; import { ForwardingHandler } from './base-handler.js'; -import type { ForwardConfig } from '../config/forwarding-types.js'; +import type { IForwardConfig } from '../config/forwarding-types.js'; import { ForwardingHandlerEvents } from '../config/forwarding-types.js'; /** @@ -14,7 +14,7 @@ export class HttpsTerminateToHttpHandler extends ForwardingHandler { * Create a new HTTPS termination with HTTP backend handler * @param config The forwarding configuration */ - constructor(config: ForwardConfig) { + constructor(config: IForwardConfig) { super(config); // Validate that this is an HTTPS terminate to HTTP configuration diff --git a/ts/forwarding/handlers/https-terminate-to-https-handler.ts b/ts/forwarding/handlers/https-terminate-to-https-handler.ts index 7d459ee..1505bfa 100644 --- a/ts/forwarding/handlers/https-terminate-to-https-handler.ts +++ b/ts/forwarding/handlers/https-terminate-to-https-handler.ts @@ -1,6 +1,6 @@ import * as plugins from '../../plugins.js'; import { ForwardingHandler } from './base-handler.js'; -import type { ForwardConfig } from '../config/forwarding-types.js'; +import type { IForwardConfig } from '../config/forwarding-types.js'; import { ForwardingHandlerEvents } from '../config/forwarding-types.js'; /** @@ -13,7 +13,7 @@ export class HttpsTerminateToHttpsHandler extends ForwardingHandler { * Create a new HTTPS termination with HTTPS backend handler * @param config The forwarding configuration */ - constructor(config: ForwardConfig) { + constructor(config: IForwardConfig) { super(config); // Validate that this is an HTTPS terminate to HTTPS configuration diff --git a/ts/http/models/http-types.ts b/ts/http/models/http-types.ts index f02b98e..681b915 100644 --- a/ts/http/models/http-types.ts +++ b/ts/http/models/http-types.ts @@ -1,8 +1,8 @@ import * as plugins from '../../plugins.js'; -import type { - ForwardConfig, - DomainOptions, - AcmeOptions +import type { + IForwardConfig, + IDomainOptions, + IAcmeOptions } from '../../certificate/models/certificate-types.js'; /** @@ -35,8 +35,8 @@ export enum HttpStatus { /** * Represents a domain configuration with certificate status information */ -export interface DomainCertificate { - options: DomainOptions; +export interface IDomainCertificate { + options: IDomainOptions; certObtained: boolean; obtainingInProgress: boolean; certificate?: string; @@ -82,7 +82,7 @@ export class ServerError extends HttpError { /** * Redirect configuration for HTTP requests */ -export interface RedirectConfig { +export interface IRedirectConfig { source: string; // Source path or pattern destination: string; // Destination URL type: HttpStatus; // Redirect status code @@ -92,7 +92,7 @@ export interface RedirectConfig { /** * HTTP router configuration */ -export interface RouterConfig { +export interface IRouterConfig { routes: Array<{ path: string; handler: (req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse) => void; @@ -102,5 +102,4 @@ export interface RouterConfig { // Backward compatibility interfaces export { HttpError as Port80HandlerError }; -export { CertificateError as CertError }; -export type IDomainCertificate = DomainCertificate; \ No newline at end of file +export { CertificateError as CertError }; \ No newline at end of file diff --git a/ts/http/port80/acme-interfaces.ts b/ts/http/port80/acme-interfaces.ts index 176901c..f29c2dd 100644 --- a/ts/http/port80/acme-interfaces.ts +++ b/ts/http/port80/acme-interfaces.ts @@ -7,7 +7,7 @@ import * as plugins from '../../plugins.js'; /** * Structure for SmartAcme certificate result */ -export interface SmartAcmeCert { +export interface ISmartAcmeCert { id?: string; domainName: string; created?: number | Date | string; @@ -20,7 +20,7 @@ export interface SmartAcmeCert { /** * Structure for SmartAcme options */ -export interface SmartAcmeOptions { +export interface ISmartAcmeOptions { accountEmail: string; certManager: ICertManager; environment: 'production' | 'integration'; @@ -39,8 +39,8 @@ export interface SmartAcmeOptions { */ export interface ICertManager { init(): Promise; - get(domainName: string): Promise; - put(cert: SmartAcmeCert): Promise; + get(domainName: string): Promise; + put(cert: ISmartAcmeCert): Promise; delete(domainName: string): Promise; close?(): Promise; } @@ -59,7 +59,7 @@ export interface IChallengeHandler { /** * HTTP-01 challenge type */ -export interface Http01Challenge { +export interface IHttp01Challenge { type: string; // 'http-01' token: string; keyAuthorization: string; @@ -69,17 +69,17 @@ export interface Http01Challenge { /** * HTTP-01 Memory Handler Interface */ -export interface Http01MemoryHandler extends IChallengeHandler { +export interface IHttp01MemoryHandler extends IChallengeHandler { handleRequest(req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse, next?: () => void): void; } /** * SmartAcme main class interface */ -export interface SmartAcme { +export interface ISmartAcme { start(): Promise; stop(): Promise; - getCertificateForDomain(domain: string): Promise; + getCertificateForDomain(domain: string): Promise; on?(event: string, listener: (data: any) => void): void; eventEmitter?: plugins.EventEmitter; } \ No newline at end of file diff --git a/ts/http/port80/challenge-responder.ts b/ts/http/port80/challenge-responder.ts index 99b3c09..4c0a6f8 100644 --- a/ts/http/port80/challenge-responder.ts +++ b/ts/http/port80/challenge-responder.ts @@ -4,15 +4,15 @@ import { CertificateEvents } from '../../certificate/events/certificate-events.js'; import type { - CertificateData, - CertificateFailure, - CertificateExpiring + ICertificateData, + ICertificateFailure, + ICertificateExpiring } from '../../certificate/models/certificate-types.js'; import type { - SmartAcme, - SmartAcmeCert, - SmartAcmeOptions, - Http01MemoryHandler + ISmartAcme, + ISmartAcmeCert, + ISmartAcmeOptions, + IHttp01MemoryHandler } from './acme-interfaces.js'; /** @@ -20,8 +20,8 @@ import type { * It acts as a bridge between the HTTP server and the ACME challenge verification process */ export class ChallengeResponder extends plugins.EventEmitter { - private smartAcme: SmartAcme | null = null; - private http01Handler: Http01MemoryHandler | null = null; + private smartAcme: ISmartAcme | null = null; + private http01Handler: IHttp01MemoryHandler | null = null; /** * Creates a new challenge responder @@ -95,7 +95,7 @@ export class ChallengeResponder extends plugins.EventEmitter { emitter.on('certificate', (data: any) => { const isRenewal = !!data.isRenewal; - const certData: CertificateData = { + const certData: ICertificateData = { domain: data.domainName || data.domain, certificate: data.publicKey || data.cert, privateKey: data.privateKey || data.key, @@ -114,7 +114,7 @@ export class ChallengeResponder extends plugins.EventEmitter { // Forward error events emitter.on('error', (error: any) => { const domain = error.domainName || error.domain || 'unknown'; - const failureData: CertificateFailure = { + const failureData: ICertificateFailure = { domain, error: error.message || String(error), isRenewal: !!error.isRenewal @@ -171,7 +171,7 @@ export class ChallengeResponder extends plugins.EventEmitter { * @param domain Domain name to request a certificate for * @param isRenewal Whether this is a renewal request */ - public async requestCertificate(domain: string, isRenewal: boolean = false): Promise { + public async requestCertificate(domain: string, isRenewal: boolean = false): Promise { if (!this.smartAcme) { throw new Error('ACME client not initialized'); } @@ -181,7 +181,7 @@ export class ChallengeResponder extends plugins.EventEmitter { const certObj = await this.smartAcme.getCertificateForDomain(domain); // Convert the certificate object to our CertificateData format - const certData: CertificateData = { + const certData: ICertificateData = { domain, certificate: certObj.publicKey, privateKey: certObj.privateKey, @@ -193,7 +193,7 @@ export class ChallengeResponder extends plugins.EventEmitter { return certData; } catch (error) { // Create failure object - const failure: CertificateFailure = { + const failure: ICertificateFailure = { domain, error: error instanceof Error ? error.message : String(error), isRenewal @@ -217,7 +217,7 @@ export class ChallengeResponder extends plugins.EventEmitter { */ public checkCertificateExpiry( domain: string, - certificate: CertificateData, + certificate: ICertificateData, thresholdDays: number = 30 ): void { if (!certificate.expiryDate) return; @@ -227,7 +227,7 @@ export class ChallengeResponder extends plugins.EventEmitter { const daysDifference = Math.floor((expiryDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)); if (daysDifference <= thresholdDays) { - const expiryInfo: CertificateExpiring = { + const expiryInfo: ICertificateExpiring = { domain, expiryDate, daysRemaining: daysDifference diff --git a/ts/http/port80/port80-handler.ts b/ts/http/port80/port80-handler.ts index 1f75f74..d9414d3 100644 --- a/ts/http/port80/port80-handler.ts +++ b/ts/http/port80/port80-handler.ts @@ -2,12 +2,12 @@ import * as plugins from '../../plugins.js'; import { IncomingMessage, ServerResponse } from 'http'; import { CertificateEvents } from '../../certificate/events/certificate-events.js'; import type { - ForwardConfig, - DomainOptions, - CertificateData, - CertificateFailure, - CertificateExpiring, - AcmeOptions + IForwardConfig, + IDomainOptions, + ICertificateData, + ICertificateFailure, + ICertificateExpiring, + IAcmeOptions } from '../../certificate/models/certificate-types.js'; import { HttpEvents, @@ -16,7 +16,7 @@ import { CertificateError, ServerError, } from '../models/http-types.js'; -import type { DomainCertificate } from '../models/http-types.js'; +import type { IDomainCertificate } from '../models/http-types.js'; import { ChallengeResponder } from './challenge-responder.js'; // Re-export for backward compatibility @@ -40,21 +40,21 @@ export const Port80HandlerEvents = CertificateEvents; * Now with glob pattern support for domain matching */ export class Port80Handler extends plugins.EventEmitter { - private domainCertificates: Map; + private domainCertificates: Map; private challengeResponder: ChallengeResponder | null = null; private server: plugins.http.Server | null = null; // Renewal scheduling is handled externally by SmartProxy private isShuttingDown: boolean = false; - private options: Required; + private options: Required; /** * Creates a new Port80Handler * @param options Configuration options */ - constructor(options: AcmeOptions = {}) { + constructor(options: IAcmeOptions = {}) { super(); - this.domainCertificates = new Map(); + this.domainCertificates = new Map(); // Default options this.options = { @@ -80,19 +80,19 @@ export class Port80Handler extends plugins.EventEmitter { ); // Forward certificate events from the challenge responder - this.challengeResponder.on(CertificateEvents.CERTIFICATE_ISSUED, (data: CertificateData) => { + this.challengeResponder.on(CertificateEvents.CERTIFICATE_ISSUED, (data: ICertificateData) => { this.emit(CertificateEvents.CERTIFICATE_ISSUED, data); }); - this.challengeResponder.on(CertificateEvents.CERTIFICATE_RENEWED, (data: CertificateData) => { + this.challengeResponder.on(CertificateEvents.CERTIFICATE_RENEWED, (data: ICertificateData) => { this.emit(CertificateEvents.CERTIFICATE_RENEWED, data); }); - this.challengeResponder.on(CertificateEvents.CERTIFICATE_FAILED, (error: CertificateFailure) => { + this.challengeResponder.on(CertificateEvents.CERTIFICATE_FAILED, (error: ICertificateFailure) => { this.emit(CertificateEvents.CERTIFICATE_FAILED, error); }); - this.challengeResponder.on(CertificateEvents.CERTIFICATE_EXPIRING, (expiry: CertificateExpiring) => { + this.challengeResponder.on(CertificateEvents.CERTIFICATE_EXPIRING, (expiry: ICertificateExpiring) => { this.emit(CertificateEvents.CERTIFICATE_EXPIRING, expiry); }); } @@ -198,7 +198,7 @@ export class Port80Handler extends plugins.EventEmitter { * Adds a domain with configuration options * @param options Domain configuration options */ - public addDomain(options: DomainOptions): void { + public addDomain(options: IDomainOptions): void { if (!options.domainName || typeof options.domainName !== 'string') { throw new HttpError('Invalid domain name'); } @@ -247,7 +247,7 @@ export class Port80Handler extends plugins.EventEmitter { * Gets the certificate for a domain if it exists * @param domain The domain to get the certificate for */ - public getCertificate(domain: string): CertificateData | null { + public getCertificate(domain: string): ICertificateData | null { // Can't get certificates for glob patterns if (this.isGlobPattern(domain)) { return null; @@ -283,7 +283,7 @@ export class Port80Handler extends plugins.EventEmitter { * @param requestDomain The actual domain from the request * @returns The domain info or null if not found */ - private getDomainInfoForRequest(requestDomain: string): { domainInfo: DomainCertificate, pattern: string } | null { + private getDomainInfoForRequest(requestDomain: string): { domainInfo: IDomainCertificate, pattern: string } | null { // Try direct match first if (this.domainCertificates.has(requestDomain)) { return { @@ -459,7 +459,7 @@ export class Port80Handler extends plugins.EventEmitter { private forwardRequest( req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse, - target: ForwardConfig, + target: IForwardConfig, requestType: string ): void { const options = { @@ -612,7 +612,7 @@ export class Port80Handler extends plugins.EventEmitter { * @param eventType The event type to emit * @param data The certificate data */ - private emitCertificateEvent(eventType: CertificateEvents, data: CertificateData): void { + private emitCertificateEvent(eventType: CertificateEvents, data: ICertificateData): void { this.emit(eventType, data); } diff --git a/ts/http/router/proxy-router.ts b/ts/http/router/proxy-router.ts index 5de282b..fdb583e 100644 --- a/ts/http/router/proxy-router.ts +++ b/ts/http/router/proxy-router.ts @@ -1,5 +1,5 @@ import * as plugins from '../../plugins.js'; -import type { ReverseProxyConfig } from '../../proxies/network-proxy/models/types.js'; +import type { IReverseProxyConfig } from '../../proxies/network-proxy/models/types.js'; /** * Optional path pattern configuration that can be added to proxy configs @@ -15,7 +15,7 @@ export type IPathPatternConfig = PathPatternConfig; * Interface for router result with additional metadata */ export interface RouterResult { - config: ReverseProxyConfig; + config: IReverseProxyConfig; pathMatch?: string; pathParams?: Record; pathRemainder?: string; @@ -41,11 +41,11 @@ export type IRouterResult = RouterResult; */ export class ProxyRouter { // Store original configs for reference - private reverseProxyConfigs: ReverseProxyConfig[] = []; + private reverseProxyConfigs: IReverseProxyConfig[] = []; // Default config to use when no match is found (optional) - private defaultConfig?: ReverseProxyConfig; + private defaultConfig?: IReverseProxyConfig; // Store path patterns separately since they're not in the original interface - private pathPatterns: Map = new Map(); + private pathPatterns: Map = new Map(); // Logger interface private logger: { error: (message: string, data?: any) => void; @@ -55,7 +55,7 @@ export class ProxyRouter { }; constructor( - configs?: ReverseProxyConfig[], + configs?: IReverseProxyConfig[], logger?: { error: (message: string, data?: any) => void; warn: (message: string, data?: any) => void; @@ -73,7 +73,7 @@ export class ProxyRouter { * Sets a new set of reverse configs to be routed to * @param reverseCandidatesArg Array of reverse proxy configurations */ - public setNewProxyConfigs(reverseCandidatesArg: ReverseProxyConfig[]): void { + public setNewProxyConfigs(reverseCandidatesArg: IReverseProxyConfig[]): void { this.reverseProxyConfigs = [...reverseCandidatesArg]; // Find default config if any (config with "*" as hostname) @@ -87,7 +87,7 @@ export class ProxyRouter { * @param req The incoming HTTP request * @returns The matching proxy config or undefined if no match found */ - public routeReq(req: plugins.http.IncomingMessage): ReverseProxyConfig { + public routeReq(req: plugins.http.IncomingMessage): IReverseProxyConfig { const result = this.routeReqWithDetails(req); return result ? result.config : undefined; } @@ -356,7 +356,7 @@ export class ProxyRouter { * Gets all currently active proxy configurations * @returns Array of all active configurations */ - public getProxyConfigs(): ReverseProxyConfig[] { + public getProxyConfigs(): IReverseProxyConfig[] { return [...this.reverseProxyConfigs]; } @@ -380,7 +380,7 @@ export class ProxyRouter { * @param pathPattern Optional path pattern for route matching */ public addProxyConfig( - config: ReverseProxyConfig, + config: IReverseProxyConfig, pathPattern?: string ): void { this.reverseProxyConfigs.push(config); @@ -398,7 +398,7 @@ export class ProxyRouter { * @returns Boolean indicating if the config was found and updated */ public setPathPattern( - config: ReverseProxyConfig, + config: IReverseProxyConfig, pathPattern: string ): boolean { const exists = this.reverseProxyConfigs.includes(config); diff --git a/ts/proxies/network-proxy/certificate-manager.ts b/ts/proxies/network-proxy/certificate-manager.ts index dcff0d7..7a70d3d 100644 --- a/ts/proxies/network-proxy/certificate-manager.ts +++ b/ts/proxies/network-proxy/certificate-manager.ts @@ -2,26 +2,26 @@ import * as plugins from '../../plugins.js'; import * as fs from 'fs'; import * as path from 'path'; import { fileURLToPath } from 'url'; -import { type NetworkProxyOptions, type CertificateEntry, type Logger, createLogger } from './models/types.js'; +import { type INetworkProxyOptions, type ICertificateEntry, type ILogger, createLogger } from './models/types.js'; import { Port80Handler } from '../../http/port80/port80-handler.js'; import { CertificateEvents } from '../../certificate/events/certificate-events.js'; import { buildPort80Handler } from '../../certificate/acme/acme-factory.js'; import { subscribeToPort80Handler } from '../../core/utils/event-utils.js'; -import type { DomainOptions } from '../../certificate/models/certificate-types.js'; +import type { IDomainOptions } from '../../certificate/models/certificate-types.js'; /** * Manages SSL certificates for NetworkProxy including ACME integration */ export class CertificateManager { private defaultCertificates: { key: string; cert: string }; - private certificateCache: Map = new Map(); + private certificateCache: Map = new Map(); private port80Handler: Port80Handler | null = null; private externalPort80Handler: boolean = false; private certificateStoreDir: string; - private logger: Logger; + private logger: ILogger; private httpsServer: plugins.https.Server | null = null; - constructor(private options: NetworkProxyOptions) { + constructor(private options: INetworkProxyOptions) { this.certificateStoreDir = path.resolve(options.acme?.certificateStore || './certs'); this.logger = createLogger(options.logLevel || 'info'); @@ -219,9 +219,9 @@ export class CertificateManager { if (!certData) { this.logger.info(`No certificate found for ${domain}, registering for issuance`); - + // Register with new domain options format - const domainOptions: DomainOptions = { + const domainOptions: IDomainOptions = { domainName: domain, sslRedirect: true, acmeMaintenance: true @@ -274,7 +274,7 @@ export class CertificateManager { /** * Gets a certificate for a domain */ - public getCertificate(domain: string): CertificateEntry | undefined { + public getCertificate(domain: string): ICertificateEntry | undefined { return this.certificateCache.get(domain); } @@ -300,7 +300,7 @@ export class CertificateManager { try { // Use the new domain options format - const domainOptions: DomainOptions = { + const domainOptions: IDomainOptions = { domainName: domain, sslRedirect: true, acmeMaintenance: true @@ -341,7 +341,7 @@ export class CertificateManager { } // Register the domain for certificate issuance with new domain options format - const domainOptions: DomainOptions = { + const domainOptions: IDomainOptions = { domainName: domain, sslRedirect: true, acmeMaintenance: true diff --git a/ts/proxies/network-proxy/connection-pool.ts b/ts/proxies/network-proxy/connection-pool.ts index 4918ec5..3c5293f 100644 --- a/ts/proxies/network-proxy/connection-pool.ts +++ b/ts/proxies/network-proxy/connection-pool.ts @@ -1,15 +1,15 @@ import * as plugins from '../../plugins.js'; -import { type NetworkProxyOptions, type ConnectionEntry, type Logger, createLogger } from './models/types.js'; +import { type INetworkProxyOptions, type IConnectionEntry, type ILogger, createLogger } from './models/types.js'; /** * Manages a pool of backend connections for efficient reuse */ export class ConnectionPool { - private connectionPool: Map> = new Map(); + private connectionPool: Map> = new Map(); private roundRobinPositions: Map = new Map(); - private logger: Logger; + private logger: ILogger; - constructor(private options: NetworkProxyOptions) { + constructor(private options: INetworkProxyOptions) { this.logger = createLogger(options.logLevel || 'info'); } diff --git a/ts/proxies/network-proxy/models/types.ts b/ts/proxies/network-proxy/models/types.ts index aefbd00..1ca5f05 100644 --- a/ts/proxies/network-proxy/models/types.ts +++ b/ts/proxies/network-proxy/models/types.ts @@ -1,10 +1,10 @@ import * as plugins from '../../../plugins.js'; -import type { AcmeOptions } from '../../../certificate/models/certificate-types.js'; +import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js'; /** * Configuration options for NetworkProxy */ -export interface NetworkProxyOptions { +export interface INetworkProxyOptions { port: number; maxConnections?: number; keepAliveTimeout?: number; @@ -16,22 +16,22 @@ export interface NetworkProxyOptions { allowHeaders?: string; maxAge?: number; }; - + // Settings for SmartProxy integration connectionPoolSize?: number; // Maximum connections to maintain in the pool to each backend portProxyIntegration?: boolean; // Flag to indicate this proxy is used by SmartProxy useExternalPort80Handler?: boolean; // Flag to indicate using external Port80Handler // Protocol to use when proxying to backends: HTTP/1.x or HTTP/2 backendProtocol?: 'http1' | 'http2'; - + // ACME certificate management options - acme?: AcmeOptions; + acme?: IAcmeOptions; } /** * Interface for a certificate entry in the cache */ -export interface CertificateEntry { +export interface ICertificateEntry { key: string; cert: string; expires?: Date; @@ -40,7 +40,7 @@ export interface CertificateEntry { /** * Interface for reverse proxy configuration */ -export interface ReverseProxyConfig { +export interface IReverseProxyConfig { destinationIps: string[]; destinationPorts: number[]; hostName: string; @@ -62,7 +62,7 @@ export interface ReverseProxyConfig { /** * Interface for connection tracking in the pool */ -export interface ConnectionEntry { +export interface IConnectionEntry { socket: plugins.net.Socket; lastUsed: number; isIdle: boolean; @@ -71,7 +71,7 @@ export interface ConnectionEntry { /** * WebSocket with heartbeat interface */ -export interface WebSocketWithHeartbeat extends plugins.wsDefault { +export interface IWebSocketWithHeartbeat extends plugins.wsDefault { lastPong: number; isAlive: boolean; } @@ -79,7 +79,7 @@ export interface WebSocketWithHeartbeat extends plugins.wsDefault { /** * Logger interface for consistent logging across components */ -export interface Logger { +export interface ILogger { debug(message: string, data?: any): void; info(message: string, data?: any): void; warn(message: string, data?: any): void; @@ -89,14 +89,14 @@ export interface Logger { /** * Creates a logger based on the specified log level */ -export function createLogger(logLevel: string = 'info'): Logger { +export function createLogger(logLevel: string = 'info'): ILogger { const logLevels = { error: 0, warn: 1, info: 2, debug: 3 }; - + return { debug: (message: string, data?: any) => { if (logLevels[logLevel] >= logLevels.debug) { @@ -119,12 +119,4 @@ export function createLogger(logLevel: string = 'info'): Logger { } } }; -} - -// Backward compatibility interfaces -export interface INetworkProxyOptions extends NetworkProxyOptions {} -export interface ICertificateEntry extends CertificateEntry {} -export interface IReverseProxyConfig extends ReverseProxyConfig {} -export interface IConnectionEntry extends ConnectionEntry {} -export interface IWebSocketWithHeartbeat extends WebSocketWithHeartbeat {} -export interface ILogger extends Logger {} \ No newline at end of file +} \ No newline at end of file diff --git a/ts/proxies/network-proxy/network-proxy.ts b/ts/proxies/network-proxy/network-proxy.ts index 02c1983..f2086bb 100644 --- a/ts/proxies/network-proxy/network-proxy.ts +++ b/ts/proxies/network-proxy/network-proxy.ts @@ -3,9 +3,9 @@ import { createLogger } from './models/types.js'; import type { - NetworkProxyOptions, - Logger, - ReverseProxyConfig + INetworkProxyOptions, + ILogger, + IReverseProxyConfig } from './models/types.js'; import { CertificateManager } from './certificate-manager.js'; import { ConnectionPool } from './connection-pool.js'; @@ -24,8 +24,8 @@ export class NetworkProxy implements IMetricsTracker { return {}; } // Configuration - public options: NetworkProxyOptions; - public proxyConfigs: ReverseProxyConfig[] = []; + public options: INetworkProxyOptions; + public proxyConfigs: IReverseProxyConfig[] = []; // Server instances (HTTP/2 with HTTP/1 fallback) public httpsServer: any; @@ -54,12 +54,12 @@ export class NetworkProxy implements IMetricsTracker { private connectionPoolCleanupInterval: NodeJS.Timeout; // Logger - private logger: Logger; + private logger: ILogger; /** * Creates a new NetworkProxy instance */ - constructor(optionsArg: NetworkProxyOptions) { + constructor(optionsArg: INetworkProxyOptions) { // Set default options this.options = { port: optionsArg.port, @@ -328,7 +328,7 @@ export class NetworkProxy implements IMetricsTracker { * Updates proxy configurations */ public async updateProxyConfigs( - proxyConfigsArg: ReverseProxyConfig[] + proxyConfigsArg: IReverseProxyConfig[] ): Promise { this.logger.info(`Updating proxy configurations (${proxyConfigsArg.length} configs)`); @@ -385,8 +385,8 @@ export class NetworkProxy implements IMetricsTracker { allowedIPs?: string[]; }>, sslKeyPair?: { key: string; cert: string } - ): ReverseProxyConfig[] { - const proxyConfigs: ReverseProxyConfig[] = []; + ): IReverseProxyConfig[] { + const proxyConfigs: IReverseProxyConfig[] = []; // Use default certificates if not provided const defaultCerts = this.certificateManager.getDefaultCertificates(); @@ -478,7 +478,7 @@ export class NetworkProxy implements IMetricsTracker { /** * Gets all proxy configurations currently in use */ - public getProxyConfigs(): ReverseProxyConfig[] { + public getProxyConfigs(): IReverseProxyConfig[] { return [...this.proxyConfigs]; } } \ No newline at end of file diff --git a/ts/proxies/network-proxy/request-handler.ts b/ts/proxies/network-proxy/request-handler.ts index 6aad191..063dcc6 100644 --- a/ts/proxies/network-proxy/request-handler.ts +++ b/ts/proxies/network-proxy/request-handler.ts @@ -1,5 +1,5 @@ import * as plugins from '../../plugins.js'; -import { type NetworkProxyOptions, type Logger, createLogger, type ReverseProxyConfig } from './models/types.js'; +import { type INetworkProxyOptions, type ILogger, createLogger, type IReverseProxyConfig } from './models/types.js'; import { ConnectionPool } from './connection-pool.js'; import { ProxyRouter } from '../../http/router/index.js'; @@ -19,13 +19,13 @@ export type MetricsTracker = IMetricsTracker; */ export class RequestHandler { private defaultHeaders: { [key: string]: string } = {}; - private logger: Logger; + private logger: ILogger; private metricsTracker: IMetricsTracker | null = null; // HTTP/2 client sessions for backend proxying private h2Sessions: Map = new Map(); constructor( - private options: NetworkProxyOptions, + private options: INetworkProxyOptions, private connectionPool: ConnectionPool, private router: ProxyRouter ) { @@ -137,7 +137,7 @@ export class RequestHandler { this.applyDefaultHeaders(res); // Determine routing configuration - let proxyConfig: ReverseProxyConfig | undefined; + let proxyConfig: IReverseProxyConfig | undefined; try { proxyConfig = this.router.routeReq(req); } catch (err) { @@ -235,7 +235,7 @@ export class RequestHandler { // Remove host header to avoid issues with virtual hosts on target server // The host header should match the target server's expected hostname if (options.headers && options.headers.host) { - if ((proxyConfig as ReverseProxyConfig).rewriteHostHeader) { + if ((proxyConfig as IReverseProxyConfig).rewriteHostHeader) { options.headers.host = `${destination.host}:${destination.port}`; } } @@ -426,7 +426,7 @@ export class RequestHandler { outboundHeaders[key] = value; } } - if (outboundHeaders.host && (proxyConfig as any).rewriteHostHeader) { + if (outboundHeaders.host && (proxyConfig as IReverseProxyConfig).rewriteHostHeader) { outboundHeaders.host = `${destination.host}:${destination.port}`; } // Create HTTP/1 proxy request diff --git a/ts/proxies/network-proxy/websocket-handler.ts b/ts/proxies/network-proxy/websocket-handler.ts index 8d50425..69c1e96 100644 --- a/ts/proxies/network-proxy/websocket-handler.ts +++ b/ts/proxies/network-proxy/websocket-handler.ts @@ -1,5 +1,5 @@ import * as plugins from '../../plugins.js'; -import { type NetworkProxyOptions, type WebSocketWithHeartbeat, type Logger, createLogger, type ReverseProxyConfig } from './models/types.js'; +import { type INetworkProxyOptions, type IWebSocketWithHeartbeat, type ILogger, createLogger, type IReverseProxyConfig } from './models/types.js'; import { ConnectionPool } from './connection-pool.js'; import { ProxyRouter } from '../../http/router/index.js'; @@ -9,10 +9,10 @@ import { ProxyRouter } from '../../http/router/index.js'; export class WebSocketHandler { private heartbeatInterval: NodeJS.Timeout | null = null; private wsServer: plugins.ws.WebSocketServer | null = null; - private logger: Logger; + private logger: ILogger; constructor( - private options: NetworkProxyOptions, + private options: INetworkProxyOptions, private connectionPool: ConnectionPool, private router: ProxyRouter ) { @@ -30,7 +30,7 @@ export class WebSocketHandler { }); // Handle WebSocket connections - this.wsServer.on('connection', (wsIncoming: WebSocketWithHeartbeat, req: plugins.http.IncomingMessage) => { + this.wsServer.on('connection', (wsIncoming: IWebSocketWithHeartbeat, req: plugins.http.IncomingMessage) => { this.handleWebSocketConnection(wsIncoming, req); }); @@ -56,9 +56,9 @@ export class WebSocketHandler { } this.logger.debug(`WebSocket heartbeat check for ${this.wsServer.clients.size} clients`); - + this.wsServer.clients.forEach((ws: plugins.wsDefault) => { - const wsWithHeartbeat = ws as WebSocketWithHeartbeat; + const wsWithHeartbeat = ws as IWebSocketWithHeartbeat; if (wsWithHeartbeat.isAlive === false) { this.logger.debug('Terminating inactive WebSocket connection'); @@ -79,7 +79,7 @@ export class WebSocketHandler { /** * Handle a new WebSocket connection */ - private handleWebSocketConnection(wsIncoming: WebSocketWithHeartbeat, req: plugins.http.IncomingMessage): void { + private handleWebSocketConnection(wsIncoming: IWebSocketWithHeartbeat, req: plugins.http.IncomingMessage): void { try { // Initialize heartbeat tracking wsIncoming.isAlive = true; @@ -127,7 +127,7 @@ export class WebSocketHandler { } // Override host header if needed - if ((proxyConfig as ReverseProxyConfig).rewriteHostHeader) { + if ((proxyConfig as IReverseProxyConfig).rewriteHostHeader) { headers['host'] = `${destination.host}:${destination.port}`; } diff --git a/ts/proxies/smart-proxy/connection-handler.ts b/ts/proxies/smart-proxy/connection-handler.ts index 3933ccd..68cd2cd 100644 --- a/ts/proxies/smart-proxy/connection-handler.ts +++ b/ts/proxies/smart-proxy/connection-handler.ts @@ -1,8 +1,8 @@ import * as plugins from '../../plugins.js'; import type { - ConnectionRecord, - DomainConfig, - SmartProxyOptions, + IConnectionRecord, + IDomainConfig, + ISmartProxyOptions, } from './models/interfaces.js'; import { ConnectionManager } from './connection-manager.js'; import { SecurityManager } from './security-manager.js'; @@ -12,14 +12,14 @@ import { NetworkProxyBridge } from './network-proxy-bridge.js'; import { TimeoutManager } from './timeout-manager.js'; import { PortRangeManager } from './port-range-manager.js'; import type { ForwardingHandler } from '../../forwarding/handlers/base-handler.js'; -import type { ForwardingType } from '../../forwarding/config/forwarding-types.js'; +import type { TForwardingType } from '../../forwarding/config/forwarding-types.js'; /** * Handles new connection processing and setup logic */ export class ConnectionHandler { constructor( - private settings: SmartProxyOptions, + private settings: ISmartProxyOptions, private connectionManager: ConnectionManager, private securityManager: SecurityManager, private domainConfigManager: DomainConfigManager, @@ -102,7 +102,7 @@ export class ConnectionHandler { */ private handleNetworkProxyConnection( socket: plugins.net.Socket, - record: ConnectionRecord + record: IConnectionRecord ): void { const connectionId = record.id; let initialDataReceived = false; @@ -307,7 +307,7 @@ export class ConnectionHandler { /** * Handle a standard (non-NetworkProxy) connection */ - private handleStandardConnection(socket: plugins.net.Socket, record: ConnectionRecord): void { + private handleStandardConnection(socket: plugins.net.Socket, record: IConnectionRecord): void { const connectionId = record.id; const localPort = record.localPort; @@ -382,7 +382,7 @@ export class ConnectionHandler { const setupConnection = ( serverName: string, initialChunk?: Buffer, - forcedDomain?: DomainConfig, + forcedDomain?: IDomainConfig, overridePort?: number ) => { // Clear the initial timeout since we've received data @@ -500,7 +500,7 @@ export class ConnectionHandler { const globalDomainConfig = { domains: ['global'], forwarding: { - type: 'http-only' as ForwardingType, + type: 'http-only' as TForwardingType, target: { host: this.settings.targetIP!, port: this.settings.toPort @@ -730,8 +730,8 @@ export class ConnectionHandler { */ private setupDirectConnection( socket: plugins.net.Socket, - record: ConnectionRecord, - domainConfig?: DomainConfig, + record: IConnectionRecord, + domainConfig?: IDomainConfig, serverName?: string, initialChunk?: Buffer, overridePort?: number diff --git a/ts/proxies/smart-proxy/connection-manager.ts b/ts/proxies/smart-proxy/connection-manager.ts index bfbe5b2..2ba0b29 100644 --- a/ts/proxies/smart-proxy/connection-manager.ts +++ b/ts/proxies/smart-proxy/connection-manager.ts @@ -1,5 +1,5 @@ import * as plugins from '../../plugins.js'; -import type { ConnectionRecord, SmartProxyOptions } from './models/interfaces.js'; +import type { IConnectionRecord, ISmartProxyOptions } from './models/interfaces.js'; import { SecurityManager } from './security-manager.js'; import { TimeoutManager } from './timeout-manager.js'; @@ -7,14 +7,14 @@ import { TimeoutManager } from './timeout-manager.js'; * Manages connection lifecycle, tracking, and cleanup */ export class ConnectionManager { - private connectionRecords: Map = new Map(); + private connectionRecords: Map = new Map(); private terminationStats: { incoming: Record; outgoing: Record; } = { incoming: {}, outgoing: {} }; constructor( - private settings: SmartProxyOptions, + private settings: ISmartProxyOptions, private securityManager: SecurityManager, private timeoutManager: TimeoutManager ) {} @@ -30,12 +30,12 @@ export class ConnectionManager { /** * Create and track a new connection */ - public createConnection(socket: plugins.net.Socket): ConnectionRecord { + public createConnection(socket: plugins.net.Socket): IConnectionRecord { const connectionId = this.generateConnectionId(); const remoteIP = socket.remoteAddress || ''; const localPort = socket.localPort || 0; - const record: ConnectionRecord = { + const record: IConnectionRecord = { id: connectionId, incoming: socket, outgoing: null, @@ -66,7 +66,7 @@ export class ConnectionManager { /** * Track an existing connection */ - public trackConnection(connectionId: string, record: ConnectionRecord): void { + public trackConnection(connectionId: string, record: IConnectionRecord): void { this.connectionRecords.set(connectionId, record); this.securityManager.trackConnectionByIP(record.remoteIP, connectionId); } @@ -74,14 +74,14 @@ export class ConnectionManager { /** * Get a connection by ID */ - public getConnection(connectionId: string): ConnectionRecord | undefined { + public getConnection(connectionId: string): IConnectionRecord | undefined { return this.connectionRecords.get(connectionId); } /** * Get all active connections */ - public getConnections(): Map { + public getConnections(): Map { return this.connectionRecords; } @@ -95,7 +95,7 @@ export class ConnectionManager { /** * Initiates cleanup once for a connection */ - public initiateCleanupOnce(record: ConnectionRecord, reason: string = 'normal'): void { + public initiateCleanupOnce(record: IConnectionRecord, reason: string = 'normal'): void { if (this.settings.enableDetailedLogging) { console.log(`[${record.id}] Connection cleanup initiated for ${record.remoteIP} (${reason})`); } @@ -110,11 +110,11 @@ export class ConnectionManager { this.cleanupConnection(record, reason); } - + /** * Clean up a connection record */ - public cleanupConnection(record: ConnectionRecord, reason: string = 'normal'): void { + public cleanupConnection(record: IConnectionRecord, reason: string = 'normal'): void { if (!record.connectionClosed) { record.connectionClosed = true; @@ -178,7 +178,7 @@ export class ConnectionManager { /** * Helper method to clean up a socket */ - private cleanupSocket(record: ConnectionRecord, side: 'incoming' | 'outgoing', socket: plugins.net.Socket): void { + private cleanupSocket(record: IConnectionRecord, side: 'incoming' | 'outgoing', socket: plugins.net.Socket): void { try { if (!socket.destroyed) { // Try graceful shutdown first, then force destroy after a short timeout @@ -213,7 +213,7 @@ export class ConnectionManager { /** * Creates a generic error handler for incoming or outgoing sockets */ - public handleError(side: 'incoming' | 'outgoing', record: ConnectionRecord) { + public handleError(side: 'incoming' | 'outgoing', record: IConnectionRecord) { return (err: Error) => { const code = (err as any).code; let reason = 'error'; @@ -256,7 +256,7 @@ export class ConnectionManager { /** * Creates a generic close handler for incoming or outgoing sockets */ - public handleClose(side: 'incoming' | 'outgoing', record: ConnectionRecord) { + public handleClose(side: 'incoming' | 'outgoing', record: IConnectionRecord) { return () => { if (this.settings.enableDetailedLogging) { console.log(`[${record.id}] Connection closed on ${side} side from ${record.remoteIP}`); diff --git a/ts/proxies/smart-proxy/domain-config-manager.ts b/ts/proxies/smart-proxy/domain-config-manager.ts index 5d900fd..1f01d97 100644 --- a/ts/proxies/smart-proxy/domain-config-manager.ts +++ b/ts/proxies/smart-proxy/domain-config-manager.ts @@ -1,6 +1,6 @@ import * as plugins from '../../plugins.js'; -import type { DomainConfig, SmartProxyOptions } from './models/interfaces.js'; -import type { ForwardingType, ForwardConfig } from '../../forwarding/config/forwarding-types.js'; +import type { IDomainConfig, ISmartProxyOptions } from './models/interfaces.js'; +import type { TForwardingType, IForwardConfig } from '../../forwarding/config/forwarding-types.js'; import type { ForwardingHandler } from '../../forwarding/handlers/base-handler.js'; import { ForwardingHandlerFactory } from '../../forwarding/factory/forwarding-factory.js'; @@ -9,17 +9,17 @@ import { ForwardingHandlerFactory } from '../../forwarding/factory/forwarding-fa */ export class DomainConfigManager { // Track round-robin indices for domain configs - private domainTargetIndices: Map = new Map(); + private domainTargetIndices: Map = new Map(); // Cache forwarding handlers for each domain config - private forwardingHandlers: Map = new Map(); + private forwardingHandlers: Map = new Map(); - constructor(private settings: SmartProxyOptions) {} + constructor(private settings: ISmartProxyOptions) {} /** * Updates the domain configurations */ - public updateDomainConfigs(newDomainConfigs: DomainConfig[]): void { + public updateDomainConfigs(newDomainConfigs: IDomainConfig[]): void { this.settings.domainConfigs = newDomainConfigs; // Reset target indices for removed configs @@ -31,7 +31,7 @@ export class DomainConfigManager { } // Clear handlers for removed configs and create handlers for new configs - const handlersToRemove: DomainConfig[] = []; + const handlersToRemove: IDomainConfig[] = []; for (const [config] of this.forwardingHandlers) { if (!currentConfigSet.has(config)) { handlersToRemove.push(config); @@ -55,29 +55,29 @@ export class DomainConfigManager { } } } - + /** * Get all domain configurations */ - public getDomainConfigs(): DomainConfig[] { + public getDomainConfigs(): IDomainConfig[] { return this.settings.domainConfigs; } - + /** * Find domain config matching a server name */ - public findDomainConfig(serverName: string): DomainConfig | undefined { + 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): DomainConfig | undefined { + public findDomainConfigForPort(port: number): IDomainConfig | undefined { return this.settings.domainConfigs.find( (domain) => { const portRanges = domain.forwarding?.advanced?.portRanges; @@ -98,7 +98,7 @@ export class DomainConfigManager { /** * Get target IP with round-robin support */ - public getTargetIP(domainConfig: DomainConfig): string { + public getTargetIP(domainConfig: IDomainConfig): string { const targetHosts = Array.isArray(domainConfig.forwarding.target.host) ? domainConfig.forwarding.target.host : [domainConfig.forwarding.target.host]; @@ -117,21 +117,21 @@ export class DomainConfigManager { * Get target host with round-robin support (for tests) * This is just an alias for getTargetIP for easier test compatibility */ - public getTargetHost(domainConfig: DomainConfig): string { + public getTargetHost(domainConfig: IDomainConfig): string { return this.getTargetIP(domainConfig); } /** * Get target port from domain config */ - public getTargetPort(domainConfig: DomainConfig, defaultPort: number): number { + public getTargetPort(domainConfig: IDomainConfig, defaultPort: number): number { return domainConfig.forwarding.target.port || defaultPort; } - + /** * Checks if a domain should use NetworkProxy */ - public shouldUseNetworkProxy(domainConfig: DomainConfig): boolean { + public shouldUseNetworkProxy(domainConfig: IDomainConfig): boolean { const forwardingType = this.getForwardingType(domainConfig); return forwardingType === 'https-terminate-to-http' || forwardingType === 'https-terminate-to-https'; @@ -140,7 +140,7 @@ export class DomainConfigManager { /** * Gets the NetworkProxy port for a domain */ - public getNetworkProxyPort(domainConfig: DomainConfig): number | undefined { + public getNetworkProxyPort(domainConfig: IDomainConfig): number | undefined { // First check if we should use NetworkProxy at all if (!this.shouldUseNetworkProxy(domainConfig)) { return undefined; @@ -148,14 +148,14 @@ export class DomainConfigManager { return domainConfig.forwarding.advanced?.networkProxyPort || this.settings.networkProxyPort; } - + /** * Get effective allowed and blocked IPs for a domain * * This method combines domain-specific security rules from the forwarding configuration * with global security defaults when necessary. */ - public getEffectiveIPRules(domainConfig: DomainConfig): { + public getEffectiveIPRules(domainConfig: IDomainConfig): { allowedIPs: string[], blockedIPs: string[] } { @@ -201,7 +201,7 @@ export class DomainConfigManager { /** * Get connection timeout for a domain */ - public getConnectionTimeout(domainConfig?: DomainConfig): number { + public getConnectionTimeout(domainConfig?: IDomainConfig): number { if (domainConfig?.forwarding.advanced?.timeout) { return domainConfig.forwarding.advanced.timeout; } @@ -212,7 +212,7 @@ export class DomainConfigManager { /** * Creates a forwarding handler for a domain configuration */ - private createForwardingHandler(domainConfig: DomainConfig): ForwardingHandler { + private createForwardingHandler(domainConfig: IDomainConfig): ForwardingHandler { // Create a new handler using the factory const handler = ForwardingHandlerFactory.createHandler(domainConfig.forwarding); @@ -228,7 +228,7 @@ export class DomainConfigManager { * Gets a forwarding handler for a domain config * If no handler exists, creates one */ - public getForwardingHandler(domainConfig: DomainConfig): ForwardingHandler { + public getForwardingHandler(domainConfig: IDomainConfig): ForwardingHandler { // If we already have a handler, return it if (this.forwardingHandlers.has(domainConfig)) { return this.forwardingHandlers.get(domainConfig)!; @@ -244,7 +244,7 @@ export class DomainConfigManager { /** * Gets the forwarding type for a domain config */ - public getForwardingType(domainConfig?: DomainConfig): ForwardingType | undefined { + public getForwardingType(domainConfig?: IDomainConfig): TForwardingType | undefined { if (!domainConfig?.forwarding) return undefined; return domainConfig.forwarding.type; } @@ -252,7 +252,7 @@ export class DomainConfigManager { /** * Checks if the forwarding type requires TLS termination */ - public requiresTlsTermination(domainConfig?: DomainConfig): boolean { + public requiresTlsTermination(domainConfig?: IDomainConfig): boolean { if (!domainConfig) return false; const forwardingType = this.getForwardingType(domainConfig); @@ -263,7 +263,7 @@ export class DomainConfigManager { /** * Checks if the forwarding type supports HTTP */ - public supportsHttp(domainConfig?: DomainConfig): boolean { + public supportsHttp(domainConfig?: IDomainConfig): boolean { if (!domainConfig) return false; const forwardingType = this.getForwardingType(domainConfig); @@ -285,7 +285,7 @@ export class DomainConfigManager { /** * Checks if HTTP requests should be redirected to HTTPS */ - public shouldRedirectToHttps(domainConfig?: DomainConfig): boolean { + public shouldRedirectToHttps(domainConfig?: IDomainConfig): boolean { if (!domainConfig?.forwarding) return false; // Only check for redirect if HTTP is enabled diff --git a/ts/proxies/smart-proxy/models/interfaces.ts b/ts/proxies/smart-proxy/models/interfaces.ts index 1846866..edbba8a 100644 --- a/ts/proxies/smart-proxy/models/interfaces.ts +++ b/ts/proxies/smart-proxy/models/interfaces.ts @@ -1,28 +1,28 @@ import * as plugins from '../../../plugins.js'; -import type { ForwardConfig } from '../../../forwarding/config/forwarding-types.js'; +import type { IForwardConfig } from '../../../forwarding/config/forwarding-types.js'; /** * Provision object for static or HTTP-01 certificate */ -export type SmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01'; +export type TSmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01'; /** * Domain configuration with forwarding configuration */ -export interface DomainConfig { +export interface IDomainConfig { domains: string[]; // Glob patterns for domain(s) - forwarding: ForwardConfig; // Unified forwarding configuration + forwarding: IForwardConfig; // Unified forwarding configuration } /** * Configuration options for the SmartProxy */ -import type { AcmeOptions } from '../../../certificate/models/certificate-types.js'; -export interface SmartProxyOptions { +import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js'; +export interface ISmartProxyOptions { fromPort: number; toPort: number; targetIP?: string; // Global target host to proxy to, defaults to 'localhost' - domainConfigs: DomainConfig[]; + domainConfigs: IDomainConfig[]; sniEnabled?: boolean; defaultAllowedIPs?: string[]; defaultBlockedIPs?: string[]; @@ -81,19 +81,19 @@ export interface SmartProxyOptions { networkProxyPort?: number; // Port where NetworkProxy is listening (default: 8443) // ACME configuration options for SmartProxy - acme?: AcmeOptions; - + acme?: IAcmeOptions; + /** * Optional certificate provider callback. Return 'http01' to use HTTP-01 challenges, * or a static certificate object for immediate provisioning. */ - certProvisionFunction?: (domain: string) => Promise; + certProvisionFunction?: (domain: string) => Promise; } /** * Enhanced connection record */ -export interface ConnectionRecord { +export interface IConnectionRecord { id: string; // Unique connection identifier incoming: plugins.net.Socket; outgoing: plugins.net.Socket | null; @@ -116,7 +116,7 @@ export interface ConnectionRecord { isTLS: boolean; // Whether this connection is a TLS connection tlsHandshakeComplete: boolean; // Whether the TLS handshake is complete hasReceivedInitialData: boolean; // Whether initial data has been received - domainConfig?: DomainConfig; // Associated domain config for this connection + domainConfig?: IDomainConfig; // Associated domain config for this connection // Keep-alive tracking hasKeepAlive: boolean; // Whether keep-alive is enabled for this connection @@ -133,10 +133,4 @@ export interface ConnectionRecord { // Browser connection tracking isBrowserConnection?: boolean; // Whether this connection appears to be from a browser domainSwitches?: number; // Number of times the domain has been switched on this connection -} - -// Backward compatibility types -export type ISmartProxyCertProvisionObject = SmartProxyCertProvisionObject; -export interface IDomainConfig extends DomainConfig {} -export interface ISmartProxyOptions extends SmartProxyOptions {} -export interface IConnectionRecord extends ConnectionRecord {} \ No newline at end of file +} \ No newline at end of file diff --git a/ts/proxies/smart-proxy/network-proxy-bridge.ts b/ts/proxies/smart-proxy/network-proxy-bridge.ts index f90a377..f96aaeb 100644 --- a/ts/proxies/smart-proxy/network-proxy-bridge.ts +++ b/ts/proxies/smart-proxy/network-proxy-bridge.ts @@ -3,8 +3,8 @@ import { NetworkProxy } from '../network-proxy/index.js'; import { Port80Handler } from '../../http/port80/port80-handler.js'; import { Port80HandlerEvents } from '../../core/models/common-types.js'; import { subscribeToPort80Handler } from '../../core/utils/event-utils.js'; -import type { CertificateData } from '../../certificate/models/certificate-types.js'; -import type { ConnectionRecord, SmartProxyOptions, DomainConfig } from './models/interfaces.js'; +import type { ICertificateData } from '../../certificate/models/certificate-types.js'; +import type { IConnectionRecord, ISmartProxyOptions, IDomainConfig } from './models/interfaces.js'; /** * Manages NetworkProxy integration for TLS termination @@ -13,7 +13,7 @@ export class NetworkProxyBridge { private networkProxy: NetworkProxy | null = null; private port80Handler: Port80Handler | null = null; - constructor(private settings: SmartProxyOptions) {} + constructor(private settings: ISmartProxyOptions) {} /** * Set the Port80Handler to use for certificate management @@ -66,23 +66,23 @@ export class NetworkProxyBridge { /** * Handle certificate issuance or renewal events */ - private handleCertificateEvent(data: CertificateData): void { + private handleCertificateEvent(data: ICertificateData): void { if (!this.networkProxy) return; - + console.log(`Received certificate for ${data.domain} from Port80Handler, updating NetworkProxy`); - + try { // Find existing config for this domain const existingConfigs = this.networkProxy.getProxyConfigs() .filter(config => config.hostName === data.domain); - + if (existingConfigs.length > 0) { // Update existing configs with new certificate for (const config of existingConfigs) { config.privateKey = data.privateKey; config.publicKey = data.certificate; } - + // Apply updated configs this.networkProxy.updateProxyConfigs(existingConfigs) .then(() => console.log(`Updated certificate for ${data.domain} in NetworkProxy`)) @@ -95,11 +95,11 @@ export class NetworkProxyBridge { console.log(`Error handling certificate event: ${err}`); } } - + /** * Apply an external (static) certificate into NetworkProxy */ - public applyExternalCertificate(data: CertificateData): void { + public applyExternalCertificate(data: ICertificateData): void { if (!this.networkProxy) { console.log(`NetworkProxy not initialized: cannot apply external certificate for ${data.domain}`); return; @@ -183,7 +183,7 @@ export class NetworkProxyBridge { public forwardToNetworkProxy( connectionId: string, socket: plugins.net.Socket, - record: ConnectionRecord, + record: IConnectionRecord, initialData: Buffer, customProxyPort?: number, onError?: (reason: string) => void diff --git a/ts/proxies/smart-proxy/port-range-manager.ts b/ts/proxies/smart-proxy/port-range-manager.ts index 4fc84f4..b18891b 100644 --- a/ts/proxies/smart-proxy/port-range-manager.ts +++ b/ts/proxies/smart-proxy/port-range-manager.ts @@ -1,10 +1,10 @@ -import type { SmartProxyOptions } from './models/interfaces.js'; +import type { ISmartProxyOptions } from './models/interfaces.js'; /** * Manages port ranges and port-based configuration */ export class PortRangeManager { - constructor(private settings: SmartProxyOptions) {} + constructor(private settings: ISmartProxyOptions) {} /** * Get all ports that should be listened on diff --git a/ts/proxies/smart-proxy/security-manager.ts b/ts/proxies/smart-proxy/security-manager.ts index 9e22eb7..6ae8672 100644 --- a/ts/proxies/smart-proxy/security-manager.ts +++ b/ts/proxies/smart-proxy/security-manager.ts @@ -1,5 +1,5 @@ import * as plugins from '../../plugins.js'; -import type { SmartProxyOptions } from './models/interfaces.js'; +import type { ISmartProxyOptions } from './models/interfaces.js'; /** * Handles security aspects like IP tracking, rate limiting, and authorization @@ -8,7 +8,7 @@ export class SecurityManager { private connectionsByIP: Map> = new Map(); private connectionRateByIP: Map = new Map(); - constructor(private settings: SmartProxyOptions) {} + constructor(private settings: ISmartProxyOptions) {} /** * Get connections count by IP diff --git a/ts/proxies/smart-proxy/smart-proxy.ts b/ts/proxies/smart-proxy/smart-proxy.ts index cf6356b..d258daf 100644 --- a/ts/proxies/smart-proxy/smart-proxy.ts +++ b/ts/proxies/smart-proxy/smart-proxy.ts @@ -13,15 +13,15 @@ import { ConnectionHandler } from './connection-handler.js'; // External dependencies from migrated modules import { Port80Handler } from '../../http/port80/port80-handler.js'; import { CertProvisioner } from '../../certificate/providers/cert-provisioner.js'; -import type { CertificateData } from '../../certificate/models/certificate-types.js'; +import type { ICertificateData } from '../../certificate/models/certificate-types.js'; import { buildPort80Handler } from '../../certificate/acme/acme-factory.js'; -import type { ForwardingType } from '../../forwarding/config/forwarding-types.js'; +import type { TForwardingType } from '../../forwarding/config/forwarding-types.js'; import { createPort80HandlerOptions } from '../../common/port80-adapter.js'; // Import types from models -import type { SmartProxyOptions, DomainConfig } from './models/interfaces.js'; +import type { ISmartProxyOptions, IDomainConfig } from './models/interfaces.js'; // Provide backward compatibility types -export type { SmartProxyOptions as IPortProxySettings, DomainConfig as IDomainConfig }; +export type { ISmartProxyOptions as IPortProxySettings, IDomainConfig }; /** * SmartProxy - Main class that coordinates all components @@ -46,7 +46,7 @@ export class SmartProxy extends plugins.EventEmitter { // CertProvisioner for unified certificate workflows private certProvisioner?: CertProvisioner; - constructor(settingsArg: SmartProxyOptions) { + constructor(settingsArg: ISmartProxyOptions) { super(); // Set reasonable defaults for all settings this.settings = { @@ -63,12 +63,12 @@ export class SmartProxy extends plugins.EventEmitter { keepAliveInitialDelay: settingsArg.keepAliveInitialDelay || 10000, maxPendingDataSize: settingsArg.maxPendingDataSize || 10 * 1024 * 1024, disableInactivityCheck: settingsArg.disableInactivityCheck || false, - enableKeepAliveProbes: + enableKeepAliveProbes: settingsArg.enableKeepAliveProbes !== undefined ? settingsArg.enableKeepAliveProbes : true, enableDetailedLogging: settingsArg.enableDetailedLogging || false, enableTlsDebugLogging: settingsArg.enableTlsDebugLogging || false, enableRandomizedTimeouts: settingsArg.enableRandomizedTimeouts || false, - allowSessionTicket: + allowSessionTicket: settingsArg.allowSessionTicket !== undefined ? settingsArg.allowSessionTicket : true, maxConnectionsPerIP: settingsArg.maxConnectionsPerIP || 100, connectionRateLimitPerMinute: settingsArg.connectionRateLimitPerMinute || 300, @@ -126,7 +126,7 @@ export class SmartProxy extends plugins.EventEmitter { /** * The settings for the port proxy */ - public settings: SmartProxyOptions; + public settings: ISmartProxyOptions; /** * Initialize the Port80Handler for ACME certificate management @@ -413,7 +413,7 @@ export class SmartProxy extends plugins.EventEmitter { /** * Updates the domain configurations for the proxy */ - public async updateDomainConfigs(newDomainConfigs: DomainConfig[]): Promise { + public async updateDomainConfigs(newDomainConfigs: IDomainConfig[]): Promise { console.log(`Updating domain configurations (${newDomainConfigs.length} configs)`); // Update domain configs in DomainConfigManager @@ -475,7 +475,7 @@ export class SmartProxy extends plugins.EventEmitter { } else { // Static certificate (e.g., DNS-01 provisioned) supports wildcards const certObj = provision as plugins.tsclass.network.ICert; - const certData: CertificateData = { + const certData: ICertificateData = { domain: certObj.domainName, certificate: certObj.publicKey, privateKey: certObj.privateKey, diff --git a/ts/proxies/smart-proxy/timeout-manager.ts b/ts/proxies/smart-proxy/timeout-manager.ts index 323035a..b3a2035 100644 --- a/ts/proxies/smart-proxy/timeout-manager.ts +++ b/ts/proxies/smart-proxy/timeout-manager.ts @@ -1,10 +1,10 @@ -import type { ConnectionRecord, SmartProxyOptions } from './models/interfaces.js'; +import type { IConnectionRecord, ISmartProxyOptions } from './models/interfaces.js'; /** * Manages timeouts and inactivity tracking for connections */ export class TimeoutManager { - constructor(private settings: SmartProxyOptions) {} + constructor(private settings: ISmartProxyOptions) {} /** * Ensure timeout values don't exceed Node.js max safe integer @@ -28,7 +28,7 @@ export class TimeoutManager { /** * Update connection activity timestamp */ - public updateActivity(record: ConnectionRecord): void { + public updateActivity(record: IConnectionRecord): void { record.lastActivity = Date.now(); // Clear any inactivity warning @@ -36,11 +36,11 @@ export class TimeoutManager { record.inactivityWarningIssued = false; } } - + /** * Calculate effective inactivity timeout based on connection type */ - public getEffectiveInactivityTimeout(record: ConnectionRecord): number { + public getEffectiveInactivityTimeout(record: IConnectionRecord): number { let effectiveTimeout = this.settings.inactivityTimeout || 14400000; // 4 hours default // For immortal keep-alive connections, use an extremely long timeout @@ -60,7 +60,7 @@ export class TimeoutManager { /** * Calculate effective max lifetime based on connection type */ - public getEffectiveMaxLifetime(record: ConnectionRecord): number { + public getEffectiveMaxLifetime(record: IConnectionRecord): number { // Use domain-specific timeout from forwarding.advanced if available const baseTimeout = record.domainConfig?.forwarding?.advanced?.timeout || this.settings.maxConnectionLifetime || @@ -91,8 +91,8 @@ export class TimeoutManager { * @returns The cleanup timer */ public setupConnectionTimeout( - record: ConnectionRecord, - onTimeout: (record: ConnectionRecord, reason: string) => void + record: IConnectionRecord, + onTimeout: (record: IConnectionRecord, reason: string) => void ): NodeJS.Timeout { // Clear any existing timer if (record.cleanupTimer) { @@ -120,7 +120,7 @@ export class TimeoutManager { * Check for inactivity on a connection * @returns Object with check results */ - public checkInactivity(record: ConnectionRecord): { + public checkInactivity(record: IConnectionRecord): { isInactive: boolean; shouldWarn: boolean; inactivityTime: number; @@ -169,7 +169,7 @@ export class TimeoutManager { /** * Apply socket timeout settings */ - public applySocketTimeouts(record: ConnectionRecord): void { + public applySocketTimeouts(record: IConnectionRecord): void { // Skip for immortal keep-alive connections if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') { // Disable timeouts completely for immortal connections diff --git a/ts/proxies/smart-proxy/tls-manager.ts b/ts/proxies/smart-proxy/tls-manager.ts index db93c80..b32c11a 100644 --- a/ts/proxies/smart-proxy/tls-manager.ts +++ b/ts/proxies/smart-proxy/tls-manager.ts @@ -1,5 +1,5 @@ import * as plugins from '../../plugins.js'; -import type { SmartProxyOptions } from './models/interfaces.js'; +import type { ISmartProxyOptions } from './models/interfaces.js'; import { SniHandler } from '../../tls/sni/sni-handler.js'; /** @@ -16,7 +16,7 @@ interface IConnectionInfo { * Manages TLS-related operations including SNI extraction and validation */ export class TlsManager { - constructor(private settings: SmartProxyOptions) {} + constructor(private settings: ISmartProxyOptions) {} /** * Check if a data chunk appears to be a TLS handshake