@detiq/crawler 1.1.9 → 1.1.11

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 (83) hide show
  1. package/dist/accessibility-auditor.js +54 -74
  2. package/dist/ai-login.js +227 -249
  3. package/dist/auth-token-rotator.js +57 -67
  4. package/dist/auth.js +299 -336
  5. package/dist/browser-extension.js +104 -142
  6. package/dist/captcha-solver.js +98 -125
  7. package/dist/color-contrast.js +77 -89
  8. package/dist/content-chunker.js +126 -126
  9. package/dist/content-dedup.js +54 -71
  10. package/dist/cookie-consent.js +68 -83
  11. package/dist/cookie-jar.js +53 -60
  12. package/dist/crawler.js +4494 -5353
  13. package/dist/custom-js-injector.js +45 -61
  14. package/dist/dark-mode-capture.js +67 -81
  15. package/dist/dead-link-detector.js +47 -55
  16. package/dist/element-hash.js +8 -12
  17. package/dist/email-otp.js +154 -195
  18. package/dist/engine-router.js +87 -98
  19. package/dist/export/bulk-export.js +70 -55
  20. package/dist/export/vector-export.js +77 -105
  21. package/dist/extractors/advanced.js +249 -266
  22. package/dist/extractors/artifact-envelope.js +59 -58
  23. package/dist/failure-analysis-agent.js +37 -33
  24. package/dist/feature-flag-detector.js +51 -66
  25. package/dist/form-detector.js +55 -75
  26. package/dist/frontier.js +76 -101
  27. package/dist/gap-pass.js +68 -89
  28. package/dist/graphql-detector.js +62 -72
  29. package/dist/http-engine.js +282 -330
  30. package/dist/incremental-diff.js +54 -87
  31. package/dist/index.js +67 -28
  32. package/dist/input-fuzzer.js +93 -97
  33. package/dist/interactive-probe.js +715 -827
  34. package/dist/job-queue.js +2151 -2169
  35. package/dist/js-coverage.js +52 -56
  36. package/dist/js-router-detector.js +86 -117
  37. package/dist/language-detector.js +51 -63
  38. package/dist/link-classifier.js +32 -50
  39. package/dist/live-view.js +91 -108
  40. package/dist/locator-extractor.js +151 -187
  41. package/dist/logger.js +9 -7
  42. package/dist/markdown-extract.js +48 -61
  43. package/dist/native-crawler.js +780 -946
  44. package/dist/network-observer.js +135 -156
  45. package/dist/network-throttle.js +29 -40
  46. package/dist/openapi-generator.js +77 -92
  47. package/dist/pdf-extractor.js +72 -90
  48. package/dist/performance-metrics.js +80 -102
  49. package/dist/phash.js +125 -144
  50. package/dist/pii-scrubber.js +65 -68
  51. package/dist/playwright-recorder.js +70 -58
  52. package/dist/policies/crawl-safety.js +31 -34
  53. package/dist/profiles/domain-profile.js +130 -125
  54. package/dist/proxy.js +146 -172
  55. package/dist/rate-limiter.js +58 -65
  56. package/dist/redirect-tracker.js +60 -64
  57. package/dist/redis-frontier.js +116 -136
  58. package/dist/redis-queue.js +157 -144
  59. package/dist/response-cache.js +127 -140
  60. package/dist/responsive-detector.js +42 -46
  61. package/dist/retry-policy.js +46 -50
  62. package/dist/robots-txt.js +69 -83
  63. package/dist/screen-reader.js +45 -70
  64. package/dist/screenshot-masker.js +59 -77
  65. package/dist/seo-checker.js +88 -107
  66. package/dist/session-capture.js +192 -212
  67. package/dist/session-export.js +107 -133
  68. package/dist/sitemap-writer.js +38 -41
  69. package/dist/sitemap.js +141 -202
  70. package/dist/skyvern.js +123 -148
  71. package/dist/sqs-queue.js +42 -42
  72. package/dist/sso-token.js +74 -90
  73. package/dist/stealth/human-behavior.js +156 -173
  74. package/dist/telemetry.js +68 -82
  75. package/dist/test-executor.js +309 -335
  76. package/dist/tls-fingerprint.js +77 -88
  77. package/dist/url-pattern-completer.js +71 -90
  78. package/dist/visual-diff-verdict.js +23 -38
  79. package/dist/webhook-notifier.js +71 -69
  80. package/dist/websocket-detector.js +56 -68
  81. package/dist/worker.js +29 -38
  82. package/package.json +1 -1
  83. package/src/job-queue.ts +136 -0
