@push.rocks/smartproxy 19.5.18 → 19.5.20

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 (110) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/core/models/index.d.ts +2 -0
  3. package/dist_ts/core/models/index.js +3 -1
  4. package/dist_ts/core/models/socket-types.d.ts +14 -0
  5. package/dist_ts/core/models/socket-types.js +15 -0
  6. package/dist_ts/core/models/wrapped-socket.d.ts +34 -0
  7. package/dist_ts/core/models/wrapped-socket.js +82 -0
  8. package/dist_ts/core/routing/index.d.ts +11 -0
  9. package/dist_ts/core/routing/index.js +17 -0
  10. package/dist_ts/core/routing/matchers/domain.d.ts +34 -0
  11. package/dist_ts/core/routing/matchers/domain.js +91 -0
  12. package/dist_ts/core/routing/matchers/header.d.ts +32 -0
  13. package/dist_ts/core/routing/matchers/header.js +94 -0
  14. package/dist_ts/core/routing/matchers/index.d.ts +18 -0
  15. package/dist_ts/core/routing/matchers/index.js +20 -0
  16. package/dist_ts/core/routing/matchers/ip.d.ts +53 -0
  17. package/dist_ts/core/routing/matchers/ip.js +169 -0
  18. package/dist_ts/core/routing/matchers/path.d.ts +44 -0
  19. package/dist_ts/core/routing/matchers/path.js +148 -0
  20. package/dist_ts/core/routing/route-manager.d.ts +88 -0
  21. package/dist_ts/core/routing/route-manager.js +342 -0
  22. package/dist_ts/core/routing/route-utils.d.ts +28 -0
  23. package/dist_ts/core/routing/route-utils.js +67 -0
  24. package/dist_ts/core/routing/specificity.d.ts +30 -0
  25. package/dist_ts/core/routing/specificity.js +115 -0
  26. package/dist_ts/core/routing/types.d.ts +41 -0
  27. package/dist_ts/core/routing/types.js +5 -0
  28. package/dist_ts/core/utils/index.d.ts +0 -2
  29. package/dist_ts/core/utils/index.js +1 -3
  30. package/dist_ts/core/utils/route-manager.d.ts +0 -30
  31. package/dist_ts/core/utils/route-manager.js +6 -47
  32. package/dist_ts/core/utils/route-utils.d.ts +2 -68
  33. package/dist_ts/core/utils/route-utils.js +21 -218
  34. package/dist_ts/core/utils/security-utils.js +4 -4
  35. package/dist_ts/core/utils/socket-utils.d.ts +0 -15
  36. package/dist_ts/core/utils/socket-utils.js +1 -35
  37. package/dist_ts/forwarding/handlers/https-terminate-to-http-handler.js +47 -32
  38. package/dist_ts/forwarding/handlers/https-terminate-to-https-handler.js +51 -32
  39. package/dist_ts/index.d.ts +2 -5
  40. package/dist_ts/index.js +5 -11
  41. package/dist_ts/proxies/http-proxy/http-proxy.d.ts +0 -1
  42. package/dist_ts/proxies/http-proxy/http-proxy.js +15 -60
  43. package/dist_ts/proxies/http-proxy/models/types.d.ts +0 -90
  44. package/dist_ts/proxies/http-proxy/models/types.js +1 -242
  45. package/dist_ts/proxies/http-proxy/request-handler.d.ts +3 -5
  46. package/dist_ts/proxies/http-proxy/request-handler.js +20 -171
  47. package/dist_ts/proxies/http-proxy/websocket-handler.d.ts +2 -5
  48. package/dist_ts/proxies/http-proxy/websocket-handler.js +15 -23
  49. package/dist_ts/proxies/index.d.ts +2 -2
  50. package/dist_ts/proxies/index.js +4 -3
  51. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +3 -1
  52. package/dist_ts/proxies/smart-proxy/connection-manager.js +15 -7
  53. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +2 -1
  54. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +5 -2
  55. package/dist_ts/proxies/smart-proxy/index.d.ts +1 -1
  56. package/dist_ts/proxies/smart-proxy/index.js +2 -2
  57. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +6 -2
  58. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +1 -1
  59. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +48 -25
  60. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +1 -1
  61. package/dist_ts/proxies/smart-proxy/smart-proxy.js +15 -4
  62. package/dist_ts/proxies/smart-proxy/utils/route-utils.js +10 -43
  63. package/dist_ts/routing/router/http-router.d.ts +89 -0
  64. package/dist_ts/routing/router/http-router.js +205 -0
  65. package/dist_ts/routing/router/index.d.ts +2 -5
  66. package/dist_ts/routing/router/index.js +3 -4
  67. package/package.json +1 -1
  68. package/readme.delete.md +187 -0
  69. package/readme.hints.md +210 -1
  70. package/readme.plan.md +621 -0
  71. package/readme.routing.md +341 -0
  72. package/ts/00_commitinfo_data.ts +1 -1
  73. package/ts/core/models/index.ts +2 -0
  74. package/ts/core/models/socket-types.ts +21 -0
  75. package/ts/core/models/wrapped-socket.ts +99 -0
  76. package/ts/core/routing/index.ts +21 -0
  77. package/ts/core/routing/matchers/domain.ts +119 -0
  78. package/ts/core/routing/matchers/header.ts +120 -0
  79. package/ts/core/routing/matchers/index.ts +22 -0
  80. package/ts/core/routing/matchers/ip.ts +207 -0
  81. package/ts/core/routing/matchers/path.ts +184 -0
  82. package/ts/core/{utils → routing}/route-manager.ts +7 -57
  83. package/ts/core/routing/route-utils.ts +88 -0
  84. package/ts/core/routing/specificity.ts +141 -0
  85. package/ts/core/routing/types.ts +49 -0
  86. package/ts/core/utils/index.ts +0 -2
  87. package/ts/core/utils/security-utils.ts +3 -7
  88. package/ts/core/utils/socket-utils.ts +0 -44
  89. package/ts/forwarding/handlers/https-terminate-to-http-handler.ts +47 -33
  90. package/ts/forwarding/handlers/https-terminate-to-https-handler.ts +55 -35
  91. package/ts/index.ts +4 -14
  92. package/ts/proxies/http-proxy/http-proxy.ts +13 -68
  93. package/ts/proxies/http-proxy/models/types.ts +0 -324
  94. package/ts/proxies/http-proxy/request-handler.ts +15 -186
  95. package/ts/proxies/http-proxy/websocket-handler.ts +15 -26
  96. package/ts/proxies/index.ts +3 -2
  97. package/ts/proxies/smart-proxy/connection-manager.ts +15 -7
  98. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +6 -2
  99. package/ts/proxies/smart-proxy/index.ts +1 -1
  100. package/ts/proxies/smart-proxy/models/interfaces.ts +8 -2
  101. package/ts/proxies/smart-proxy/route-connection-handler.ts +58 -30
  102. package/ts/proxies/smart-proxy/smart-proxy.ts +15 -3
  103. package/ts/proxies/smart-proxy/utils/route-utils.ts +11 -49
  104. package/ts/routing/router/http-router.ts +266 -0
  105. package/ts/routing/router/index.ts +3 -8
  106. package/readme.problems.md +0 -170
  107. package/ts/core/utils/route-utils.ts +0 -312
  108. package/ts/proxies/smart-proxy/route-manager.ts +0 -554
  109. package/ts/routing/router/proxy-router.ts +0 -437
  110. package/ts/routing/router/route-router.ts +0 -482
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '19.5.3',
6
+ version: '19.5.19',
7
7
  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.'
