@push.rocks/smartproxy 15.0.2 → 16.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/certificate/index.d.ts +10 -4
  3. package/dist_ts/certificate/index.js +5 -7
  4. package/dist_ts/certificate/models/certificate-types.d.ts +35 -15
  5. package/dist_ts/certificate/providers/cert-provisioner.d.ts +41 -15
  6. package/dist_ts/certificate/providers/cert-provisioner.js +201 -41
  7. package/dist_ts/forwarding/config/forwarding-types.d.ts +40 -76
  8. package/dist_ts/forwarding/config/forwarding-types.js +19 -18
  9. package/dist_ts/forwarding/config/index.d.ts +4 -2
  10. package/dist_ts/forwarding/config/index.js +5 -3
  11. package/dist_ts/forwarding/handlers/base-handler.js +3 -1
  12. package/dist_ts/forwarding/index.d.ts +5 -6
  13. package/dist_ts/forwarding/index.js +3 -3
  14. package/dist_ts/http/models/http-types.js +1 -1
  15. package/dist_ts/http/port80/acme-interfaces.d.ts +30 -0
  16. package/dist_ts/http/port80/acme-interfaces.js +46 -1
  17. package/dist_ts/http/port80/port80-handler.d.ts +17 -2
  18. package/dist_ts/http/port80/port80-handler.js +49 -11
  19. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +2 -61
  20. package/dist_ts/proxies/smart-proxy/models/interfaces.js +5 -4
  21. package/dist_ts/proxies/smart-proxy/models/route-types.d.ts +118 -4
  22. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.d.ts +70 -4
  23. package/dist_ts/proxies/smart-proxy/network-proxy-bridge.js +193 -43
  24. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +2 -5
  25. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +25 -146
  26. package/dist_ts/proxies/smart-proxy/route-helpers/index.d.ts +7 -0
  27. package/dist_ts/proxies/smart-proxy/route-helpers/index.js +9 -0
  28. package/dist_ts/proxies/smart-proxy/route-helpers.d.ts +54 -1
  29. package/dist_ts/proxies/smart-proxy/route-helpers.js +102 -1
  30. package/dist_ts/proxies/smart-proxy/route-manager.d.ts +3 -9
  31. package/dist_ts/proxies/smart-proxy/route-manager.js +3 -115
  32. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +72 -10
  33. package/dist_ts/proxies/smart-proxy/smart-proxy.js +135 -268
  34. package/dist_ts/proxies/smart-proxy/timeout-manager.js +3 -3
  35. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +12 -0
  36. package/dist_ts/proxies/smart-proxy/utils/index.js +19 -0
  37. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +174 -0
  38. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +332 -0
  39. package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.d.ts +51 -0
  40. package/dist_ts/proxies/smart-proxy/utils/route-migration-utils.js +124 -0
  41. package/dist_ts/proxies/smart-proxy/utils/route-patterns.d.ts +131 -0
  42. package/dist_ts/proxies/smart-proxy/utils/route-patterns.js +217 -0
  43. package/dist_ts/proxies/smart-proxy/utils/route-utils.d.ts +79 -0
  44. package/dist_ts/proxies/smart-proxy/utils/route-utils.js +266 -0
  45. package/dist_ts/proxies/smart-proxy/utils/route-validators.d.ts +73 -0
  46. package/dist_ts/proxies/smart-proxy/utils/route-validators.js +242 -0
  47. package/package.json +1 -1
  48. package/readme.md +139 -111
  49. package/readme.plan.md +164 -312
  50. package/ts/00_commitinfo_data.ts +1 -1
  51. package/ts/certificate/index.ts +17 -9
  52. package/ts/certificate/models/certificate-types.ts +37 -16
  53. package/ts/certificate/providers/cert-provisioner.ts +247 -54
  54. package/ts/forwarding/config/forwarding-types.ts +79 -107
  55. package/ts/forwarding/config/index.ts +4 -2
  56. package/ts/forwarding/handlers/base-handler.ts +4 -2
  57. package/ts/forwarding/index.ts +3 -2
  58. package/ts/http/models/http-types.ts +0 -1
  59. package/ts/http/port80/acme-interfaces.ts +84 -0
  60. package/ts/http/port80/port80-handler.ts +61 -15
  61. package/ts/proxies/smart-proxy/models/interfaces.ts +7 -64
  62. package/ts/proxies/smart-proxy/models/route-types.ts +152 -22
  63. package/ts/proxies/smart-proxy/network-proxy-bridge.ts +226 -55
  64. package/ts/proxies/smart-proxy/route-connection-handler.ts +36 -205
  65. package/ts/proxies/smart-proxy/route-helpers/index.ts +9 -0
  66. package/ts/proxies/smart-proxy/route-helpers.ts +165 -11
  67. package/ts/proxies/smart-proxy/route-manager.ts +3 -130
  68. package/ts/proxies/smart-proxy/smart-proxy.ts +157 -329
  69. package/ts/proxies/smart-proxy/timeout-manager.ts +2 -2
  70. package/ts/proxies/smart-proxy/utils/index.ts +40 -0
  71. package/ts/proxies/smart-proxy/utils/route-helpers.ts +455 -0
  72. package/ts/proxies/smart-proxy/utils/route-migration-utils.ts +165 -0
  73. package/ts/proxies/smart-proxy/utils/route-patterns.ts +309 -0
  74. package/ts/proxies/smart-proxy/utils/route-utils.ts +330 -0
  75. package/ts/proxies/smart-proxy/utils/route-validators.ts +269 -0
  76. package/ts/forwarding/config/domain-config.ts +0 -28
  77. package/ts/forwarding/config/domain-manager.ts +0 -283
  78. package/ts/proxies/smart-proxy/connection-handler.ts +0 -1240
  79. package/ts/proxies/smart-proxy/port-range-manager.ts +0 -211
  80. /package/ts/proxies/smart-proxy/{domain-config-manager.ts → domain-config-manager.ts.bak} +0 -0
