@push.rocks/smartproxy 25.17.9 → 26.0.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 (179) hide show
  1. package/changelog.md +16 -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/socket-handler-server.js +6 -1
  18. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +0 -7
  19. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +50 -51
  20. package/dist_ts/routing/index.d.ts +0 -1
  21. package/dist_ts/routing/index.js +1 -3
  22. package/package.json +1 -1
  23. package/ts/00_commitinfo_data.ts +1 -1
  24. package/ts/core/index.ts +0 -1
  25. package/ts/core/models/index.ts +0 -1
  26. package/ts/core/utils/index.ts +0 -12
  27. package/ts/index.ts +1 -7
  28. package/ts/protocols/http/index.ts +1 -2
  29. package/ts/protocols/index.ts +0 -7
  30. package/ts/proxies/smart-proxy/socket-handler-server.ts +6 -0
  31. package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +60 -59
  32. package/ts/routing/index.ts +0 -3
  33. package/dist_ts/core/events/index.d.ts +0 -4
  34. package/dist_ts/core/events/index.js +0 -5
  35. package/dist_ts/core/models/socket-augmentation.d.ts +0 -15
  36. package/dist_ts/core/models/socket-augmentation.js +0 -18
  37. package/dist_ts/core/utils/async-utils.d.ts +0 -81
  38. package/dist_ts/core/utils/async-utils.js +0 -216
  39. package/dist_ts/core/utils/binary-heap.d.ts +0 -73
  40. package/dist_ts/core/utils/binary-heap.js +0 -193
  41. package/dist_ts/core/utils/enhanced-connection-pool.d.ts +0 -110
  42. package/dist_ts/core/utils/enhanced-connection-pool.js +0 -325
  43. package/dist_ts/core/utils/fs-utils.d.ts +0 -144
  44. package/dist_ts/core/utils/fs-utils.js +0 -252
  45. package/dist_ts/core/utils/ip-utils.d.ts +0 -69
  46. package/dist_ts/core/utils/ip-utils.js +0 -270
  47. package/dist_ts/core/utils/lifecycle-component.d.ts +0 -59
  48. package/dist_ts/core/utils/lifecycle-component.js +0 -211
  49. package/dist_ts/core/utils/log-deduplicator.d.ts +0 -39
  50. package/dist_ts/core/utils/log-deduplicator.js +0 -305
  51. package/dist_ts/core/utils/security-utils.d.ts +0 -111
  52. package/dist_ts/core/utils/security-utils.js +0 -212
  53. package/dist_ts/core/utils/shared-security-manager.d.ts +0 -128
  54. package/dist_ts/core/utils/shared-security-manager.js +0 -362
  55. package/dist_ts/core/utils/socket-utils.d.ts +0 -63
  56. package/dist_ts/core/utils/socket-utils.js +0 -249
  57. package/dist_ts/core/utils/template-utils.d.ts +0 -37
  58. package/dist_ts/core/utils/template-utils.js +0 -104
  59. package/dist_ts/core/utils/validation-utils.d.ts +0 -61
  60. package/dist_ts/core/utils/validation-utils.js +0 -149
  61. package/dist_ts/core/utils/websocket-utils.d.ts +0 -22
  62. package/dist_ts/core/utils/websocket-utils.js +0 -30
  63. package/dist_ts/detection/detectors/http-detector.d.ts +0 -33
  64. package/dist_ts/detection/detectors/http-detector.js +0 -101
  65. package/dist_ts/detection/detectors/quick-detector.d.ts +0 -28
  66. package/dist_ts/detection/detectors/quick-detector.js +0 -131
  67. package/dist_ts/detection/detectors/routing-extractor.d.ts +0 -28
  68. package/dist_ts/detection/detectors/routing-extractor.js +0 -122
  69. package/dist_ts/detection/detectors/tls-detector.d.ts +0 -47
  70. package/dist_ts/detection/detectors/tls-detector.js +0 -183
  71. package/dist_ts/detection/index.d.ts +0 -17
  72. package/dist_ts/detection/index.js +0 -22
  73. package/dist_ts/detection/models/detection-types.d.ts +0 -87
  74. package/dist_ts/detection/models/detection-types.js +0 -5
  75. package/dist_ts/detection/models/interfaces.d.ts +0 -97
  76. package/dist_ts/detection/models/interfaces.js +0 -5
  77. package/dist_ts/detection/protocol-detector.d.ts +0 -79
  78. package/dist_ts/detection/protocol-detector.js +0 -253
  79. package/dist_ts/detection/utils/buffer-utils.d.ts +0 -61
  80. package/dist_ts/detection/utils/buffer-utils.js +0 -127
  81. package/dist_ts/detection/utils/fragment-manager.d.ts +0 -31
  82. package/dist_ts/detection/utils/fragment-manager.js +0 -53
  83. package/dist_ts/detection/utils/parser-utils.d.ts +0 -42
  84. package/dist_ts/detection/utils/parser-utils.js +0 -63
  85. package/dist_ts/protocols/common/fragment-handler.d.ts +0 -73
  86. package/dist_ts/protocols/common/fragment-handler.js +0 -121
  87. package/dist_ts/protocols/common/index.d.ts +0 -7
  88. package/dist_ts/protocols/common/index.js +0 -8
  89. package/dist_ts/protocols/common/types.d.ts +0 -68
  90. package/dist_ts/protocols/common/types.js +0 -7
  91. package/dist_ts/protocols/http/parser.d.ts +0 -58
  92. package/dist_ts/protocols/http/parser.js +0 -184
  93. package/dist_ts/protocols/proxy/index.d.ts +0 -5
  94. package/dist_ts/protocols/proxy/index.js +0 -6
  95. package/dist_ts/protocols/proxy/types.d.ts +0 -47
  96. package/dist_ts/protocols/proxy/types.js +0 -6
  97. package/dist_ts/protocols/tls/alerts/index.d.ts +0 -4
  98. package/dist_ts/protocols/tls/alerts/index.js +0 -5
  99. package/dist_ts/protocols/tls/alerts/tls-alert.d.ts +0 -150
  100. package/dist_ts/protocols/tls/alerts/tls-alert.js +0 -226
  101. package/dist_ts/protocols/tls/index.d.ts +0 -12
  102. package/dist_ts/protocols/tls/index.js +0 -27
  103. package/dist_ts/protocols/tls/sni/client-hello-parser.d.ts +0 -100
  104. package/dist_ts/protocols/tls/sni/client-hello-parser.js +0 -463
  105. package/dist_ts/protocols/tls/sni/index.d.ts +0 -5
  106. package/dist_ts/protocols/tls/sni/index.js +0 -6
  107. package/dist_ts/protocols/tls/sni/sni-extraction.d.ts +0 -58
  108. package/dist_ts/protocols/tls/sni/sni-extraction.js +0 -275
  109. package/dist_ts/protocols/tls/utils/index.d.ts +0 -4
  110. package/dist_ts/protocols/tls/utils/index.js +0 -5
  111. package/dist_ts/protocols/tls/utils/tls-utils.d.ts +0 -158
  112. package/dist_ts/protocols/tls/utils/tls-utils.js +0 -187
  113. package/dist_ts/protocols/websocket/constants.d.ts +0 -55
  114. package/dist_ts/protocols/websocket/constants.js +0 -58
  115. package/dist_ts/protocols/websocket/index.d.ts +0 -7
  116. package/dist_ts/protocols/websocket/index.js +0 -8
  117. package/dist_ts/protocols/websocket/types.d.ts +0 -47
  118. package/dist_ts/protocols/websocket/types.js +0 -5
  119. package/dist_ts/protocols/websocket/utils.d.ts +0 -25
  120. package/dist_ts/protocols/websocket/utils.js +0 -103
  121. package/dist_ts/routing/router/http-router.d.ts +0 -89
  122. package/dist_ts/routing/router/http-router.js +0 -205
  123. package/dist_ts/routing/router/index.d.ts +0 -5
  124. package/dist_ts/routing/router/index.js +0 -6
  125. package/dist_ts/tls/index.d.ts +0 -16
  126. package/dist_ts/tls/index.js +0 -24
  127. package/dist_ts/tls/sni/index.d.ts +0 -4
  128. package/dist_ts/tls/sni/index.js +0 -5
  129. package/dist_ts/tls/sni/sni-handler.d.ts +0 -154
  130. package/dist_ts/tls/sni/sni-handler.js +0 -191
  131. package/ts/core/events/index.ts +0 -3
  132. package/ts/core/models/socket-augmentation.ts +0 -38
  133. package/ts/core/utils/async-utils.ts +0 -275
  134. package/ts/core/utils/binary-heap.ts +0 -225
  135. package/ts/core/utils/enhanced-connection-pool.ts +0 -425
  136. package/ts/core/utils/fs-utils.ts +0 -270
  137. package/ts/core/utils/ip-utils.ts +0 -303
  138. package/ts/core/utils/lifecycle-component.ts +0 -251
  139. package/ts/core/utils/log-deduplicator.ts +0 -370
  140. package/ts/core/utils/security-utils.ts +0 -305
  141. package/ts/core/utils/shared-security-manager.ts +0 -470
  142. package/ts/core/utils/socket-utils.ts +0 -322
  143. package/ts/core/utils/template-utils.ts +0 -124
  144. package/ts/core/utils/validation-utils.ts +0 -177
  145. package/ts/core/utils/websocket-utils.ts +0 -33
  146. package/ts/detection/detectors/http-detector.ts +0 -127
  147. package/ts/detection/detectors/quick-detector.ts +0 -148
  148. package/ts/detection/detectors/routing-extractor.ts +0 -147
  149. package/ts/detection/detectors/tls-detector.ts +0 -223
  150. package/ts/detection/index.ts +0 -25
  151. package/ts/detection/models/detection-types.ts +0 -102
  152. package/ts/detection/models/interfaces.ts +0 -115
  153. package/ts/detection/protocol-detector.ts +0 -319
  154. package/ts/detection/utils/buffer-utils.ts +0 -141
  155. package/ts/detection/utils/fragment-manager.ts +0 -64
  156. package/ts/detection/utils/parser-utils.ts +0 -77
  157. package/ts/protocols/common/fragment-handler.ts +0 -167
  158. package/ts/protocols/common/index.ts +0 -8
  159. package/ts/protocols/common/types.ts +0 -76
  160. package/ts/protocols/http/parser.ts +0 -219
  161. package/ts/protocols/proxy/index.ts +0 -6
  162. package/ts/protocols/proxy/types.ts +0 -53
  163. package/ts/protocols/tls/alerts/index.ts +0 -3
  164. package/ts/protocols/tls/alerts/tls-alert.ts +0 -259
  165. package/ts/protocols/tls/index.ts +0 -37
  166. package/ts/protocols/tls/sni/client-hello-parser.ts +0 -629
  167. package/ts/protocols/tls/sni/index.ts +0 -6
  168. package/ts/protocols/tls/sni/sni-extraction.ts +0 -353
  169. package/ts/protocols/tls/utils/index.ts +0 -3
  170. package/ts/protocols/tls/utils/tls-utils.ts +0 -201
  171. package/ts/protocols/websocket/constants.ts +0 -60
  172. package/ts/protocols/websocket/index.ts +0 -8
  173. package/ts/protocols/websocket/types.ts +0 -53
  174. package/ts/protocols/websocket/utils.ts +0 -98
  175. package/ts/routing/router/http-router.ts +0 -266
  176. package/ts/routing/router/index.ts +0 -7
  177. package/ts/tls/index.ts +0 -29
  178. package/ts/tls/sni/index.ts +0 -3
  179. 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
- }