@detiq/crawler 1.1.9 → 1.1.10
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.
- package/dist/accessibility-auditor.js +54 -74
- package/dist/ai-login.js +227 -249
- package/dist/auth-token-rotator.js +57 -67
- package/dist/auth.js +299 -336
- package/dist/browser-extension.js +104 -142
- package/dist/captcha-solver.js +98 -125
- package/dist/color-contrast.js +77 -89
- package/dist/content-chunker.js +126 -126
- package/dist/content-dedup.js +54 -71
- package/dist/cookie-consent.js +68 -83
- package/dist/cookie-jar.js +53 -60
- package/dist/crawler.js +4494 -5353
- package/dist/custom-js-injector.js +45 -61
- package/dist/dark-mode-capture.js +67 -81
- package/dist/dead-link-detector.js +47 -55
- package/dist/element-hash.js +8 -12
- package/dist/email-otp.js +154 -195
- package/dist/engine-router.js +87 -98
- package/dist/export/bulk-export.js +70 -55
- package/dist/export/vector-export.js +77 -105
- package/dist/extractors/advanced.js +249 -266
- package/dist/extractors/artifact-envelope.js +59 -58
- package/dist/failure-analysis-agent.js +37 -33
- package/dist/feature-flag-detector.js +51 -66
- package/dist/form-detector.js +55 -75
- package/dist/frontier.js +76 -101
- package/dist/gap-pass.js +68 -89
- package/dist/graphql-detector.js +62 -72
- package/dist/http-engine.js +282 -330
- package/dist/incremental-diff.js +54 -87
- package/dist/index.js +67 -28
- package/dist/input-fuzzer.js +93 -97
- package/dist/interactive-probe.js +715 -827
- package/dist/job-queue.js +2151 -2169
- package/dist/js-coverage.js +52 -56
- package/dist/js-router-detector.js +86 -117
- package/dist/language-detector.js +51 -63
- package/dist/link-classifier.js +32 -50
- package/dist/live-view.js +91 -108
- package/dist/locator-extractor.js +151 -187
- package/dist/logger.js +9 -7
- package/dist/markdown-extract.js +48 -61
- package/dist/native-crawler.js +780 -946
- package/dist/network-observer.js +135 -156
- package/dist/network-throttle.js +29 -40
- package/dist/openapi-generator.js +77 -92
- package/dist/pdf-extractor.js +72 -90
- package/dist/performance-metrics.js +80 -102
- package/dist/phash.js +125 -144
- package/dist/pii-scrubber.js +65 -68
- package/dist/playwright-recorder.js +70 -58
- package/dist/policies/crawl-safety.js +31 -34
- package/dist/profiles/domain-profile.js +130 -125
- package/dist/proxy.js +146 -172
- package/dist/rate-limiter.js +58 -65
- package/dist/redirect-tracker.js +60 -64
- package/dist/redis-frontier.js +116 -136
- package/dist/redis-queue.js +157 -144
- package/dist/response-cache.js +127 -140
- package/dist/responsive-detector.js +42 -46
- package/dist/retry-policy.js +46 -50
- package/dist/robots-txt.js +69 -83
- package/dist/screen-reader.js +45 -70
- package/dist/screenshot-masker.js +59 -77
- package/dist/seo-checker.js +88 -107
- package/dist/session-capture.js +192 -212
- package/dist/session-export.js +107 -133
- package/dist/sitemap-writer.js +38 -41
- package/dist/sitemap.js +141 -202
- package/dist/skyvern.js +123 -148
- package/dist/sqs-queue.js +42 -42
- package/dist/sso-token.js +74 -90
- package/dist/stealth/human-behavior.js +156 -173
- package/dist/telemetry.js +68 -82
- package/dist/test-executor.js +309 -335
- package/dist/tls-fingerprint.js +77 -88
- package/dist/url-pattern-completer.js +71 -90
- package/dist/visual-diff-verdict.js +23 -38
- package/dist/webhook-notifier.js +71 -69
- package/dist/websocket-detector.js +56 -68
- package/dist/worker.js +29 -38
- package/package.json +1 -1
|
@@ -1,72 +1,60 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WebSocket detection — intercepts WS connections opened during page crawl.
|
|
3
|
-
* Records connection URLs, message schemas, and message counts.
|
|
4
|
-
* This lets ZeTa discover real-time API contracts (chat, notifications, presence)
|
|
5
|
-
* that would be invisible to HTTP-only crawlers.
|
|
6
|
-
*/
|
|
7
1
|
function inferProtocol(sample) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return 'raw';
|
|
20
|
-
}
|
|
2
|
+
try {
|
|
3
|
+
const obj = JSON.parse(sample);
|
|
4
|
+
if (obj?.jsonrpc) return "json-rpc";
|
|
5
|
+
if (obj?.type === "connection_init" || obj?.type === "subscribe") return "graphql-ws";
|
|
6
|
+
if (typeof obj?.sid === "string" || sample.startsWith("0{")) return "socket.io";
|
|
7
|
+
return "json";
|
|
8
|
+
} catch {
|
|
9
|
+
return "raw";
|
|
10
|
+
}
|
|
21
11
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
cdpSession.
|
|
12
|
+
function attachWebSocketDetector(cdpSession) {
|
|
13
|
+
const connections = /* @__PURE__ */ new Map();
|
|
14
|
+
const onCreated = (evt) => {
|
|
15
|
+
const { requestId, url, timestamp } = evt ?? {};
|
|
16
|
+
if (!requestId || !url) return;
|
|
17
|
+
connections.set(requestId, {
|
|
18
|
+
url,
|
|
19
|
+
framesSent: 0,
|
|
20
|
+
framesReceived: 0,
|
|
21
|
+
samples: [],
|
|
22
|
+
protocol: "unknown",
|
|
23
|
+
openedAt: new Date(timestamp * 1e3).toISOString()
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const onFrame = (evt, direction) => {
|
|
27
|
+
const { requestId, response } = evt ?? {};
|
|
28
|
+
if (!requestId) return;
|
|
29
|
+
const conn = connections.get(requestId);
|
|
30
|
+
if (!conn) return;
|
|
31
|
+
if (direction === "sent") conn.framesSent++;
|
|
32
|
+
else conn.framesReceived++;
|
|
33
|
+
if (conn.samples.length < 10 && response?.payloadData) {
|
|
34
|
+
const payload = String(response.payloadData).slice(0, 500);
|
|
35
|
+
conn.samples.push({ direction, payload, ts: (/* @__PURE__ */ new Date()).toISOString() });
|
|
36
|
+
if (conn.protocol === "unknown") conn.protocol = inferProtocol(payload);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const onSent = (evt) => onFrame(evt, "sent");
|
|
40
|
+
const onReceived = (evt) => onFrame(evt, "received");
|
|
41
|
+
if (cdpSession?.on) {
|
|
42
|
+
cdpSession.on("Network.webSocketCreated", onCreated);
|
|
43
|
+
cdpSession.on("Network.webSocketFrameSent", onSent);
|
|
44
|
+
cdpSession.on("Network.webSocketFrameReceived", onReceived);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
getConnections: () => [...connections.values()],
|
|
48
|
+
detach() {
|
|
49
|
+
if (cdpSession?.off) {
|
|
50
|
+
cdpSession.off("Network.webSocketCreated", onCreated);
|
|
51
|
+
cdpSession.off("Network.webSocketFrameSent", onSent);
|
|
52
|
+
cdpSession.off("Network.webSocketFrameReceived", onReceived);
|
|
53
|
+
}
|
|
61
54
|
}
|
|
62
|
-
|
|
63
|
-
getConnections: () => [...connections.values()],
|
|
64
|
-
detach() {
|
|
65
|
-
if (cdpSession?.off) {
|
|
66
|
-
cdpSession.off('Network.webSocketCreated', onCreated);
|
|
67
|
-
cdpSession.off('Network.webSocketFrameSent', onSent);
|
|
68
|
-
cdpSession.off('Network.webSocketFrameReceived', onReceived);
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
};
|
|
55
|
+
};
|
|
72
56
|
}
|
|
57
|
+
export {
|
|
58
|
+
attachWebSocketDetector
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=websocket-detector.js.map
|
package/dist/worker.js
CHANGED
|
@@ -1,42 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* separate from the API server (see infrastructure/ecs-task-definitions/crawler.json).
|
|
4
|
-
*
|
|
5
|
-
* index.ts is a side-effect-free library barrel imported by @detiq/api — it must NOT
|
|
6
|
-
* start any background loop itself, or importing a single helper from @detiq/crawler
|
|
7
|
-
* would silently spin up a second worker inside the API process too. This file is
|
|
8
|
-
* the actual entrypoint that keeps a dedicated worker container's process alive and
|
|
9
|
-
* consuming jobs: `node dist/worker.js`.
|
|
10
|
-
*/
|
|
11
|
-
import { startJobWorkerLoop, processDataRetentionPurge } from './job-queue.js';
|
|
12
|
-
import { logger } from './logger.js';
|
|
1
|
+
import { startJobWorkerLoop, processDataRetentionPurge } from "./job-queue.js";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
13
3
|
async function main() {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const { startSqsWorker } = await import('./sqs-queue.js');
|
|
31
|
-
startSqsWorker().catch((err) => {
|
|
32
|
-
logger.error({ err: String(err) }, '[worker] SQS worker crashed');
|
|
33
|
-
process.exit(1);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
4
|
+
logger.info("[worker] starting standalone crawler worker process");
|
|
5
|
+
startJobWorkerLoop();
|
|
6
|
+
const runPurge = () => {
|
|
7
|
+
processDataRetentionPurge().catch((err) => {
|
|
8
|
+
logger.error({ err: String(err) }, "[worker] data-retention purge failed");
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
runPurge();
|
|
12
|
+
setInterval(runPurge, 24 * 60 * 60 * 1e3);
|
|
13
|
+
if (process.env.JOB_QUEUE_BACKEND === "sqs") {
|
|
14
|
+
const { startSqsWorker } = await import("./sqs-queue.js");
|
|
15
|
+
startSqsWorker().catch((err) => {
|
|
16
|
+
logger.error({ err: String(err) }, "[worker] SQS worker crashed");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
36
20
|
}
|
|
37
|
-
process.on(
|
|
38
|
-
|
|
21
|
+
process.on("SIGTERM", () => {
|
|
22
|
+
logger.info("[worker] SIGTERM received, exiting");
|
|
23
|
+
process.exit(0);
|
|
24
|
+
});
|
|
25
|
+
process.on("SIGINT", () => {
|
|
26
|
+
logger.info("[worker] SIGINT received, exiting");
|
|
27
|
+
process.exit(0);
|
|
28
|
+
});
|
|
39
29
|
main().catch((err) => {
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
logger.error({ err: String(err) }, "[worker] fatal startup error");
|
|
31
|
+
process.exit(1);
|
|
42
32
|
});
|
|
33
|
+
//# sourceMappingURL=worker.js.map
|