perfgraph 0.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.
- package/LICENSE +21 -0
- package/README.md +280 -0
- package/dist/causal/builder.d.ts +34 -0
- package/dist/causal/builder.d.ts.map +1 -0
- package/dist/causal/builder.js +132 -0
- package/dist/causal/builder.js.map +1 -0
- package/dist/causal/index.d.ts +11 -0
- package/dist/causal/index.d.ts.map +1 -0
- package/dist/causal/index.js +10 -0
- package/dist/causal/index.js.map +1 -0
- package/dist/causal/rules/js.d.ts +49 -0
- package/dist/causal/rules/js.d.ts.map +1 -0
- package/dist/causal/rules/js.js +209 -0
- package/dist/causal/rules/js.js.map +1 -0
- package/dist/causal/rules/layout.d.ts +39 -0
- package/dist/causal/rules/layout.d.ts.map +1 -0
- package/dist/causal/rules/layout.js +169 -0
- package/dist/causal/rules/layout.js.map +1 -0
- package/dist/causal/rules/lcp.d.ts +49 -0
- package/dist/causal/rules/lcp.d.ts.map +1 -0
- package/dist/causal/rules/lcp.js +250 -0
- package/dist/causal/rules/lcp.js.map +1 -0
- package/dist/causal/rules/network.d.ts +39 -0
- package/dist/causal/rules/network.d.ts.map +1 -0
- package/dist/causal/rules/network.js +140 -0
- package/dist/causal/rules/network.js.map +1 -0
- package/dist/causal/types.d.ts +142 -0
- package/dist/causal/types.d.ts.map +1 -0
- package/dist/causal/types.js +88 -0
- package/dist/causal/types.js.map +1 -0
- package/dist/cli/analyze.d.ts +33 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +137 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/collect.d.ts +28 -0
- package/dist/cli/collect.d.ts.map +1 -0
- package/dist/cli/collect.js +125 -0
- package/dist/cli/collect.js.map +1 -0
- package/dist/cli/extract.d.ts +31 -0
- package/dist/cli/extract.d.ts.map +1 -0
- package/dist/cli/extract.js +135 -0
- package/dist/cli/extract.js.map +1 -0
- package/dist/cli/mcp.d.ts +14 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +53 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/normalize.d.ts +58 -0
- package/dist/cli/normalize.d.ts.map +1 -0
- package/dist/cli/normalize.js +179 -0
- package/dist/cli/normalize.js.map +1 -0
- package/dist/cli/report.d.ts +33 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +137 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/run.d.ts +49 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +243 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/collect/buffer-monitor.d.ts +25 -0
- package/dist/collect/buffer-monitor.d.ts.map +1 -0
- package/dist/collect/buffer-monitor.js +69 -0
- package/dist/collect/buffer-monitor.js.map +1 -0
- package/dist/collect/console.d.ts +25 -0
- package/dist/collect/console.d.ts.map +1 -0
- package/dist/collect/console.js +82 -0
- package/dist/collect/console.js.map +1 -0
- package/dist/collect/coverage.d.ts +26 -0
- package/dist/collect/coverage.d.ts.map +1 -0
- package/dist/collect/coverage.js +99 -0
- package/dist/collect/coverage.js.map +1 -0
- package/dist/collect/dom.d.ts +37 -0
- package/dist/collect/dom.d.ts.map +1 -0
- package/dist/collect/dom.js +118 -0
- package/dist/collect/dom.js.map +1 -0
- package/dist/collect/lighthouse.d.ts +41 -0
- package/dist/collect/lighthouse.d.ts.map +1 -0
- package/dist/collect/lighthouse.js +111 -0
- package/dist/collect/lighthouse.js.map +1 -0
- package/dist/collect/network.d.ts +32 -0
- package/dist/collect/network.d.ts.map +1 -0
- package/dist/collect/network.js +236 -0
- package/dist/collect/network.js.map +1 -0
- package/dist/collect/orchestrator.d.ts +23 -0
- package/dist/collect/orchestrator.d.ts.map +1 -0
- package/dist/collect/orchestrator.js +350 -0
- package/dist/collect/orchestrator.js.map +1 -0
- package/dist/collect/performance.d.ts +28 -0
- package/dist/collect/performance.d.ts.map +1 -0
- package/dist/collect/performance.js +108 -0
- package/dist/collect/performance.js.map +1 -0
- package/dist/collect/runtime.d.ts +26 -0
- package/dist/collect/runtime.d.ts.map +1 -0
- package/dist/collect/runtime.js +81 -0
- package/dist/collect/runtime.js.map +1 -0
- package/dist/collect/session.d.ts +58 -0
- package/dist/collect/session.d.ts.map +1 -0
- package/dist/collect/session.js +162 -0
- package/dist/collect/session.js.map +1 -0
- package/dist/collect/trace.d.ts +40 -0
- package/dist/collect/trace.d.ts.map +1 -0
- package/dist/collect/trace.js +127 -0
- package/dist/collect/trace.js.map +1 -0
- package/dist/collect/types.d.ts +317 -0
- package/dist/collect/types.d.ts.map +1 -0
- package/dist/collect/types.js +12 -0
- package/dist/collect/types.js.map +1 -0
- package/dist/distill/insights.d.ts +67 -0
- package/dist/distill/insights.d.ts.map +1 -0
- package/dist/distill/insights.js +317 -0
- package/dist/distill/insights.js.map +1 -0
- package/dist/distill/summaries.d.ts +71 -0
- package/dist/distill/summaries.d.ts.map +1 -0
- package/dist/distill/summaries.js +165 -0
- package/dist/distill/summaries.js.map +1 -0
- package/dist/extract/critical-path.d.ts +17 -0
- package/dist/extract/critical-path.d.ts.map +1 -0
- package/dist/extract/critical-path.js +95 -0
- package/dist/extract/critical-path.js.map +1 -0
- package/dist/extract/index.d.ts +16 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/index.js +32 -0
- package/dist/extract/index.js.map +1 -0
- package/dist/extract/js-hotspots.d.ts +15 -0
- package/dist/extract/js-hotspots.d.ts.map +1 -0
- package/dist/extract/js-hotspots.js +22 -0
- package/dist/extract/js-hotspots.js.map +1 -0
- package/dist/extract/layout-shifts.d.ts +19 -0
- package/dist/extract/layout-shifts.d.ts.map +1 -0
- package/dist/extract/layout-shifts.js +47 -0
- package/dist/extract/layout-shifts.js.map +1 -0
- package/dist/extract/lcp-breakdown.d.ts +19 -0
- package/dist/extract/lcp-breakdown.d.ts.map +1 -0
- package/dist/extract/lcp-breakdown.js +110 -0
- package/dist/extract/lcp-breakdown.js.map +1 -0
- package/dist/extract/main-thread.d.ts +16 -0
- package/dist/extract/main-thread.d.ts.map +1 -0
- package/dist/extract/main-thread.js +41 -0
- package/dist/extract/main-thread.js.map +1 -0
- package/dist/extract/render-blocking.d.ts +16 -0
- package/dist/extract/render-blocking.d.ts.map +1 -0
- package/dist/extract/render-blocking.js +79 -0
- package/dist/extract/render-blocking.js.map +1 -0
- package/dist/extract/third-party.d.ts +15 -0
- package/dist/extract/third-party.d.ts.map +1 -0
- package/dist/extract/third-party.js +127 -0
- package/dist/extract/third-party.js.map +1 -0
- package/dist/extract/types.d.ts +183 -0
- package/dist/extract/types.d.ts.map +1 -0
- package/dist/extract/types.js +118 -0
- package/dist/extract/types.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +188 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/handlers.d.ts +72 -0
- package/dist/mcp/handlers.d.ts.map +1 -0
- package/dist/mcp/handlers.js +285 -0
- package/dist/mcp/handlers.js.map +1 -0
- package/dist/mcp/progress.d.ts +37 -0
- package/dist/mcp/progress.d.ts.map +1 -0
- package/dist/mcp/progress.js +51 -0
- package/dist/mcp/progress.js.map +1 -0
- package/dist/mcp/prompts.d.ts +57 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +225 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +48 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +149 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +34 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +452 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/types.d.ts +47 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +67 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/normalize/clock.d.ts +40 -0
- package/dist/normalize/clock.d.ts.map +1 -0
- package/dist/normalize/clock.js +96 -0
- package/dist/normalize/clock.js.map +1 -0
- package/dist/normalize/dom-ir.d.ts +16 -0
- package/dist/normalize/dom-ir.d.ts.map +1 -0
- package/dist/normalize/dom-ir.js +48 -0
- package/dist/normalize/dom-ir.js.map +1 -0
- package/dist/normalize/index.d.ts +23 -0
- package/dist/normalize/index.d.ts.map +1 -0
- package/dist/normalize/index.js +118 -0
- package/dist/normalize/index.js.map +1 -0
- package/dist/normalize/lighthouse-insights.d.ts +27 -0
- package/dist/normalize/lighthouse-insights.d.ts.map +1 -0
- package/dist/normalize/lighthouse-insights.js +318 -0
- package/dist/normalize/lighthouse-insights.js.map +1 -0
- package/dist/normalize/lighthouse-ir.d.ts +25 -0
- package/dist/normalize/lighthouse-ir.d.ts.map +1 -0
- package/dist/normalize/lighthouse-ir.js +151 -0
- package/dist/normalize/lighthouse-ir.js.map +1 -0
- package/dist/normalize/network-ir.d.ts +23 -0
- package/dist/normalize/network-ir.d.ts.map +1 -0
- package/dist/normalize/network-ir.js +180 -0
- package/dist/normalize/network-ir.js.map +1 -0
- package/dist/normalize/runtime-ir.d.ts +18 -0
- package/dist/normalize/runtime-ir.d.ts.map +1 -0
- package/dist/normalize/runtime-ir.js +114 -0
- package/dist/normalize/runtime-ir.js.map +1 -0
- package/dist/normalize/trace-ir.d.ts +20 -0
- package/dist/normalize/trace-ir.d.ts.map +1 -0
- package/dist/normalize/trace-ir.js +224 -0
- package/dist/normalize/trace-ir.js.map +1 -0
- package/dist/normalize/types.d.ts +536 -0
- package/dist/normalize/types.d.ts.map +1 -0
- package/dist/normalize/types.js +242 -0
- package/dist/normalize/types.js.map +1 -0
- package/dist/output/manifest.d.ts +44 -0
- package/dist/output/manifest.d.ts.map +1 -0
- package/dist/output/manifest.js +232 -0
- package/dist/output/manifest.js.map +1 -0
- package/dist/output/toon.d.ts +19 -0
- package/dist/output/toon.d.ts.map +1 -0
- package/dist/output/toon.js +22 -0
- package/dist/output/toon.js.map +1 -0
- package/dist/output/writer.d.ts +31 -0
- package/dist/output/writer.d.ts.map +1 -0
- package/dist/output/writer.js +51 -0
- package/dist/output/writer.js.map +1 -0
- package/dist/report/analyzer.d.ts +29 -0
- package/dist/report/analyzer.d.ts.map +1 -0
- package/dist/report/analyzer.js +330 -0
- package/dist/report/analyzer.js.map +1 -0
- package/dist/report/index.d.ts +13 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +12 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/markdown.d.ts +21 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +182 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/remediations.d.ts +42 -0
- package/dist/report/remediations.d.ts.map +1 -0
- package/dist/report/remediations.js +179 -0
- package/dist/report/remediations.js.map +1 -0
- package/dist/report/scorer.d.ts +35 -0
- package/dist/report/scorer.d.ts.map +1 -0
- package/dist/report/scorer.js +72 -0
- package/dist/report/scorer.js.map +1 -0
- package/dist/report/types.d.ts +201 -0
- package/dist/report/types.d.ts.map +1 -0
- package/dist/report/types.js +149 -0
- package/dist/report/types.js.map +1 -0
- package/dist/shared/fs-utils.d.ts +12 -0
- package/dist/shared/fs-utils.d.ts.map +1 -0
- package/dist/shared/fs-utils.js +44 -0
- package/dist/shared/fs-utils.js.map +1 -0
- package/dist/shared/types.d.ts +69 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +18 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/utils.d.ts +6 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/shared/utils.js +9 -0
- package/dist/shared/utils.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOMCollector — captures DOM structure metadata via page.evaluate().
|
|
3
|
+
*
|
|
4
|
+
* Extracts the following from the live page after navigation:
|
|
5
|
+
* - Total node count (elements, text nodes, comments)
|
|
6
|
+
* - Maximum DOM tree depth
|
|
7
|
+
* - Element type distribution (count per tag name)
|
|
8
|
+
* - Total text content length
|
|
9
|
+
*
|
|
10
|
+
* Uses page.evaluate() rather than CDP domains for lightweight introspection.
|
|
11
|
+
* Does NOT traverse the full DOM tree — collects aggregate stats only.
|
|
12
|
+
*/
|
|
13
|
+
import {} from 'playwright';
|
|
14
|
+
export class DOMCollector {
|
|
15
|
+
page;
|
|
16
|
+
name = 'dom';
|
|
17
|
+
session = null;
|
|
18
|
+
/**
|
|
19
|
+
* @param page - Playwright Page instance used for evaluate() calls.
|
|
20
|
+
* The page reference is required because DOM stats are
|
|
21
|
+
* extracted via in-page JavaScript, not CDP commands.
|
|
22
|
+
*/
|
|
23
|
+
constructor(page) {
|
|
24
|
+
this.page = page;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Start collecting DOM data.
|
|
28
|
+
* Currently a no-op — DOM snapshot is taken on stop() after navigation.
|
|
29
|
+
*/
|
|
30
|
+
async start(session, _options) {
|
|
31
|
+
this.session = session;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Stop collecting and return DOM metadata.
|
|
35
|
+
* Runs page.evaluate() to extract aggregate DOM statistics.
|
|
36
|
+
*/
|
|
37
|
+
async stop() {
|
|
38
|
+
const page = this.page;
|
|
39
|
+
try {
|
|
40
|
+
const result = await page.evaluate(() => {
|
|
41
|
+
let totalNodes = 0;
|
|
42
|
+
let maxDepth = 0;
|
|
43
|
+
const elementCounts = {};
|
|
44
|
+
/**
|
|
45
|
+
* Recursively walk the DOM tree counting nodes and tracking depth.
|
|
46
|
+
* Walks via childNodes to capture text nodes and comments too.
|
|
47
|
+
*/
|
|
48
|
+
function walk(node, depth) {
|
|
49
|
+
// Count this node
|
|
50
|
+
totalNodes++;
|
|
51
|
+
if (depth > maxDepth)
|
|
52
|
+
maxDepth = depth;
|
|
53
|
+
// If it's an element, count its tag and recurse through children
|
|
54
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
55
|
+
const el = node;
|
|
56
|
+
const tag = el.tagName.toLowerCase();
|
|
57
|
+
elementCounts[tag] = (elementCounts[tag] ?? 0) + 1;
|
|
58
|
+
// Recurse only through element children (children is live but
|
|
59
|
+
// we're reading sequentially, not mutating)
|
|
60
|
+
const children = el.children;
|
|
61
|
+
for (let i = 0; i < children.length; i++) {
|
|
62
|
+
walk(children[i], depth + 1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Count non-element children (text nodes, comments, etc.)
|
|
66
|
+
// These are found via childNodes but NOT recursed into since
|
|
67
|
+
// they cannot contain elements
|
|
68
|
+
if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE) {
|
|
69
|
+
const childNodes = node.childNodes;
|
|
70
|
+
for (let i = 0; i < childNodes.length; i++) {
|
|
71
|
+
const child = childNodes[i];
|
|
72
|
+
if (child.nodeType === Node.TEXT_NODE ||
|
|
73
|
+
child.nodeType === Node.COMMENT_NODE ||
|
|
74
|
+
child.nodeType === Node.CDATA_SECTION_NODE ||
|
|
75
|
+
child.nodeType === Node.PROCESSING_INSTRUCTION_NODE) {
|
|
76
|
+
totalNodes++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Start walking from body (document is above body/html which would
|
|
82
|
+
// double-count)
|
|
83
|
+
if (document.body) {
|
|
84
|
+
walk(document.body, 0);
|
|
85
|
+
}
|
|
86
|
+
const textContentLength = document.body?.textContent?.length ?? 0;
|
|
87
|
+
return {
|
|
88
|
+
totalNodes,
|
|
89
|
+
elementCount: elementCounts,
|
|
90
|
+
maxDepth,
|
|
91
|
+
textContentLength,
|
|
92
|
+
elementDistribution: elementCounts,
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
const distribution = result.elementDistribution;
|
|
96
|
+
return {
|
|
97
|
+
ok: true,
|
|
98
|
+
data: {
|
|
99
|
+
stats: {
|
|
100
|
+
totalNodes: result.totalNodes,
|
|
101
|
+
elementCount: Object.values(distribution).reduce((sum, n) => sum + n, 0),
|
|
102
|
+
maxDepth: result.maxDepth,
|
|
103
|
+
textContentLength: result.textContentLength,
|
|
104
|
+
},
|
|
105
|
+
elementDistribution: distribution,
|
|
106
|
+
warnings: [],
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return {
|
|
112
|
+
ok: false,
|
|
113
|
+
error: `DOMCollector: failed to collect DOM stats — ${String(error)}`,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/collect/dom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAA8B,MAAM,YAAY,CAAC;AAIxD,MAAM,OAAO,YAAY;IAUM;IATpB,IAAI,GAAG,KAAK,CAAC;IAEd,OAAO,GAAsB,IAAI,CAAC;IAE1C;;;;OAIG;IACH,YAA6B,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAAG,CAAC;IAE3C;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,OAAmB,EAAE,QAA8B;QAC7D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAEvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;gBACtC,IAAI,UAAU,GAAG,CAAC,CAAC;gBACnB,IAAI,QAAQ,GAAG,CAAC,CAAC;gBACjB,MAAM,aAAa,GAA2B,EAAE,CAAC;gBAEjD;;;mBAGG;gBACH,SAAS,IAAI,CAAC,IAAU,EAAE,KAAa;oBACrC,kBAAkB;oBAClB,UAAU,EAAE,CAAC;oBAEb,IAAI,KAAK,GAAG,QAAQ;wBAAE,QAAQ,GAAG,KAAK,CAAC;oBAEvC,iEAAiE;oBACjE,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;wBACxC,MAAM,EAAE,GAAG,IAAe,CAAC;wBAC3B,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;wBACrC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;wBAEnD,8DAA8D;wBAC9D,4CAA4C;wBAC5C,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC;wBAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;4BACzC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;wBAChC,CAAC;oBACH,CAAC;oBAED,0DAA0D;oBAC1D,6DAA6D;oBAC7D,+BAA+B;oBAC/B,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;wBAChF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;wBACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;4BAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAE,CAAC;4BAC7B,IACE,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS;gCACjC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY;gCACpC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,kBAAkB;gCAC1C,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,2BAA2B,EACnD,CAAC;gCACD,UAAU,EAAE,CAAC;4BACf,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,mEAAmE;gBACnE,gBAAgB;gBAChB,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;oBAClB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBACzB,CAAC;gBAED,MAAM,iBAAiB,GAAG,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC;gBAElE,OAAO;oBACL,UAAU;oBACV,YAAY,EAAE,aAAa;oBAC3B,QAAQ;oBACR,iBAAiB;oBACjB,mBAAmB,EAAE,aAAa;iBACnC,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,MAAM,YAAY,GAAG,MAAM,CAAC,mBAA6C,CAAC;YAE1E,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE;oBACJ,KAAK,EAAE;wBACL,UAAU,EAAE,MAAM,CAAC,UAAU;wBAC7B,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAC9C,CAAC,GAAW,EAAE,CAAS,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CACvC;wBACD,QAAQ,EAAE,MAAM,CAAC,QAAQ;wBACzB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;qBAC5C;oBACD,mBAAmB,EAAE,YAAY;oBACjC,QAAQ,EAAE,EAAE;iBACb;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,+CAA+C,MAAM,CAAC,KAAK,CAAC,EAAE;aACtE,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LighthouseCollector — runs a Lighthouse audit against the target URL.
|
|
3
|
+
*
|
|
4
|
+
* Unlike other collectors, Lighthouse manages its own browser instance via
|
|
5
|
+
* chrome-launcher. This collector does NOT participate in the normal CDP
|
|
6
|
+
* start/stop flow. Instead, call `runCollection(url)` directly from the
|
|
7
|
+
* orchestrator AFTER the CDP session's browser has been closed.
|
|
8
|
+
*
|
|
9
|
+
* This avoids interference between Lighthouse and CDP tracing/coverage.
|
|
10
|
+
*/
|
|
11
|
+
import { type CDPSession } from 'playwright';
|
|
12
|
+
import type { Collector, CollectorResult, LighthouseRawData } from './types.js';
|
|
13
|
+
import type { CollectorRunOptions } from '../shared/types.js';
|
|
14
|
+
export declare class LighthouseCollector implements Collector {
|
|
15
|
+
readonly name = "lighthouse";
|
|
16
|
+
/** Categories to include in every Lighthouse run */
|
|
17
|
+
private readonly defaultCategories;
|
|
18
|
+
/**
|
|
19
|
+
* Start is a no-op because Lighthouse manages its own browser.
|
|
20
|
+
* Use runCollection() instead.
|
|
21
|
+
*/
|
|
22
|
+
start(_session: CDPSession, _options?: CollectorRunOptions): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Stop is a no-op because Lighthouse manages its own lifecycle.
|
|
25
|
+
* Use runCollection() instead.
|
|
26
|
+
*/
|
|
27
|
+
stop(): Promise<CollectorResult<LighthouseRawData>>;
|
|
28
|
+
/**
|
|
29
|
+
* Execute a full Lighthouse audit.
|
|
30
|
+
*
|
|
31
|
+
* When `cdpPort` is provided, connects to an existing Chrome instance
|
|
32
|
+
* (e.g. the Playwright browser used for CDP collection). Otherwise
|
|
33
|
+
* launches its own headless Chrome instance via chrome-launcher.
|
|
34
|
+
*
|
|
35
|
+
* @param url - Target URL to audit
|
|
36
|
+
* @param cdpPort - Optional CDP debugging port of an existing Chrome instance
|
|
37
|
+
* @returns CollectorResult with full Lighthouse result
|
|
38
|
+
*/
|
|
39
|
+
runCollection(url: string, cdpPort?: number): Promise<CollectorResult<LighthouseRawData>>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=lighthouse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lighthouse.d.ts","sourceRoot":"","sources":["../../src/collect/lighthouse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,iBAAiB,EAAsB,MAAM,YAAY,CAAC;AACpG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,qBAAa,mBAAoB,YAAW,SAAS;IACnD,QAAQ,CAAC,IAAI,gBAAgB;IAE7B,oDAAoD;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAKhC;IAEF;;;OAGG;IACG,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhF;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;IAOzD;;;;;;;;;;OAUG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;CA8DhG"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LighthouseCollector — runs a Lighthouse audit against the target URL.
|
|
3
|
+
*
|
|
4
|
+
* Unlike other collectors, Lighthouse manages its own browser instance via
|
|
5
|
+
* chrome-launcher. This collector does NOT participate in the normal CDP
|
|
6
|
+
* start/stop flow. Instead, call `runCollection(url)` directly from the
|
|
7
|
+
* orchestrator AFTER the CDP session's browser has been closed.
|
|
8
|
+
*
|
|
9
|
+
* This avoids interference between Lighthouse and CDP tracing/coverage.
|
|
10
|
+
*/
|
|
11
|
+
import {} from 'playwright';
|
|
12
|
+
import { launch as launchChrome } from 'chrome-launcher';
|
|
13
|
+
import lighthouse from 'lighthouse';
|
|
14
|
+
export class LighthouseCollector {
|
|
15
|
+
name = 'lighthouse';
|
|
16
|
+
/** Categories to include in every Lighthouse run */
|
|
17
|
+
defaultCategories = [
|
|
18
|
+
'performance',
|
|
19
|
+
'accessibility',
|
|
20
|
+
'best-practices',
|
|
21
|
+
'seo',
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Start is a no-op because Lighthouse manages its own browser.
|
|
25
|
+
* Use runCollection() instead.
|
|
26
|
+
*/
|
|
27
|
+
async start(_session, _options) {
|
|
28
|
+
// No-op — Lighthouse manages its own browser lifecycle
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Stop is a no-op because Lighthouse manages its own lifecycle.
|
|
32
|
+
* Use runCollection() instead.
|
|
33
|
+
*/
|
|
34
|
+
async stop() {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
error: 'LighthouseCollector: use runCollection() instead of stop()',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Execute a full Lighthouse audit.
|
|
42
|
+
*
|
|
43
|
+
* When `cdpPort` is provided, connects to an existing Chrome instance
|
|
44
|
+
* (e.g. the Playwright browser used for CDP collection). Otherwise
|
|
45
|
+
* launches its own headless Chrome instance via chrome-launcher.
|
|
46
|
+
*
|
|
47
|
+
* @param url - Target URL to audit
|
|
48
|
+
* @param cdpPort - Optional CDP debugging port of an existing Chrome instance
|
|
49
|
+
* @returns CollectorResult with full Lighthouse result
|
|
50
|
+
*/
|
|
51
|
+
async runCollection(url, cdpPort) {
|
|
52
|
+
let chrome = null;
|
|
53
|
+
try {
|
|
54
|
+
const flags = {
|
|
55
|
+
port: 0,
|
|
56
|
+
output: 'json',
|
|
57
|
+
onlyCategories: this.defaultCategories,
|
|
58
|
+
};
|
|
59
|
+
if (cdpPort !== undefined) {
|
|
60
|
+
// Connect to an existing browser instance (Option C — same Chrome as CDP collectors)
|
|
61
|
+
flags.port = cdpPort;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Fallback: launch a dedicated Chrome instance for Lighthouse
|
|
65
|
+
chrome = await launchChrome({
|
|
66
|
+
chromeFlags: [
|
|
67
|
+
'--headless',
|
|
68
|
+
'--no-sandbox',
|
|
69
|
+
'--disable-setuid-sandbox',
|
|
70
|
+
'--disable-gpu',
|
|
71
|
+
'--disable-dev-shm-usage',
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
flags.port = chrome.port;
|
|
75
|
+
}
|
|
76
|
+
const result = await lighthouse(url, flags);
|
|
77
|
+
if (!result) {
|
|
78
|
+
return { ok: false, error: 'LighthouseCollector: Lighthouse returned no result' };
|
|
79
|
+
}
|
|
80
|
+
// The LHR may be a string (JSON) or already an object depending on
|
|
81
|
+
// the output flag. We handle both.
|
|
82
|
+
const lhr = typeof result.lhr === 'string' ? JSON.parse(result.lhr) : result.lhr;
|
|
83
|
+
return {
|
|
84
|
+
ok: true,
|
|
85
|
+
data: {
|
|
86
|
+
lhr,
|
|
87
|
+
categories: this.defaultCategories,
|
|
88
|
+
warnings: [],
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
error: `LighthouseCollector: ${String(error)}`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
// Always clean up the browser
|
|
100
|
+
if (chrome) {
|
|
101
|
+
try {
|
|
102
|
+
await chrome.kill();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Best-effort cleanup
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=lighthouse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lighthouse.js","sourceRoot":"","sources":["../../src/collect/lighthouse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAmB,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,MAAM,IAAI,YAAY,EAAuB,MAAM,iBAAiB,CAAC;AAC9E,OAAO,UAAU,MAAM,YAAY,CAAC;AAIpC,MAAM,OAAO,mBAAmB;IACrB,IAAI,GAAG,YAAY,CAAC;IAE7B,oDAAoD;IACnC,iBAAiB,GAAyB;QACzD,aAAa;QACb,eAAe;QACf,gBAAgB;QAChB,KAAK;KACN,CAAC;IAEF;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,QAAoB,EAAE,QAA8B;QAC9D,uDAAuD;IACzD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,4DAA4D;SACpE,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,OAAgB;QAC/C,IAAI,MAAM,GAA0B,IAAI,CAAC;QAEzC,IAAI,CAAC;YACH,MAAM,KAAK,GAA2E;gBACpF,IAAI,EAAE,CAAC;gBACP,MAAM,EAAE,MAAM;gBACd,cAAc,EAAE,IAAI,CAAC,iBAAiB;aACvC,CAAC;YAEF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,qFAAqF;gBACrF,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,8DAA8D;gBAC9D,MAAM,GAAG,MAAM,YAAY,CAAC;oBAC1B,WAAW,EAAE;wBACX,YAAY;wBACZ,cAAc;wBACd,0BAA0B;wBAC1B,eAAe;wBACf,yBAAyB;qBAC1B;iBACF,CAAC,CAAC;gBACH,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YAC3B,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAE5C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,oDAAoD,EAAE,CAAC;YACpF,CAAC;YAED,mEAAmE;YACnE,mCAAmC;YACnC,MAAM,GAAG,GACP,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YAEvE,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE;oBACJ,GAAG;oBACH,UAAU,EAAE,IAAI,CAAC,iBAAiB;oBAClC,QAAQ,EAAE,EAAE;iBACb;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,wBAAwB,MAAM,CAAC,KAAK,CAAC,EAAE;aAC/C,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,8BAA8B;YAC9B,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBACtB,CAAC;gBAAC,MAAM,CAAC;oBACP,sBAAsB;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NetworkCollector — captures HTTP request/response data via the CDP Network domain.
|
|
3
|
+
*
|
|
4
|
+
* Enables the Network domain and listens for:
|
|
5
|
+
* - Network.requestWillBeSent (request metadata + redirect tracking)
|
|
6
|
+
* - Network.responseReceived (response metadata + timing)
|
|
7
|
+
* - Network.loadingFailed (failure information)
|
|
8
|
+
* - Network.requestServedFromCache
|
|
9
|
+
*
|
|
10
|
+
* Correlates requests and responses by CDP requestId.
|
|
11
|
+
*/
|
|
12
|
+
import { type CDPSession } from 'playwright';
|
|
13
|
+
import type { Collector, CollectorResult } from './types.js';
|
|
14
|
+
import type { NetworkRawData } from './types.js';
|
|
15
|
+
import type { CollectorRunOptions } from '../shared/types.js';
|
|
16
|
+
export declare class NetworkCollector implements Collector {
|
|
17
|
+
#private;
|
|
18
|
+
readonly name = "network";
|
|
19
|
+
private session;
|
|
20
|
+
/** Map of requestId -> entry (covers redirect chains) */
|
|
21
|
+
private requestMap;
|
|
22
|
+
/** Maintain insertion order for chronological output */
|
|
23
|
+
private requestOrder;
|
|
24
|
+
private requestCount;
|
|
25
|
+
private failedCount;
|
|
26
|
+
private startTime;
|
|
27
|
+
private endTime;
|
|
28
|
+
private collected;
|
|
29
|
+
start(session: CDPSession, _options?: CollectorRunOptions): Promise<void>;
|
|
30
|
+
stop(): Promise<CollectorResult<NetworkRawData>>;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/collect/network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAsC,MAAM,YAAY,CAAC;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAyG9D,qBAAa,gBAAiB,YAAW,SAAS;;IAChD,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,OAAO,CAA2B;IAC1C,yDAAyD;IACzD,OAAO,CAAC,UAAU,CAA0C;IAC5D,wDAAwD;IACxD,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,SAAS,CAAS;IAEpB,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCzE,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;CA4LvD"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NetworkCollector — captures HTTP request/response data via the CDP Network domain.
|
|
3
|
+
*
|
|
4
|
+
* Enables the Network domain and listens for:
|
|
5
|
+
* - Network.requestWillBeSent (request metadata + redirect tracking)
|
|
6
|
+
* - Network.responseReceived (response metadata + timing)
|
|
7
|
+
* - Network.loadingFailed (failure information)
|
|
8
|
+
* - Network.requestServedFromCache
|
|
9
|
+
*
|
|
10
|
+
* Correlates requests and responses by CDP requestId.
|
|
11
|
+
*/
|
|
12
|
+
import {} from 'playwright';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Validate that collected network data contains at least some expected entries.
|
|
16
|
+
*
|
|
17
|
+
* @param entries - Array of collected network request entries
|
|
18
|
+
* @returns Array of warning strings
|
|
19
|
+
*/
|
|
20
|
+
function validateNetworkData(entries) {
|
|
21
|
+
const warnings = [];
|
|
22
|
+
if (entries.length === 0) {
|
|
23
|
+
warnings.push('No network requests were captured — page may not have loaded.');
|
|
24
|
+
}
|
|
25
|
+
const documentRequests = entries.filter((e) => e.type === 'Document');
|
|
26
|
+
if (documentRequests.length === 0) {
|
|
27
|
+
warnings.push('No document (main-frame) request found in network data.');
|
|
28
|
+
}
|
|
29
|
+
const failedEntries = entries.filter((e) => e.failed);
|
|
30
|
+
if (failedEntries.length > 0) {
|
|
31
|
+
const failedUrls = failedEntries.map((e) => e.url).slice(0, 5);
|
|
32
|
+
warnings.push(`${failedEntries.length} network request(s) failed. First failures: ${failedUrls.join(', ')}`);
|
|
33
|
+
}
|
|
34
|
+
return warnings;
|
|
35
|
+
}
|
|
36
|
+
export class NetworkCollector {
|
|
37
|
+
name = 'network';
|
|
38
|
+
session = null;
|
|
39
|
+
/** Map of requestId -> entry (covers redirect chains) */
|
|
40
|
+
requestMap = new Map();
|
|
41
|
+
/** Maintain insertion order for chronological output */
|
|
42
|
+
requestOrder = [];
|
|
43
|
+
requestCount = 0;
|
|
44
|
+
failedCount = 0;
|
|
45
|
+
startTime = 0;
|
|
46
|
+
endTime = 0;
|
|
47
|
+
collected = false;
|
|
48
|
+
async start(session, _options) {
|
|
49
|
+
this.session = session;
|
|
50
|
+
this.requestMap.clear();
|
|
51
|
+
this.requestOrder = [];
|
|
52
|
+
this.requestCount = 0;
|
|
53
|
+
this.failedCount = 0;
|
|
54
|
+
this.startTime = 0;
|
|
55
|
+
this.endTime = 0;
|
|
56
|
+
this.collected = false;
|
|
57
|
+
// Register CDP event listeners (cast to unknown to bypass strict typed overloads)
|
|
58
|
+
session.on('Network.requestWillBeSent', this.#onRequestWillBeSent.bind(this));
|
|
59
|
+
session.on('Network.responseReceived', this.#onResponseReceived.bind(this));
|
|
60
|
+
session.on('Network.loadingFailed', this.#onLoadingFailed.bind(this));
|
|
61
|
+
session.on('Network.requestServedFromCache', this.#onRequestServedFromCache.bind(this));
|
|
62
|
+
// Enable the Network domain
|
|
63
|
+
await session.send('Network.enable', {
|
|
64
|
+
maxTotalBufferSize: 10_000_000,
|
|
65
|
+
maxResourceBufferSize: 5_000_000,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async stop() {
|
|
69
|
+
this.collected = true;
|
|
70
|
+
if (!this.session) {
|
|
71
|
+
return { ok: false, error: 'NetworkCollector: session not initialized' };
|
|
72
|
+
}
|
|
73
|
+
const warnings = [];
|
|
74
|
+
try {
|
|
75
|
+
// Disable the Network domain to stop receiving events
|
|
76
|
+
await this.session.send('Network.disable');
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
warnings.push(`NetworkCollector: error disabling Network domain — ${String(error)}`);
|
|
80
|
+
}
|
|
81
|
+
// Build ordered array of entries
|
|
82
|
+
const requests = [];
|
|
83
|
+
for (const id of this.requestOrder) {
|
|
84
|
+
const entry = this.requestMap.get(id);
|
|
85
|
+
if (entry) {
|
|
86
|
+
requests.push(entry);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Calculate metadata
|
|
90
|
+
const totalRequests = requests.length;
|
|
91
|
+
const totalFailed = requests.filter((r) => r.failed).length;
|
|
92
|
+
// Collect total bytes from completed responses
|
|
93
|
+
let totalBytes = 0;
|
|
94
|
+
for (const r of requests) {
|
|
95
|
+
if (r.response) {
|
|
96
|
+
totalBytes += r.response.encodedDataLength;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Run completeness validation
|
|
100
|
+
const validationWarnings = validateNetworkData(requests);
|
|
101
|
+
warnings.push(...validationWarnings);
|
|
102
|
+
return {
|
|
103
|
+
ok: true,
|
|
104
|
+
data: {
|
|
105
|
+
requests,
|
|
106
|
+
metadata: {
|
|
107
|
+
totalRequests,
|
|
108
|
+
totalFailed,
|
|
109
|
+
totalBytes,
|
|
110
|
+
startTime: this.startTime,
|
|
111
|
+
endTime: this.endTime,
|
|
112
|
+
},
|
|
113
|
+
warnings,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Handle Network.requestWillBeSent — captures request metadata.
|
|
119
|
+
* The CDP payload nests url/method/headers inside `request`.
|
|
120
|
+
* For redirects, updates the existing entry and stores redirect info.
|
|
121
|
+
*/
|
|
122
|
+
#onRequestWillBeSent(raw) {
|
|
123
|
+
const { requestId, request: req, type, timestamp, wallTime, initiator, redirectResponse } = raw;
|
|
124
|
+
if (this.startTime === 0 || timestamp < this.startTime) {
|
|
125
|
+
this.startTime = timestamp;
|
|
126
|
+
}
|
|
127
|
+
this.endTime = Math.max(this.endTime, timestamp);
|
|
128
|
+
// Check if this is a new request or part of a redirect chain
|
|
129
|
+
const existing = this.requestMap.get(requestId);
|
|
130
|
+
if (existing) {
|
|
131
|
+
// This is a redirect — save the redirect response and update entry
|
|
132
|
+
if (redirectResponse) {
|
|
133
|
+
existing.redirectChain = existing.redirectChain ?? [];
|
|
134
|
+
existing.redirectChain.push({
|
|
135
|
+
url: redirectResponse.url,
|
|
136
|
+
status: redirectResponse.status,
|
|
137
|
+
statusText: redirectResponse.statusText,
|
|
138
|
+
headers: redirectResponse.headers,
|
|
139
|
+
timing: redirectResponse.timing,
|
|
140
|
+
encodedDataLength: redirectResponse.encodedDataLength,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// Update the entry with final request data
|
|
144
|
+
existing.url = req.url;
|
|
145
|
+
existing.method = req.method;
|
|
146
|
+
existing.type = type ?? existing.type;
|
|
147
|
+
existing.timestamp = timestamp;
|
|
148
|
+
existing.wallTime = wallTime ?? existing.wallTime;
|
|
149
|
+
existing.request = {
|
|
150
|
+
headers: req.headers,
|
|
151
|
+
postData: req.postData,
|
|
152
|
+
initialPriority: req.initialPriority,
|
|
153
|
+
referrerPolicy: req.referrerPolicy,
|
|
154
|
+
};
|
|
155
|
+
if (initiator) {
|
|
156
|
+
existing.initiator = initiator;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// New request
|
|
161
|
+
const entry = {
|
|
162
|
+
requestId,
|
|
163
|
+
url: req.url,
|
|
164
|
+
method: req.method,
|
|
165
|
+
type,
|
|
166
|
+
request: {
|
|
167
|
+
headers: req.headers,
|
|
168
|
+
postData: req.postData,
|
|
169
|
+
initialPriority: req.initialPriority,
|
|
170
|
+
referrerPolicy: req.referrerPolicy,
|
|
171
|
+
},
|
|
172
|
+
timestamp,
|
|
173
|
+
wallTime,
|
|
174
|
+
initiator: initiator,
|
|
175
|
+
};
|
|
176
|
+
this.requestMap.set(requestId, entry);
|
|
177
|
+
this.requestOrder.push(requestId);
|
|
178
|
+
this.requestCount++;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Handle Network.responseReceived — captures response metadata.
|
|
183
|
+
*/
|
|
184
|
+
#onResponseReceived(raw) {
|
|
185
|
+
const { requestId, type, response: res } = raw;
|
|
186
|
+
const entry = this.requestMap.get(requestId);
|
|
187
|
+
if (!entry) {
|
|
188
|
+
return; // May happen if request started before Network.enable
|
|
189
|
+
}
|
|
190
|
+
// Update type from response (more reliable than requestWillBeSent's type)
|
|
191
|
+
entry.type = type ?? entry.type;
|
|
192
|
+
// Fill in response data
|
|
193
|
+
entry.response = {
|
|
194
|
+
status: res.status,
|
|
195
|
+
statusText: res.statusText,
|
|
196
|
+
headers: res.headers,
|
|
197
|
+
mimeType: res.mimeType,
|
|
198
|
+
timing: res.timing,
|
|
199
|
+
fromDiskCache: res.fromDiskCache,
|
|
200
|
+
fromServiceWorker: res.fromServiceWorker,
|
|
201
|
+
encodedDataLength: res.encodedDataLength,
|
|
202
|
+
responseTime: res.responseTime,
|
|
203
|
+
protocol: res.protocol,
|
|
204
|
+
remoteIPAddress: res.remoteIPAddress,
|
|
205
|
+
remotePort: res.remotePort,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Handle Network.loadingFailed — captures failure information.
|
|
210
|
+
*/
|
|
211
|
+
#onLoadingFailed(raw) {
|
|
212
|
+
const { requestId, type, errorText, canceled, blockedReason, timestamp } = raw;
|
|
213
|
+
const entry = this.requestMap.get(requestId);
|
|
214
|
+
if (!entry) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
entry.failed = true;
|
|
218
|
+
entry.errorText = errorText;
|
|
219
|
+
entry.canceled = canceled;
|
|
220
|
+
entry.blockedReason = blockedReason;
|
|
221
|
+
entry.type = type ?? entry.type;
|
|
222
|
+
this.failedCount++;
|
|
223
|
+
this.endTime = Math.max(this.endTime, timestamp);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Handle Network.requestServedFromCache — marks cache-served requests.
|
|
227
|
+
*/
|
|
228
|
+
#onRequestServedFromCache(raw) {
|
|
229
|
+
const entry = this.requestMap.get(raw.requestId);
|
|
230
|
+
if (!entry) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
entry.fromCache = true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/collect/network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAmB,MAAM,YAAY,CAAC;AA6E7C,8EAA8E;AAE9E;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,OAA8B;IACzD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IACtE,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/D,QAAQ,CAAC,IAAI,CACX,GAAG,aAAa,CAAC,MAAM,+CAA+C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9F,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAG,SAAS,CAAC;IAElB,OAAO,GAAsB,IAAI,CAAC;IAC1C,yDAAyD;IACjD,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC5D,wDAAwD;IAChD,YAAY,GAAa,EAAE,CAAC;IAC5B,YAAY,GAAG,CAAC,CAAC;IACjB,WAAW,GAAG,CAAC,CAAC;IAChB,SAAS,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,CAAC,CAAC;IACZ,SAAS,GAAG,KAAK,CAAC;IAE1B,KAAK,CAAC,KAAK,CAAC,OAAmB,EAAE,QAA8B;QAC7D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QAEvB,kFAAkF;QAClF,OAAO,CAAC,EAAE,CACR,2BAA2B,EAC3B,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAA+B,CACnE,CAAC;QACF,OAAO,CAAC,EAAE,CACR,0BAA0B,EAC1B,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAA+B,CAClE,CAAC;QACF,OAAO,CAAC,EAAE,CACR,uBAAuB,EACvB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAA+B,CAC/D,CAAC;QACF,OAAO,CAAC,EAAE,CACR,gCAAgC,EAChC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAA+B,CACxE,CAAC;QAEF,4BAA4B;QAC5B,MAAM,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE;YACnC,kBAAkB,EAAE,UAAU;YAC9B,qBAAqB,EAAE,SAAS;SACjC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAEtB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2CAA2C,EAAE,CAAC;QAC3E,CAAC;QAED,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,IAAI,CAAC;YACH,sDAAsD;YACtD,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,sDAAsD,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;QAED,iCAAiC;QACjC,MAAM,QAAQ,GAA0B,EAAE,CAAC;QAC3C,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACtC,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,qBAAqB;QACrB,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;QACtC,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;QAE5D,+CAA+C;QAC/C,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACf,UAAU,IAAI,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACzD,QAAQ,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,CAAC;QAErC,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE;gBACJ,QAAQ;gBACR,QAAQ,EAAE;oBACR,aAAa;oBACb,WAAW;oBACX,UAAU;oBACV,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB;gBACD,QAAQ;aACT;SACF,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,oBAAoB,CAAC,GAAyB;QAC5C,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,GACvF,GAAG,CAAC;QAEN,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YACvD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAEjD,6DAA6D;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEhD,IAAI,QAAQ,EAAE,CAAC;YACb,mEAAmE;YACnE,IAAI,gBAAgB,EAAE,CAAC;gBACrB,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,IAAI,EAAE,CAAC;gBACtD,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC;oBAC1B,GAAG,EAAE,gBAAgB,CAAC,GAAG;oBACzB,MAAM,EAAE,gBAAgB,CAAC,MAAM;oBAC/B,UAAU,EAAE,gBAAgB,CAAC,UAAU;oBACvC,OAAO,EAAE,gBAAgB,CAAC,OAAO;oBACjC,MAAM,EAAE,gBAAgB,CAAC,MAAM;oBAC/B,iBAAiB,EAAE,gBAAgB,CAAC,iBAAiB;iBACtD,CAAC,CAAC;YACL,CAAC;YAED,2CAA2C;YAC3C,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;YACvB,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YAC7B,QAAQ,CAAC,IAAI,GAAG,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC;YACtC,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC;YAC/B,QAAQ,CAAC,QAAQ,GAAG,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC;YAClD,QAAQ,CAAC,OAAO,GAAG;gBACjB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,eAAe,EAAE,GAAG,CAAC,eAAe;gBACpC,cAAc,EAAE,GAAG,CAAC,cAAc;aACnC,CAAC;YACF,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,CAAC,SAAS,GAAG,SAA6C,CAAC;YACrE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,cAAc;YACd,MAAM,KAAK,GAAwB;gBACjC,SAAS;gBACT,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI;gBACJ,OAAO,EAAE;oBACP,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,eAAe,EAAE,GAAG,CAAC,eAAe;oBACpC,cAAc,EAAE,GAAG,CAAC,cAAc;iBACnC;gBACD,SAAS;gBACT,QAAQ;gBACR,SAAS,EAAE,SAAyD;aACrE,CAAC;YAEF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACtC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAClC,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,GAAwB;QAC1C,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,sDAAsD;QAChE,CAAC;QAED,0EAA0E;QAC1E,KAAK,CAAC,IAAI,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;QAEhC,wBAAwB;QACxB,KAAK,CAAC,QAAQ,GAAG;YACf,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;YACxC,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;YACxC,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,eAAe,EAAE,GAAG,CAAC,eAAe;YACpC,UAAU,EAAE,GAAG,CAAC,UAAU;SAC3B,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,GAAqB;QACpC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC;QAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QAED,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAC5B,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC1B,KAAK,CAAC,aAAa,GAAG,aAAa,CAAC;QACpC,KAAK,CAAC,IAAI,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;QAChC,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,yBAAyB,CAAC,GAAuB;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QAED,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collector orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Coordinates the full collection lifecycle for a single run:
|
|
5
|
+
* 1. Validate URL
|
|
6
|
+
* 2. Launch browser + create CDP session
|
|
7
|
+
* 3. Run each active collector in the correct order
|
|
8
|
+
* 4. Write results to the output directory
|
|
9
|
+
* 5. Clean up browser
|
|
10
|
+
* 6. Run Lighthouse audit (separate browser, after CDP session closes)
|
|
11
|
+
*
|
|
12
|
+
* Designed for multi-run support: `run()` wraps `runOnce()`.
|
|
13
|
+
*/
|
|
14
|
+
import type { CollectorRunOptions, RunResult } from '../shared/types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Run one or more collection runs against the given URL.
|
|
17
|
+
*
|
|
18
|
+
* @param url - Target URL to collect data from
|
|
19
|
+
* @param partialOptions - Partial options (merged with defaults)
|
|
20
|
+
* @returns Array of RunResult — one per run
|
|
21
|
+
*/
|
|
22
|
+
export declare function run(url: string, partialOptions?: Partial<CollectorRunOptions>): Promise<RunResult[]>;
|
|
23
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/collect/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAqTzE;;;;;;GAMG;AACH,wBAAsB,GAAG,CACvB,GAAG,EAAE,MAAM,EACX,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAC5C,OAAO,CAAC,SAAS,EAAE,CAAC,CA8EtB"}
|