@push.rocks/smartproxy 25.17.10 → 26.1.0

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 (184) hide show
  1. package/changelog.md +15 -0
  2. package/dist_rust/rustproxy_linux_amd64 +0 -0
  3. package/dist_rust/rustproxy_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +2 -2
  5. package/dist_ts/core/index.d.ts +0 -1
  6. package/dist_ts/core/index.js +1 -2
  7. package/dist_ts/core/models/index.d.ts +0 -1
  8. package/dist_ts/core/models/index.js +1 -2
  9. package/dist_ts/core/utils/index.d.ts +0 -12
  10. package/dist_ts/core/utils/index.js +1 -13
  11. package/dist_ts/index.d.ts +0 -3
  12. package/dist_ts/index.js +2 -7
  13. package/dist_ts/protocols/http/index.d.ts +0 -1
  14. package/dist_ts/protocols/http/index.js +1 -2
  15. package/dist_ts/protocols/index.d.ts +0 -7
  16. package/dist_ts/protocols/index.js +1 -8
  17. package/dist_ts/proxies/smart-proxy/models/metrics-types.d.ts +20 -0
  18. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.d.ts +2 -1
  19. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +4 -1
  20. package/dist_ts/proxies/smart-proxy/socket-handler-server.js +6 -1
  21. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +0 -7
  22. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +50 -51
  23. package/dist_ts/routing/index.d.ts +0 -1
  24. package/dist_ts/routing/index.js +1 -3
  25. package/package.json +1 -1
  26. package/ts/00_commitinfo_data.ts +1 -1
  27. package/ts/core/index.ts +0 -1
  28. package/ts/core/models/index.ts +0 -1
  29. package/ts/core/utils/index.ts +0 -12
  30. package/ts/index.ts +1 -7
  31. package/ts/protocols/http/index.ts +1 -2
  32. package/ts/protocols/index.ts +0 -7
  33. package/ts/proxies/smart-proxy/models/metrics-types.ts +21 -0
  34. package/ts/proxies/smart-proxy/rust-metrics-adapter.ts +4 -1
  35. package/ts/proxies/smart-proxy/socket-handler-server.ts +6 -0
  36. package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +60 -59
  37. package/ts/routing/index.ts +0 -3
  38. package/dist_ts/core/events/index.d.ts +0 -4
  39. package/dist_ts/core/events/index.js +0 -5
  40. package/dist_ts/core/models/socket-augmentation.d.ts +0 -15
  41. package/dist_ts/core/models/socket-augmentation.js +0 -18
  42. package/dist_ts/core/utils/async-utils.d.ts +0 -81
  43. package/dist_ts/core/utils/async-utils.js +0 -216
  44. package/dist_ts/core/utils/binary-heap.d.ts +0 -73
  45. package/dist_ts/core/utils/binary-heap.js +0 -193
  46. package/dist_ts/core/utils/enhanced-connection-pool.d.ts +0 -110
  47. package/dist_ts/core/utils/enhanced-connection-pool.js +0 -325
  48. package/dist_ts/core/utils/fs-utils.d.ts +0 -144
  49. package/dist_ts/core/utils/fs-utils.js +0 -252
  50. package/dist_ts/core/utils/ip-utils.d.ts +0 -69
  51. package/dist_ts/core/utils/ip-utils.js +0 -270
  52. package/dist_ts/core/utils/lifecycle-component.d.ts +0 -59
  53. package/dist_ts/core/utils/lifecycle-component.js +0 -211
  54. package/dist_ts/core/utils/log-deduplicator.d.ts +0 -39
  55. package/dist_ts/core/utils/log-deduplicator.js +0 -305
  56. package/dist_ts/core/utils/security-utils.d.ts +0 -111
  57. package/dist_ts/core/utils/security-utils.js +0 -212
  58. package/dist_ts/core/utils/shared-security-manager.d.ts +0 -128
  59. package/dist_ts/core/utils/shared-security-manager.js +0 -362
  60. package/dist_ts/core/utils/socket-utils.d.ts +0 -63
  61. package/dist_ts/core/utils/socket-utils.js +0 -249
  62. package/dist_ts/core/utils/template-utils.d.ts +0 -37
  63. package/dist_ts/core/utils/template-utils.js +0 -104
  64. package/dist_ts/core/utils/validation-utils.d.ts +0 -61
  65. package/dist_ts/core/utils/validation-utils.js +0 -149
  66. package/dist_ts/core/utils/websocket-utils.d.ts +0 -22
  67. package/dist_ts/core/utils/websocket-utils.js +0 -30
  68. package/dist_ts/detection/detectors/http-detector.d.ts +0 -33
  69. package/dist_ts/detection/detectors/http-detector.js +0 -101
  70. package/dist_ts/detection/detectors/quick-detector.d.ts +0 -28
  71. package/dist_ts/detection/detectors/quick-detector.js +0 -131
  72. package/dist_ts/detection/detectors/routing-extractor.d.ts +0 -28
  73. package/dist_ts/detection/detectors/routing-extractor.js +0 -122
  74. package/dist_ts/detection/detectors/tls-detector.d.ts +0 -47
  75. package/dist_ts/detection/detectors/tls-detector.js +0 -183
  76. package/dist_ts/detection/index.d.ts +0 -17
  77. package/dist_ts/detection/index.js +0 -22
  78. package/dist_ts/detection/models/detection-types.d.ts +0 -87
  79. package/dist_ts/detection/models/detection-types.js +0 -5
  80. package/dist_ts/detection/models/interfaces.d.ts +0 -97
  81. package/dist_ts/detection/models/interfaces.js +0 -5
  82. package/dist_ts/detection/protocol-detector.d.ts +0 -79
  83. package/dist_ts/detection/protocol-detector.js +0 -253
  84. package/dist_ts/detection/utils/buffer-utils.d.ts +0 -61
  85. package/dist_ts/detection/utils/buffer-utils.js +0 -127
  86. package/dist_ts/detection/utils/fragment-manager.d.ts +0 -31
  87. package/dist_ts/detection/utils/fragment-manager.js +0 -53
  88. package/dist_ts/detection/utils/parser-utils.d.ts +0 -42
  89. package/dist_ts/detection/utils/parser-utils.js +0 -63
  90. package/dist_ts/protocols/common/fragment-handler.d.ts +0 -73
  91. package/dist_ts/protocols/common/fragment-handler.js +0 -121
  92. package/dist_ts/protocols/common/index.d.ts +0 -7
  93. package/dist_ts/protocols/common/index.js +0 -8
  94. package/dist_ts/protocols/common/types.d.ts +0 -68
  95. package/dist_ts/protocols/common/types.js +0 -7
  96. package/dist_ts/protocols/http/parser.d.ts +0 -58
  97. package/dist_ts/protocols/http/parser.js +0 -184
  98. package/dist_ts/protocols/proxy/index.d.ts +0 -5
  99. package/dist_ts/protocols/proxy/index.js +0 -6
  100. package/dist_ts/protocols/proxy/types.d.ts +0 -47
  101. package/dist_ts/protocols/proxy/types.js +0 -6
  102. package/dist_ts/protocols/tls/alerts/index.d.ts +0 -4
  103. package/dist_ts/protocols/tls/alerts/index.js +0 -5
  104. package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +0 -150
  105. package/dist_ts/protocols/tls/alerts/tls-alert.js +0 -226
  106. package/dist_ts/protocols/tls/index.d.ts +0 -12
  107. package/dist_ts/protocols/tls/index.js +0 -27
  108. package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +0 -100
  109. package/dist_ts/protocols/tls/sni/client-hello-parser.js +0 -463
  110. package/dist_ts/protocols/tls/sni/index.d.ts +0 -5
  111. package/dist_ts/protocols/tls/sni/index.js +0 -6
  112. package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +0 -58
  113. package/dist_ts/protocols/tls/sni/sni-extraction.js +0 -275
  114. package/dist_ts/protocols/tls/utils/index.d.ts +0 -4
  115. package/dist_ts/protocols/tls/utils/index.js +0 -5
  116. package/dist_ts/protocols/tls/utils/tls-utils.d.ts +0 -158
  117. package/dist_ts/protocols/tls/utils/tls-utils.js +0 -187
  118. package/dist_ts/protocols/websocket/constants.d.ts +0 -55
  119. package/dist_ts/protocols/websocket/constants.js +0 -58
  120. package/dist_ts/protocols/websocket/index.d.ts +0 -7
  121. package/dist_ts/protocols/websocket/index.js +0 -8
  122. package/dist_ts/protocols/websocket/types.d.ts +0 -47
  123. package/dist_ts/protocols/websocket/types.js +0 -5
  124. package/dist_ts/protocols/websocket/utils.d.ts +0 -25
  125. package/dist_ts/protocols/websocket/utils.js +0 -103
  126. package/dist_ts/routing/router/http-router.d.ts +0 -89
  127. package/dist_ts/routing/router/http-router.js +0 -205
  128. package/dist_ts/routing/router/index.d.ts +0 -5
  129. package/dist_ts/routing/router/index.js +0 -6
  130. package/dist_ts/tls/index.d.ts +0 -16
  131. package/dist_ts/tls/index.js +0 -24
  132. package/dist_ts/tls/sni/index.d.ts +0 -4
  133. package/dist_ts/tls/sni/index.js +0 -5
  134. package/dist_ts/tls/sni/sni-handler.d.ts +0 -154
  135. package/dist_ts/tls/sni/sni-handler.js +0 -191
  136. package/ts/core/events/index.ts +0 -3
  137. package/ts/core/models/socket-augmentation.ts +0 -38
  138. package/ts/core/utils/async-utils.ts +0 -275
  139. package/ts/core/utils/binary-heap.ts +0 -225
  140. package/ts/core/utils/enhanced-connection-pool.ts +0 -425
  141. package/ts/core/utils/fs-utils.ts +0 -270
  142. package/ts/core/utils/ip-utils.ts +0 -303
  143. package/ts/core/utils/lifecycle-component.ts +0 -251
  144. package/ts/core/utils/log-deduplicator.ts +0 -370
  145. package/ts/core/utils/security-utils.ts +0 -305
  146. package/ts/core/utils/shared-security-manager.ts +0 -470
  147. package/ts/core/utils/socket-utils.ts +0 -322
  148. package/ts/core/utils/template-utils.ts +0 -124
  149. package/ts/core/utils/validation-utils.ts +0 -177
  150. package/ts/core/utils/websocket-utils.ts +0 -33
  151. package/ts/detection/detectors/http-detector.ts +0 -127
  152. package/ts/detection/detectors/quick-detector.ts +0 -148
  153. package/ts/detection/detectors/routing-extractor.ts +0 -147
  154. package/ts/detection/detectors/tls-detector.ts +0 -223
  155. package/ts/detection/index.ts +0 -25
  156. package/ts/detection/models/detection-types.ts +0 -102
  157. package/ts/detection/models/interfaces.ts +0 -115
  158. package/ts/detection/protocol-detector.ts +0 -319
  159. package/ts/detection/utils/buffer-utils.ts +0 -141
  160. package/ts/detection/utils/fragment-manager.ts +0 -64
  161. package/ts/detection/utils/parser-utils.ts +0 -77
  162. package/ts/protocols/common/fragment-handler.ts +0 -167
  163. package/ts/protocols/common/index.ts +0 -8
  164. package/ts/protocols/common/types.ts +0 -76
  165. package/ts/protocols/http/parser.ts +0 -219
  166. package/ts/protocols/proxy/index.ts +0 -6
  167. package/ts/protocols/proxy/types.ts +0 -53
  168. package/ts/protocols/tls/alerts/index.ts +0 -3
  169. package/ts/protocols/tls/alerts/tls-alert.ts +0 -259
  170. package/ts/protocols/tls/index.ts +0 -37
  171. package/ts/protocols/tls/sni/client-hello-parser.ts +0 -629
  172. package/ts/protocols/tls/sni/index.ts +0 -6
  173. package/ts/protocols/tls/sni/sni-extraction.ts +0 -353
  174. package/ts/protocols/tls/utils/index.ts +0 -3
  175. package/ts/protocols/tls/utils/tls-utils.ts +0 -201
  176. package/ts/protocols/websocket/constants.ts +0 -60
  177. package/ts/protocols/websocket/index.ts +0 -8
  178. package/ts/protocols/websocket/types.ts +0 -53
  179. package/ts/protocols/websocket/utils.ts +0 -98
  180. package/ts/routing/router/http-router.ts +0 -266
  181. package/ts/routing/router/index.ts +0 -7
  182. package/ts/tls/index.ts +0 -29
  183. package/ts/tls/sni/index.ts +0 -3
  184. package/ts/tls/sni/sni-handler.ts +0 -264
