BREAKING CHANGE(documentation): Update readme documentation to comprehensively describe the new unified route-based configuration system in v14.0.0
This commit is contained in:
		| @@ -1,5 +1,14 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
|  | ## 2025-05-10 - 15.0.0 - BREAKING CHANGE(documentation) | ||||||
|  | Update readme documentation to comprehensively describe the new unified route-based configuration system in v14.0.0 | ||||||
|  |  | ||||||
|  | - Added detailed description of IRouteConfig, IRouteMatch, and IRouteAction interfaces | ||||||
|  | - Improved explanation of port, domain, path, client IP, and TLS version matching features | ||||||
|  | - Included examples of helper functions (createHttpRoute, createHttpsRoute, etc.) with usage of template variables | ||||||
|  | - Enhanced migration guide from legacy configurations to the new match/action pattern | ||||||
|  | - Updated examples and tests to reflect the new documentation structure | ||||||
|  |  | ||||||
| ## 2025-05-09 - 13.1.3 - fix(documentation) | ## 2025-05-09 - 13.1.3 - fix(documentation) | ||||||
| Update readme.md to provide a unified and comprehensive overview of SmartProxy, with reorganized sections, enhanced diagrams, and detailed usage examples for various proxy scenarios. | Update readme.md to provide a unified and comprehensive overview of SmartProxy, with reorganized sections, enhanced diagrams, and detailed usage examples for various proxy scenarios. | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										254
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										254
									
								
								readme.md
									
									
									
									
									
								
							| @@ -202,64 +202,234 @@ await proxy.stop(); | |||||||
