nfunc-mcp 0.3.0 → 0.5.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/README.md +121 -379
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mappers/a11yDedupe.js +38 -7
- package/dist/mappers/a11yDedupe.js.map +1 -1
- package/dist/mappers/defectFormatter.d.ts +9 -1
- package/dist/mappers/defectFormatter.js +53 -13
- package/dist/mappers/defectFormatter.js.map +1 -1
- package/dist/mappers/labFieldComparator.d.ts +62 -0
- package/dist/mappers/labFieldComparator.js +134 -0
- package/dist/mappers/labFieldComparator.js.map +1 -0
- package/dist/mappers/priorityMapper.d.ts +42 -0
- package/dist/mappers/priorityMapper.js +58 -0
- package/dist/mappers/priorityMapper.js.map +1 -1
- package/dist/mappers/psiAggregator.d.ts +130 -0
- package/dist/mappers/psiAggregator.js +293 -0
- package/dist/mappers/psiAggregator.js.map +1 -0
- package/dist/mappers/runComparator.d.ts +85 -0
- package/dist/mappers/runComparator.js +165 -0
- package/dist/mappers/runComparator.js.map +1 -0
- package/dist/mappers/wcagLevels.d.ts +73 -0
- package/dist/mappers/wcagLevels.js +320 -0
- package/dist/mappers/wcagLevels.js.map +1 -0
- package/dist/mappers/webVitalsMapper.d.ts +52 -0
- package/dist/mappers/webVitalsMapper.js +131 -0
- package/dist/mappers/webVitalsMapper.js.map +1 -0
- package/dist/tools/accessibility.d.ts +1 -0
- package/dist/tools/accessibility.js +488 -63
- package/dist/tools/accessibility.js.map +1 -1
- package/dist/tools/lighthouse.js +370 -102
- package/dist/tools/lighthouse.js.map +1 -1
- package/dist/tools/performanceAudit.d.ts +2 -0
- package/dist/tools/performanceAudit.js +446 -0
- package/dist/tools/performanceAudit.js.map +1 -0
- package/dist/tools/performanceAuditPlan.d.ts +2 -0
- package/dist/tools/performanceAuditPlan.js +438 -0
- package/dist/tools/performanceAuditPlan.js.map +1 -0
- package/dist/utils/batchState.d.ts +75 -0
- package/dist/utils/batchState.js +128 -0
- package/dist/utils/batchState.js.map +1 -0
- package/dist/utils/csvReader.d.ts +20 -0
- package/dist/utils/csvReader.js +172 -0
- package/dist/utils/csvReader.js.map +1 -0
- package/dist/utils/httpClient.d.ts +84 -0
- package/dist/utils/httpClient.js +171 -0
- package/dist/utils/httpClient.js.map +1 -0
- package/dist/utils/outputParsers.js +26 -30
- package/dist/utils/outputParsers.js.map +1 -1
- package/dist/utils/psiAuth.d.ts +26 -0
- package/dist/utils/psiAuth.js +36 -0
- package/dist/utils/psiAuth.js.map +1 -0
- package/dist/utils/psiParser.d.ts +135 -0
- package/dist/utils/psiParser.js +200 -0
- package/dist/utils/psiParser.js.map +1 -0
- package/dist/utils/publicUrl.d.ts +17 -0
- package/dist/utils/publicUrl.js +115 -0
- package/dist/utils/publicUrl.js.map +1 -0
- package/dist/utils/sitemapReader.d.ts +27 -0
- package/dist/utils/sitemapReader.js +272 -0
- package/dist/utils/sitemapReader.js.map +1 -0
- package/dist/utils/urlClassifier.d.ts +45 -0
- package/dist/utils/urlClassifier.js +267 -0
- package/dist/utils/urlClassifier.js.map +1 -0
- package/dist/utils/urlInput.d.ts +30 -0
- package/dist/utils/urlInput.js +130 -0
- package/dist/utils/urlInput.js.map +1 -0
- package/docs/manual.md +769 -0
- package/docs/psi-report-spec.md +174 -0
- package/package.json +13 -3
package/dist/tools/lighthouse.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
1
3
|
import { z } from "zod";
|
|
2
4
|
import { runShell } from "../utils/shellRunner.js";
|
|
3
5
|
import { parseLighthouseJSON } from "../utils/outputParsers.js";
|
|
6
|
+
import { extractLabMetrics } from "../utils/psiParser.js";
|
|
7
|
+
import { resolveUrlInputs } from "../utils/urlInput.js";
|
|
8
|
+
import { compareRuns } from "../mappers/runComparator.js";
|
|
9
|
+
import { classifyUrls } from "../utils/urlClassifier.js";
|
|
10
|
+
import { aggregate } from "../mappers/psiAggregator.js";
|
|
11
|
+
import { DEFAULT_MAX_SECONDS_PER_CALL, decodeCursor, encodeCursor, elapsedSeconds, filterCompleted, hasBudget, mergeIndex, readIndex, slugForUrl, } from "../utils/batchState.js";
|
|
4
12
|
import { shellErrorResponse, parseErrorResponse, } from "../utils/toolResponse.js";
|
|
5
13
|
import { formatLighthouseFinding } from "../mappers/defectFormatter.js";
|
|
6
14
|
import { sortFindingsByPriority } from "../mappers/priorityMapper.js";
|
|
@@ -19,8 +27,36 @@ import { sortFindingsByPriority } from "../mappers/priorityMapper.js";
|
|
|
19
27
|
export function formFactorArgs(ff) {
|
|
20
28
|
return ff === "desktop" ? ["--preset=desktop"] : ["--form-factor=mobile"];
|
|
21
29
|
}
|
|
30
|
+
/** A single local Lighthouse run, measured. Used to reserve chunk budget. */
|
|
31
|
+
const TYPICAL_RUN_MS = 40_000;
|
|
32
|
+
const DEFAULT_OUTPUT_DIR = "./lighthouse-reports";
|
|
22
33
|
const inputShape = {
|
|
23
|
-
url: z
|
|
34
|
+
url: z
|
|
35
|
+
.string()
|
|
36
|
+
.min(1)
|
|
37
|
+
.describe("One URL, several comma- or newline-separated URLs, or a path to a CSV " +
|
|
38
|
+
"containing a URL column. More than one URL switches the tool into " +
|
|
39
|
+
"batch mode: results are written to output_dir and a cursor is " +
|
|
40
|
+
"returned to continue with."),
|
|
41
|
+
urls: z
|
|
42
|
+
.array(z.string())
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("Explicit URL list, as an alternative to packing them into `url`."),
|
|
45
|
+
output_dir: z.string().optional(),
|
|
46
|
+
cursor: z.string().optional().describe("Resume token from a previous batch call."),
|
|
47
|
+
max_seconds_per_call: z.number().int().min(30).max(900).optional(),
|
|
48
|
+
skip_completed: z
|
|
49
|
+
.boolean()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe("Batch mode only. Skip URL/form-factor pairs already in the output " +
|
|
52
|
+
"index (default true), so re-running fills gaps instead of redoing work."),
|
|
53
|
+
baseline_dir: z
|
|
54
|
+
.string()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Compare this run against a previous run's index: which audits were " +
|
|
57
|
+
"fixed, which still fail, which are newly introduced, and how each " +
|
|
58
|
+
"category score moved. Point it at an earlier output_dir. May be the " +
|
|
59
|
+
"same as output_dir; the baseline is read before anything is written."),
|
|
24
60
|
categories: z.array(z.string()).optional(),
|
|
25
61
|
thresholds: z.record(z.string(), z.number()).optional(),
|
|
26
62
|
form_factor: z
|
|
@@ -36,126 +72,358 @@ const inputShape = {
|
|
|
36
72
|
"device-specific, since the two profiles render different DOM and " +
|
|
37
73
|
"genuinely find different accessibility and SEO problems."),
|
|
38
74
|
};
|
|
75
|
+
/** One Lighthouse invocation. Returns the parsed report and the raw LHR. */
|
|
76
|
+
async function runLighthouseOnce(url, factor, categories) {
|
|
77
|
+
const args = [
|
|
78
|
+
url,
|
|
79
|
+
"--output=json",
|
|
80
|
+
"--quiet",
|
|
81
|
+
"--chrome-flags=--headless",
|
|
82
|
+
...formFactorArgs(factor),
|
|
83
|
+
];
|
|
84
|
+
if (categories && categories.length > 0) {
|
|
85
|
+
args.push(`--only-categories=${categories.join(",")}`);
|
|
86
|
+
}
|
|
87
|
+
const result = await runShell("lighthouse", args, { timeoutMs: 180_000 });
|
|
88
|
+
if (!result.stdout)
|
|
89
|
+
return { result };
|
|
90
|
+
try {
|
|
91
|
+
return { run: { factor, parsed: parseLighthouseJSON(result.stdout), raw: result.stdout }, result };
|
|
92
|
+
}
|
|
93
|
+
catch (parseError) {
|
|
94
|
+
return { result, parseError };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function buildFindings(parsed, thresholds) {
|
|
98
|
+
const out = [];
|
|
99
|
+
for (const audit of parsed.failedAudits) {
|
|
100
|
+
const threshold = thresholds?.[audit.id];
|
|
101
|
+
if (typeof threshold === "number" && audit.score >= threshold)
|
|
102
|
+
continue;
|
|
103
|
+
const finding = formatLighthouseFinding(audit);
|
|
104
|
+
if (finding)
|
|
105
|
+
out.push(finding);
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Merge findings across form factors on audit id, recording which profiles each
|
|
111
|
+
* affects so "fails on desktop only" is readable straight off the finding.
|
|
112
|
+
*/
|
|
113
|
+
function mergeAcrossFactors(runs, thresholds) {
|
|
114
|
+
const merged = new Map();
|
|
115
|
+
for (const { factor, parsed } of runs) {
|
|
116
|
+
for (const finding of buildFindings(parsed, thresholds)) {
|
|
117
|
+
const key = String(finding.evidence["audit_id"]);
|
|
118
|
+
const existing = merged.get(key);
|
|
119
|
+
if (existing)
|
|
120
|
+
existing._ff.push(factor);
|
|
121
|
+
else
|
|
122
|
+
merged.set(key, { ...finding, _ff: [factor] });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const findings = [...merged.values()].map(({ _ff, ...finding }) => ({
|
|
126
|
+
...finding,
|
|
127
|
+
evidence: {
|
|
128
|
+
...finding.evidence,
|
|
129
|
+
affects_form_factors: _ff,
|
|
130
|
+
form_factor_specific: _ff.length === 1,
|
|
131
|
+
},
|
|
132
|
+
}));
|
|
133
|
+
return sortFindingsByPriority(findings);
|
|
134
|
+
}
|
|
135
|
+
const auditIdOf = (f) => String(f.evidence["audit_id"] ?? f.title);
|
|
136
|
+
function toDefects(findings) {
|
|
137
|
+
return findings.map((f) => ({ id: auditIdOf(f), priority: f.priority, title: f.title }));
|
|
138
|
+
}
|
|
139
|
+
function recordsToDefectRefs(records) {
|
|
140
|
+
const refs = [];
|
|
141
|
+
for (const record of records) {
|
|
142
|
+
for (const d of record.defects ?? []) {
|
|
143
|
+
refs.push({ url: record.url, variant: record.variant, id: d.id, priority: d.priority, title: d.title });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return refs;
|
|
147
|
+
}
|
|
148
|
+
/** Category scores keyed url|variant, for the score-delta half of a comparison. */
|
|
149
|
+
function recordsToScores(records) {
|
|
150
|
+
return new Map(records.map((r) => [`${r.url}|${r.variant}`, r.scores]));
|
|
151
|
+
}
|
|
152
|
+
const text = (payload) => ({
|
|
153
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
|
|
154
|
+
});
|
|
39
155
|
export function registerLighthouseTool(server) {
|
|
40
156
|
server.registerTool("run_lighthouse", {
|
|
41
|
-
description: "Runs Google Lighthouse
|
|
42
|
-
"
|
|
157
|
+
description: "Runs Google Lighthouse and returns a QA-style report with category " +
|
|
158
|
+
"scores, TTFB, and prioritised findings (P1/P2/P3). " +
|
|
159
|
+
"\n\n" +
|
|
160
|
+
"**Accepts one URL, a comma- or newline-separated list, or a path to a " +
|
|
161
|
+
"CSV with a URL column.** A single URL returns one report immediately. " +
|
|
162
|
+
"Several URLs switch to batch mode: each report is written to " +
|
|
163
|
+
"`output_dir`, a running `_index.json` accumulates, a `cursor` is " +
|
|
164
|
+
"returned to continue with, and the final call adds an `aggregate` " +
|
|
165
|
+
"block with cross-page means, per-template rollups and outliers — " +
|
|
166
|
+
"quote those rather than recomputing them. Re-run with the same URLs " +
|
|
167
|
+
"and no cursor to fill any gaps; completed work is skipped. " +
|
|
43
168
|
"\n\n" +
|
|
44
|
-
"`form_factor` selects the device profile: '
|
|
45
|
-
"throttled slow 4G
|
|
46
|
-
"'both'. **Prefer 'both' when auditing
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"form factor and each finding carries affects_form_factors plus " +
|
|
50
|
-
"form_factor_specific, so device-only regressions are obvious. " +
|
|
169
|
+
"`form_factor` selects the device profile: 'desktop' (default, " +
|
|
170
|
+
"unthrottled), 'mobile' (throttled slow 4G, 4x CPU slowdown), or " +
|
|
171
|
+
"'both'. **Prefer 'both' when auditing properly** — the two profiles " +
|
|
172
|
+
"render different DOM and find different defects, not just different " +
|
|
173
|
+
"performance numbers. " +
|
|
51
174
|
"\n\n" +
|
|
52
175
|
"Requires the Lighthouse CLI on PATH (`npm install -g lighthouse`) " +
|
|
53
|
-
"and a Chrome/Chromium binary
|
|
176
|
+
"and a Chrome/Chromium binary.",
|
|
54
177
|
inputSchema: inputShape,
|
|
55
|
-
}, async ({ url, categories, thresholds, form_factor }) => {
|
|
178
|
+
}, async ({ url, urls, categories, thresholds, form_factor, output_dir, cursor, max_seconds_per_call, skip_completed, baseline_dir, }) => {
|
|
56
179
|
const requested = form_factor ?? "desktop";
|
|
57
180
|
const factors = requested === "both" ? ["mobile", "desktop"] : [requested];
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
...
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
181
|
+
let resolved;
|
|
182
|
+
try {
|
|
183
|
+
resolved = resolveUrlInputs(url, urls);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
return {
|
|
187
|
+
...text({ error: "unusable_url_input", message: err.message }),
|
|
188
|
+
isError: true,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const warnings = [...resolved.warnings];
|
|
192
|
+
// Read the baseline before anything is written, so baseline_dir may be
|
|
193
|
+
// the same directory as output_dir.
|
|
194
|
+
const baselineRecords = baseline_dir
|
|
195
|
+
? await readIndex(resolve(baseline_dir))
|
|
196
|
+
: null;
|
|
197
|
+
if (baseline_dir && baselineRecords && baselineRecords.length === 0) {
|
|
198
|
+
warnings.push(`No previous results found in ${resolve(baseline_dir)} — nothing to compare against. ` +
|
|
199
|
+
"Run once with output_dir set to create a baseline.");
|
|
200
|
+
}
|
|
201
|
+
const compareWith = async (records) => {
|
|
202
|
+
if (!baselineRecords)
|
|
203
|
+
return undefined;
|
|
204
|
+
const result = compareRuns(resolve(baseline_dir), recordsToDefectRefs(baselineRecords), recordsToDefectRefs(records), {
|
|
205
|
+
baselineScores: recordsToScores(baselineRecords),
|
|
206
|
+
currentScores: recordsToScores(records),
|
|
207
|
+
});
|
|
208
|
+
warnings.push(...result.warnings);
|
|
209
|
+
const { warnings: _dropped, ...rest } = result;
|
|
210
|
+
return rest;
|
|
70
211
|
};
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
212
|
+
// ---- Single URL: unchanged contract ------------------------------
|
|
213
|
+
if (resolved.urls.length === 1) {
|
|
214
|
+
const target = resolved.urls[0];
|
|
215
|
+
const outcomes = await Promise.all(factors.map((factor) => runLighthouseOnce(target, factor, categories)));
|
|
216
|
+
const good = outcomes.filter((o) => o.run).map((o) => o.run);
|
|
217
|
+
if (good.length === 0) {
|
|
218
|
+
const first = outcomes[0];
|
|
219
|
+
return first.parseError
|
|
220
|
+
? parseErrorResponse("Failed to parse Lighthouse JSON", first.parseError, first.result)
|
|
221
|
+
: shellErrorResponse("Lighthouse produced no JSON output", first.result);
|
|
222
|
+
}
|
|
223
|
+
// Per-factor records, so a single-URL run can seed or be compared to a
|
|
224
|
+
// baseline exactly like a batch one.
|
|
225
|
+
const singleRecords = good.map(({ factor, parsed, raw }) => {
|
|
226
|
+
const findings = sortFindingsByPriority(buildFindings(parsed, thresholds));
|
|
227
|
+
return {
|
|
228
|
+
url: target,
|
|
229
|
+
variant: factor,
|
|
230
|
+
scores: parsed.categoryScores,
|
|
231
|
+
ttfb_ms: parsed.ttfbMs,
|
|
232
|
+
lab: extractLabMetrics(raw),
|
|
233
|
+
finding_count: findings.length,
|
|
234
|
+
p1_count: findings.filter((f) => f.priority === "P1").length,
|
|
235
|
+
defects: toDefects(findings),
|
|
236
|
+
report_file: "",
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
// Only touches disk when asked to: a one-off check stays a one-off.
|
|
240
|
+
let indexFile;
|
|
241
|
+
if (output_dir) {
|
|
242
|
+
const dir = resolve(output_dir);
|
|
243
|
+
await mkdir(dir, { recursive: true });
|
|
244
|
+
for (const [i, { factor, raw }] of good.entries()) {
|
|
245
|
+
const file = `${slugForUrl(target)}_${factor}.json`;
|
|
246
|
+
singleRecords[i].report_file = file;
|
|
247
|
+
await writeFile(join(dir, file), raw, "utf8");
|
|
78
248
|
}
|
|
79
|
-
|
|
249
|
+
indexFile = (await mergeIndex(dir, singleRecords)).indexPath;
|
|
80
250
|
}
|
|
81
|
-
|
|
82
|
-
|
|
251
|
+
const comparison = await compareWith(singleRecords);
|
|
252
|
+
const persisted = indexFile
|
|
253
|
+
? { output_dir: resolve(output_dir), index_file: indexFile }
|
|
254
|
+
: {};
|
|
255
|
+
if (factors.length === 1) {
|
|
256
|
+
const { parsed } = good[0];
|
|
257
|
+
return text({
|
|
258
|
+
url: target,
|
|
259
|
+
form_factor: factors[0],
|
|
260
|
+
scores: parsed.categoryScores,
|
|
261
|
+
ttfb_ms: parsed.ttfbMs,
|
|
262
|
+
findings: sortFindingsByPriority(buildFindings(parsed, thresholds)),
|
|
263
|
+
...persisted,
|
|
264
|
+
...(comparison ? { comparison } : {}),
|
|
265
|
+
...(warnings.length ? { warnings } : {}),
|
|
266
|
+
});
|
|
83
267
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
268
|
+
const scores = {};
|
|
269
|
+
const ttfb = {};
|
|
270
|
+
for (const { factor, parsed } of good) {
|
|
271
|
+
scores[factor] = parsed.categoryScores;
|
|
272
|
+
ttfb[factor] = parsed.ttfbMs;
|
|
88
273
|
}
|
|
274
|
+
return text({
|
|
275
|
+
url: target,
|
|
276
|
+
form_factor: "both",
|
|
277
|
+
form_factors_run: good.map((g) => g.factor),
|
|
278
|
+
scores,
|
|
279
|
+
ttfb_ms: ttfb,
|
|
280
|
+
findings: mergeAcrossFactors(good, thresholds),
|
|
281
|
+
...persisted,
|
|
282
|
+
...(comparison ? { comparison } : {}),
|
|
283
|
+
...(warnings.length ? { warnings } : {}),
|
|
284
|
+
});
|
|
89
285
|
}
|
|
90
|
-
|
|
91
|
-
|
|
286
|
+
// ---- Batch -------------------------------------------------------
|
|
287
|
+
const dir = resolve(output_dir ?? DEFAULT_OUTPUT_DIR);
|
|
288
|
+
// Before anything writes into it. mergeIndex creates it too, but that
|
|
289
|
+
// runs after the loop, which is too late for the first report file.
|
|
290
|
+
await mkdir(dir, { recursive: true });
|
|
291
|
+
const budgetMs = (max_seconds_per_call ?? DEFAULT_MAX_SECONDS_PER_CALL) * 1000;
|
|
292
|
+
const startedAt = Date.now();
|
|
293
|
+
const allUnits = resolved.urls.flatMap((u) => factors.map((factor) => ({ url: u, variant: factor })));
|
|
294
|
+
// When comparing, re-measuring is the point — skipping completed work
|
|
295
|
+
// would compare a run against itself.
|
|
296
|
+
const { units, skipped } = await filterCompleted(dir, allUnits, skip_completed ?? !baseline_dir, cursor);
|
|
297
|
+
if (skipped > 0) {
|
|
298
|
+
warnings.push(`Skipped ${skipped} URL/form-factor pair(s) already in ${join(dir, "_index.json")}. ` +
|
|
299
|
+
"Pass skip_completed:false to re-measure them.");
|
|
92
300
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
out.push(f);
|
|
102
|
-
}
|
|
103
|
-
return out;
|
|
104
|
-
};
|
|
105
|
-
// Single form factor keeps the original flat report shape.
|
|
106
|
-
if (parsedByFactor.size === 1 && factors.length === 1) {
|
|
107
|
-
const parsed = parsedByFactor.get(factors[0]);
|
|
108
|
-
const findings = buildFindings(parsed);
|
|
109
|
-
sortFindingsByPriority(findings);
|
|
110
|
-
return {
|
|
111
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
112
|
-
url,
|
|
113
|
-
form_factor: factors[0],
|
|
114
|
-
scores: parsed.categoryScores,
|
|
115
|
-
ttfb_ms: parsed.ttfbMs,
|
|
116
|
-
findings,
|
|
117
|
-
}, null, 2) }],
|
|
118
|
-
};
|
|
301
|
+
if (units.length === 0) {
|
|
302
|
+
return text({
|
|
303
|
+
complete: true,
|
|
304
|
+
progress: { done: 0, total: 0, failed: 0 },
|
|
305
|
+
message: "Every requested URL/form-factor pair is already in the index.",
|
|
306
|
+
index_file: join(dir, "_index.json"),
|
|
307
|
+
warnings,
|
|
308
|
+
});
|
|
119
309
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
310
|
+
const start = decodeCursor(cursor);
|
|
311
|
+
const records = [];
|
|
312
|
+
const results = [];
|
|
313
|
+
const failures = [];
|
|
314
|
+
let index = start;
|
|
315
|
+
let budgetExhausted = false;
|
|
316
|
+
while (index < units.length) {
|
|
317
|
+
// Sequential, not concurrent. Two Chrome instances on one machine
|
|
318
|
+
// contend for CPU, and this tool's whole job is measuring how long
|
|
319
|
+
// things take — a half-busy machine reports numbers nobody can act on.
|
|
320
|
+
// The single-URL path keeps its concurrency: one page, documented.
|
|
321
|
+
if (!hasBudget(startedAt, budgetMs, TYPICAL_RUN_MS, index - start)) {
|
|
322
|
+
budgetExhausted = true;
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
const unit = units[index];
|
|
326
|
+
const factor = unit.variant;
|
|
327
|
+
const outcome = await runLighthouseOnce(unit.url, factor, categories);
|
|
328
|
+
if (!outcome.run) {
|
|
329
|
+
failures.push({
|
|
330
|
+
url: unit.url,
|
|
331
|
+
form_factor: factor,
|
|
332
|
+
error: outcome.parseError
|
|
333
|
+
? `unparseable Lighthouse JSON: ${outcome.parseError.message}`
|
|
334
|
+
: outcome.result.stderr.slice(0, 300) || `exit ${outcome.result.exitCode}`,
|
|
335
|
+
});
|
|
336
|
+
index++;
|
|
128
337
|
continue;
|
|
129
|
-
scores[ff] = parsed.categoryScores;
|
|
130
|
-
ttfb[ff] = parsed.ttfbMs;
|
|
131
|
-
for (const f of buildFindings(parsed)) {
|
|
132
|
-
const key = String(f.evidence["audit_id"]);
|
|
133
|
-
const existing = merged.get(key);
|
|
134
|
-
if (existing)
|
|
135
|
-
existing._ff.push(ff);
|
|
136
|
-
else
|
|
137
|
-
merged.set(key, { ...f, _ff: [ff] });
|
|
138
338
|
}
|
|
339
|
+
const { parsed, raw } = outcome.run;
|
|
340
|
+
const reportFile = `${slugForUrl(unit.url)}_${factor}.json`;
|
|
341
|
+
// The raw LHR, not the parsed summary: the individual audits are what
|
|
342
|
+
// anyone diagnosing a finding actually needs, and they do not survive
|
|
343
|
+
// parsing. The summary lives in the index.
|
|
344
|
+
await writeFile(join(dir, reportFile), raw, "utf8");
|
|
345
|
+
const findings = sortFindingsByPriority(buildFindings(parsed, thresholds));
|
|
346
|
+
records.push({
|
|
347
|
+
url: unit.url,
|
|
348
|
+
variant: factor,
|
|
349
|
+
scores: parsed.categoryScores,
|
|
350
|
+
ttfb_ms: parsed.ttfbMs,
|
|
351
|
+
lab: extractLabMetrics(raw),
|
|
352
|
+
finding_count: findings.length,
|
|
353
|
+
p1_count: findings.filter((f) => f.priority === "P1").length,
|
|
354
|
+
defects: toDefects(findings),
|
|
355
|
+
report_file: reportFile,
|
|
356
|
+
});
|
|
357
|
+
results.push({
|
|
358
|
+
url: unit.url,
|
|
359
|
+
form_factor: factor,
|
|
360
|
+
scores: parsed.categoryScores,
|
|
361
|
+
ttfb_ms: parsed.ttfbMs,
|
|
362
|
+
findings,
|
|
363
|
+
report_file: reportFile,
|
|
364
|
+
});
|
|
365
|
+
index++;
|
|
139
366
|
}
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
367
|
+
const { indexPath } = await mergeIndex(dir, records);
|
|
368
|
+
const complete = index >= units.length;
|
|
369
|
+
if (budgetExhausted) {
|
|
370
|
+
warnings.push(`Stopped after ${elapsedSeconds(startedAt)}s to stay inside the per-call budget. ` +
|
|
371
|
+
"Call again with the cursor to continue.");
|
|
372
|
+
}
|
|
373
|
+
if (failures.length > 0) {
|
|
374
|
+
warnings.push(`${failures.length} run(s) failed. Call again with the same URLs and no cursor — ` +
|
|
375
|
+
"completed pairs are skipped, so only the gaps are retried.");
|
|
376
|
+
}
|
|
377
|
+
let aggregateBlock;
|
|
378
|
+
let comparison;
|
|
379
|
+
if (complete) {
|
|
380
|
+
const all = await readIndex(dir);
|
|
381
|
+
comparison = await compareWith(all);
|
|
382
|
+
// Group by page template so the rollup says "PDPs average 61" rather
|
|
383
|
+
// than listing twelve product URLs. Same classifier the PSI plan uses.
|
|
384
|
+
const { templates } = classifyUrls(all.map((r) => r.url));
|
|
385
|
+
const templateOf = new Map();
|
|
386
|
+
for (const t of templates) {
|
|
387
|
+
for (const candidate of t.candidates)
|
|
388
|
+
templateOf.set(candidate, { id: t.id, label: t.label });
|
|
389
|
+
}
|
|
390
|
+
const runs = all.map((r) => {
|
|
391
|
+
const t = templateOf.get(r.url);
|
|
392
|
+
return {
|
|
393
|
+
template: t?.id ?? "all",
|
|
394
|
+
label: t?.label ?? "All pages",
|
|
395
|
+
url: r.url,
|
|
396
|
+
strategy: r.variant,
|
|
397
|
+
runs: 1,
|
|
398
|
+
scores: r.scores,
|
|
399
|
+
lab: r.lab,
|
|
400
|
+
field: null,
|
|
401
|
+
comparisons: [],
|
|
402
|
+
findings: [],
|
|
403
|
+
report_file: r.report_file,
|
|
404
|
+
};
|
|
405
|
+
});
|
|
406
|
+
const { lab_vs_field_summary, ...rest } = aggregate(runs);
|
|
407
|
+
// No field data in a local run, so the lab-vs-field block would be an
|
|
408
|
+
// empty shape inviting a wrong conclusion. PSI is where that lives.
|
|
409
|
+
aggregateBlock = { ...rest, field_data: "not available — use run_performance_audit for real-user data" };
|
|
410
|
+
}
|
|
411
|
+
return text({
|
|
412
|
+
complete,
|
|
413
|
+
...(complete ? {} : { cursor: encodeCursor(index) }),
|
|
414
|
+
progress: { done: index, total: units.length, failed: failures.length },
|
|
415
|
+
input_kind: resolved.kind,
|
|
416
|
+
...(resolved.source ? { input_source: resolved.source } : {}),
|
|
417
|
+
form_factor: requested,
|
|
418
|
+
output_dir: dir,
|
|
419
|
+
index_file: indexPath,
|
|
420
|
+
results,
|
|
421
|
+
...(failures.length ? { failures } : {}),
|
|
422
|
+
...(aggregateBlock ? { aggregate: aggregateBlock } : {}),
|
|
423
|
+
...(comparison ? { comparison } : {}),
|
|
424
|
+
...(complete ? {} : { next_step: "Call run_lighthouse again with this cursor and the same input." }),
|
|
425
|
+
warnings,
|
|
426
|
+
});
|
|
159
427
|
});
|
|
160
428
|
}
|
|
161
429
|
//# sourceMappingURL=lighthouse.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lighthouse.js","sourceRoot":"","sources":["../../src/tools/lighthouse.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lighthouse.js","sourceRoot":"","sources":["../../src/tools/lighthouse.ts"],"names":[],"mappings":"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"}
|