@@ -1,93 +1,78 @@
1
- /**
2
- * Cookie consent auto-acceptor.
3
- *
4
- * Detects and clicks "Accept" on common cookie consent banners before the
5
- * crawler proceeds. Without this, many EU sites show a consent wall that
6
- * blocks content or shows a different layout, making crawl results unreliable.
7
- *
8
- * Supports: Cookiebot, OneTrust, TrustArc, Usercentrics, GDPR Cookie Compliance,
9
- * generic "Accept All" / "Accept Cookies" buttons.
10
- *
11
- * Strategy: try known selectors first, then fall back to text-based button search.
12
- * Non-blocking — if no banner is found or click fails, crawl proceeds normally.
13
- */
14
- // Known consent platform selectors
15
1
  const CONSENT_SELECTORS = [
16
- // Cookiebot
17
- '#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll',
18
- '#CybotCookiebotDialogBodyButtonAccept',
19
- // OneTrust
20
- '#onetrust-accept-btn-handler',
21
- '.ot-sdk-accept-btn',
22
- // TrustArc
23
- '.truste_popframe [title*="Accept"]',
24
- '#truste-consent-button',
25
- // Usercentrics
26
- '[data-testid="uc-accept-all-button"]',
27
- // Generic high-confidence
28
- '[id*="accept"][id*="cookie"]',
29
- '[class*="accept"][class*="cookie"]',
30
- '[class*="cookie"][class*="accept"]',
31
- // GDPR Cookie Compliance
32
- '.gdpr-cookie-notice-accept',
33
- // Quantcast
34
- '.qc-cmp2-summary-buttons button:first-child',
2
+ // Cookiebot
3
+ "#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll",
4
+ "#CybotCookiebotDialogBodyButtonAccept",
5
+ // OneTrust
6
+ "#onetrust-accept-btn-handler",
7
+ ".ot-sdk-accept-btn",
8
+ // TrustArc
9
+ '.truste_popframe [title*="Accept"]',
10
+ "#truste-consent-button",
11
+ // Usercentrics
12
+ '[data-testid="uc-accept-all-button"]',
13
+ // Generic high-confidence
14
+ '[id*="accept"][id*="cookie"]',
15
+ '[class*="accept"][class*="cookie"]',
16
+ '[class*="cookie"][class*="accept"]',
17
+ // GDPR Cookie Compliance
18
+ ".gdpr-cookie-notice-accept",
19
+ // Quantcast
20
+ ".qc-cmp2-summary-buttons button:first-child"
35
21
  ];
36
- // Fallback: button text matching
37
22
  const ACCEPT_TEXT_PATTERNS = [
38
- /^accept all$/i,
39
- /^accept all cookies$/i,
40
- /^allow all$/i,
41
- /^i accept$/i,
42
- /^agree$/i,
43
- /^ok$/i,
44
- /^got it$/i,
45
- /^allow cookies$/i,
23
+ /^accept all$/i,
24
+ /^accept all cookies$/i,
25
+ /^allow all$/i,
26
+ /^i accept$/i,
27
+ /^agree$/i,
28
+ /^ok$/i,
29
+ /^got it$/i,
30
+ /^allow cookies$/i
46
31
  ];