|  |  | ||||||
| ## Route-Based Configuration System | ## Route-Based Configuration System | ||||||
|  |  | ||||||
| The new route-based configuration in v14.0.0 follows a match/action pattern, making it more powerful and flexible: | SmartProxy v14.0.0 introduces a new unified route configuration system based on the `IRouteConfig` interface. This system follows a match/action pattern that makes routing more powerful, flexible, and declarative. | ||||||
|  |  | ||||||
|  | ### IRouteConfig Interface | ||||||
|  |  | ||||||
|  | The `IRouteConfig` interface is the core building block of SmartProxy's configuration system. Each route definition consists of match criteria and an action to perform on matched traffic: | ||||||
|  |  | ||||||
|  | ```typescript | ||||||
|  | interface IRouteConfig { | ||||||
|  |   // What traffic to match (required) | ||||||
|  |   match: IRouteMatch; | ||||||
|  |  | ||||||
|  |   // What to do with matched traffic (required) | ||||||
|  |   action: IRouteAction; | ||||||
|  |  | ||||||
|  |   // Metadata (all optional) | ||||||
|  |   name?: string;             // Human-readable name for this route | ||||||
|  |   description?: string;      // Description of the route's purpose | ||||||
|  |   priority?: number;         // Controls matching order (higher = matched first) | ||||||
|  |   tags?: string[];           // Arbitrary tags for categorization | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Match Criteria (IRouteMatch) | ||||||
|  |  | ||||||
|  | The `match` property defines criteria for identifying which incoming traffic should be handled by this route: | ||||||
|  |  | ||||||
|  | ```typescript | ||||||
|  | interface IRouteMatch { | ||||||
|  |   // Listen on these ports (required) | ||||||
|  |   ports: TPortRange;  // number | number[] | Array<{ from: number; to: number }> | ||||||
|  |  | ||||||
|  |   // Optional domain patterns to match (default: all domains) | ||||||
|  |   domains?: string | string[];  // Supports wildcards like '*.example.com' | ||||||
|  |  | ||||||
|  |   // Advanced matching criteria (all optional) | ||||||
|  |   path?: string;           // Match specific URL paths, supports glob patterns | ||||||
|  |   clientIp?: string[];     // Match specific client IPs, supports glob patterns | ||||||
|  |   tlsVersion?: string[];   // Match specific TLS versions e.g. ['TLSv1.2', 'TLSv1.3'] | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **Port Specification:** | ||||||
|  | - **Single port:** `ports: 80` | ||||||
|  | - **Multiple ports:** `ports: [80, 443]` | ||||||
|  | - **Port ranges:** `ports: [{ from: 8000, to: 8100 }]` | ||||||
|  | - **Mixed format:** `ports: [80, 443, { from: 8000, to: 8100 }]` | ||||||
|  |  | ||||||
|  | **Domain Matching:** | ||||||
|  | - **Single domain:** `domains: 'example.com'` | ||||||
|  | - **Multiple domains:** `domains: ['example.com', 'api.example.com']` | ||||||
|  | - **Wildcard domains:** `domains: '*.example.com'` (matches any subdomain) | ||||||
|  | - **Root domain + subdomains:** `domains: ['example.com', '*.example.com']` | ||||||
|  |  | ||||||
|  | **Path Matching:** | ||||||
|  | - **Exact path:** `path: '/api'` (matches only /api exactly) | ||||||
|  | - **Prefix match:** `path: '/api/*'` (matches /api and any paths under it) | ||||||
|  | - **Multiple patterns:** Use multiple routes with different priorities | ||||||
|  |  | ||||||
|  | **Client IP Matching:** | ||||||
|  | - **Exact IP:** `clientIp: ['192.168.1.1']` | ||||||
|  | - **Subnet wildcards:** `clientIp: ['10.0.0.*', '192.168.1.*']` | ||||||
|  | - **CIDR notation:** `clientIp: ['10.0.0.0/24']` | ||||||
|  |  | ||||||
|  | **TLS Version Matching:** | ||||||
|  | - `tlsVersion: ['TLSv1.2', 'TLSv1.3']` (only match these TLS versions) | ||||||
|  |  | ||||||
|  | #### Action Configuration (IRouteAction) | ||||||
|  |  | ||||||
|  | The `action` property defines what to do with traffic that matches the criteria: | ||||||
|  |  | ||||||
|  | ```typescript | ||||||
|  | interface IRouteAction { | ||||||
|  |   // Action type (required) | ||||||
|  |   type: 'forward' | 'redirect' | 'block'; | ||||||
|  |  | ||||||
|  |   // For 'forward' actions | ||||||
|  |   target?: IRouteTarget; | ||||||
|  |  | ||||||
|  |   // TLS handling for 'forward' actions | ||||||
|  |   tls?: IRouteTls; | ||||||
|  |  | ||||||
|  |   // For 'redirect' actions | ||||||
|  |   redirect?: IRouteRedirect; | ||||||
|  |  | ||||||
|  |   // Security options for any action | ||||||
|  |   security?: IRouteSecurity; | ||||||
|  |  | ||||||
|  |   // Advanced options | ||||||
|  |   advanced?: IRouteAdvanced; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **Forward Action:** | ||||||
|  | When `type: 'forward'`, the traffic is forwarded to the specified target: | ||||||
|  | ```typescript | ||||||
|  | interface IRouteTarget { | ||||||
|  |   host: string | string[];  // Target host(s) - string array enables round-robin | ||||||
|  |   port: number;             // Target port | ||||||
|  |   preservePort?: boolean;   // Use incoming port as target port (default: false) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **TLS Configuration:** | ||||||
|  | When forwarding with TLS, you can configure how TLS is handled: | ||||||
|  | ```typescript | ||||||
|  | interface IRouteTls { | ||||||
|  |   mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt'; | ||||||
|  |   certificate?: 'auto' | {   // 'auto' = use ACME (Let's Encrypt) | ||||||
|  |     key: string;            // TLS private key content | ||||||
|  |     cert: string;           // TLS certificate content | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **TLS Modes:** | ||||||
|  | - **passthrough:** Forward raw encrypted TLS traffic without decryption | ||||||
|  | - **terminate:** Terminate TLS and forward as HTTP | ||||||
|  | - **terminate-and-reencrypt:** Terminate TLS and create a new TLS connection to the backend | ||||||
|  |  | ||||||
|  | **Redirect Action:** | ||||||
|  | When `type: 'redirect'`, the client is redirected: | ||||||
|  | ```typescript | ||||||
|  | interface IRouteRedirect { | ||||||
|  |   to: string;                   // URL or template with variables | ||||||
|  |   status: 301 | 302 | 307 | 308;  // HTTP status code | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **Block Action:** | ||||||
|  | When `type: 'block'`, the connection is immediately closed. | ||||||
|  |  | ||||||
|  | **Security Options:** | ||||||
|  | For any action type, you can add security controls: | ||||||
|  | ```typescript | ||||||
|  | interface IRouteSecurity { | ||||||
|  |   allowedIps?: string[];     // IP allowlist with glob pattern support | ||||||
|  |   blockedIps?: string[];     // IP blocklist with glob pattern support | ||||||
|  |   maxConnections?: number;   // Maximum concurrent connections | ||||||
|  |   authentication?: {         // Optional authentication (future support) | ||||||
|  |     type: 'basic' | 'digest' | 'oauth'; | ||||||
|  |     // Auth-specific options | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **Advanced Options:** | ||||||
|  | Additional advanced configurations: | ||||||
|  | ```typescript | ||||||
|  | interface IRouteAdvanced { | ||||||
|  |   timeout?: number;                 // Connection timeout in milliseconds | ||||||
|  |   headers?: Record<string, string>; // Custom HTTP headers | ||||||
|  |   keepAlive?: boolean;              // Enable connection pooling | ||||||
|  |   // Additional advanced options | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Template Variables | ||||||
|  |  | ||||||
|  | String values in redirect URLs and headers can include variables: | ||||||
|  |  | ||||||
|  | - `{domain}`: The requested domain name | ||||||
|  | - `{port}`: The incoming port number | ||||||
|  | - `{path}`: The requested URL path | ||||||
|  | - `{query}`: The query string | ||||||
|  | - `{clientIp}`: The client's IP address | ||||||
|  | - `{sni}`: The SNI hostname | ||||||
|  |  | ||||||
|  | Example with template variables: | ||||||
|  | ```typescript | ||||||
|  | redirect: { | ||||||
|  |   to: 'https://{domain}{path}?source=redirect', | ||||||
|  |   status: 301 | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | #### Route Metadata and Prioritization | ||||||
|  |  | ||||||
|  | You can add metadata to routes to help with organization and control matching priority: | ||||||
|  |  | ||||||
| ```typescript | ```typescript | ||||||
| // Basic structure of a route configuration |  | ||||||
| { | { | ||||||
|   // What traffic to match |   name: 'API Server',                 // Human-readable name | ||||||
|  |   description: 'Main API endpoints',  // Description | ||||||
|  |   priority: 100,                      // Matching priority (higher = matched first) | ||||||
|  |   tags: ['api', 'internal']           // Arbitrary tags | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Routes with higher priority values are matched first, allowing you to create specialized routes that take precedence over more general ones. | ||||||
|  |  | ||||||
|  | #### Complete Route Configuration Example | ||||||
|  |  | ||||||
|  | ```typescript | ||||||
|  | // Example of a complete route configuration | ||||||
|  | { | ||||||
|   match: { |   match: { | ||||||
|     ports: 443,                          // Required: port(s) to listen on |     ports: 443, | ||||||
|     domains: 'example.com',              // Optional: domain(s) to match |     domains: ['api.example.com', 'api-v2.example.com'], | ||||||
|     path: '/api',                        // Optional: URL path pattern |     path: '/secure/*', | ||||||
|     clientIp: ['10.0.0.*'],              // Optional: client IP patterns to match |     clientIp: ['10.0.0.*', '192.168.1.*'] | ||||||
|     tlsVersion: ['TLSv1.2', 'TLSv1.3']   // Optional: TLS versions to match |  | ||||||
|   }, |   }, | ||||||
|    |  | ||||||
|   // What to do with matched traffic |  | ||||||
|   action: { |   action: { | ||||||
|     type: 'forward',                     // 'forward', 'redirect', or 'block' |     type: 'forward', | ||||||
|      |  | ||||||
|     // For 'forward' actions |  | ||||||
|     target: { |     target: { | ||||||
|       host: 'localhost',                 // Target host(s) for forwarding |       host: ['10.0.0.1', '10.0.0.2'],  // Round-robin between these hosts | ||||||
|       port: 8080                         // Target port |       port: 8080 | ||||||
|     }, |     }, | ||||||
|      |  | ||||||
|     // TLS handling (for 'forward' actions) |  | ||||||
|     tls: { |     tls: { | ||||||
|       mode: 'terminate',                 // 'passthrough', 'terminate', 'terminate-and-reencrypt' |       mode: 'terminate', | ||||||
|       certificate: 'auto'                // 'auto' for Let's Encrypt or {key, cert} |       certificate: 'auto'  // Use Let's Encrypt | ||||||
|     }, |     }, | ||||||
|      |  | ||||||
|     // For 'redirect' actions |  | ||||||
|     redirect: { |  | ||||||
|       to: 'https://{domain}{path}',      // URL pattern with variables |  | ||||||
|       status: 301                        // HTTP status code |  | ||||||
|     }, |  | ||||||
|      |  | ||||||
|     // Security controls for any action |  | ||||||
|     security: { |     security: { | ||||||
|       allowedIps: ['10.0.0.*'],          // IP allowlist |       allowedIps: ['10.0.0.*'], | ||||||
|       blockedIps: ['1.2.3.4'],           // IP blocklist |       maxConnections: 100 | ||||||
|       maxConnections: 100                // Connection limits |  | ||||||
|     }, |     }, | ||||||
|      |  | ||||||
|     // Advanced options |  | ||||||
|     advanced: { |     advanced: { | ||||||
|       timeout: 30000,                    // Connection timeout |       timeout: 30000, | ||||||
|       headers: {                         // Custom headers |       headers: { | ||||||
|         'X-Forwarded-For': '{clientIp}' |         'X-Original-Host': '{domain}', | ||||||
|  |         'X-Client-IP': '{clientIp}' | ||||||
|       }, |       }, | ||||||
|       keepAlive: true                    // Connection pooling |       keepAlive: true | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|    |   name: 'Secure API Route', | ||||||
|   // Metadata (optional) |   description: 'Route for secure API endpoints with authentication', | ||||||
|   name: 'API Server',                    // Human-readable name |   priority: 100, | ||||||
|   description: 'Main API endpoints',     // Description |   tags: ['api', 'secure', 'internal'] | ||||||
|   priority: 100,                         // Matching priority (higher = matched first) |  | ||||||
|   tags: ['api', 'internal']              // Arbitrary tags |  | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ import { | |||||||
| } from '../ts/proxies/smart-proxy/index.js'; | } from '../ts/proxies/smart-proxy/index.js'; | ||||||
|  |  | ||||||
| // Import test helpers | // Import test helpers | ||||||
| import { getCertificate } from './helpers/certificates.js'; | import { loadTestCertificates } from './helpers/certificates.js'; | ||||||
|  |  | ||||||
| tap.test('Routes: Should create basic HTTP route', async () => { | tap.test('Routes: Should create basic HTTP route', async () => { | ||||||
|   // Create a simple HTTP route |   // Create a simple HTTP route | ||||||
| @@ -31,12 +31,12 @@ tap.test('Routes: Should create basic HTTP route', async () => { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   // Validate the route configuration |   // Validate the route configuration | ||||||
|   expect(httpRoute.match.ports).to.equal(8080); |   expect(httpRoute.match.ports).toEqual(8080); | ||||||
|   expect(httpRoute.match.domains).to.equal('example.com'); |   expect(httpRoute.match.domains).toEqual('example.com'); | ||||||
|   expect(httpRoute.action.type).to.equal('forward'); |   expect(httpRoute.action.type).toEqual('forward'); | ||||||
|   expect(httpRoute.action.target?.host).to.equal('localhost'); |   expect(httpRoute.action.target?.host).toEqual('localhost'); | ||||||
|   expect(httpRoute.action.target?.port).to.equal(3000); |   expect(httpRoute.action.target?.port).toEqual(3000); | ||||||
|   expect(httpRoute.name).to.equal('Basic HTTP Route'); |   expect(httpRoute.name).toEqual('Basic HTTP Route'); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| tap.test('Routes: Should create HTTPS route with TLS termination', async () => { | tap.test('Routes: Should create HTTPS route with TLS termination', async () => { | ||||||
| @@ -52,14 +52,14 @@ tap.test('Routes: Should create HTTPS route with TLS termination', async () => { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   // Validate the route configuration |   // Validate the route configuration | ||||||
|   expect(httpsRoute.match.ports).to.equal(443); // Default HTTPS port |   expect(httpsRoute.match.ports).toEqual(443); // Default HTTPS port | ||||||
|   expect(httpsRoute.match.domains).to.equal('secure.example.com'); |   expect(httpsRoute.match.domains).toEqual('secure.example.com'); | ||||||
|   expect(httpsRoute.action.type).to.equal('forward'); |   expect(httpsRoute.action.type).toEqual('forward'); | ||||||
|   expect(httpsRoute.action.tls?.mode).to.equal('terminate'); |   expect(httpsRoute.action.tls?.mode).toEqual('terminate'); | ||||||
|   expect(httpsRoute.action.tls?.certificate).to.equal('auto'); |   expect(httpsRoute.action.tls?.certificate).toEqual('auto'); | ||||||
|   expect(httpsRoute.action.target?.host).to.equal('localhost'); |   expect(httpsRoute.action.target?.host).toEqual('localhost'); | ||||||
|   expect(httpsRoute.action.target?.port).to.equal(8080); |   expect(httpsRoute.action.target?.port).toEqual(8080); | ||||||
|   expect(httpsRoute.name).to.equal('HTTPS Route'); |   expect(httpsRoute.name).toEqual('HTTPS Route'); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| tap.test('Routes: Should create HTTP to HTTPS redirect', async () => { | tap.test('Routes: Should create HTTP to HTTPS redirect', async () => { | ||||||
| @@ -70,11 +70,11 @@ tap.test('Routes: Should create HTTP to HTTPS redirect', async () => { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   // Validate the route configuration |   // Validate the route configuration | ||||||
|   expect(redirectRoute.match.ports).to.equal(80); |   expect(redirectRoute.match.ports).toEqual(80); | ||||||
|   expect(redirectRoute.match.domains).to.equal('example.com'); |   expect(redirectRoute.match.domains).toEqual('example.com'); | ||||||
|   expect(redirectRoute.action.type).to.equal('redirect'); |   expect(redirectRoute.action.type).toEqual('redirect'); | ||||||
|   expect(redirectRoute.action.redirect?.to).to.equal('https://{domain}{path}'); |   expect(redirectRoute.action.redirect?.to).toEqual('https://{domain}{path}'); | ||||||
|   expect(redirectRoute.action.redirect?.status).to.equal(301); |   expect(redirectRoute.action.redirect?.status).toEqual(301); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| tap.test('Routes: Should create complete HTTPS server with redirects', async () => { | tap.test('Routes: Should create complete HTTPS server with redirects', async () => { | ||||||
| @@ -90,20 +90,20 @@ tap.test('Routes: Should create complete HTTPS server with redirects', async () | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   // Validate that we got two routes (HTTPS route and HTTP redirect) |   // Validate that we got two routes (HTTPS route and HTTP redirect) | ||||||
|   expect(routes.length).to.equal(2); |   expect(routes.length).toEqual(2); | ||||||
|  |  | ||||||
|   // Validate HTTPS route |   // Validate HTTPS route | ||||||
|   const httpsRoute = routes[0]; |   const httpsRoute = routes[0]; | ||||||
|   expect(httpsRoute.match.ports).to.equal(443); |   expect(httpsRoute.match.ports).toEqual(443); | ||||||
|   expect(httpsRoute.match.domains).to.equal('example.com'); |   expect(httpsRoute.match.domains).toEqual('example.com'); | ||||||
|   expect(httpsRoute.action.type).to.equal('forward'); |   expect(httpsRoute.action.type).toEqual('forward'); | ||||||
|   expect(httpsRoute.action.tls?.mode).to.equal('terminate'); |   expect(httpsRoute.action.tls?.mode).toEqual('terminate'); | ||||||
|  |  | ||||||
|   // Validate HTTP redirect route |   // Validate HTTP redirect route | ||||||
|   const redirectRoute = routes[1]; |   const redirectRoute = routes[1]; | ||||||
|   expect(redirectRoute.match.ports).to.equal(80); |   expect(redirectRoute.match.ports).toEqual(80); | ||||||
|   expect(redirectRoute.action.type).to.equal('redirect'); |   expect(redirectRoute.action.type).toEqual('redirect'); | ||||||
|   expect(redirectRoute.action.redirect?.to).to.equal('https://{domain}{path}'); |   expect(redirectRoute.action.redirect?.to).toEqual('https://{domain}{path}'); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| tap.test('Routes: Should create load balancer route', async () => { | tap.test('Routes: Should create load balancer route', async () => { | ||||||
| @@ -118,18 +118,18 @@ tap.test('Routes: Should create load balancer route', async () => { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   // Validate the route configuration |   // Validate the route configuration | ||||||
|   expect(lbRoute.match.domains).to.equal('app.example.com'); |   expect(lbRoute.match.domains).toEqual('app.example.com'); | ||||||
|   expect(lbRoute.action.type).to.equal('forward'); |   expect(lbRoute.action.type).toEqual('forward'); | ||||||
|   expect(Array.isArray(lbRoute.action.target?.host)).to.equal(true); |   expect(Array.isArray(lbRoute.action.target?.host)).toBeTrue(); | ||||||
|   expect((lbRoute.action.target?.host as string[]).length).to.equal(3); |   expect((lbRoute.action.target?.host as string[]).length).toEqual(3); | ||||||
|   expect((lbRoute.action.target?.host as string[])[0]).to.equal('10.0.0.1'); |   expect((lbRoute.action.target?.host as string[])[0]).toEqual('10.0.0.1'); | ||||||
|   expect(lbRoute.action.target?.port).to.equal(8080); |   expect(lbRoute.action.target?.port).toEqual(8080); | ||||||
|   expect(lbRoute.action.tls?.mode).to.equal('terminate'); |   expect(lbRoute.action.tls?.mode).toEqual('terminate'); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| tap.test('SmartProxy: Should create instance with route-based config', async () => { | tap.test('SmartProxy: Should create instance with route-based config', async () => { | ||||||
|   // Create TLS certificates for testing |   // Create TLS certificates for testing | ||||||
|   const cert = await getCertificate(); |   const certs = loadTestCertificates(); | ||||||
|  |  | ||||||
|   // Create a SmartProxy instance with route-based configuration |   // Create a SmartProxy instance with route-based configuration | ||||||
|   const proxy = new SmartProxy({ |   const proxy = new SmartProxy({ | ||||||
| @@ -150,8 +150,8 @@ tap.test('SmartProxy: Should create instance with route-based config', async () | |||||||
|           port: 8443 |           port: 8443 | ||||||
|         }, |         }, | ||||||
|         certificate: { |         certificate: { | ||||||
|           key: cert.key, |           key: certs.privateKey, | ||||||
|           cert: cert.cert |           cert: certs.publicKey | ||||||
|         }, |         }, | ||||||
|         name: 'HTTPS Route' |         name: 'HTTPS Route' | ||||||
|       }) |       }) | ||||||
| @@ -173,9 +173,9 @@ tap.test('SmartProxy: Should create instance with route-based config', async () | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   // Simply verify the instance was created successfully |   // Simply verify the instance was created successfully | ||||||
|   expect(proxy).to.be.an('object'); |   expect(typeof proxy).toEqual('object'); | ||||||
|   expect(proxy.start).to.be.a('function'); |   expect(typeof proxy.start).toEqual('function'); | ||||||
|   expect(proxy.stop).to.be.a('function'); |   expect(typeof proxy.stop).toEqual('function'); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| export default tap.start(); | export default tap.start(); | ||||||
| @@ -3,6 +3,6 @@ | |||||||
|  */ |  */ | ||||||
| export const commitinfo = { | export const commitinfo = { | ||||||
|   name: '@push.rocks/smartproxy', |   name: '@push.rocks/smartproxy', | ||||||
|   version: '13.1.3', |   version: '15.0.0', | ||||||
|   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.' |   description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.' | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user