apex-auditor 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +85 -18
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6,6 +6,16 @@ const ANSI_RESET = "\u001B[0m";
6
6
  const ANSI_RED = "\u001B[31m";
7
7
  const ANSI_YELLOW = "\u001B[33m";
8
8
  const ANSI_GREEN = "\u001B[32m";
9
+ const ANSI_CYAN = "\u001B[36m";
10
+ const ANSI_BLUE = "\u001B[34m";
11
+ const LCP_GOOD_MS = 2500;
12
+ const LCP_WARN_MS = 4000;
13
+ const FCP_GOOD_MS = 1800;
14
+ const FCP_WARN_MS = 3000;
15
+ const TBT_GOOD_MS = 200;
16
+ const TBT_WARN_MS = 600;
17
+ const CLS_GOOD = 0.1;
18
+ const CLS_WARN = 0.25;
9
19
  function parseArgs(argv) {
10
20
  let configPath;
11
21
  let ci = false;
@@ -70,11 +80,12 @@ export async function runAuditCli(argv) {
70
80
  printLowestPerformancePages(summary.results, useColor);
71
81
  const elapsedMs = Date.now() - startTimeMs;
72
82
  const elapsedText = formatElapsedTime(elapsedMs);
83
+ const elapsedDisplay = useColor ? `${ANSI_CYAN}${elapsedText}${ANSI_RESET}` : elapsedText;
73
84
  const runsPerTarget = effectiveConfig.runs ?? 1;
74
85
  const comboCount = summary.results.length;
75
86
  const totalRuns = comboCount * runsPerTarget;
76
87
  // eslint-disable-next-line no-console
77
- console.log(`\nCompleted in ${elapsedText} (${comboCount} page/device combinations x ${runsPerTarget} runs = ${totalRuns} Lighthouse runs).`);
88
+ console.log(`\nCompleted in ${elapsedDisplay} (${comboCount} page/device combinations x ${runsPerTarget} runs = ${totalRuns} Lighthouse runs).`);
78
89
  }
79
90
  function buildMarkdown(results) {
80
91
  const header = [
@@ -104,32 +115,37 @@ function buildRow(result) {
104
115
  return `| ${result.label} | ${result.path} | ${result.device} | ${scores.performance ?? "-"} | ${scores.accessibility ?? "-"} | ${scores.bestPractices ?? "-"} | ${scores.seo ?? "-"} | ${lcpSeconds} | ${fcpSeconds} | ${tbtMs} | ${cls} | ${error} | ${issues} |`;
105
116
  }
106
117
  function buildConsoleRow(result, useColor) {
107
- const line1 = buildConsoleRowLine1(result, useColor);
108
- const line2 = buildConsoleRowLine2(result, useColor);
109
- const line3 = buildConsoleRowLine3(result);
110
- const lines = [line1];
111
- if (line2.length > 0) {
112
- lines.push(line2);
118
+ const scoreLine = buildConsoleScoreLine(result, useColor);
119
+ const metricsLine = buildConsoleMetricsLine(result, useColor);
120
+ const errorLine = buildConsoleErrorLine(result, useColor);
121
+ const issuesLine = buildConsoleIssuesLine(result);
122
+ const lines = [scoreLine, metricsLine];
123
+ if (errorLine.length > 0) {
124
+ lines.push(errorLine);
113
125
  }
114
- if (line3.length > 0) {
115
- lines.push(line3);
126
+ if (issuesLine.length > 0) {
127
+ lines.push(issuesLine);
116
128
  }
117
129
  return lines.join("\n");
118
130
  }
119
- function buildConsoleRowLine1(result, useColor) {
131
+ function buildConsoleScoreLine(result, useColor) {
120
132
  const scores = result.scores;
121
- const metrics = result.metrics;
122
- const lcpSeconds = metrics.lcpMs !== undefined ? (metrics.lcpMs / 1000).toFixed(1) : "-";
123
- const fcpSeconds = metrics.fcpMs !== undefined ? (metrics.fcpMs / 1000).toFixed(1) : "-";
124
- const tbtMs = metrics.tbtMs !== undefined ? Math.round(metrics.tbtMs).toString() : "-";
125
- const cls = metrics.cls !== undefined ? metrics.cls.toFixed(3) : "-";
126
133
  const performanceText = colourScore(scores.performance, useColor);
127
134
  const accessibilityText = colourScore(scores.accessibility, useColor);
128
135
  const bestPracticesText = colourScore(scores.bestPractices, useColor);
129
136
  const seoText = colourScore(scores.seo, useColor);
130
- return `| ${result.label} | ${result.path} | ${result.device} | ${performanceText} | ${accessibilityText} | ${bestPracticesText} | ${seoText} | ${lcpSeconds} | ${fcpSeconds} | ${tbtMs} | ${cls} |`;
137
+ const deviceText = formatDeviceLabel(result.device, useColor);
138
+ return `| ${result.label} | ${result.path} | ${deviceText} | ${performanceText} | ${accessibilityText} | ${bestPracticesText} | ${seoText} | | | | |`;
131
139
  }
132
- function buildConsoleRowLine2(result, useColor) {
140
+ function buildConsoleMetricsLine(result, useColor) {
141
+ const metrics = result.metrics;
142
+ const lcpText = formatMetricSeconds(metrics.lcpMs, LCP_GOOD_MS, LCP_WARN_MS, useColor);
143
+ const fcpText = formatMetricSeconds(metrics.fcpMs, FCP_GOOD_MS, FCP_WARN_MS, useColor);
144
+ const tbtText = formatMetricMilliseconds(metrics.tbtMs, TBT_GOOD_MS, TBT_WARN_MS, useColor);
145
+ const clsText = formatMetricRatio(metrics.cls, CLS_GOOD, CLS_WARN, useColor);
146
+ return `| | | | | | | | ${lcpText} | ${fcpText} | ${tbtText} | ${clsText} |`;
147
+ }
148
+ function buildConsoleErrorLine(result, useColor) {
133
149
  const errorCode = result.runtimeErrorCode;
134
150
  const errorMessage = result.runtimeErrorMessage;
135
151
  if (!errorCode && !errorMessage) {
@@ -139,7 +155,7 @@ function buildConsoleRowLine2(result, useColor) {
139
155
  const prefix = useColor ? `${ANSI_RED}↳ Error:${ANSI_RESET}` : "↳ Error:";
140
156
  return ` ${prefix} ${errorText}`;
141
157
  }
142
- function buildConsoleRowLine3(result) {
158
+ function buildConsoleIssuesLine(result) {
143
159
  const issues = formatTopIssues(result.opportunities);
144
160
  if (issues.length === 0) {
145
161
  return "";
@@ -159,6 +175,57 @@ function formatTopIssues(opportunities) {
159
175
  });
160
176
  return items.join("; ");
161
177
  }
178
+ function formatMetricSeconds(valueMs, goodThresholdMs, warnThresholdMs, useColor) {
179
+ if (valueMs === undefined) {
180
+ return "-";
181
+ }
182
+ const seconds = valueMs / 1000;
183
+ const text = `${seconds.toFixed(1)}s`;
184
+ if (!useColor) {
185
+ return text;
186
+ }
187
+ const colour = selectColourForThreshold(valueMs, goodThresholdMs, warnThresholdMs);
188
+ return `${colour}${text}${ANSI_RESET}`;
189
+ }
190
+ function formatMetricMilliseconds(valueMs, goodThresholdMs, warnThresholdMs, useColor) {
191
+ if (valueMs === undefined) {
192
+ return "-";
193
+ }
194
+ const rounded = Math.round(valueMs);
195
+ const text = `${rounded}ms`;
196
+ if (!useColor) {
197
+ return text;
198
+ }
199
+ const colour = selectColourForThreshold(valueMs, goodThresholdMs, warnThresholdMs);
200
+ return `${colour}${text}${ANSI_RESET}`;
201
+ }
202
+ function formatMetricRatio(value, goodThreshold, warnThreshold, useColor) {
203
+ if (value === undefined) {
204
+ return "-";
205
+ }
206
+ const text = value.toFixed(3);
207
+ if (!useColor) {
208
+ return text;
209
+ }
210
+ const colour = selectColourForThreshold(value, goodThreshold, warnThreshold);
211
+ return `${colour}${text}${ANSI_RESET}`;
212
+ }
213
+ function selectColourForThreshold(value, goodThreshold, warnThreshold) {
214
+ if (value <= goodThreshold) {
215
+ return ANSI_GREEN;
216
+ }
217
+ if (value <= warnThreshold) {
218
+ return ANSI_YELLOW;
219
+ }
220
+ return ANSI_RED;
221
+ }
222
+ function formatDeviceLabel(device, useColor) {
223
+ if (!useColor) {
224
+ return device;
225
+ }
226
+ const colour = device === "mobile" ? ANSI_CYAN : ANSI_BLUE;
227
+ return `${colour}${device}${ANSI_RESET}`;
228
+ }
162
229
  function colourScore(score, useColor) {
163
230
  if (score === undefined) {
164
231
  return "-";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apex-auditor",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "description": "CLI to run structured Lighthouse audits (Performance, Accessibility, Best Practices, SEO) across routes.",
6
6
  "type": "module",