@fanboynz/network-scanner 2.0.66 → 3.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.
@@ -2,7 +2,8 @@
2
2
  // Handles comprehensive site data clearing via CDP and page-level fallbacks
3
3
  // Resolves SecurityError issues with localStorage/sessionStorage access
4
4
 
5
- const { formatLogMessage } = require('./colorize');
5
+ const { formatLogMessage, messageColors } = require('./colorize');
6
+ const CLEAR_SITEDATA_TAG = messageColors.processing('[clear_sitedata]');
6
7
 
7
8
  /**
8
9
  * Clears site data using CDP (bypasses same-origin restrictions)
@@ -15,14 +16,23 @@ const { formatLogMessage } = require('./colorize');
15
16
  async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = false) {
16
17
  let clearDataSession = null;
17
18
  const completedOperations = [];
18
-
19
+
19
20
  try {
20
- clearDataSession = await Promise.race([
21
- page.target().createCDPSession(),
22
- new Promise((_, reject) =>
23
- setTimeout(() => reject(new Error('CDP session timeout')), 10000)
24
- )
25
- ]);
21
+ // Capture the timeout-timer ID so we can clear it once the race
22
+ // resolves. Previously the setTimeout fired 10s after the success
23
+ // path completed — reject was swallowed (race already settled)
24
+ // but the timer kept the event loop reference for up to 10s.
25
+ let timeoutTimer;
26
+ const sessionPromise = page.target().createCDPSession();
27
+ const timeoutPromise = new Promise((_, reject) => {
28
+ timeoutTimer = setTimeout(() => reject(new Error('CDP session timeout')), 10000);
29
+ if (typeof timeoutTimer.unref === 'function') timeoutTimer.unref();
30
+ });
31
+ try {
32
+ clearDataSession = await Promise.race([sessionPromise, timeoutPromise]);
33
+ } finally {
34
+ clearTimeout(timeoutTimer);
35
+ }
26
36
 
27
37
  const origin = new URL(currentUrl).origin;
28
38
 
@@ -38,7 +48,7 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
38
48
  completedOperations.push(op.name);
39
49
  } catch (opErr) {
40
50
  if (forceDebug) {
41
- console.log(formatLogMessage('debug', `[clear_sitedata] ${op.name} clear failed: ${opErr.message}`));
51
+ console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} ${op.name} clear failed: ${opErr.message}`));
42
52
  }
43
53
  }
44
54
  }
@@ -71,7 +81,7 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
71
81
  completedOperations.push(storage.name);
72
82
  } catch (individualErr) {
73
83
  if (forceDebug) {
74
- console.log(formatLogMessage('debug', `[clear_sitedata] ${storage.name} clear failed: ${individualErr.message}`));
84
+ console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} ${storage.name} clear failed: ${individualErr.message}`));
75
85
  }
76
86
  }
77
87
  }
@@ -79,14 +89,14 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
79
89
  }
80
90
 
81
91
  if (forceDebug && completedOperations.length > 0) {
82
- console.log(formatLogMessage('debug', `[clear_sitedata] CDP cleared: ${completedOperations.join(', ')}`));
92
+ console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} CDP cleared: ${completedOperations.join(', ')}`));
83
93
  }
84
94
 
85
95
  return { success: completedOperations.length > 0, operations: completedOperations };
86
96
 
87
97
  } catch (cdpErr) {
88
98
  if (forceDebug) {
89
- console.log(formatLogMessage('debug', `[clear_sitedata] CDP session failed: ${cdpErr.message}`));
99
+ console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} CDP session failed: ${cdpErr.message}`));
90
100
  }
91
101
  return { success: false, operations: completedOperations };
92
102
  } finally {
@@ -108,12 +118,21 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
108
118
  */