47
- export async function acceptCookieConsent(page, opts = {}) {
48
- const { waitMs = 1_500 } = opts;
49
- // Wait briefly for consent banners to appear
50
- await page.waitForTimeout(waitMs).catch(() => { });
51
- // Try known selectors first
52
- for (const selector of CONSENT_SELECTORS) {
53
- try {
54
- const el = await page.$(selector);
55
- if (el && await el.isVisible()) {
56
- await el.click({ timeout: 2_000 });
57
- await page.waitForTimeout(500);
58
- return { found: true, clicked: true, method: `selector: ${selector}` };
59
- }
60
- }
61
- catch { /* try next */ }
62
- }
63
- // Fallback: find buttons with accept-like text
32
+ async function acceptCookieConsent(page, opts = {}) {
33
+ const { waitMs = 1500 } = opts;
34
+ await page.waitForTimeout(waitMs).catch(() => {
35
+ });
36
+ for (const selector of CONSENT_SELECTORS) {
64
37
  try {
65
- const buttons = await page.$$('button, [role="button"], a[class*="cookie"]');
66
- for (const btn of buttons) {
67
- const text = ((await btn.textContent()) ?? '').trim();
68
- if (ACCEPT_TEXT_PATTERNS.some(re => re.test(text))) {
69
- if (await btn.isVisible()) {
70
- await btn.click({ timeout: 2_000 });
71
- await page.waitForTimeout(500);
72
- return { found: true, clicked: true, method: `text: "${text}"` };
73
- }
74
- }
75
- }
38
+ const el = await page.$(selector);
39
+ if (el && await el.isVisible()) {
40
+ await el.click({ timeout: 2e3 });
41
+ await page.waitForTimeout(500);
42
+ return { found: true, clicked: true, method: `selector: ${selector}` };
43
+ }
44
+ } catch {
76
45
  }
77
- catch { /* non-fatal */ }
78
- return { found: false, clicked: false };
79
- }
80
- /** Check if a consent banner is still visible after attempted dismissal */
81
- export async function isConsentBannerVisible(page) {
82
- try {
83
- for (const sel of CONSENT_SELECTORS.slice(0, 5)) {
84
- const el = await page.$(sel);
85
- if (el && await el.isVisible())
86
- return true;
46
+ }
47
+ try {
48
+ const buttons = await page.$$('button, [role="button"], a[class*="cookie"]');
49
+ for (const btn of buttons) {
50
+ const text = (await btn.textContent() ?? "").trim();
51
+ if (ACCEPT_TEXT_PATTERNS.some((re) => re.test(text))) {
52
+ if (await btn.isVisible()) {
53
+ await btn.click({ timeout: 2e3 });
54
+ await page.waitForTimeout(500);
55
+ return { found: true, clicked: true, method: `text: "${text}"` };
87
56
  }
88
- return false;
57
+ }
89
58
  }
90
- catch {
91
- return false;
59
+ } catch {
60
+ }
61
+ return { found: false, clicked: false };
62
+ }
63
+ async function isConsentBannerVisible(page) {
64
+ try {
65
+ for (const sel of CONSENT_SELECTORS.slice(0, 5)) {
66
+ const el = await page.$(sel);
67
+ if (el && await el.isVisible()) return true;
92
68
  }
69
+ return false;
70
+ } catch {
71
+ return false;
72
+ }
93
73
  }
74
+ export {
75
+ acceptCookieConsent,
76
+ isConsentBannerVisible
77
+ };
78
+ //# sourceMappingURL=cookie-consent.js.map
@@ -1,68 +1,61 @@
1
- /**
2
- * Cookie jar — persist and restore Playwright storageState cookies between
3
- * crawl segments and restarts. Enables continuous auth across session boundaries
4
- * (e.g. segment 1 logs in, segment 2–N inherit the session without re-login).
5
- *
6
- * Storage: JSON file per project in the crawl cache dir.
7
- * Format: Playwright's storageState shape (cookies + origins).
8
- */
9
- import * as fs from 'fs/promises';
10
- import * as path from 'path';
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
11
3
  function jarPath(cacheDir, projectId) {
12
- return path.join(cacheDir, `cookie-jar-${projectId}.json`);
4
+ return path.join(cacheDir, `cookie-jar-${projectId}.json`);
13
5
  }
14
- export async function saveCookieJar(cacheDir, projectId, tenantId, storageState, domain) {
15
- await fs.mkdir(cacheDir, { recursive: true });
16
- const entry = {
17
- projectId,
18
- tenantId,
19
- storageState,
20
- savedAt: new Date().toISOString(),
21
- domain,
22
- };
23
- await fs.writeFile(jarPath(cacheDir, projectId), JSON.stringify(entry, null, 2), 'utf8');
6
+ async function saveCookieJar(cacheDir, projectId, tenantId, storageState, domain) {
7
+ await fs.mkdir(cacheDir, { recursive: true });
8
+ const entry = {
9
+ projectId,
10
+ tenantId,
11
+ storageState,
12
+ savedAt: (/* @__PURE__ */ new Date()).toISOString(),
13
+ domain
14
+ };
15
+ await fs.writeFile(jarPath(cacheDir, projectId), JSON.stringify(entry, null, 2), "utf8");
24
16
  }
25
- export async function loadCookieJar(cacheDir, projectId, maxAgeMs = 8 * 60 * 60 * 1000) {
26
- try {
27
- const raw = await fs.readFile(jarPath(cacheDir, projectId), 'utf8');
28
- const entry = JSON.parse(raw);
29
- const age = Date.now() - new Date(entry.savedAt).getTime();
30
- if (age > maxAgeMs)
31
- return null; // expired
32
- return entry.storageState;
33
- }
34
- catch {
35
- return null;
36
- }
17
+ async function loadCookieJar(cacheDir, projectId, maxAgeMs = 8 * 60 * 60 * 1e3) {
18
+ try {
19
+ const raw = await fs.readFile(jarPath(cacheDir, projectId), "utf8");
20
+ const entry = JSON.parse(raw);
21
+ const age = Date.now() - new Date(entry.savedAt).getTime();
22
+ if (age > maxAgeMs) return null;
23
+ return entry.storageState;
24
+ } catch {
25
+ return null;
26
+ }
37
27
  }
38
- export async function clearCookieJar(cacheDir, projectId) {
39
- try {
40
- await fs.unlink(jarPath(cacheDir, projectId));
41
- }
42
- catch { /* already gone */ }
28
+ async function clearCookieJar(cacheDir, projectId) {
29
+ try {
30
+ await fs.unlink(jarPath(cacheDir, projectId));
31
+ } catch {
32
+ }
43
33
  }
44
- /** Merge two storageState JSON strings — second takes priority for same-domain cookies. */
45
- export function mergeStorageStates(base, overlay) {
46
- try {
47
- const a = JSON.parse(base);
48
- const b = JSON.parse(overlay);
49
- // Cookies: overlay replaces same-name+domain+path cookies from base
50
- const cookies = [...(a.cookies ?? [])];
51
- for (const ck of (b.cookies ?? [])) {
52
- const idx = cookies.findIndex((c) => c.name === ck.name && c.domain === ck.domain && c.path === ck.path);
53
- if (idx >= 0)
54
- cookies[idx] = ck;
55
- else
56
- cookies.push(ck);
57
- }
58
- // Origins: merge origins, overlay wins on same-origin
59
- const originsMap = new Map();
60
- for (const o of [...(a.origins ?? []), ...(b.origins ?? [])]) {
61
- originsMap.set(o.origin, o);
62
- }
63
- return JSON.stringify({ cookies, origins: [...originsMap.values()] });
34
+ function mergeStorageStates(base, overlay) {
35
+ try {
36
+ const a = JSON.parse(base);
37
+ const b = JSON.parse(overlay);
38
+ const cookies = [...a.cookies ?? []];
39
+ for (const ck of b.cookies ?? []) {
40
+ const idx = cookies.findIndex(
41
+ (c) => c.name === ck.name && c.domain === ck.domain && c.path === ck.path
42
+ );
43
+ if (idx >= 0) cookies[idx] = ck;
44
+ else cookies.push(ck);
64
45
  }
65
- catch {
66
- return overlay || base;
46
+ const originsMap = /* @__PURE__ */ new Map();
47
+ for (const o of [...a.origins ?? [], ...b.origins ?? []]) {
48
+ originsMap.set(o.origin, o);
67
49
  }
50
+ return JSON.stringify({ cookies, origins: [...originsMap.values()] });
51
+ } catch {
52
+ return overlay || base;
53
+ }
68
54
  }
55
+ export {
56
+ clearCookieJar,
57
+ loadCookieJar,
58
+ mergeStorageStates,
59
+ saveCookieJar
60
+ };
61
+ //# sourceMappingURL=cookie-jar.js.map