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
package/dist/cli/run.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `run` subcommand — full pipeline in one command.
|
|
3
|
+
*
|
|
4
|
+
* Chains collect → normalize → extract → analyze → report,
|
|
5
|
+
* writing intermediate artifacts to a temp directory and
|
|
6
|
+
* outputting only the final Report JSON.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* perfgraph run --url <url> [--output <dir>] [--runs <n>] [--pretty]
|
|
10
|
+
*/
|
|
11
|
+
import { writeFileSync } from 'node:fs';
|
|
12
|
+
import { resolve } from 'node:path';
|
|
13
|
+
import { writeManifest } from '../output/manifest.js';
|
|
14
|
+
import { convertToon } from '../output/toon.js';
|
|
15
|
+
import { run } from '../collect/orchestrator.js';
|
|
16
|
+
import { loadRunDir } from '../shared/fs-utils.js';
|
|
17
|
+
import { normalize } from '../normalize/index.js';
|
|
18
|
+
import { extract } from '../extract/index.js';
|
|
19
|
+
import { buildInsights } from '../distill/insights.js';
|
|
20
|
+
import { buildNetworkSummary, buildLighthouseSummary, buildCoverageSummary, } from '../distill/summaries.js';
|
|
21
|
+
import { buildCausalGraph } from '../causal/index.js';
|
|
22
|
+
import { buildReport } from '../report/index.js';
|
|
23
|
+
import { buildReportMarkdown } from '../report/markdown.js';
|
|
24
|
+
import { DEFAULT_RUN_OPTIONS } from '../shared/types.js';
|
|
25
|
+
/** Help text */
|
|
26
|
+
const RUN_HELP = `
|
|
27
|
+
RUN OPTIONS
|
|
28
|
+
--url <url> Target URL to analyze (required)
|
|
29
|
+
--output <dir> Output directory (default: ./perfgraph-output)
|
|
30
|
+
--runs <n> Number of collection runs (default: 1)
|
|
31
|
+
--pretty Pretty-print final report JSON
|
|
32
|
+
--device <name> Device name for mobile emulation (e.g. "iPhone 13")
|
|
33
|
+
--no-lighthouse Skip Lighthouse collection
|
|
34
|
+
--no-coverage Skip JS/CSS coverage collection
|
|
35
|
+
--no-console Skip console log collection
|
|
36
|
+
--no-dom Skip DOM snapshot collection
|
|
37
|
+
--help, -h Show this help message
|
|
38
|
+
|
|
39
|
+
EXAMPLES
|
|
40
|
+
perfgraph run --url https://example.com
|
|
41
|
+
perfgraph run --url https://example.com --pretty
|
|
42
|
+
perfgraph run --url https://example.com --pretty --runs 3
|
|
43
|
+
`;
|
|
44
|
+
/**
|
|
45
|
+
* Execute the full pipeline.
|
|
46
|
+
*
|
|
47
|
+
* @param url - Target URL
|
|
48
|
+
* @param output - Base output directory for collection + final report
|
|
49
|
+
* @param runs - Number of collection runs
|
|
50
|
+
* @param pretty - Pretty-print final report
|
|
51
|
+
* @param flags - boolean flags for skipping collectors
|
|
52
|
+
* @param mobile - Device name for mobile emulation (e.g. "iPhone 13")
|
|
53
|
+
* @returns RunResult
|
|
54
|
+
*/
|
|
55
|
+
export async function runRun(url, output, runs, pretty, flags, mobile) {
|
|
56
|
+
// -----------------------------------------------------------------------
|
|
57
|
+
// 1. Collect
|
|
58
|
+
// -----------------------------------------------------------------------
|
|
59
|
+
const options = {
|
|
60
|
+
...DEFAULT_RUN_OPTIONS,
|
|
61
|
+
url,
|
|
62
|
+
output,
|
|
63
|
+
runs,
|
|
64
|
+
noLighthouse: flags.noLighthouse ?? false,
|
|
65
|
+
noCoverage: flags.noCoverage ?? false,
|
|
66
|
+
noConsole: flags.noConsole ?? false,
|
|
67
|
+
noDom: flags.noDom ?? false,
|
|
68
|
+
mobile,
|
|
69
|
+
};
|
|
70
|
+
const collectResults = await run(url, options);
|
|
71
|
+
const successRuns = collectResults.filter((r) => r.success);
|
|
72
|
+
if (successRuns.length === 0) {
|
|
73
|
+
console.error('Error: All collection runs failed');
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
// Use the first successful run's output dir
|
|
77
|
+
const runDir = resolve(successRuns[0].outputDir);
|
|
78
|
+
// File paths for intermediate artifacts (set during pipeline)
|
|
79
|
+
let irFile = '';
|
|
80
|
+
let featuresFile = '';
|
|
81
|
+
let insightsFile = '';
|
|
82
|
+
let graphFile = '';
|
|
83
|
+
// -----------------------------------------------------------------------
|
|
84
|
+
// 2. Normalize
|
|
85
|
+
// -----------------------------------------------------------------------
|
|
86
|
+
const raw = loadRunDir(runDir);
|
|
87
|
+
let ir;
|
|
88
|
+
try {
|
|
89
|
+
ir = normalize(raw);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.error(`Error: Normalization failed: ${err.message}`);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
// Write intermediate representation
|
|
96
|
+
irFile = resolve(runDir, 'ir.json');
|
|
97
|
+
writeFileSync(irFile, JSON.stringify(ir, null, 2), 'utf-8');
|
|
98
|
+
// Write compact summaries of raw data files
|
|
99
|
+
if (raw.network) {
|
|
100
|
+
const networkSummary = buildNetworkSummary(raw.network);
|
|
101
|
+
writeFileSync(resolve(runDir, 'network-summary.toon'), await convertToon(networkSummary), 'utf-8');
|
|
102
|
+
}
|
|
103
|
+
if (raw.lighthouse) {
|
|
104
|
+
const lighthouseSummary = buildLighthouseSummary(raw.lighthouse);
|
|
105
|
+
writeFileSync(resolve(runDir, 'lighthouse-summary.toon'), await convertToon(lighthouseSummary), 'utf-8');
|
|
106
|
+
}
|
|
107
|
+
if (raw.coverage) {
|
|
108
|
+
const coverageSummary = buildCoverageSummary(raw.coverage);
|
|
109
|
+
writeFileSync(resolve(runDir, 'coverage-summary.toon'), await convertToon(coverageSummary), 'utf-8');
|
|
110
|
+
}
|
|
111
|
+
// -----------------------------------------------------------------------
|
|
112
|
+
// 3. Extract
|
|
113
|
+
// -----------------------------------------------------------------------
|
|
114
|
+
const features = extract(ir);
|
|
115
|
+
// Write extracted features
|
|
116
|
+
featuresFile = resolve(runDir, 'features.toon');
|
|
117
|
+
writeFileSync(featuresFile, await convertToon(features), 'utf-8');
|
|
118
|
+
// Build and write insights.toon
|
|
119
|
+
const insights = buildInsights(features, raw.lighthouse ?? {});
|
|
120
|
+
insightsFile = resolve(runDir, 'insights.toon');
|
|
121
|
+
writeFileSync(insightsFile, await convertToon(insights), 'utf-8');
|
|
122
|
+
// -----------------------------------------------------------------------
|
|
123
|
+
// 4. Analyze (causal graph)
|
|
124
|
+
// -----------------------------------------------------------------------
|
|
125
|
+
const graph = buildCausalGraph(features);
|
|
126
|
+
// Write causal graph
|
|
127
|
+
graphFile = resolve(runDir, 'graph.toon');
|
|
128
|
+
writeFileSync(graphFile, await convertToon(graph), 'utf-8');
|
|
129
|
+
// -----------------------------------------------------------------------
|
|
130
|
+
// 5. Report
|
|
131
|
+
// -----------------------------------------------------------------------
|
|
132
|
+
const report = buildReport(graph, features);
|
|
133
|
+
// Write report as .toon (AI consumption) + keep JSON for stdout
|
|
134
|
+
const reportFile = resolve(runDir, 'report.toon');
|
|
135
|
+
writeFileSync(reportFile, await convertToon(report), 'utf-8');
|
|
136
|
+
const reportJson = JSON.stringify(report, null, pretty ? 2 : 0);
|
|
137
|
+
// Write human-readable markdown report
|
|
138
|
+
const reportMarkdown = buildReportMarkdown(report, insights);
|
|
139
|
+
const reportMdFile = resolve(runDir, 'report.md');
|
|
140
|
+
writeFileSync(reportMdFile, reportMarkdown, 'utf-8');
|
|
141
|
+
// Write manifest
|
|
142
|
+
await writeManifest(runDir);
|
|
143
|
+
// Also print to stdout
|
|
144
|
+
console.log(reportJson);
|
|
145
|
+
console.error(`Report written to ${reportFile}`);
|
|
146
|
+
return {
|
|
147
|
+
success: true,
|
|
148
|
+
reportFile,
|
|
149
|
+
outputDir: runDir,
|
|
150
|
+
files: {
|
|
151
|
+
ir: irFile,
|
|
152
|
+
features: featuresFile,
|
|
153
|
+
graph: graphFile,
|
|
154
|
+
report: reportFile,
|
|
155
|
+
insights: insightsFile,
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Parse CLI arguments for the run command and execute.
|
|
161
|
+
*/
|
|
162
|
+
export async function runRunFromArgs(args) {
|
|
163
|
+
let url;
|
|
164
|
+
let output = DEFAULT_RUN_OPTIONS.output;
|
|
165
|
+
let runs = DEFAULT_RUN_OPTIONS.runs;
|
|
166
|
+
let pretty = false;
|
|
167
|
+
let mobile;
|
|
168
|
+
const flags = {
|
|
169
|
+
noLighthouse: false,
|
|
170
|
+
noCoverage: false,
|
|
171
|
+
noConsole: false,
|
|
172
|
+
noDom: false,
|
|
173
|
+
};
|
|
174
|
+
for (let i = 0; i < args.length; i++) {
|
|
175
|
+
const arg = args[i];
|
|
176
|
+
switch (arg) {
|
|
177
|
+
case '--url':
|
|
178
|
+
if (i + 1 >= args.length) {
|
|
179
|
+
console.error('Error: --url requires a value');
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
url = args[++i];
|
|
183
|
+
break;
|
|
184
|
+
case '--output':
|
|
185
|
+
if (i + 1 >= args.length) {
|
|
186
|
+
console.error('Error: --output requires a value');
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
output = args[++i];
|
|
190
|
+
break;
|
|
191
|
+
case '--runs':
|
|
192
|
+
if (i + 1 >= args.length) {
|
|
193
|
+
console.error('Error: --runs requires a value');
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
runs = parseInt(args[++i], 10);
|
|
197
|
+
if (isNaN(runs) || runs < 1) {
|
|
198
|
+
console.error('Error: --runs must be a positive integer');
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
case '--pretty':
|
|
203
|
+
pretty = true;
|
|
204
|
+
break;
|
|
205
|
+
case '--no-lighthouse':
|
|
206
|
+
flags.noLighthouse = true;
|
|
207
|
+
break;
|
|
208
|
+
case '--no-coverage':
|
|
209
|
+
flags.noCoverage = true;
|
|
210
|
+
break;
|
|
211
|
+
case '--no-console':
|
|
212
|
+
flags.noConsole = true;
|
|
213
|
+
break;
|
|
214
|
+
case '--no-dom':
|
|
215
|
+
flags.noDom = true;
|
|
216
|
+
break;
|
|
217
|
+
case '--device':
|
|
218
|
+
if (i + 1 >= args.length) {
|
|
219
|
+
console.error('Error: --device requires a value');
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
mobile = args[++i];
|
|
223
|
+
break;
|
|
224
|
+
case '--help':
|
|
225
|
+
case '-h':
|
|
226
|
+
console.log(RUN_HELP);
|
|
227
|
+
return null;
|
|
228
|
+
default:
|
|
229
|
+
if (arg.startsWith('--')) {
|
|
230
|
+
console.error(`Error: Unknown flag "${arg}"`);
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (!url) {
|
|
237
|
+
console.error('Error: --url is required');
|
|
238
|
+
console.error('Usage: perfgraph run --url <url> [--output <dir>] [--runs <n>] [--pretty]');
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
return runRun(url, output, runs, pretty, flags, mobile);
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* buffer-monitor — standalone trace buffer health analysis.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from TraceCollector so that buffer health checks can be tested
|
|
5
|
+
* and reused independently of the CDP session lifecycle.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { BufferUsageSample } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Analyse collected buffer-usage samples and return human-readable warnings
|
|
12
|
+
* when the ring buffer exceeded safe thresholds.
|
|
13
|
+
*
|
|
14
|
+
* @param samples - Array of buffer usage samples from `Tracing.bufferUsage`
|
|
15
|
+
* @returns Warning strings (empty array = buffer health OK)
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkBufferHealth(samples: BufferUsageSample[]): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Validate trace completeness by checking for expected critical event names.
|
|
20
|
+
*
|
|
21
|
+
* @param eventNames - Set or array of event name strings present in a trace
|
|
22
|
+
* @returns Warning strings for each missing critical event type
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateTraceCompleteness(eventNames: string[] | Set<string>): string[];
|
|
25
|
+
//# sourceMappingURL=buffer-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer-monitor.d.ts","sourceRoot":"","sources":["../../src/collect/buffer-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAwBpD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAqBxE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAmBtF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* buffer-monitor — standalone trace buffer health analysis.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from TraceCollector so that buffer health checks can be tested
|
|
5
|
+
* and reused independently of the CDP session lifecycle.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Constants
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/** Warnings are emitted when peak usage exceeds this fraction (80%) */
|
|
13
|
+
const WARN_THRESHOLD = 0.8;
|
|
14
|
+
/** Critical warnings are emitted when peak usage exceeds this fraction (95%) */
|
|
15
|
+
const CRITICAL_THRESHOLD = 0.95;
|
|
16
|
+
/** Event names that should typically appear in a complete trace */
|
|
17
|
+
const CRITICAL_TRACE_EVENTS = [
|
|
18
|
+
'navigationStart',
|
|
19
|
+
'firstContentfulPaint',
|
|
20
|
+
'firstPaint',
|
|
21
|
+
'LargestContentfulPaint',
|
|
22
|
+
];
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Public API
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Analyse collected buffer-usage samples and return human-readable warnings
|
|
28
|
+
* when the ring buffer exceeded safe thresholds.
|
|
29
|
+
*
|
|
30
|
+
* @param samples - Array of buffer usage samples from `Tracing.bufferUsage`
|
|
31
|
+
* @returns Warning strings (empty array = buffer health OK)
|
|
32
|
+
*/
|
|
33
|
+
export function checkBufferHealth(samples) {
|
|
34
|
+
const warnings = [];
|
|
35
|
+
if (samples.length === 0) {
|
|
36
|
+
return warnings;
|
|
37
|
+
}
|
|
38
|
+
const peakUsage = Math.max(...samples.map((s) => s.value));
|
|
39
|
+
if (peakUsage >= CRITICAL_THRESHOLD) {
|
|
40
|
+
warnings.push(`Trace buffer usage reached ${Math.round(peakUsage * 100)}% — data is very likely incomplete. ` +
|
|
41
|
+
'Consider reducing trace categories or increasing the buffer size.');
|
|
42
|
+
}
|
|
43
|
+
else if (peakUsage > WARN_THRESHOLD) {
|
|
44
|
+
warnings.push(`Trace buffer usage reached ${Math.round(peakUsage * 100)}% — data may be incomplete.`);
|
|
45
|
+
}
|
|
46
|
+
return warnings;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Validate trace completeness by checking for expected critical event names.
|
|
50
|
+
*
|
|
51
|
+
* @param eventNames - Set or array of event name strings present in a trace
|
|
52
|
+
* @returns Warning strings for each missing critical event type
|
|
53
|
+
*/
|
|
54
|
+
export function validateTraceCompleteness(eventNames) {
|
|
55
|
+
const warnings = [];
|
|
56
|
+
const present = eventNames instanceof Set ? eventNames : new Set(eventNames);
|
|
57
|
+
const missing = [];
|
|
58
|
+
for (const eventName of CRITICAL_TRACE_EVENTS) {
|
|
59
|
+
if (!present.has(eventName)) {
|
|
60
|
+
missing.push(eventName);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (missing.length > 0) {
|
|
64
|
+
warnings.push(`Trace may be incomplete — missing expected events: ${missing.join(', ')}. ` +
|
|
65
|
+
'This may be normal for early-page-load traces.');
|
|
66
|
+
}
|
|
67
|
+
return warnings;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=buffer-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer-monitor.js","sourceRoot":"","sources":["../../src/collect/buffer-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,uEAAuE;AACvE,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B,gFAAgF;AAChF,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,mEAAmE;AACnE,MAAM,qBAAqB,GAAG;IAC5B,iBAAiB;IACjB,sBAAsB;IACtB,YAAY;IACZ,wBAAwB;CAChB,CAAC;AAEX,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA4B;IAC5D,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAE3D,IAAI,SAAS,IAAI,kBAAkB,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CACX,8BAA8B,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,sCAAsC;YAC7F,mEAAmE,CACtE,CAAC;IACJ,CAAC;SAAM,IAAI,SAAS,GAAG,cAAc,EAAE,CAAC;QACtC,QAAQ,CAAC,IAAI,CACX,8BAA8B,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,6BAA6B,CACvF,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,UAAkC;IAC1E,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,UAAU,YAAY,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,SAAS,IAAI,qBAAqB,EAAE,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CACX,sDAAsD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAC1E,gDAAgD,CACnD,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConsoleCollector — captures console API calls from the page via CDP.
|
|
3
|
+
*
|
|
4
|
+
* Listens for Runtime.consoleAPICalled events and records each entry
|
|
5
|
+
* with its type, arguments, timestamp, and optional stack trace.
|
|
6
|
+
* Groups entries by severity for quick analysis.
|
|
7
|
+
*/
|
|
8
|
+
import { type CDPSession } from 'playwright';
|
|
9
|
+
import type { Collector, CollectorResult, ConsoleRawData } from './types.js';
|
|
10
|
+
import type { CollectorRunOptions } from '../shared/types.js';
|
|
11
|
+
export declare class ConsoleCollector implements Collector {
|
|
12
|
+
readonly name = "console";
|
|
13
|
+
private session;
|
|
14
|
+
private entries;
|
|
15
|
+
/**
|
|
16
|
+
* Start collecting console API calls.
|
|
17
|
+
* Enables Runtime domain and subscribes to consoleAPICalled events.
|
|
18
|
+
*/
|
|
19
|
+
start(session: CDPSession, _options?: CollectorRunOptions): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Stop collecting and return console data with severity counts.
|
|
22
|
+
*/
|
|
23
|
+
stop(): Promise<CollectorResult<ConsoleRawData>>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=console.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/collect/console.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAgB,MAAM,YAAY,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,qBAAa,gBAAiB,YAAW,SAAS;IAChD,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAAiC;IAEhD;;;OAGG;IACG,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC/E;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;CA4BvD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConsoleCollector — captures console API calls from the page via CDP.
|
|
3
|
+
*
|
|
4
|
+
* Listens for Runtime.consoleAPICalled events and records each entry
|
|
5
|
+
* with its type, arguments, timestamp, and optional stack trace.
|
|
6
|
+
* Groups entries by severity for quick analysis.
|
|
7
|
+
*/
|
|
8
|
+
import {} from 'playwright';
|
|
9
|
+
export class ConsoleCollector {
|
|
10
|
+
name = 'console';
|
|
11
|
+
session = null;
|
|
12
|
+
entries = [];
|
|
13
|
+
/**
|
|
14
|
+
* Start collecting console API calls.
|
|
15
|
+
* Enables Runtime domain and subscribes to consoleAPICalled events.
|
|
16
|
+
*/
|
|
17
|
+
async start(session, _options) {
|
|
18
|
+
this.session = session;
|
|
19
|
+
this.entries = [];
|
|
20
|
+
// Ensure Runtime domain is enabled for console API events
|
|
21
|
+
await session.send('Runtime.enable');
|
|
22
|
+
// Capture every console API call
|
|
23
|
+
session.on('Runtime.consoleAPICalled', (event) => {
|
|
24
|
+
// Serialise arguments: prefer value, fall back to description, then type hint
|
|
25
|
+
const args = (event.args ?? []).map((a) => a.value ?? a.description ?? `<${a.type}>`);
|
|
26
|
+
const entry = {
|
|
27
|
+
// CDP timestamp is in seconds; convert to milliseconds
|
|
28
|
+
timestamp: event.timestamp * 1000,
|
|
29
|
+
type: event.type,
|
|
30
|
+
args,
|
|
31
|
+
stackTrace: event.stackTrace?.callFrames?.map((f) => ({
|
|
32
|
+
url: f.url,
|
|
33
|
+
lineNumber: f.lineNumber,
|
|
34
|
+
columnNumber: f.columnNumber,
|
|
35
|
+
functionName: f.functionName,
|
|
36
|
+
})),
|
|
37
|
+
};
|
|
38
|
+
this.entries.push(entry);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Stop collecting and return console data with severity counts.
|
|
43
|
+
*/
|
|
44
|
+
async stop() {
|
|
45
|
+
if (!this.session) {
|
|
46
|
+
return { ok: false, error: 'ConsoleCollector: session not initialised' };
|
|
47
|
+
}
|
|
48
|
+
// Compute severity counts
|
|
49
|
+
const counts = { log: 0, warn: 0, error: 0, info: 0, debug: 0, other: 0 };
|
|
50
|
+
for (const entry of this.entries) {
|
|
51
|
+
switch (entry.type) {
|
|
52
|
+
case 'log':
|
|
53
|
+
counts.log++;
|
|
54
|
+
break;
|
|
55
|
+
case 'warn':
|
|
56
|
+
counts.warn++;
|
|
57
|
+
break;
|
|
58
|
+
case 'error':
|
|
59
|
+
counts.error++;
|
|
60
|
+
break;
|
|
61
|
+
case 'info':
|
|
62
|
+
counts.info++;
|
|
63
|
+
break;
|
|
64
|
+
case 'debug':
|
|
65
|
+
counts.debug++;
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
counts.other++;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
ok: true,
|
|
74
|
+
data: {
|
|
75
|
+
entries: this.entries,
|
|
76
|
+
counts,
|
|
77
|
+
warnings: [],
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/collect/console.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAmB,MAAM,YAAY,CAAC;AAI7C,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAG,SAAS,CAAC;IAElB,OAAO,GAAsB,IAAI,CAAC;IAClC,OAAO,GAA8B,EAAE,CAAC;IAEhD;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,OAAmB,EAAE,QAA8B;QAC7D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAElB,0DAA0D;QAC1D,MAAM,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAErC,iCAAiC;QACjC,OAAO,CAAC,EAAE,CAAC,0BAA0B,EAAE,CAAC,KAKvC,EAAE,EAAE;YACH,8EAA8E;YAC9E,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,IAAI,GAAG,CACjD,CAAC;YAEF,MAAM,KAAK,GAAsC;gBAC/C,uDAAuD;gBACvD,SAAS,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;gBACjC,IAAI,EAAE,KAAK,CAAC,IAAiD;gBAC7D,IAAI;gBACJ,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACpD,GAAG,EAAE,CAAC,CAAC,GAAG;oBACV,UAAU,EAAE,CAAC,CAAC,UAAU;oBACxB,YAAY,EAAE,CAAC,CAAC,YAAY;oBAC5B,YAAY,EAAE,CAAC,CAAC,YAAY;iBAC7B,CAAC,CAAC;aACJ,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2CAA2C,EAAE,CAAC;QAC3E,CAAC;QAED,0BAA0B;QAC1B,MAAM,MAAM,GAA6B,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAEpG,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;gBACnB,KAAK,KAAK;oBAAI,MAAM,CAAC,GAAG,EAAE,CAAC;oBAAG,MAAM;gBACpC,KAAK,MAAM;oBAAG,MAAM,CAAC,IAAI,EAAE,CAAC;oBAAE,MAAM;gBACpC,KAAK,OAAO;oBAAE,MAAM,CAAC,KAAK,EAAE,CAAC;oBAAC,MAAM;gBACpC,KAAK,MAAM;oBAAG,MAAM,CAAC,IAAI,EAAE,CAAC;oBAAE,MAAM;gBACpC,KAAK,OAAO;oBAAE,MAAM,CAAC,KAAK,EAAE,CAAC;oBAAC,MAAM;gBACpC;oBAAc,MAAM,CAAC,KAAK,EAAE,CAAC;oBAAC,MAAM;YACtC,CAAC;QACH,CAAC;QAED,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE;gBACJ,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,MAAM;gBACN,QAAQ,EAAE,EAAE;aACb;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CoverageCollector — captures JavaScript and CSS code coverage via CDP.
|
|
3
|
+
*
|
|
4
|
+
* Uses Profiler.startPreciseCoverage for JS and CSS.startRuleUsageTracking
|
|
5
|
+
* for stylesheets. Both are started pre-navigation and stopped post-navigation
|
|
6
|
+
* to capture coverage data for the full page lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
import { type CDPSession } from 'playwright';
|
|
9
|
+
import type { Collector, CollectorResult, CoverageRawData } from './types.js';
|
|
10
|
+
import type { CollectorRunOptions } from '../shared/types.js';
|
|
11
|
+
export declare class CoverageCollector implements Collector {
|
|
12
|
+
readonly name = "coverage";
|
|
13
|
+
private session;
|
|
14
|
+
/**
|
|
15
|
+
* Start collecting coverage data.
|
|
16
|
+
* Enables Profiler and CSS domains, then starts precise JS coverage
|
|
17
|
+
* and CSS rule usage tracking.
|
|
18
|
+
*/
|
|
19
|
+
start(session: CDPSession, _options?: CollectorRunOptions): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Stop collecting and return coverage data.
|
|
22
|
+
* Takes precise JS coverage + CSS rule usage, then stops both trackers.
|
|
23
|
+
*/
|
|
24
|
+
stop(): Promise<CollectorResult<CoverageRawData>>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/collect/coverage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAiC,MAAM,YAAY,CAAC;AAC7G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,qBAAa,iBAAkB,YAAW,SAAS;IACjD,QAAQ,CAAC,IAAI,cAAc;IAE3B,OAAO,CAAC,OAAO,CAA2B;IAE1C;;;;OAIG;IACG,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB/E;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;CAiFxD"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CoverageCollector — captures JavaScript and CSS code coverage via CDP.
|
|
3
|
+
*
|
|
4
|
+
* Uses Profiler.startPreciseCoverage for JS and CSS.startRuleUsageTracking
|
|
5
|
+
* for stylesheets. Both are started pre-navigation and stopped post-navigation
|
|
6
|
+
* to capture coverage data for the full page lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
import {} from 'playwright';
|
|
9
|
+
export class CoverageCollector {
|
|
10
|
+
name = 'coverage';
|
|
11
|
+
session = null;
|
|
12
|
+
/**
|
|
13
|
+
* Start collecting coverage data.
|
|
14
|
+
* Enables Profiler and CSS domains, then starts precise JS coverage
|
|
15
|
+
* and CSS rule usage tracking.
|
|
16
|
+
*/
|
|
17
|
+
async start(session, _options) {
|
|
18
|
+
this.session = session;
|
|
19
|
+
// Enable required domains (CSS.enable requires DOM.enable first)
|
|
20
|
+
await session.send('DOM.enable');
|
|
21
|
+
await session.send('Profiler.enable');
|
|
22
|
+
await session.send('CSS.enable');
|
|
23
|
+
// Start precise JS coverage (detailed = true gives per-byte ranges)
|
|
24
|
+
await session.send('Profiler.startPreciseCoverage', {
|
|
25
|
+
callCount: false,
|
|
26
|
+
detailed: true,
|
|
27
|
+
});
|
|
28
|
+
// Start CSS rule usage tracking
|
|
29
|
+
await session.send('CSS.startRuleUsageTracking');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Stop collecting and return coverage data.
|
|
33
|
+
* Takes precise JS coverage + CSS rule usage, then stops both trackers.
|
|
34
|
+
*/
|
|
35
|
+
async stop() {
|
|
36
|
+
if (!this.session) {
|
|
37
|
+
return { ok: false, error: 'CoverageCollector: session not initialised' };
|
|
38
|
+
}
|
|
39
|
+
const warnings = [];
|
|
40
|
+
let js = [];
|
|
41
|
+
let css = [];
|
|
42
|
+
// --- Collect JS coverage ---
|
|
43
|
+
try {
|
|
44
|
+
const jsResult = await this.session.send('Profiler.takePreciseCoverage');
|
|
45
|
+
js = (jsResult.result ?? []).map((entry) => ({
|
|
46
|
+
scriptId: entry.scriptId,
|
|
47
|
+
url: entry.url,
|
|
48
|
+
functions: entry.functions.map((f) => ({
|
|
49
|
+
functionName: f.functionName,
|
|
50
|
+
ranges: f.ranges.map((r) => ({
|
|
51
|
+
startOffset: r.startOffset,
|
|
52
|
+
endOffset: r.endOffset,
|
|
53
|
+
count: r.count,
|
|
54
|
+
})),
|
|
55
|
+
isBlockCoverage: f.isBlockCoverage,
|
|
56
|
+
})),
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
warnings.push(`Failed to collect JS coverage: ${String(error)}`);
|
|
61
|
+
}
|
|
62
|
+
// --- Collect CSS coverage ---
|
|
63
|
+
try {
|
|
64
|
+
const cssResult = await this.session.send('CSS.stopRuleUsageTracking');
|
|
65
|
+
// CSS rule usage entries have styleSheetId + ranges but not the URL
|
|
66
|
+
// directly at the rule level — group them by styleSheetId
|
|
67
|
+
const cssBySheet = new Map();
|
|
68
|
+
const rawEntries = cssResult.ruleUsage ?? [];
|
|
69
|
+
for (const entry of rawEntries) {
|
|
70
|
+
let sheet = cssBySheet.get(entry.styleSheetId);
|
|
71
|
+
if (!sheet) {
|
|
72
|
+
sheet = { styleSheetId: entry.styleSheetId, url: '', ranges: [] };
|
|
73
|
+
cssBySheet.set(entry.styleSheetId, sheet);
|
|
74
|
+
}
|
|
75
|
+
sheet.ranges.push({
|
|
76
|
+
startOffset: entry.startOffset,
|
|
77
|
+
endOffset: entry.endOffset,
|
|
78
|
+
count: entry.used ? 1 : 0,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
css = [...cssBySheet.values()];
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
warnings.push(`Failed to collect CSS coverage: ${String(error)}`);
|
|
85
|
+
}
|
|
86
|
+
// --- Clean up JS profiler ---
|
|
87
|
+
try {
|
|
88
|
+
await this.session.send('Profiler.stopPreciseCoverage');
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Non-critical cleanup
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
ok: true,
|
|
95
|
+
data: { js, css, warnings },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/collect/coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
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 { type CDPSession, type Page } from 'playwright';
|
|
14
|
+
import type { Collector, CollectorResult, DomRawData } from './types.js';
|
|
15
|
+
import type { CollectorRunOptions } from '../shared/types.js';
|
|
16
|
+
export declare class DOMCollector implements Collector {
|
|
17
|
+
private readonly page;
|
|
18
|
+
readonly name = "dom";
|
|
19
|
+
private session;
|
|
20
|
+
/**
|
|
21
|
+
* @param page - Playwright Page instance used for evaluate() calls.
|
|
22
|
+
* The page reference is required because DOM stats are
|
|
23
|
+
* extracted via in-page JavaScript, not CDP commands.
|
|
24
|
+
*/
|
|
25
|
+
constructor(page: Page);
|
|
26
|
+
/**
|
|
27
|
+
* Start collecting DOM data.
|
|
28
|
+
* Currently a no-op — DOM snapshot is taken on stop() after navigation.
|
|
29
|
+
*/
|
|
30
|
+
start(session: CDPSession, _options?: CollectorRunOptions): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Stop collecting and return DOM metadata.
|
|
33
|
+
* Runs page.evaluate() to extract aggregate DOM statistics.
|
|
34
|
+
*/
|
|
35
|
+
stop(): Promise<CollectorResult<DomRawData>>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/collect/dom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,qBAAa,YAAa,YAAW,SAAS;IAUhC,OAAO,CAAC,QAAQ,CAAC,IAAI;IATjC,QAAQ,CAAC,IAAI,SAAS;IAEtB,OAAO,CAAC,OAAO,CAA2B;IAE1C;;;;OAIG;gBAC0B,IAAI,EAAE,IAAI;IAEvC;;;OAGG;IACG,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/E;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;CA6FnD"}
|