@@ -1,12 +1,10 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type {
3
3
  IConnectionRecord,
4
- IDomainConfig,
5
4
  ISmartProxyOptions
6
5
  } from './models/interfaces.js';
7
6
  import {
8
- isRoutedOptions,
9
- isLegacyOptions
7
+ isRoutedOptions
10
8
  } from './models/interfaces.js';
11
9
  import type {
12
10
  IRouteConfig,
@@ -14,13 +12,11 @@ import type {
14
12
  } from './models/route-types.js';
15
13
  import { ConnectionManager } from './connection-manager.js';
16
14
  import { SecurityManager } from './security-manager.js';
17
- import { DomainConfigManager } from './domain-config-manager.js';
18
15
  import { TlsManager } from './tls-manager.js';
19
16
  import { NetworkProxyBridge } from './network-proxy-bridge.js';
20
17
  import { TimeoutManager } from './timeout-manager.js';
21
18
  import { RouteManager } from './route-manager.js';
22
19
  import type { ForwardingHandler } from '../../forwarding/handlers/base-handler.js';
23
- import type { TForwardingType } from '../../forwarding/config/forwarding-types.js';
24
20
 
25
21
  /**
26
22
  * Handles new connection processing and setup logic with support for route-based configuration
@@ -32,7 +28,6 @@ export class RouteConnectionHandler {
32
28
  settings: ISmartProxyOptions,
33
29
  private connectionManager: ConnectionManager,
34
30
  private securityManager: SecurityManager,
35
- private domainConfigManager: DomainConfigManager,
36
31
  private tlsManager: TlsManager,
37
32
  private networkProxyBridge: NetworkProxyBridge,
38
33
  private timeoutManager: TimeoutManager,
@@ -244,37 +239,20 @@ export class RouteConnectionHandler {
244
239
 
245
240
  if (!routeMatch) {
246
241
  console.log(`[${connectionId}] No route found for ${serverName || 'connection'} on port ${localPort}`);
247
-
248
- // Fall back to legacy matching if we're using a hybrid configuration
249
- const domainConfig = serverName
250
- ? this.domainConfigManager.findDomainConfig(serverName)
251
- : this.domainConfigManager.findDomainConfigForPort(localPort);
252
242
 
253
- if (domainConfig) {
254
- if (this.settings.enableDetailedLogging) {
255
- console.log(`[${connectionId}] Using legacy domain configuration for ${serverName || 'port ' + localPort}`);
256
- }
257
-
258
- // Associate this domain config with the connection
259
- record.domainConfig = domainConfig;
260
-
261
- // Handle the connection using the legacy setup
262
- return this.handleLegacyConnection(socket, record, serverName, domainConfig, initialChunk);
263
- }
264
-
265
- // No matching route or domain config, use default/fallback handling
243
+ // No matching route, use default/fallback handling
266
244
  console.log(`[${connectionId}] Using default route handling for connection`);
267
-
245
+
268
246
  // Check default security settings
269
247
  const defaultSecuritySettings = this.settings.defaults?.security;
270
248
  if (defaultSecuritySettings) {
271
- if (defaultSecuritySettings.allowedIPs && defaultSecuritySettings.allowedIPs.length > 0) {
249
+ if (defaultSecuritySettings.allowedIps && defaultSecuritySettings.allowedIps.length > 0) {
272
250
  const isAllowed = this.securityManager.isIPAuthorized(
273
251
  remoteIP,
274
- defaultSecuritySettings.allowedIPs,
275
- defaultSecuritySettings.blockedIPs || []
252
+ defaultSecuritySettings.allowedIps,
253
+ defaultSecuritySettings.blockedIps || []
276
254
  );
277
-
255
+
278
256
  if (!isAllowed) {
279
257
  console.log(`[${connectionId}] IP ${remoteIP} not in default allowed list`);
280
258
  socket.end();
@@ -282,34 +260,24 @@ export class RouteConnectionHandler {
282
260
  return;
283
261
  }
284
262
  }
285
- } else if (this.settings.defaultAllowedIPs && this.settings.defaultAllowedIPs.length > 0) {
286
- // Legacy default IP restrictions
287
- const isAllowed = this.securityManager.isIPAuthorized(
288
- remoteIP,
289
- this.settings.defaultAllowedIPs,
290
- this.settings.defaultBlockedIPs || []
291
- );
292
-
293
- if (!isAllowed) {
294
- console.log(`[${connectionId}] IP ${remoteIP} not in default allowed list`);
295
- socket.end();
296
- this.connectionManager.cleanupConnection(record, 'ip_blocked');
297
- return;
298
- }
299
263
  }
300
264
 
301
265
  // Setup direct connection with default settings
302
- let targetHost: string;
303
- let targetPort: number;
304
-
305
- if (isRoutedOptions(this.settings) && this.settings.defaults?.target) {
306
- // Use defaults from routed configuration
307
- targetHost = this.settings.defaults.target.host;
308
- targetPort = this.settings.defaults.target.port;
309
- } else if (this.settings.targetIP && this.settings.toPort) {
310
- // Fall back to legacy settings
311
- targetHost = this.settings.targetIP;
312
- targetPort = this.settings.toPort;
266
+ if (this.settings.defaults?.target) {
267
+ // Use defaults from configuration
268
+ const targetHost = this.settings.defaults.target.host;
269
+ const targetPort = this.settings.defaults.target.port;
270
+
271
+ return this.setupDirectConnection(
272
+ socket,
273
+ record,
274
+ undefined,
275
+ serverName,
276
+ initialChunk,
277
+ undefined,
278
+ targetHost,
279
+ targetPort
280
+ );
313
281
  } else {
314
282
  // No default target available, terminate the connection
315
283
  console.log(`[${connectionId}] No default target configured. Closing connection.`);
@@ -317,17 +285,6 @@ export class RouteConnectionHandler {
317
285
  this.connectionManager.cleanupConnection(record, 'no_default_target');
318
286
  return;
319
287
  }
320
-
321
- return this.setupDirectConnection(
322
- socket,
323
- record,
324
- undefined,
325
- serverName,
326
- initialChunk,
327
- undefined,
328
- targetHost,
329
- targetPort
330
- );
331
288
  }
332
289
 
333
290
  // A matching route was found
@@ -575,114 +532,8 @@ export class RouteConnectionHandler {
575
532
  }
576
533
 
577
534
  /**
578
- * Handle a connection using legacy domain configuration
535
+ * Legacy connection handling has been removed in favor of pure route-based approach
579
536
  */
580
- private handleLegacyConnection(
581
- socket: plugins.net.Socket,
582
- record: IConnectionRecord,
583
- serverName: string,
584
- domainConfig: IDomainConfig,
585
- initialChunk?: Buffer
586
- ): void {
587
- const connectionId = record.id;
588
-
589
- // Get the forwarding type for this domain
590
- const forwardingType = this.domainConfigManager.getForwardingType(domainConfig);
591
-
592
- // IP validation
593
- const ipRules = this.domainConfigManager.getEffectiveIPRules(domainConfig);
594
-
595
- if (!this.securityManager.isIPAuthorized(record.remoteIP, ipRules.allowedIPs, ipRules.blockedIPs)) {
596
- console.log(
597
- `[${connectionId}] Connection rejected: IP ${record.remoteIP} not allowed for domain ${domainConfig.domains.join(', ')}`
598
- );
599
- socket.end();
600
- this.connectionManager.initiateCleanupOnce(record, 'ip_blocked');
601
- return;
602
- }
603
-
604
- // Handle based on forwarding type
605
- switch (forwardingType) {
606
- case 'http-only':
607
- // For HTTP-only configs with TLS traffic
608
- if (record.isTLS) {
609
- console.log(`[${connectionId}] Received TLS connection for HTTP-only domain ${serverName}`);
610
- socket.end();
611
- this.connectionManager.initiateCleanupOnce(record, 'wrong_protocol');
612
- return;
613
- }
614
- break;
615
-
616
- case 'https-passthrough':
617
- // For TLS passthrough with TLS traffic
618
- if (record.isTLS) {
619
- try {
620
- const handler = this.domainConfigManager.getForwardingHandler(domainConfig);
621
-
622
- if (this.settings.enableDetailedLogging) {
623
- console.log(`[${connectionId}] Using forwarding handler for SNI passthrough to ${serverName}`);
624
- }
625
-
626
- // Handle the connection using the handler
627
- return handler.handleConnection(socket);
628
- } catch (err) {
629
- console.log(`[${connectionId}] Error using forwarding handler: ${err}`);
630
- }
631
- }
632
- break;
633
-
634
- case 'https-terminate-to-http':
635
- case 'https-terminate-to-https':
636
- // For TLS termination with TLS traffic
637
- if (record.isTLS) {
638
- const networkProxyPort = this.domainConfigManager.getNetworkProxyPort(domainConfig);
639
-
640
- if (this.settings.enableDetailedLogging) {
641
- console.log(`[${connectionId}] Using TLS termination (${forwardingType}) for ${serverName} on port ${networkProxyPort}`);
642
- }
643
-
644
- // Forward to NetworkProxy with domain-specific port
645
- return this.networkProxyBridge.forwardToNetworkProxy(
646
- connectionId,
647
- socket,
648
- record,
649
- initialChunk!,
650
- networkProxyPort,
651
- (reason) => this.connectionManager.initiateCleanupOnce(record, reason)
652
- );
653
- }
654
- break;
655
- }
656
-
657
- // If we're still here, use the forwarding handler if available
658
- try {
659
- const handler = this.domainConfigManager.getForwardingHandler(domainConfig);
660
-
661
- if (this.settings.enableDetailedLogging) {
662
- console.log(`[${connectionId}] Using general forwarding handler for domain ${serverName || 'unknown'}`);
663
- }
664
-
665
- // Handle the connection using the handler
666
- return handler.handleConnection(socket);
667
- } catch (err) {
668
- console.log(`[${connectionId}] Error using forwarding handler: ${err}`);
669
- }
670
-
671
- // Fallback: set up direct connection
672
- const targetIp = this.domainConfigManager.getTargetIP(domainConfig);
673
- const targetPort = this.domainConfigManager.getTargetPort(domainConfig, this.settings.toPort);
674
-
675
- return this.setupDirectConnection(
676
- socket,
677
- record,
678
- domainConfig,
679
- serverName,
680
- initialChunk,
681
- undefined,
682
- targetIp,
683
- targetPort
684
- );
685
- }
686
537
 
687
538
  /**
688
539
  * Sets up a direct connection to the target
@@ -690,7 +541,7 @@ export class RouteConnectionHandler {
690
541
  private setupDirectConnection(
691
542
  socket: plugins.net.Socket,
692
543
  record: IConnectionRecord,
693
- domainConfig?: IDomainConfig,
544
+ _unused?: any, // kept for backward compatibility
694
545
  serverName?: string,
695
546
  initialChunk?: Buffer,
696
547
  overridePort?: number,
@@ -698,22 +549,15 @@ export class RouteConnectionHandler {
698
549
  targetPort?: number
699
550
  ): void {
700
551
  const connectionId = record.id;
701
-
552
+
702
553
  // Determine target host and port if not provided
703
- const finalTargetHost = targetHost || (domainConfig
704
- ? this.domainConfigManager.getTargetIP(domainConfig)
705
- : this.settings.defaults?.target?.host
706
- ? this.settings.defaults.target.host
707
- : this.settings.targetIP!);
554
+ const finalTargetHost = targetHost ||
555
+ (this.settings.defaults?.target?.host || 'localhost');
708
556
 
709
- // Determine target port - first try explicit port, then forwarding config, then fallback
710
- const finalTargetPort = targetPort || (overridePort !== undefined
711
- ? overridePort
712
- : domainConfig
713
- ? this.domainConfigManager.getTargetPort(domainConfig, this.settings.toPort)
714
- : this.settings.defaults?.target?.port
715
- ? this.settings.defaults.target.port
716
- : this.settings.toPort);
557
+ // Determine target port
558
+ const finalTargetPort = targetPort ||
559
+ (overridePort !== undefined ? overridePort :
560
+ (this.settings.defaults?.target?.port || 443));
717
561
 
718
562
  // Setup connection options
719
563
  const connectionOptions: plugins.net.NetConnectOpts = {
@@ -897,20 +741,7 @@ export class RouteConnectionHandler {
897
741
  this.connectionManager.incrementTerminationStat('outgoing', 'connection_failed');
898
742
  }
899
743
 
900
- // If we have a forwarding handler for this domain, let it handle the error
901
- if (domainConfig) {
902
- try {
903
- const forwardingHandler = this.domainConfigManager.getForwardingHandler(domainConfig);
904
- forwardingHandler.emit('connection_error', {
905
- socket,
906
- error: err,
907
- connectionId
908
- });
909
- } catch (handlerErr) {
910
- // If getting the handler fails, just log and continue with normal cleanup
911
- console.log(`Error getting forwarding handler for error handling: ${handlerErr}`);
912
- }
913
- }
744
+ // Route-based configuration doesn't use domain handlers
914
745
 
915
746
  // Clean up the connection
916
747
  this.connectionManager.initiateCleanupOnce(record, `connection_failed_${code}`);
@@ -1043,8 +874,8 @@ export class RouteConnectionHandler {
1043
874
  `${
1044
875
  serverName
1045
876
  ? ` (SNI: ${serverName})`
1046
- : domainConfig
1047
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
877
+ : record.lockedDomain
878
+ ? ` (Domain: ${record.lockedDomain})`
1048
879
  : ''
1049
880
  }` +
1050
881
  ` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${
@@ -1057,8 +888,8 @@ export class RouteConnectionHandler {
1057
888
  `${
1058
889
  serverName
1059
890
  ? ` (SNI: ${serverName})`
1060
- : domainConfig
1061
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
891
+ : record.lockedDomain
892
+ ? ` (Domain: ${record.lockedDomain})`
1062
893
  : ''
1063
894
  }`
1064
895
  );
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Route helpers for SmartProxy
3
+ *
4
+ * This module provides helper functions for creating various types of route configurations
5
+ * to be used with the SmartProxy system.
6
+ */
7
+
8
+ // Re-export all functions from the route-helpers.ts file
9
+ export * from '../route-helpers.js';
@@ -1,12 +1,13 @@
1
- import type {
2
- IRouteConfig,
3
- IRouteMatch,
4
- IRouteAction,
1
+ import type {
2
+ IRouteConfig,
3
+ IRouteMatch,
4
+ IRouteAction,
5
5
  IRouteTarget,
6
6
  IRouteTls,
7
7
  IRouteRedirect,
8
8
  IRouteSecurity,
9
- IRouteAdvanced
9
+ IRouteAdvanced,
10
+ TPortRange
10
11
  } from './models/route-types.js';
11
12
 
12
13
  /**
@@ -30,7 +31,7 @@ export function createRoute(
30
31
  }
31
32
 
32
33
  /**
33
- * Create a basic HTTP route configuration
34
+ * Create a basic HTTP route configuration
34
35
  */
35
36
  export function createHttpRoute(
36
37
  options: {
@@ -206,7 +207,7 @@ export function createHttpToHttpsRedirect(
206
207
  }
207
208
  ): IRouteConfig {
208
209
  const domainArray = Array.isArray(options.domains) ? options.domains : [options.domains];
209
-
210
+
210
211
  return createRedirectRoute({
211
212
  ports: 80,
212
213
  domains: options.domains,
@@ -270,7 +271,7 @@ export function createLoadBalancerRoute(
270
271
  ): IRouteConfig {
271
272
  const useTls = options.tlsMode !== undefined;
272
273
  const defaultPort = useTls ? 443 : 80;
273
-
274
+
274
275
  return createRoute(
275
276
  {
276
277
  ports: options.ports || defaultPort,
@@ -321,7 +322,7 @@ export function createHttpsServer(
321
322
  ): IRouteConfig[] {
322
323
  const routes: IRouteConfig[] = [];
323
324
  const domainArray = Array.isArray(options.domains) ? options.domains : [options.domains];
324
-
325
+
325
326
  // Add HTTPS route
326
327
  routes.push(createHttpsRoute({
327
328
  domains: options.domains,
@@ -330,7 +331,7 @@ export function createHttpsServer(
330
331
  security: options.security,
331
332
  name: options.name || `HTTPS Server for ${domainArray.join(', ')}`
332
333
  }));
333
-
334
+
334
335
  // Add HTTP to HTTPS redirect if requested
335
336
  if (options.addHttpRedirect !== false) {
336
337
  routes.push(createHttpToHttpsRedirect({
@@ -339,6 +340,159 @@ export function createHttpsServer(
339
340
  priority: 100
340
341
  }));
341
342
  }
342
-
343
+
343
344
  return routes;
345
+ }
346
+
347
+ /**
348
+ * Create a port range configuration from various input formats
349
+ */
350
+ export function createPortRange(
351
+ ports: number | number[] | string | Array<{ from: number; to: number }>
352
+ ): TPortRange {
353
+ // If it's a string like "80,443" or "8000-9000", parse it
354
+ if (typeof ports === 'string') {
355
+ if (ports.includes('-')) {
356
+ // Handle range like "8000-9000"
357
+ const [start, end] = ports.split('-').map(p => parseInt(p.trim(), 10));
358
+ return [{ from: start, to: end }];
359
+ } else if (ports.includes(',')) {
360
+ // Handle comma-separated list like "80,443,8080"
361
+ return ports.split(',').map(p => parseInt(p.trim(), 10));
362
+ } else {
363
+ // Handle single port as string
364
+ return parseInt(ports.trim(), 10);
365
+ }
366
+ }
367
+
368
+ // Otherwise return as is
369
+ return ports;
370
+ }
371
+
372
+ /**
373
+ * Create a security configuration object
374
+ */
375
+ export function createSecurityConfig(
376
+ options: {
377
+ allowedIps?: string[];
378
+ blockedIps?: string[];
379
+ maxConnections?: number;
380
+ authentication?: {
381
+ type: 'basic' | 'digest' | 'oauth';
382
+ // Auth-specific options
383
+ [key: string]: any;
384
+ };
385
+ }
386
+ ): IRouteSecurity {
387
+ return {
388
+ ...(options.allowedIps ? { allowedIps: options.allowedIps } : {}),
389
+ ...(options.blockedIps ? { blockedIps: options.blockedIps } : {}),
390
+ ...(options.maxConnections ? { maxConnections: options.maxConnections } : {}),
391
+ ...(options.authentication ? { authentication: options.authentication } : {})
392
+ };
393
+ }
394
+
395
+ /**
396
+ * Create a static file server route
397
+ */
398
+ export function createStaticFileRoute(
399
+ options: {
400
+ ports?: number | number[]; // Default: 80
401
+ domains: string | string[];
402
+ path?: string;
403
+ targetDirectory: string;
404
+ tlsMode?: 'terminate' | 'terminate-and-reencrypt';
405
+ certificate?: 'auto' | { key: string; cert: string };
406
+ headers?: Record<string, string>;
407
+ security?: IRouteSecurity;
408
+ name?: string;
409
+ description?: string;
410
+ priority?: number;
411
+ tags?: string[];
412
+ }
413
+ ): IRouteConfig {
414
+ const useTls = options.tlsMode !== undefined;
415
+ const defaultPort = useTls ? 443 : 80;
416
+
417
+ return createRoute(
418
+ {
419
+ ports: options.ports || defaultPort,
420
+ domains: options.domains,
421
+ ...(options.path ? { path: options.path } : {})
422
+ },
423
+ {
424
+ type: 'forward',
425
+ target: {
426
+ host: 'localhost', // Static file serving is typically handled locally
427
+ port: 0, // Special value indicating a static file server
428
+ preservePort: false
429
+ },
430
+ ...(useTls ? {
431
+ tls: {
432
+ mode: options.tlsMode!,
433
+ certificate: options.certificate || 'auto'
434
+ }
435
+ } : {}),
436
+ advanced: {
437
+ ...(options.headers ? { headers: options.headers } : {}),
438
+ staticFiles: {
439
+ root: options.targetDirectory,
440
+ index: ['index.html', 'index.htm'],
441
+ directory: options.targetDirectory // For backward compatibility
442
+ }
443
+ },
444
+ ...(options.security ? { security: options.security } : {})
445
+ },
446
+ {
447
+ name: options.name || 'Static File Server',
448
+ description: options.description || `Serving static files from ${options.targetDirectory}`,
449
+ priority: options.priority,
450
+ tags: options.tags
451
+ }
452
+ );
453
+ }
454
+
455
+ /**
456
+ * Create a test route for debugging purposes
457
+ */
458
+ export function createTestRoute(
459
+ options: {
460
+ ports?: number | number[]; // Default: 8000
461
+ domains?: string | string[];
462
+ path?: string;
463
+ response?: {
464
+ status?: number;
465
+ headers?: Record<string, string>;
466
+ body?: string;
467
+ };
468
+ name?: string;
469
+ }
470
+ ): IRouteConfig {
471
+ return createRoute(
472
+ {
473
+ ports: options.ports || 8000,
474
+ ...(options.domains ? { domains: options.domains } : {}),
475
+ ...(options.path ? { path: options.path } : {})
476
+ },
477
+ {
478
+ type: 'forward',
479
+ target: {
480
+ host: 'test', // Special value indicating a test route
481
+ port: 0
482
+ },
483
+ advanced: {
484
+ testResponse: {
485
+ status: options.response?.status || 200,
486
+ headers: options.response?.headers || { 'Content-Type': 'text/plain' },
487
+ body: options.response?.body || 'Test route is working!'
488
+ }
489
+ }
490
+ },
491
+ {
492
+ name: options.name || 'Test Route',
493
+ description: 'Route for testing and debugging',
494
+ priority: 500,
495
+ tags: ['test', 'debug']
496
+ }
497
+ );
344
498
  }