8
8
  };
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHFQQUFxUDtDQUNuUSxDQUFBIn0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLHFQQUFxUDtDQUNuUSxDQUFBIn0=
@@ -4,3 +4,5 @@
4
4
  export * from './common-types.js';
5
5
  export * from './socket-augmentation.js';
6
6
  export * from './route-context.js';
7
+ export * from './wrapped-socket.js';
8
+ export * from './socket-types.js';
@@ -4,4 +4,6 @@
4
4
  export * from './common-types.js';
5
5
  export * from './socket-augmentation.js';
6
6
  export * from './route-context.js';
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL21vZGVscy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLG9CQUFvQixDQUFDIn0=
7
+ export * from './wrapped-socket.js';
8
+ export * from './socket-types.js';
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL21vZGVscy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxtQkFBbUIsQ0FBQyJ9
@@ -0,0 +1,14 @@
1
+ import * as net from 'net';
2
+ import { WrappedSocket } from './wrapped-socket.js';
3
+ /**
4
+ * Type guard to check if a socket is a WrappedSocket
5
+ */
6
+ export declare function isWrappedSocket(socket: net.Socket | WrappedSocket): socket is WrappedSocket;
7
+ /**
8
+ * Helper to get the underlying socket from either a Socket or WrappedSocket
9
+ */
10
+ export declare function getUnderlyingSocket(socket: net.Socket | WrappedSocket): net.Socket;
11
+ /**
12
+ * Type that represents either a regular socket or a wrapped socket
13
+ */
14
+ export type AnySocket = net.Socket | WrappedSocket;
@@ -0,0 +1,15 @@
1
+ import * as net from 'net';
2
+ import { WrappedSocket } from './wrapped-socket.js';
3
+ /**
4
+ * Type guard to check if a socket is a WrappedSocket
5
+ */
6
+ export function isWrappedSocket(socket) {
7
+ return socket instanceof WrappedSocket || 'socket' in socket;
8
+ }
9
+ /**
10
+ * Helper to get the underlying socket from either a Socket or WrappedSocket
11
+ */
12
+ export function getUnderlyingSocket(socket) {
13
+ return isWrappedSocket(socket) ? socket.socket : socket;
14
+ }
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0LXR5cGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvY29yZS9tb2RlbHMvc29ja2V0LXR5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxHQUFHLE1BQU0sS0FBSyxDQUFDO0FBQzNCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVwRDs7R0FFRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsTUFBa0M7SUFDaEUsT0FBTyxNQUFNLFlBQVksYUFBYSxJQUFJLFFBQVEsSUFBSSxNQUFNLENBQUM7QUFDL0QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE1BQWtDO0lBQ3BFLE9BQU8sZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7QUFDMUQsQ0FBQyJ9
@@ -0,0 +1,34 @@
1
+ import * as plugins from '../../plugins.js';
2
+ /**
3
+ * WrappedSocket wraps a regular net.Socket to provide transparent access
4
+ * to the real client IP and port when behind a proxy using PROXY protocol.
5
+ *
6
+ * This is the FOUNDATION for all PROXY protocol support and must be implemented
7
+ * before any protocol parsing can occur.
8
+ *
9
+ * This implementation uses a Proxy to delegate all properties and methods
10
+ * to the underlying socket while allowing override of specific properties.
11
+ */
12
+ export declare class WrappedSocket {
13
+ readonly socket: plugins.net.Socket;
14
+ private realClientIP?;
15
+ private realClientPort?;
16
+ [key: string]: any;
17
+ constructor(socket: plugins.net.Socket, realClientIP?: string, realClientPort?: number);
18
+ /**
19
+ * Returns the real client IP if available, otherwise the socket's remote address
20
+ */
21
+ get remoteAddress(): string | undefined;
22
+ /**
23
+ * Returns the real client port if available, otherwise the socket's remote port
24
+ */
25
+ get remotePort(): number | undefined;
26
+ /**
27
+ * Indicates if this connection came through a trusted proxy
28
+ */
29
+ get isFromTrustedProxy(): boolean;
30
+ /**
31
+ * Updates the real client information (called after parsing PROXY protocol)
32
+ */
33
+ setProxyInfo(ip: string, port: number): void;
34
+ }
@@ -0,0 +1,82 @@
1
+ import * as plugins from '../../plugins.js';
2
+ /**
3
+ * WrappedSocket wraps a regular net.Socket to provide transparent access
4
+ * to the real client IP and port when behind a proxy using PROXY protocol.
5
+ *
6
+ * This is the FOUNDATION for all PROXY protocol support and must be implemented
7
+ * before any protocol parsing can occur.
8
+ *
9
+ * This implementation uses a Proxy to delegate all properties and methods
10
+ * to the underlying socket while allowing override of specific properties.
11
+ */
12
+ export class WrappedSocket {
13
+ constructor(socket, realClientIP, realClientPort) {
14
+ this.socket = socket;
15
+ this.realClientIP = realClientIP;
16
+ this.realClientPort = realClientPort;
17
+ // Create a proxy that delegates everything to the underlying socket
18
+ return new Proxy(this, {
19
+ get(target, prop, receiver) {
20
+ // Override specific properties
21
+ if (prop === 'remoteAddress') {
22
+ return target.remoteAddress;
23
+ }
24
+ if (prop === 'remotePort') {
25
+ return target.remotePort;
26
+ }
27
+ if (prop === 'socket') {
28
+ return target.socket;
29
+ }
30
+ if (prop === 'realClientIP') {
31
+ return target.realClientIP;
32
+ }
33
+ if (prop === 'realClientPort') {
34
+ return target.realClientPort;
35
+ }
36
+ if (prop === 'isFromTrustedProxy') {
37
+ return target.isFromTrustedProxy;
38
+ }
39
+ if (prop === 'setProxyInfo') {
40
+ return target.setProxyInfo.bind(target);
41
+ }
42
+ // For all other properties/methods, delegate to the underlying socket
43
+ const value = target.socket[prop];
44
+ if (typeof value === 'function') {
45
+ return value.bind(target.socket);
46
+ }
47
+ return value;
48
+ },
49
+ set(target, prop, value) {
50
+ // Set on the underlying socket
51
+ target.socket[prop] = value;
52
+ return true;
53
+ }
54
+ });
55
+ }
56
+ /**
57
+ * Returns the real client IP if available, otherwise the socket's remote address
58
+ */
59
+ get remoteAddress() {
60
+ return this.realClientIP || this.socket.remoteAddress;
61
+ }
62
+ /**
63
+ * Returns the real client port if available, otherwise the socket's remote port
64
+ */
65
+ get remotePort() {
66
+ return this.realClientPort || this.socket.remotePort;
67
+ }
68
+ /**
69
+ * Indicates if this connection came through a trusted proxy
70
+ */
71
+ get isFromTrustedProxy() {
72
+ return !!this.realClientIP;
73
+ }
74
+ /**
75
+ * Updates the real client information (called after parsing PROXY protocol)
76
+ */
77
+ setProxyInfo(ip, port) {
78
+ this.realClientIP = ip;
79
+ this.realClientPort = port;
80
+ }
81
+ }
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JhcHBlZC1zb2NrZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL21vZGVscy93cmFwcGVkLXNvY2tldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBUXhCLFlBQ0UsTUFBMEIsRUFDMUIsWUFBcUIsRUFDckIsY0FBdUI7UUFFdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFFckMsb0VBQW9FO1FBQ3BFLE9BQU8sSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFO1lBQ3JCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLFFBQVE7Z0JBQ3hCLCtCQUErQjtnQkFDL0IsSUFBSSxJQUFJLEtBQUssZUFBZSxFQUFFLENBQUM7b0JBQzdCLE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQztnQkFDOUIsQ0FBQztnQkFDRCxJQUFJLElBQUksS0FBSyxZQUFZLEVBQUUsQ0FBQztvQkFDMUIsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUFDO2dCQUMzQixDQUFDO2dCQUNELElBQUksSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUN0QixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQ3ZCLENBQUM7Z0JBQ0QsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7b0JBQzVCLE9BQU8sTUFBTSxDQUFDLFlBQVksQ0FBQztnQkFDN0IsQ0FBQztnQkFDRCxJQUFJLElBQUksS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO29CQUM5QixPQUFPLE1BQU0sQ0FBQyxjQUFjLENBQUM7Z0JBQy9CLENBQUM7Z0JBQ0QsSUFBSSxJQUFJLEtBQUssb0JBQW9CLEVBQUUsQ0FBQztvQkFDbEMsT0FBTyxNQUFNLENBQUMsa0JBQWtCLENBQUM7Z0JBQ25DLENBQUM7Z0JBQ0QsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7b0JBQzVCLE9BQU8sTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzFDLENBQUM7Z0JBRUQsc0VBQXNFO2dCQUN0RSxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQWdDLENBQUMsQ0FBQztnQkFDOUQsSUFBSSxPQUFPLEtBQUssS0FBSyxVQUFVLEVBQUUsQ0FBQztvQkFDaEMsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDbkMsQ0FBQztnQkFDRCxPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7WUFDRCxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLO2dCQUNyQiwrQkFBK0I7Z0JBQzlCLE1BQU0sQ0FBQyxNQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO2dCQUNyQyxPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7U0FDRixDQUFRLENBQUM7SUFDWixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLGFBQWE7UUFDZixPQUFPLElBQUksQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUM7SUFDeEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxVQUFVO1FBQ1osT0FBTyxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO0lBQ3ZELENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksa0JBQWtCO1FBQ3BCLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsWUFBWSxDQUFDLEVBQVUsRUFBRSxJQUFZO1FBQ25DLElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO0lBQzdCLENBQUM7Q0FDRiJ9
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Unified routing module
3
+ * Provides all routing functionality in a centralized location
4
+ */
5
+ export * from './types.js';
6
+ export * from './matchers/index.js';
7
+ export * from './specificity.js';
8
+ export * from './route-manager.js';
9
+ export * from './route-utils.js';
10
+ export { matchers } from './matchers/index.js';
11
+ export { RouteSpecificity } from './specificity.js';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Unified routing module
3
+ * Provides all routing functionality in a centralized location
4
+ */
5
+ // Export all types
6
+ export * from './types.js';
7
+ // Export all matchers
8
+ export * from './matchers/index.js';
9
+ // Export specificity calculator
10
+ export * from './specificity.js';
11
+ // Export route management
12
+ export * from './route-manager.js';
13
+ export * from './route-utils.js';
14
+ // Convenience re-exports
15
+ export { matchers } from './matchers/index.js';
16
+ export { RouteSpecificity } from './specificity.js';
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3JvdXRpbmcvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsbUJBQW1CO0FBQ25CLGNBQWMsWUFBWSxDQUFDO0FBRTNCLHNCQUFzQjtBQUN0QixjQUFjLHFCQUFxQixDQUFDO0FBRXBDLGdDQUFnQztBQUNoQyxjQUFjLGtCQUFrQixDQUFDO0FBRWpDLDBCQUEwQjtBQUMxQixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsa0JBQWtCLENBQUM7QUFFakMseUJBQXlCO0FBQ3pCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQyJ9
@@ -0,0 +1,34 @@
1
+ import type { IMatcher, IDomainMatchOptions } from '../types.js';
2
+ /**
3
+ * DomainMatcher provides comprehensive domain matching functionality
4
+ * Supporting exact matches, wildcards, and case-insensitive matching
5
+ */
6
+ export declare class DomainMatcher implements IMatcher<boolean, IDomainMatchOptions> {
7
+ private static wildcardToRegex;
8
+ /**
9
+ * Match a domain pattern against a hostname
10
+ * @param pattern The pattern to match (supports wildcards like *.example.com)
11
+ * @param hostname The hostname to test
12
+ * @param options Matching options
13
+ * @returns true if the hostname matches the pattern
14
+ */
15
+ static match(pattern: string, hostname: string, options?: IDomainMatchOptions): boolean;
16
+ /**
17
+ * Check if a pattern contains wildcards
18
+ */
19
+ static isWildcardPattern(pattern: string): boolean;
20
+ /**
21
+ * Calculate the specificity of a domain pattern
22
+ * Higher values mean more specific patterns
23
+ */
24
+ static calculateSpecificity(pattern: string): number;
25
+ /**
26
+ * Find all matching patterns from a list
27
+ * Returns patterns sorted by specificity (most specific first)
28
+ */
29
+ static findAllMatches(patterns: string[], hostname: string, options?: IDomainMatchOptions): string[];
30
+ /**
31
+ * Instance method for interface compliance
32
+ */
33
+ match(pattern: string, hostname: string, options?: IDomainMatchOptions): boolean;
34
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * DomainMatcher provides comprehensive domain matching functionality
3
+ * Supporting exact matches, wildcards, and case-insensitive matching
4
+ */
5
+ export class DomainMatcher {
6
+ static wildcardToRegex(pattern) {
7
+ // Escape special regex characters except *
8
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
9
+ // Replace * with regex equivalent
10
+ const regexPattern = escaped.replace(/\*/g, '.*');
11
+ return new RegExp(`^${regexPattern}$`, 'i');
12
+ }
13
+ /**
14
+ * Match a domain pattern against a hostname
15
+ * @param pattern The pattern to match (supports wildcards like *.example.com)
16
+ * @param hostname The hostname to test
17
+ * @param options Matching options
18
+ * @returns true if the hostname matches the pattern
19
+ */
20
+ static match(pattern, hostname, options = {}) {
21
+ // Handle null/undefined cases
22
+ if (!pattern || !hostname) {
23
+ return false;
24
+ }
25
+ // Normalize inputs
26
+ const normalizedPattern = pattern.toLowerCase().trim();
27
+ const normalizedHostname = hostname.toLowerCase().trim();
28
+ // Remove trailing dots (FQDN normalization)
29
+ const cleanPattern = normalizedPattern.replace(/\.$/, '');
30
+ const cleanHostname = normalizedHostname.replace(/\.$/, '');
31
+ // Exact match (most common case)
32
+ if (cleanPattern === cleanHostname) {
33
+ return true;
34
+ }
35
+ // Wildcard matching
36
+ if (options.allowWildcards !== false && cleanPattern.includes('*')) {
37
+ const regex = this.wildcardToRegex(cleanPattern);
38
+ return regex.test(cleanHostname);
39
+ }
40
+ // No match
41
+ return false;
42
+ }
43
+ /**
44
+ * Check if a pattern contains wildcards
45
+ */
46
+ static isWildcardPattern(pattern) {
47
+ return pattern.includes('*');
48
+ }
49
+ /**
50
+ * Calculate the specificity of a domain pattern
51
+ * Higher values mean more specific patterns
52
+ */
53
+ static calculateSpecificity(pattern) {
54
+ if (!pattern)
55
+ return 0;
56
+ let score = 0;
57
+ // Exact domains are most specific
58
+ if (!pattern.includes('*')) {
59
+ score += 100;
60
+ }
61
+ // Count domain segments
62
+ const segments = pattern.split('.');
63
+ score += segments.length * 10;
64
+ // Penalize wildcards based on position
65
+ if (pattern.startsWith('*')) {
66
+ score -= 50; // Leading wildcard is very generic
67
+ }
68
+ else if (pattern.includes('*')) {
69
+ score -= 20; // Wildcard elsewhere is less generic
70
+ }
71
+ // Bonus for longer patterns
72
+ score += pattern.length;
73
+ return score;
74
+ }
75
+ /**
76
+ * Find all matching patterns from a list
77
+ * Returns patterns sorted by specificity (most specific first)
78
+ */
79
+ static findAllMatches(patterns, hostname, options = {}) {
80
+ const matches = patterns.filter(pattern => this.match(pattern, hostname, options));
81
+ // Sort by specificity (highest first)
82
+ return matches.sort((a, b) => this.calculateSpecificity(b) - this.calculateSpecificity(a));
83
+ }
84
+ /**
85
+ * Instance method for interface compliance
86
+ */
87
+ match(pattern, hostname, options) {
88
+ return DomainMatcher.match(pattern, hostname, options);
89
+ }
90
+ }
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tYWluLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvY29yZS9yb3V0aW5nL21hdGNoZXJzL2RvbWFpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUNoQixNQUFNLENBQUMsZUFBZSxDQUFDLE9BQWU7UUFDNUMsMkNBQTJDO1FBQzNDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDOUQsa0NBQWtDO1FBQ2xDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2xELE9BQU8sSUFBSSxNQUFNLENBQUMsSUFBSSxZQUFZLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FDVixPQUFlLEVBQ2YsUUFBZ0IsRUFDaEIsVUFBK0IsRUFBRTtRQUVqQyw4QkFBOEI7UUFDOUIsSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzFCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELG1CQUFtQjtRQUNuQixNQUFNLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN2RCxNQUFNLGtCQUFrQixHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV6RCw0Q0FBNEM7UUFDNUMsTUFBTSxZQUFZLEdBQUcsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMxRCxNQUFNLGFBQWEsR0FBRyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRTVELGlDQUFpQztRQUNqQyxJQUFJ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
@@ -0,0 +1,32 @@
1
+ import type { IMatcher, IHeaderMatchOptions } from '../types.js';
2
+ /**
3
+ * HeaderMatcher provides HTTP header matching functionality
4
+ * Supporting exact matches, patterns, and case-insensitive matching
5
+ */
6
+ export declare class HeaderMatcher implements IMatcher<boolean, IHeaderMatchOptions> {
7
+ /**
8
+ * Match a header value against a pattern
9
+ * @param pattern The pattern to match
10
+ * @param value The header value to test
11
+ * @param options Matching options
12
+ * @returns true if the value matches the pattern
13
+ */
14
+ static match(pattern: string, value: string | undefined, options?: IHeaderMatchOptions): boolean;
15
+ /**
16
+ * Match multiple headers against a set of required headers
17
+ * @param requiredHeaders Headers that must match
18
+ * @param actualHeaders Actual request headers
19
+ * @param options Matching options
20
+ * @returns true if all required headers match
21
+ */
22
+ static matchAll(requiredHeaders: Record<string, string>, actualHeaders: Record<string, string | string[] | undefined>, options?: IHeaderMatchOptions): boolean;
23
+ /**
24
+ * Calculate the specificity of header requirements
25
+ * More headers = more specific
26
+ */
27
+ static calculateSpecificity(headers: Record<string, string>): number;
28
+ /**
29
+ * Instance method for interface compliance
30
+ */
31
+ match(pattern: string, value: string, options?: IHeaderMatchOptions): boolean;
32
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * HeaderMatcher provides HTTP header matching functionality
3
+ * Supporting exact matches, patterns, and case-insensitive matching
4
+ */
5
+ export class HeaderMatcher {
6
+ /**
7
+ * Match a header value against a pattern
8
+ * @param pattern The pattern to match
9
+ * @param value The header value to test
10
+ * @param options Matching options
11
+ * @returns true if the value matches the pattern
12
+ */
13
+ static match(pattern, value, options = {}) {
14
+ // Handle missing header
15
+ if (value === undefined || value === null) {
16
+ return pattern === '' || pattern === null || pattern === undefined;
17
+ }
18
+ // Convert to string and normalize
19
+ const normalizedPattern = String(pattern);
20
+ const normalizedValue = String(value);
21
+ // Apply case sensitivity
22
+ const comparePattern = options.caseInsensitive !== false
23
+ ? normalizedPattern.toLowerCase()
24
+ : normalizedPattern;
25
+ const compareValue = options.caseInsensitive !== false
26
+ ? normalizedValue.toLowerCase()
27
+ : normalizedValue;
28
+ // Exact match
29
+ if (options.exactMatch !== false) {
30
+ return comparePattern === compareValue;
31
+ }
32
+ // Pattern matching (simple wildcard support)
33
+ if (comparePattern.includes('*')) {
34
+ const regex = new RegExp('^' + comparePattern.replace(/\*/g, '.*') + '$', options.caseInsensitive !== false ? 'i' : '');
35
+ return regex.test(normalizedValue);
36
+ }
37
+ // Contains match (if not exact match mode)
38
+ return compareValue.includes(comparePattern);
39
+ }
40
+ /**
41
+ * Match multiple headers against a set of required headers
42
+ * @param requiredHeaders Headers that must match
43
+ * @param actualHeaders Actual request headers
44
+ * @param options Matching options
45
+ * @returns true if all required headers match
46
+ */
47
+ static matchAll(requiredHeaders, actualHeaders, options = {}) {
48
+ for (const [name, pattern] of Object.entries(requiredHeaders)) {
49
+ const headerName = options.caseInsensitive !== false
50
+ ? name.toLowerCase()
51
+ : name;
52
+ // Find the actual header (case-insensitive search if needed)
53
+ let actualValue;
54
+ if (options.caseInsensitive !== false) {
55
+ const actualKey = Object.keys(actualHeaders).find(key => key.toLowerCase() === headerName);
56
+ const rawValue = actualKey ? actualHeaders[actualKey] : undefined;
57
+ // Handle array values (multiple headers with same name)
58
+ actualValue = Array.isArray(rawValue) ? rawValue.join(', ') : rawValue;
59
+ }
60
+ else {
61
+ const rawValue = actualHeaders[name];
62
+ // Handle array values (multiple headers with same name)
63
+ actualValue = Array.isArray(rawValue) ? rawValue.join(', ') : rawValue;
64
+ }
65
+ // Check if this header matches
66
+ if (!this.match(pattern, actualValue, options)) {
67
+ return false;
68
+ }
69
+ }
70
+ return true;
71
+ }
72
+ /**
73
+ * Calculate the specificity of header requirements
74
+ * More headers = more specific
75
+ */
76
+ static calculateSpecificity(headers) {
77
+ const count = Object.keys(headers).length;
78
+ let score = count * 10;
79
+ // Bonus for headers without wildcards (more specific)
80
+ for (const value of Object.values(headers)) {
81
+ if (!value.includes('*')) {
82
+ score += 5;
83
+ }
84
+ }
85
+ return score;
86
+ }
87
+ /**
88
+ * Instance method for interface compliance
89
+ */
90
+ match(pattern, value, options) {
91
+ return HeaderMatcher.match(pattern, value, options);
92
+ }
93
+ }
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvY29yZS9yb3V0aW5nL21hdGNoZXJzL2hlYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUN4Qjs7Ozs7O09BTUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUNWLE9BQWUsRUFDZixLQUF5QixFQUN6QixVQUErQixFQUFFO1FBRWpDLHdCQUF3QjtRQUN4QixJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzFDLE9BQU8sT0FBTyxLQUFLLEVBQUUsSUFBSSxPQUFPLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxTQUFTLENBQUM7UUFDckUsQ0FBQztRQUVELGtDQUFrQztRQUNsQyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQyxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFdEMseUJBQXlCO1FBQ3pCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLEtBQUssS0FBSztZQUN0RCxDQUFDLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFO1lBQ2pDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQztRQUN0QixNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsZUFBZSxLQUFLLEtBQUs7WUFDcEQsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxXQUFXLEVBQUU7WUFDL0IsQ0FBQyxDQUFDLGVBQWUsQ0FBQztRQUVwQixjQUFjO1FBQ2QsSUFBSSxPQUFPLENBQUMsVUFBVSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQ2pDLE9BQU8sY0FBYyxLQUFLLFlBQVksQ0FBQztRQUN6QyxDQUFDO1FBRUQsNkNBQTZDO1FBQzdDLElBQUksY0FBYyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2pDLE1BQU0s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
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Unified matching utilities for the routing system
3
+ * All route matching logic should use these matchers for consistency
4
+ */
5
+ export * from './domain.js';
6
+ export * from './path.js';
7
+ export * from './ip.js';
8
+ export * from './header.js';
9
+ import { DomainMatcher } from './domain.js';
10
+ import { PathMatcher } from './path.js';
11
+ import { IpMatcher } from './ip.js';
12
+ import { HeaderMatcher } from './header.js';
13
+ export declare const matchers: {
14
+ readonly domain: typeof DomainMatcher;
15
+ readonly path: typeof PathMatcher;
16
+ readonly ip: typeof IpMatcher;
17
+ readonly header: typeof HeaderMatcher;
18
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Unified matching utilities for the routing system
3
+ * All route matching logic should use these matchers for consistency
4
+ */
5
+ export * from './domain.js';
6
+ export * from './path.js';
7
+ export * from './ip.js';
8
+ export * from './header.js';
9
+ // Re-export for convenience
10
+ import { DomainMatcher } from './domain.js';
11
+ import { PathMatcher } from './path.js';
12
+ import { IpMatcher } from './ip.js';
13
+ import { HeaderMatcher } from './header.js';
14
+ export const matchers = {
15
+ domain: DomainMatcher,
16
+ path: PathMatcher,
17
+ ip: IpMatcher,
18
+ header: HeaderMatcher
19
+ };
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9jb3JlL3JvdXRpbmcvbWF0Y2hlcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxTQUFTLENBQUM7QUFDeEIsY0FBYyxhQUFhLENBQUM7QUFFNUIsNEJBQTRCO0FBQzVCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN4QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFNUMsTUFBTSxDQUFDLE1BQU0sUUFBUSxHQUFHO0lBQ3RCLE1BQU0sRUFBRSxhQUFhO0lBQ3JCLElBQUksRUFBRSxXQUFXO0lBQ2pCLEVBQUUsRUFBRSxTQUFTO0lBQ2IsTUFBTSxFQUFFLGFBQWE7Q0FDYixDQUFDIn0=
@@ -0,0 +1,53 @@
1
+ import type { IMatcher, IIpMatchOptions } from '../types.js';
2
+ /**
3
+ * IpMatcher provides comprehensive IP address matching functionality
4
+ * Supporting exact matches, CIDR notation, ranges, and wildcards
5
+ */
6
+ export declare class IpMatcher implements IMatcher<boolean, IIpMatchOptions> {
7
+ /**
8
+ * Check if a value is a valid IPv4 address
9
+ */
10
+ static isValidIpv4(ip: string): boolean;
11
+ /**
12
+ * Check if a value is a valid IPv6 address (simplified check)
13
+ */
14
+ static isValidIpv6(ip: string): boolean;
15
+ /**
16
+ * Convert IP address to numeric value for comparison
17
+ */
18
+ private static ipToNumber;
19
+ /**
20
+ * Match an IP against a CIDR notation pattern
21
+ */
22
+ static matchCidr(cidr: string, ip: string): boolean;
23
+ /**
24
+ * Match an IP against a wildcard pattern
25
+ */
26
+ static matchWildcard(pattern: string, ip: string): boolean;
27
+ /**
28
+ * Match an IP against a range (e.g., "192.168.1.1-192.168.1.100")
29
+ */
30
+ static matchRange(range: string, ip: string): boolean;
31
+ /**
32
+ * Match an IP pattern against an IP address
33
+ * Supports multiple formats:
34
+ * - Exact match: "192.168.1.1"
35
+ * - CIDR: "192.168.1.0/24"
36
+ * - Wildcard: "192.168.1.*"
37
+ * - Range: "192.168.1.1-192.168.1.100"
38
+ */
39
+ static match(pattern: string, ip: string, options?: IIpMatchOptions): boolean;
40
+ /**
41
+ * Check if an IP is authorized based on allow and block lists
42
+ */
43
+ static isAuthorized(ip: string, allowList?: string[], blockList?: string[]): boolean;
44
+ /**
45
+ * Calculate the specificity of an IP pattern
46
+ * Higher values mean more specific patterns
47
+ */
48
+ static calculateSpecificity(pattern: string): number;
49
+ /**
50
+ * Instance method for interface compliance
51
+ */
52
+ match(pattern: string, ip: string, options?: IIpMatchOptions): boolean;
53
+ }