@@ -1,425 +0,0 @@
1
- import { LifecycleComponent } from './lifecycle-component.js';
2
- import { BinaryHeap } from './binary-heap.js';
3
- import { AsyncMutex } from './async-utils.js';
4
- import { EventEmitter } from 'node:events';
5
-
6
- /**
7
- * Interface for pooled connection
8
- */
9
- export interface IPooledConnection<T> {
10
- id: string;
11
- connection: T;
12
- createdAt: number;
13
- lastUsedAt: number;
14
- useCount: number;
15
- inUse: boolean;
16
- metadata?: any;
17
- }
18
-
19
- /**
20
- * Configuration options for the connection pool
21
- */
22
- export interface IConnectionPoolOptions<T> {
23
- minSize?: number;
24
- maxSize?: number;
25
- acquireTimeout?: number;
26
- idleTimeout?: number;
27
- maxUseCount?: number;
28
- validateOnAcquire?: boolean;
29
- validateOnReturn?: boolean;
30
- queueTimeout?: number;
31
- connectionFactory: () => Promise<T>;
32
- connectionValidator?: (connection: T) => Promise<boolean>;
33
- connectionDestroyer?: (connection: T) => Promise<void>;
34
- onConnectionError?: (error: Error, connection?: T) => void;
35
- }
36
-
37
- /**
38
- * Interface for queued acquire request
39
- */
40
- interface IAcquireRequest<T> {
41
- id: string;
42
- priority: number;
43
- timestamp: number;
44
- resolve: (connection: IPooledConnection<T>) => void;
45
- reject: (error: Error) => void;
46
- timeoutHandle?: NodeJS.Timeout;
47
- }
48
-
49
- /**
50
- * Enhanced connection pool with priority queue, backpressure, and lifecycle management
51
- */
52
- export class EnhancedConnectionPool<T> extends LifecycleComponent {
53
- private readonly options: Required<Omit<IConnectionPoolOptions<T>, 'connectionValidator' | 'connectionDestroyer' | 'onConnectionError'>> & Pick<IConnectionPoolOptions<T>, 'connectionValidator' | 'connectionDestroyer' | 'onConnectionError'>;
54
- private readonly availableConnections: IPooledConnection<T>[] = [];
55
- private readonly activeConnections: Map<string, IPooledConnection<T>> = new Map();
56
- private readonly waitQueue: BinaryHeap<IAcquireRequest<T>>;
57
- private readonly mutex = new AsyncMutex();
58
- private readonly eventEmitter = new EventEmitter();
59
-
60
- private connectionIdCounter = 0;
61
- private requestIdCounter = 0;
62
- private isClosing = false;
63
-
64
- // Metrics
65
- private metrics = {
66
- connectionsCreated: 0,
67
- connectionsDestroyed: 0,
68
- connectionsAcquired: 0,
69
- connectionsReleased: 0,
70
- acquireTimeouts: 0,
71
- validationFailures: 0,
72
- queueHighWaterMark: 0,
73
- };
74
-
75
- constructor(options: IConnectionPoolOptions<T>) {
76
- super();
77
-
78
- this.options = {
79
- minSize: 0,
80
- maxSize: 10,
81
- acquireTimeout: 30000,
82
- idleTimeout: 300000, // 5 minutes
83
- maxUseCount: Infinity,
84
- validateOnAcquire: true,
85
- validateOnReturn: false,
86
- queueTimeout: 60000,
87
- ...options,
88
- };
89
-
90
- // Initialize priority queue (higher priority = extracted first)
91
- this.waitQueue = new BinaryHeap<IAcquireRequest<T>>(
92
- (a, b) => b.priority - a.priority || a.timestamp - b.timestamp,
93
- (item) => item.id
94
- );
95
-
96
- // Start maintenance cycle
97
- this.startMaintenance();
98
-
99
- // Initialize minimum connections
100
- this.initializeMinConnections();
101
- }
102
-
103
- /**
104
- * Initialize minimum number of connections
105
- */
106
- private async initializeMinConnections(): Promise<void> {
107
- const promises: Promise<void>[] = [];
108
-
109
- for (let i = 0; i < this.options.minSize; i++) {
110
- promises.push(
111
- this.createConnection()
112
- .then(conn => {
113
- this.availableConnections.push(conn);
114
- })
115
- .catch(err => {
116
- if (this.options.onConnectionError) {
117
- this.options.onConnectionError(err);
118
- }
119
- })
120
- );
121
- }
122
-
123
- await Promise.all(promises);
124
- }
125
-
126
- /**
127
- * Start maintenance timer for idle connection cleanup
128
- */
129
- private startMaintenance(): void {
130
- this.setInterval(() => {
131
- this.performMaintenance();
132
- }, 30000); // Every 30 seconds
133
- }
134
-
135
- /**
136
- * Perform maintenance tasks
137
- */
138
- private async performMaintenance(): Promise<void> {
139
- await this.mutex.runExclusive(async () => {
140
- const now = Date.now();
141
- const toRemove: IPooledConnection<T>[] = [];
142
-
143
- // Check for idle connections beyond minimum size
144
- for (let i = this.availableConnections.length - 1; i >= 0; i--) {
145
- const conn = this.availableConnections[i];
146
-
147
- // Keep minimum connections
148
- if (this.availableConnections.length <= this.options.minSize) {
149
- break;
150
- }
151
-
152
- // Remove idle connections
153
- if (now - conn.lastUsedAt > this.options.idleTimeout) {
154
- toRemove.push(conn);
155
- this.availableConnections.splice(i, 1);
156
- }
157
- }
158
-
159
- // Destroy idle connections
160
- for (const conn of toRemove) {
161
- await this.destroyConnection(conn);
162
- }
163
- });
164
- }
165
-
166
- /**
167
- * Acquire a connection from the pool
168
- */
169
- public async acquire(priority: number = 0, timeout?: number): Promise<IPooledConnection<T>> {
170
- if (this.isClosing) {
171
- throw new Error('Connection pool is closing');
172
- }
173
-
174
- return this.mutex.runExclusive(async () => {
175
- // Try to get an available connection
176
- const connection = await this.tryAcquireConnection();
177
- if (connection) {
178
- return connection;
179
- }
180
-
181
- // Check if we can create a new connection
182
- const totalConnections = this.availableConnections.length + this.activeConnections.size;
183
- if (totalConnections < this.options.maxSize) {
184
- try {
185
- const newConnection = await this.createConnection();
186
- return this.checkoutConnection(newConnection);
187
- } catch (err) {
188
- // Fall through to queue if creation fails
189
- }
190
- }
191
-
192
- // Add to wait queue
193
- return this.queueAcquireRequest(priority, timeout);
194
- });
195
- }
196
-
197
- /**
198
- * Try to acquire an available connection
199
- */
200
- private async tryAcquireConnection(): Promise<IPooledConnection<T> | null> {
201
- while (this.availableConnections.length > 0) {
202
- const connection = this.availableConnections.shift()!;
203
-
204
- // Check if connection exceeded max use count
205
- if (connection.useCount >= this.options.maxUseCount) {
206
- await this.destroyConnection(connection);
207
- continue;
208
- }
209
-
210
- // Validate connection if required
211
- if (this.options.validateOnAcquire && this.options.connectionValidator) {
212
- try {
213
- const isValid = await this.options.connectionValidator(connection.connection);
214
- if (!isValid) {
215
- this.metrics.validationFailures++;
216
- await this.destroyConnection(connection);
217
- continue;
218
- }
219
- } catch (err) {
220
- this.metrics.validationFailures++;
221
- await this.destroyConnection(connection);
222
- continue;
223
- }
224
- }
225
-
226
- return this.checkoutConnection(connection);
227
- }
228
-
229
- return null;
230
- }
231
-
232
- /**
233
- * Checkout a connection for use
234
- */
235
- private checkoutConnection(connection: IPooledConnection<T>): IPooledConnection<T> {
236
- connection.inUse = true;
237
- connection.lastUsedAt = Date.now();
238
- connection.useCount++;
239
-
240
- this.activeConnections.set(connection.id, connection);
241
- this.metrics.connectionsAcquired++;
242
-
243
- this.eventEmitter.emit('acquire', connection);
244
- return connection;
245
- }
246
-
247
- /**
248
- * Queue an acquire request
249
- */
250
- private queueAcquireRequest(priority: number, timeout?: number): Promise<IPooledConnection<T>> {
251
- return new Promise<IPooledConnection<T>>((resolve, reject) => {
252
- const request: IAcquireRequest<T> = {
253
- id: `req-${this.requestIdCounter++}`,
254
- priority,
255
- timestamp: Date.now(),
256
- resolve,
257
- reject,
258
- };
259
-
260
- // Set timeout
261
- const timeoutMs = timeout || this.options.queueTimeout;
262
- request.timeoutHandle = this.setTimeout(() => {
263
- if (this.waitQueue.extractByKey(request.id)) {
264
- this.metrics.acquireTimeouts++;
265
- reject(new Error(`Connection acquire timeout after ${timeoutMs}ms`));
266
- }
267
- }, timeoutMs);
268
-
269
- this.waitQueue.insert(request);
270
- this.metrics.queueHighWaterMark = Math.max(
271
- this.metrics.queueHighWaterMark,
272
- this.waitQueue.size
273
- );
274
-
275
- this.eventEmitter.emit('enqueue', { queueSize: this.waitQueue.size });
276
- });
277
- }
278
-
279
- /**
280
- * Release a connection back to the pool
281
- */
282
- public async release(connection: IPooledConnection<T>): Promise<void> {
283
- return this.mutex.runExclusive(async () => {
284
- if (!connection.inUse || !this.activeConnections.has(connection.id)) {
285
- throw new Error('Connection is not active');
286
- }
287
-
288
- this.activeConnections.delete(connection.id);
289
- connection.inUse = false;
290
- connection.lastUsedAt = Date.now();
291
- this.metrics.connectionsReleased++;
292
-
293
- // Check if connection should be destroyed
294
- if (connection.useCount >= this.options.maxUseCount) {
295
- await this.destroyConnection(connection);
296
- return;
297
- }
298
-
299
- // Validate on return if required
300
- if (this.options.validateOnReturn && this.options.connectionValidator) {
301
- try {
302
- const isValid = await this.options.connectionValidator(connection.connection);
303
- if (!isValid) {
304
- await this.destroyConnection(connection);
305
- return;
306
- }
307
- } catch (err) {
308
- await this.destroyConnection(connection);
309
- return;
310
- }
311
- }
312
-
313
- // Check if there are waiting requests
314
- const request = this.waitQueue.extract();
315
- if (request) {
316
- this.clearTimeout(request.timeoutHandle!);
317
- request.resolve(this.checkoutConnection(connection));
318
- this.eventEmitter.emit('dequeue', { queueSize: this.waitQueue.size });
319
- } else {
320
- // Return to available pool
321
- this.availableConnections.push(connection);
322
- this.eventEmitter.emit('release', connection);
323
- }
324
- });
325
- }
326
-
327
- /**
328
- * Create a new connection
329
- */
330
- private async createConnection(): Promise<IPooledConnection<T>> {
331
- const rawConnection = await this.options.connectionFactory();
332
-
333
- const connection: IPooledConnection<T> = {
334
- id: `conn-${this.connectionIdCounter++}`,
335
- connection: rawConnection,
336
- createdAt: Date.now(),
337
- lastUsedAt: Date.now(),
338
- useCount: 0,
339
- inUse: false,
340
- };
341
-
342
- this.metrics.connectionsCreated++;
343
- this.eventEmitter.emit('create', connection);
344
-
345
- return connection;
346
- }
347
-
348
- /**
349
- * Destroy a connection
350
- */
351
- private async destroyConnection(connection: IPooledConnection<T>): Promise<void> {
352
- try {
353
- if (this.options.connectionDestroyer) {
354
- await this.options.connectionDestroyer(connection.connection);
355
- }
356
-
357
- this.metrics.connectionsDestroyed++;
358
- this.eventEmitter.emit('destroy', connection);
359
- } catch (err) {
360
- if (this.options.onConnectionError) {
361
- this.options.onConnectionError(err as Error, connection.connection);
362
- }
363
- }
364
- }
365
-
366
- /**
367
- * Get current pool statistics
368
- */
369
- public getStats() {
370
- return {
371
- available: this.availableConnections.length,
372
- active: this.activeConnections.size,
373
- waiting: this.waitQueue.size,
374
- total: this.availableConnections.length + this.activeConnections.size,
375
- ...this.metrics,
376
- };
377
- }
378
-
379
- /**
380
- * Subscribe to pool events
381
- */
382
- public on(event: string, listener: Function): void {
383
- this.addEventListener(this.eventEmitter, event, listener);
384
- }
385
-
386
- /**
387
- * Close the pool and cleanup resources
388
- */
389
- protected async onCleanup(): Promise<void> {
390
- this.isClosing = true;
391
-
392
- // Clear the wait queue
393
- while (!this.waitQueue.isEmpty()) {
394
- const request = this.waitQueue.extract();
395
- if (request) {
396
- this.clearTimeout(request.timeoutHandle!);
397
- request.reject(new Error('Connection pool is closing'));
398
- }
399
- }
400
-
401
- // Wait for active connections to be released (with timeout)
402
- const timeout = 30000;
403
- const startTime = Date.now();
404
-
405
- while (this.activeConnections.size > 0 && Date.now() - startTime < timeout) {
406
- await new Promise(resolve => {
407
- const timer = setTimeout(resolve, 100);
408
- if (typeof timer.unref === 'function') {
409
- timer.unref();
410
- }
411
- });
412
- }
413
-
414
- // Destroy all connections
415
- const allConnections = [
416
- ...this.availableConnections,
417
- ...this.activeConnections.values(),
418
- ];
419
-
420
- await Promise.all(allConnections.map(conn => this.destroyConnection(conn)));
421
-
422
- this.availableConnections.length = 0;
423
- this.activeConnections.clear();
424
- }
425
- }
@@ -1,270 +0,0 @@
1
- /**
2
- * Async filesystem utilities for SmartProxy
3
- * Provides non-blocking alternatives to synchronous filesystem operations
4
- */
5
-
6
- import * as plugins from '../../plugins.js';
7
-
8
- export class AsyncFileSystem {
9
- /**
10
- * Check if a file or directory exists
11
- * @param path - Path to check
12
- * @returns Promise resolving to true if exists, false otherwise
13
- */
14
- static async exists(path: string): Promise<boolean> {
15
- try {
16
- await plugins.fs.promises.access(path);
17
- return true;
18
- } catch {
19
- return false;
20
- }
21
- }
22
-
23
- /**
24
- * Ensure a directory exists, creating it if necessary
25
- * @param dirPath - Directory path to ensure
26
- * @returns Promise that resolves when directory is ensured
27
- */
28
- static async ensureDir(dirPath: string): Promise<void> {
29
- await plugins.fs.promises.mkdir(dirPath, { recursive: true });
30
- }
31
-
32
- /**
33
- * Read a file as string
34
- * @param filePath - Path to the file
35
- * @param encoding - File encoding (default: utf8)
36
- * @returns Promise resolving to file contents
37
- */
38
- static async readFile(filePath: string, encoding: BufferEncoding = 'utf8'): Promise<string> {
39
- return plugins.fs.promises.readFile(filePath, encoding);
40
- }
41
-
42
- /**
43
- * Read a file as buffer
44
- * @param filePath - Path to the file
45
- * @returns Promise resolving to file buffer
46
- */
47
- static async readFileBuffer(filePath: string): Promise<Buffer> {
48
- return plugins.fs.promises.readFile(filePath);
49
- }
50
-
51
- /**
52
- * Write string data to a file
53
- * @param filePath - Path to the file
54
- * @param data - String data to write
55
- * @param encoding - File encoding (default: utf8)
56
- * @returns Promise that resolves when file is written
57
- */
58
- static async writeFile(filePath: string, data: string, encoding: BufferEncoding = 'utf8'): Promise<void> {
59
- // Ensure directory exists
60
- const dir = plugins.path.dirname(filePath);
61
- await this.ensureDir(dir);
62
- await plugins.fs.promises.writeFile(filePath, data, encoding);
63
- }
64
-
65
- /**
66
- * Write buffer data to a file
67
- * @param filePath - Path to the file
68
- * @param data - Buffer data to write
69
- * @returns Promise that resolves when file is written
70
- */
71
- static async writeFileBuffer(filePath: string, data: Buffer): Promise<void> {
72
- const dir = plugins.path.dirname(filePath);
73
- await this.ensureDir(dir);
74
- await plugins.fs.promises.writeFile(filePath, data);
75
- }
76
-
77
- /**
78
- * Remove a file
79
- * @param filePath - Path to the file
80
- * @returns Promise that resolves when file is removed
81
- */
82
- static async remove(filePath: string): Promise<void> {
83
- try {
84
- await plugins.fs.promises.unlink(filePath);
85
- } catch (error: any) {
86
- if (error.code !== 'ENOENT') {
87
- throw error;
88
- }
89
- // File doesn't exist, which is fine
90
- }
91
- }
92
-
93
- /**
94
- * Remove a directory and all its contents
95
- * @param dirPath - Path to the directory
96
- * @returns Promise that resolves when directory is removed
97
- */
98
- static async removeDir(dirPath: string): Promise<void> {
99
- try {
100
- await plugins.fs.promises.rm(dirPath, { recursive: true, force: true });
101
- } catch (error: any) {
102
- if (error.code !== 'ENOENT') {
103
- throw error;
104
- }
105
- }
106
- }
107
-
108
- /**
109
- * Read JSON from a file
110
- * @param filePath - Path to the JSON file
111
- * @returns Promise resolving to parsed JSON
112
- */
113
- static async readJSON<T = any>(filePath: string): Promise<T> {
114
- const content = await this.readFile(filePath);
115
- return JSON.parse(content);
116
- }
117
-
118
- /**
119
- * Write JSON to a file
120
- * @param filePath - Path to the file
121
- * @param data - Data to write as JSON
122
- * @param pretty - Whether to pretty-print JSON (default: true)
123
- * @returns Promise that resolves when file is written
124
- */
125
- static async writeJSON(filePath: string, data: any, pretty = true): Promise<void> {
126
- const jsonString = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
127
- await this.writeFile(filePath, jsonString);
128
- }
129
-
130
- /**
131
- * Copy a file from source to destination
132
- * @param source - Source file path
133
- * @param destination - Destination file path
134
- * @returns Promise that resolves when file is copied
135
- */
136
- static async copyFile(source: string, destination: string): Promise<void> {
137
- const destDir = plugins.path.dirname(destination);
138
- await this.ensureDir(destDir);
139
- await plugins.fs.promises.copyFile(source, destination);
140
- }
141
-
142
- /**
143
- * Move/rename a file
144
- * @param source - Source file path
145
- * @param destination - Destination file path
146
- * @returns Promise that resolves when file is moved
147
- */
148
- static async moveFile(source: string, destination: string): Promise<void> {
149
- const destDir = plugins.path.dirname(destination);
150
- await this.ensureDir(destDir);
151
- await plugins.fs.promises.rename(source, destination);
152
- }
153
-
154
- /**
155
- * Get file stats
156
- * @param filePath - Path to the file
157
- * @returns Promise resolving to file stats or null if doesn't exist
158
- */
159
- static async getStats(filePath: string): Promise<plugins.fs.Stats | null> {
160
- try {
161
- return await plugins.fs.promises.stat(filePath);
162
- } catch (error: any) {
163
- if (error.code === 'ENOENT') {
164
- return null;
165
- }
166
- throw error;
167
- }
168
- }
169
-
170
- /**
171
- * List files in a directory
172
- * @param dirPath - Directory path
173
- * @returns Promise resolving to array of filenames
174
- */
175
- static async listFiles(dirPath: string): Promise<string[]> {
176
- try {
177
- return await plugins.fs.promises.readdir(dirPath);
178
- } catch (error: any) {
179
- if (error.code === 'ENOENT') {
180
- return [];
181
- }
182
- throw error;
183
- }
184
- }
185
-
186
- /**
187
- * List files in a directory with full paths
188
- * @param dirPath - Directory path
189
- * @returns Promise resolving to array of full file paths
190
- */
191
- static async listFilesFullPath(dirPath: string): Promise<string[]> {
192
- const files = await this.listFiles(dirPath);
193
- return files.map(file => plugins.path.join(dirPath, file));
194
- }
195
-
196
- /**
197
- * Recursively list all files in a directory
198
- * @param dirPath - Directory path
199
- * @param fileList - Accumulator for file list (used internally)
200
- * @returns Promise resolving to array of all file paths
201
- */
202
- static async listFilesRecursive(dirPath: string, fileList: string[] = []): Promise<string[]> {
203
- const files = await this.listFiles(dirPath);
204
-
205
- for (const file of files) {
206
- const filePath = plugins.path.join(dirPath, file);
207
- const stats = await this.getStats(filePath);
208
-
209
- if (stats?.isDirectory()) {
210
- await this.listFilesRecursive(filePath, fileList);
211
- } else if (stats?.isFile()) {
212
- fileList.push(filePath);
213
- }
214
- }
215
-
216
- return fileList;
217
- }
218
-
219
- /**
220
- * Create a read stream for a file
221
- * @param filePath - Path to the file
222
- * @param options - Stream options
223
- * @returns Read stream
224
- */
225
- static createReadStream(filePath: string, options?: Parameters<typeof plugins.fs.createReadStream>[1]): plugins.fs.ReadStream {
226
- return plugins.fs.createReadStream(filePath, options);
227
- }
228
-
229
- /**
230
- * Create a write stream for a file
231
- * @param filePath - Path to the file
232
- * @param options - Stream options
233
- * @returns Write stream
234
- */
235
- static createWriteStream(filePath: string, options?: Parameters<typeof plugins.fs.createWriteStream>[1]): plugins.fs.WriteStream {
236
- return plugins.fs.createWriteStream(filePath, options);
237
- }
238
-
239
- /**
240
- * Ensure a file exists, creating an empty file if necessary
241
- * @param filePath - Path to the file
242
- * @returns Promise that resolves when file is ensured
243
- */
244
- static async ensureFile(filePath: string): Promise<void> {
245
- const exists = await this.exists(filePath);
246
- if (!exists) {
247
- await this.writeFile(filePath, '');
248
- }
249
- }
250
-
251
- /**
252
- * Check if a path is a directory
253
- * @param path - Path to check
254
- * @returns Promise resolving to true if directory, false otherwise
255
- */
256
- static async isDirectory(path: string): Promise<boolean> {
257
- const stats = await this.getStats(path);
258
- return stats?.isDirectory() ?? false;
259
- }
260
-
261
- /**
262
- * Check if a path is a file
263
- * @param path - Path to check
264
- * @returns Promise resolving to true if file, false otherwise
265
- */
266
- static async isFile(path: string): Promise<boolean> {
267
- const stats = await this.getStats(path);
268
- return stats?.isFile() ?? false;
269
- }
270
- }