109
119
  async function clearSiteDataViaPage(page, forceDebug) {
110
120
  try {
111
- const result = await page.evaluate(() => {
121
+ // Page-side body is now async so we can `await` the IndexedDB
122
+ // cleanup chain. Previously it was sync and the indexedDB.databases()
123
+ // promise was fire-and-forget — cleared.push('indexedDB') ran before
124
+ // the deletion actually completed, so callers saw 'indexedDB' in the
125
+ // operations list even though the dbs were still pending deletion
126
+ // when page.evaluate returned.
127
+ const result = await page.evaluate(async () => {
112
128
  const cleared = [];
113
-
129
+
114
130
  // Test and clear localStorage
115
131
  try {
116
132
  if (window.localStorage && typeof window.localStorage.setItem === 'function') {
133
+ // setItem+removeItem is a permission probe — throws SecurityError
134
+ // on some origins before we get to clear(). Don't simplify to
135
+ // just clear() unless you want to swallow those errors silently.
117
136
  const testKey = '__nwss_access_test__';
118
137
  localStorage.setItem(testKey, 'test');
119
138
  localStorage.removeItem(testKey);
@@ -123,8 +142,8 @@ async function clearSiteDataViaPage(page, forceDebug) {
123
142
  } catch (e) {
124
143
  // Security error expected on some sites
125
144
  }
126
-
127
- // Test and clear sessionStorage
145
+
146
+ // Test and clear sessionStorage
128
147
  try {
129
148
  if (window.sessionStorage && typeof window.sessionStorage.setItem === 'function') {
130
149
  const testKey = '__nwss_access_test__';
@@ -136,38 +155,40 @@ async function clearSiteDataViaPage(page, forceDebug) {
136
155
  } catch (e) {
137
156
  // Security error expected on some sites
138
157
  }
139
-
140
- // Clear IndexedDB
158
+
159
+ // Clear IndexedDB — actually wait for the deletion chain to
160
+ // complete before reporting. indexedDB.deleteDatabase returns an
161
+ // IDBRequest (not a Promise), so wrap each in a Promise that
162
+ // resolves on success/error/blocked, then Promise.all.
141
163
  try {
142
164
  if (window.indexedDB && typeof window.indexedDB.databases === 'function') {
143
- window.indexedDB.databases().then(dbs => {
144
- dbs.forEach(db => {
145
- try {
146
- window.indexedDB.deleteDatabase(db.name);
147
- } catch (dbErr) {
148
- // Individual DB deletion may fail
149
- }
150
- });
151
- }).catch(() => {
152
- // Database listing may fail
153
- });
165
+ const dbs = await window.indexedDB.databases();
166
+ await Promise.all(dbs.map(db => new Promise((resolve) => {
167
+ if (!db.name) return resolve();
168
+ let req;
169
+ try { req = window.indexedDB.deleteDatabase(db.name); }
170
+ catch (_) { return resolve(); }
171
+ req.onsuccess = () => resolve();
172
+ req.onerror = () => resolve(); // best-effort — don't fail the batch
173
+ req.onblocked = () => resolve(); // another tab has it open; can't wait forever
174
+ })));
154
175
  cleared.push('indexedDB');
155
176
  }
156
177
  } catch (e) {
157
- // IndexedDB may not be available
178
+ // IndexedDB may not be available, or databases() may reject
158
179
  }
159
-
180
+
160
181
  return cleared;
161
182
  });
162
183
 
163
184
  if (forceDebug && result.length > 0) {
164
- console.log(formatLogMessage('debug', `[clear_sitedata] Page-level cleared: ${result.join(', ')}`));
185
+ console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} Page-level cleared: ${result.join(', ')}`));
165
186
  }
166
187
 
167
188
  return { success: result.length > 0, operations: result };
168
189
  } catch (pageErr) {
169
190
  if (forceDebug) {
170
- console.log(formatLogMessage('debug', `[clear_sitedata] Page evaluation failed: ${pageErr.message}`));
191
+ console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} Page evaluation failed: ${pageErr.message}`));
171
192
  }
172
193
  return { success: false, operations: [] };
173
194
  }
@@ -216,132 +237,13 @@ async function clearSiteData(page, currentUrl, forceDebug, quickMode = false) {
216
237
  };
217
238
  }
218
239
 
219
- /**
220
- * Enhanced site data clearing with additional browser-level operations
221
- * Includes cache warming prevention and comprehensive storage cleanup
222
- * @param {Page} page - Puppeteer page instance
223
- * @param {string} currentUrl - URL being processed
224
- * @param {boolean} forceDebug - Debug logging flag
225
- * @returns {Promise<{success: boolean, operations: string[], method: string}>}
226
- */
227
- async function clearSiteDataEnhanced(page, currentUrl, forceDebug) {
228
- let clearDataSession = null;
229
- const completedOperations = [];
230
-
231
- try {
232
- clearDataSession = await Promise.race([
233
- page.target().createCDPSession(),
234
- new Promise((_, reject) =>
235
- setTimeout(() => reject(new Error('Enhanced CDP session timeout')), 15000)
236
- )
237
- ]);
238
-
239
- const origin = new URL(currentUrl).origin;
240
-
241
- // Enhanced clearing operations
242
- const enhancedOperations = [
243
- // Network layer
244
- { cmd: 'Network.clearBrowserCookies', name: 'cookies' },
245
- { cmd: 'Network.clearBrowserCache', name: 'cache' },
246
-
247
- // Storage layer - comprehensive
248
- {
249
- cmd: 'Storage.clearDataForOrigin',
250
- params: { origin, storageTypes: 'all' },
251
- name: 'all_storage'
252
- },
253
-
254
- // Runtime layer
255
- { cmd: 'Runtime.discardConsoleEntries', name: 'console' },
256
-
257
- // Security layer
258
- { cmd: 'Security.disable', name: 'security_reset' }
259
- ];
260
-
261
- for (const op of enhancedOperations) {
262
- try {
263
- if (op.params) {
264
- await clearDataSession.send(op.cmd, op.params);
265
- } else {
266
- await clearDataSession.send(op.cmd);
267
- }
268
- completedOperations.push(op.name);
269
- } catch (opErr) {
270
- if (forceDebug) {
271
- console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] ${op.name} failed: ${opErr.message}`));
272
- }
273
-
274
- // For storage operations, try individual fallbacks
275
- if (op.name === 'all_storage') {
276
- const individualTypes = ['local_storage', 'session_storage', 'indexeddb', 'websql', 'service_workers'];
277
- for (const type of individualTypes) {
278
- try {
279
- await clearDataSession.send('Storage.clearDataForOrigin', {
280
- origin,
281
- storageTypes: type
282
- });
283
- completedOperations.push(type);
284
- } catch (individualErr) {
285
- // Continue trying other types
286
- }
287
- }
288
- }
289
- }
290
- }
291
-
292
- // Additional DOM cleanup via page evaluation
293
- try {
294
- await page.evaluate(() => {
295
- // Clear any cached DOM queries
296
- if (window.document && document.querySelectorAll) {
297
- // Force garbage collection of cached selectors
298
- const div = document.createElement('div');
299
- document.body.appendChild(div);
300
- document.body.removeChild(div);
301
- }
302
-
303
- // Clear performance entries
304
- if (window.performance && performance.clearMarks) {
305
- performance.clearMarks();
306
- performance.clearMeasures();
307
- }
308
- });
309
- completedOperations.push('dom_cleanup');
310
- } catch (domErr) {
311
- if (forceDebug) {
312
- console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] DOM cleanup failed: ${domErr.message}`));
313
- }
314
- }
315
-
316
- if (forceDebug && completedOperations.length > 0) {
317
- console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] Cleared: ${completedOperations.join(', ')}`));
318
- }
319
-
320
- return {
321
- success: completedOperations.length > 0,
322
- operations: completedOperations,
323
- method: 'enhanced_CDP'
324
- };
325
-
326
- } catch (enhancedErr) {
327
- if (forceDebug) {
328
- console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] Failed: ${enhancedErr.message}`));
329
- }
330
-
331
- // Fallback to regular clearing
332
- return await clearSiteData(page, currentUrl, forceDebug, false);
333
-
334
- } finally {
335
- if (clearDataSession) {
336
- try {
337
- await clearDataSession.detach();
338
- } catch (detachErr) {
339
- // Ignore detach errors
340
- }
341
- }
342
- }
343
- }
344
-
240
+ // Public surface. clearSiteDataViaCDP / clearSiteDataViaPage are
241
+ // internal helpers but exported for testing / advanced callers.
242
+ // (Previously also defined a clearSiteDataEnhanced function that wasn't
243
+ // even exported and had zero callers anywhere — 117 lines of dead code
244
+ // removed, including a mislabeled "Security.disable" CDP call dressed
245
+ // up as "security_reset" that just disabled the CDP Security domain
246
+ // with no actual security effect.)
345
247
  module.exports = {
346
248
  clearSiteData,
347
249
  clearSiteDataViaCDP,