@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,275 +0,0 @@
1
- /**
2
- * Async utility functions for SmartProxy
3
- * Provides non-blocking alternatives to synchronous operations
4
- */
5
-
6
- /**
7
- * Delays execution for the specified number of milliseconds
8
- * Non-blocking alternative to busy wait loops
9
- * @param ms - Number of milliseconds to delay
10
- * @returns Promise that resolves after the delay
11
- */
12
- export async function delay(ms: number): Promise<void> {
13
- return new Promise(resolve => setTimeout(resolve, ms));
14
- }
15
-
16
- /**
17
- * Retry an async operation with exponential backoff
18
- * @param fn - The async function to retry
19
- * @param options - Retry options
20
- * @returns The result of the function or throws the last error
21
- */
22
- export async function retryWithBackoff<T>(
23
- fn: () => Promise<T>,
24
- options: {
25
- maxAttempts?: number;
26
- initialDelay?: number;
27
- maxDelay?: number;
28
- factor?: number;
29
- onRetry?: (attempt: number, error: Error) => void;
30
- } = {}
31
- ): Promise<T> {
32
- const {
33
- maxAttempts = 3,
34
- initialDelay = 100,
35
- maxDelay = 10000,
36
- factor = 2,
37
- onRetry
38
- } = options;
39
-
40
- let lastError: Error | null = null;
41
- let currentDelay = initialDelay;
42
-
43
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
44
- try {
45
- return await fn();
46
- } catch (error: any) {
47
- lastError = error;
48
-
49
- if (attempt === maxAttempts) {
50
- throw error;
51
- }
52
-
53
- if (onRetry) {
54
- onRetry(attempt, error);
55
- }
56
-
57
- await delay(currentDelay);
58
- currentDelay = Math.min(currentDelay * factor, maxDelay);
59
- }
60
- }
61
-
62
- throw lastError || new Error('Retry failed');
63
- }
64
-
65
- /**
66
- * Execute an async operation with a timeout
67
- * @param fn - The async function to execute
68
- * @param timeoutMs - Timeout in milliseconds
69
- * @param timeoutError - Optional custom timeout error
70
- * @returns The result of the function or throws timeout error
71
- */
72
- export async function withTimeout<T>(
73
- fn: () => Promise<T>,
74
- timeoutMs: number,
75
- timeoutError?: Error
76
- ): Promise<T> {
77
- const timeoutPromise = new Promise<never>((_, reject) => {
78
- setTimeout(() => {
79
- reject(timeoutError || new Error(`Operation timed out after ${timeoutMs}ms`));
80
- }, timeoutMs);
81
- });
82
-
83
- return Promise.race([fn(), timeoutPromise]);
84
- }
85
-
86
- /**
87
- * Run multiple async operations in parallel with a concurrency limit
88
- * @param items - Array of items to process
89
- * @param fn - Async function to run for each item
90
- * @param concurrency - Maximum number of concurrent operations
91
- * @returns Array of results in the same order as input
92
- */
93
- export async function parallelLimit<T, R>(
94
- items: T[],
95
- fn: (item: T, index: number) => Promise<R>,
96
- concurrency: number
97
- ): Promise<R[]> {
98
- const results: R[] = new Array(items.length);
99
- const executing: Set<Promise<void>> = new Set();
100
-
101
- for (let i = 0; i < items.length; i++) {
102
- const promise = fn(items[i], i).then(result => {
103
- results[i] = result;
104
- executing.delete(promise);
105
- });
106
-
107
- executing.add(promise);
108
-
109
- if (executing.size >= concurrency) {
110
- await Promise.race(executing);
111
- }
112
- }
113
-
114
- await Promise.all(executing);
115
- return results;
116
- }
117
-
118
- /**
119
- * Debounce an async function
120
- * @param fn - The async function to debounce
121
- * @param delayMs - Delay in milliseconds
122
- * @returns Debounced function with cancel method
123
- */
124
- export function debounceAsync<T extends (...args: any[]) => Promise<any>>(
125
- fn: T,
126
- delayMs: number
127
- ): T & { cancel: () => void } {
128
- let timeoutId: NodeJS.Timeout | null = null;
129
- let lastPromise: Promise<any> | null = null;
130
-
131
- const debounced = ((...args: Parameters<T>) => {
132
- if (timeoutId) {
133
- clearTimeout(timeoutId);
134
- }
135
-
136
- lastPromise = new Promise((resolve, reject) => {
137
- timeoutId = setTimeout(async () => {
138
- timeoutId = null;
139
- try {
140
- const result = await fn(...args);
141
- resolve(result);
142
- } catch (error) {
143
- reject(error);
144
- }
145
- }, delayMs);
146
- });
147
-
148
- return lastPromise;
149
- }) as any;
150
-
151
- debounced.cancel = () => {
152
- if (timeoutId) {
153
- clearTimeout(timeoutId);
154
- timeoutId = null;
155
- }
156
- };
157
-
158
- return debounced as T & { cancel: () => void };
159
- }
160
-
161
- /**
162
- * Create a mutex for ensuring exclusive access to a resource
163
- */
164
- export class AsyncMutex {
165
- private queue: Array<() => void> = [];
166
- private locked = false;
167
-
168
- async acquire(): Promise<() => void> {
169
- if (!this.locked) {
170
- this.locked = true;
171
- return () => this.release();
172
- }
173
-
174
- return new Promise<() => void>(resolve => {
175
- this.queue.push(() => {
176
- resolve(() => this.release());
177
- });
178
- });
179
- }
180
-
181
- private release(): void {
182
- const next = this.queue.shift();
183
- if (next) {
184
- next();
185
- } else {
186
- this.locked = false;
187
- }
188
- }
189
-
190
- async runExclusive<T>(fn: () => Promise<T>): Promise<T> {
191
- const release = await this.acquire();
192
- try {
193
- return await fn();
194
- } finally {
195
- release();
196
- }
197
- }
198
- }
199
-
200
- /**
201
- * Circuit breaker for protecting against cascading failures
202
- */
203
- export class CircuitBreaker {
204
- private failureCount = 0;
205
- private lastFailureTime = 0;
206
- private state: 'closed' | 'open' | 'half-open' = 'closed';
207
-
208
- constructor(
209
- private options: {
210
- failureThreshold: number;
211
- resetTimeout: number;
212
- onStateChange?: (state: 'closed' | 'open' | 'half-open') => void;
213
- }
214
- ) {}
215
-
216
- async execute<T>(fn: () => Promise<T>): Promise<T> {
217
- if (this.state === 'open') {
218
- if (Date.now() - this.lastFailureTime > this.options.resetTimeout) {
219
- this.setState('half-open');
220
- } else {
221
- throw new Error('Circuit breaker is open');
222
- }
223
- }
224
-
225
- try {
226
- const result = await fn();
227
- this.onSuccess();
228
- return result;
229
- } catch (error) {
230
- this.onFailure();
231
- throw error;
232
- }
233
- }
234
-
235
- private onSuccess(): void {
236
- this.failureCount = 0;
237
- if (this.state !== 'closed') {
238
- this.setState('closed');
239
- }
240
- }
241
-
242
- private onFailure(): void {
243
- this.failureCount++;
244
- this.lastFailureTime = Date.now();
245
-
246
- if (this.failureCount >= this.options.failureThreshold) {
247
- this.setState('open');
248
- }
249
- }
250
-
251
- private setState(state: 'closed' | 'open' | 'half-open'): void {
252
- if (this.state !== state) {
253
- this.state = state;
254
- if (this.options.onStateChange) {
255
- this.options.onStateChange(state);
256
- }
257
- }
258
- }
259
-
260
- isOpen(): boolean {
261
- return this.state === 'open';
262
- }
263
-
264
- getState(): 'closed' | 'open' | 'half-open' {
265
- return this.state;
266
- }
267
-
268
- recordSuccess(): void {
269
- this.onSuccess();
270
- }
271
-
272
- recordFailure(): void {
273
- this.onFailure();
274
- }
275
- }
@@ -1,225 +0,0 @@
1
- /**
2
- * A binary heap implementation for efficient priority queue operations
3
- * Supports O(log n) insert and extract operations
4
- */
5
- export class BinaryHeap<T> {
6
- private heap: T[] = [];
7
- private keyMap?: Map<string, number>; // For efficient key-based lookups
8
-
9
- constructor(
10
- private compareFn: (a: T, b: T) => number,
11
- private extractKey?: (item: T) => string
12
- ) {
13
- if (extractKey) {
14
- this.keyMap = new Map();
15
- }
16
- }
17
-
18
- /**
19
- * Get the current size of the heap
20
- */
21
- public get size(): number {
22
- return this.heap.length;
23
- }
24
-
25
- /**
26
- * Check if the heap is empty
27
- */
28
- public isEmpty(): boolean {
29
- return this.heap.length === 0;
30
- }
31
-
32
- /**
33
- * Peek at the top element without removing it
34
- */
35
- public peek(): T | undefined {
36
- return this.heap[0];
37
- }
38
-
39
- /**
40
- * Insert a new item into the heap
41
- * O(log n) time complexity
42
- */
43
- public insert(item: T): void {
44
- const index = this.heap.length;
45
- this.heap.push(item);
46
-
47
- if (this.keyMap && this.extractKey) {
48
- const key = this.extractKey(item);
49
- this.keyMap.set(key, index);
50
- }
51
-
52
- this.bubbleUp(index);
53
- }
54
-
55
- /**
56
- * Extract the top element from the heap
57
- * O(log n) time complexity
58
- */
59
- public extract(): T | undefined {
60
- if (this.heap.length === 0) return undefined;
61
- if (this.heap.length === 1) {
62
- const item = this.heap.pop()!;
63
- if (this.keyMap && this.extractKey) {
64
- this.keyMap.delete(this.extractKey(item));
65
- }
66
- return item;
67
- }
68
-
69
- const result = this.heap[0];
70
- const lastItem = this.heap.pop()!;
71
- this.heap[0] = lastItem;
72
-
73
- if (this.keyMap && this.extractKey) {
74
- this.keyMap.delete(this.extractKey(result));
75
- this.keyMap.set(this.extractKey(lastItem), 0);
76
- }
77
-
78
- this.bubbleDown(0);
79
- return result;
80
- }
81
-
82
- /**
83
- * Extract an element that matches the predicate
84
- * O(n) time complexity for search, O(log n) for extraction
85
- */
86
- public extractIf(predicate: (item: T) => boolean): T | undefined {
87
- const index = this.heap.findIndex(predicate);
88
- if (index === -1) return undefined;
89
-
90
- return this.extractAt(index);
91
- }
92
-
93
- /**
94
- * Extract an element by its key (if extractKey was provided)
95
- * O(log n) time complexity
96
- */
97
- public extractByKey(key: string): T | undefined {
98
- if (!this.keyMap || !this.extractKey) {
99
- throw new Error('extractKey function must be provided to use key-based extraction');
100
- }
101
-
102
- const index = this.keyMap.get(key);
103
- if (index === undefined) return undefined;
104
-
105
- return this.extractAt(index);
106
- }
107
-
108
- /**
109
- * Check if a key exists in the heap
110
- * O(1) time complexity
111
- */
112
- public hasKey(key: string): boolean {
113
- if (!this.keyMap) return false;
114
- return this.keyMap.has(key);
115
- }
116
-
117
- /**
118
- * Get all elements as an array (does not modify heap)
119
- * O(n) time complexity
120
- */
121
- public toArray(): T[] {
122
- return [...this.heap];
123
- }
124
-
125
- /**
126
- * Clear the heap
127
- */
128
- public clear(): void {
129
- this.heap = [];
130
- if (this.keyMap) {
131
- this.keyMap.clear();
132
- }
133
- }
134
-
135
- /**
136
- * Extract element at specific index
137
- */
138
- private extractAt(index: number): T {
139
- const item = this.heap[index];
140
-
141
- if (this.keyMap && this.extractKey) {
142
- this.keyMap.delete(this.extractKey(item));
143
- }
144
-
145
- if (index === this.heap.length - 1) {
146
- this.heap.pop();
147
- return item;
148
- }
149
-
150
- const lastItem = this.heap.pop()!;
151
- this.heap[index] = lastItem;
152
-
153
- if (this.keyMap && this.extractKey) {
154
- this.keyMap.set(this.extractKey(lastItem), index);
155
- }
156
-
157
- // Try bubbling up first
158
- const parentIndex = Math.floor((index - 1) / 2);
159
- if (parentIndex >= 0 && this.compareFn(this.heap[index], this.heap[parentIndex]) < 0) {
160
- this.bubbleUp(index);
161
- } else {
162
- this.bubbleDown(index);
163
- }
164
-
165
- return item;
166
- }
167
-
168
- /**
169
- * Bubble up element at given index to maintain heap property
170
- */
171
- private bubbleUp(index: number): void {
172
- while (index > 0) {
173
- const parentIndex = Math.floor((index - 1) / 2);
174
-
175
- if (this.compareFn(this.heap[index], this.heap[parentIndex]) >= 0) {
176
- break;
177
- }
178
-
179
- this.swap(index, parentIndex);
180
- index = parentIndex;
181
- }
182
- }
183
-
184
- /**
185
- * Bubble down element at given index to maintain heap property
186
- */
187
- private bubbleDown(index: number): void {
188
- const length = this.heap.length;
189
-
190
- while (true) {
191
- const leftChild = 2 * index + 1;
192
- const rightChild = 2 * index + 2;
193
- let smallest = index;
194
-
195
- if (leftChild < length &&
196
- this.compareFn(this.heap[leftChild], this.heap[smallest]) < 0) {
197
- smallest = leftChild;
198
- }
199
-
200
- if (rightChild < length &&
201
- this.compareFn(this.heap[rightChild], this.heap[smallest]) < 0) {
202
- smallest = rightChild;
203
- }
204
-
205
- if (smallest === index) break;
206
-
207
- this.swap(index, smallest);
208
- index = smallest;
209
- }
210
- }
211
-
212
- /**
213
- * Swap two elements in the heap
214
- */
215
- private swap(i: number, j: number): void {
216
- const temp = this.heap[i];
217
- this.heap[i] = this.heap[j];
218
- this.heap[j] = temp;
219
-
220
- if (this.keyMap && this.extractKey) {
221
- this.keyMap.set(this.extractKey(this.heap[i]), i);
222
- this.keyMap.set(this.extractKey(this.heap[j]), j);
223
- }
224
- }
225
- }