@reddoorla/maintenance 0.13.0 → 0.14.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/dist/cli/bin.js +176 -27
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.js +176 -27
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/index.d.ts +13 -3
- package/dist/index.js +124 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/bin.js
CHANGED
|
@@ -40,7 +40,10 @@ __export(websites_exports, {
|
|
|
40
40
|
listWebsites: () => listWebsites,
|
|
41
41
|
mapRow: () => mapRow,
|
|
42
42
|
siteSlug: () => siteSlug,
|
|
43
|
-
|
|
43
|
+
updateA11yCounts: () => updateA11yCounts,
|
|
44
|
+
updateDepsCounts: () => updateDepsCounts,
|
|
45
|
+
updateScores: () => updateScores,
|
|
46
|
+
updateSecurityCounts: () => updateSecurityCounts
|
|
44
47
|
});
|
|
45
48
|
function siteSlug(name) {
|
|
46
49
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
@@ -68,6 +71,13 @@ function mapRow(rec) {
|
|
|
68
71
|
bpScore: f["bpScore"] ?? null,
|
|
69
72
|
seoScore: f["seoScore"] ?? null,
|
|
70
73
|
lastLighthouseAuditAt: f["Last lighthouse audit at"] ?? null,
|
|
74
|
+
a11yViolations: f["A11y Violations"] ?? null,
|
|
75
|
+
depsDrifted: f["Deps Drifted"] ?? null,
|
|
76
|
+
depsMajorBehind: f["Deps Major Behind"] ?? null,
|
|
77
|
+
securityVulnsCritical: f["Security Vulns Critical"] ?? null,
|
|
78
|
+
securityVulnsHigh: f["Security Vulns High"] ?? null,
|
|
79
|
+
securityVulnsModerate: f["Security Vulns Moderate"] ?? null,
|
|
80
|
+
securityVulnsLow: f["Security Vulns Low"] ?? null,
|
|
71
81
|
dashboardToken: (() => {
|
|
72
82
|
const raw = f["Dashboard Token"];
|
|
73
83
|
if (typeof raw !== "string") return null;
|
|
@@ -98,6 +108,28 @@ async function updateScores(base, recordId, scores) {
|
|
|
98
108
|
};
|
|
99
109
|
await base(WEBSITES_TABLE).update([{ id: recordId, fields }]);
|
|
100
110
|
}
|
|
111
|
+
async function updateA11yCounts(base, recordId, counts) {
|
|
112
|
+
const fields = {
|
|
113
|
+
"A11y Violations": counts.violations
|
|
114
|
+
};
|
|
115
|
+
await base(WEBSITES_TABLE).update([{ id: recordId, fields }]);
|
|
116
|
+
}
|
|
117
|
+
async function updateDepsCounts(base, recordId, counts) {
|
|
118
|
+
const fields = {
|
|
119
|
+
"Deps Drifted": counts.drifted,
|
|
120
|
+
"Deps Major Behind": counts.majorBehind
|
|
121
|
+
};
|
|
122
|
+
await base(WEBSITES_TABLE).update([{ id: recordId, fields }]);
|
|
123
|
+
}
|
|
124
|
+
async function updateSecurityCounts(base, recordId, counts) {
|
|
125
|
+
const fields = {
|
|
126
|
+
"Security Vulns Critical": counts.critical,
|
|
127
|
+
"Security Vulns High": counts.high,
|
|
128
|
+
"Security Vulns Moderate": counts.moderate,
|
|
129
|
+
"Security Vulns Low": counts.low
|
|
130
|
+
};
|
|
131
|
+
await base(WEBSITES_TABLE).update([{ id: recordId, fields }]);
|
|
132
|
+
}
|
|
101
133
|
var WEBSITES_TABLE;
|
|
102
134
|
var init_websites = __esm({
|
|
103
135
|
"src/reports/airtable/websites.ts"() {
|
|
@@ -193,6 +225,128 @@ var init_lighthouse_airtable = __esm({
|
|
|
193
225
|
}
|
|
194
226
|
});
|
|
195
227
|
|
|
228
|
+
// src/audits/a11y-airtable.ts
|
|
229
|
+
function hasA11yCounts(result) {
|
|
230
|
+
if (result.audit !== "a11y") return false;
|
|
231
|
+
const details = result.details;
|
|
232
|
+
return typeof details?.totalViolations === "number";
|
|
233
|
+
}
|
|
234
|
+
function a11yCountsFromResult(result) {
|
|
235
|
+
if (result.audit !== "a11y") {
|
|
236
|
+
throw new Error(`Expected an 'a11y' AuditResult, got '${result.audit}'`);
|
|
237
|
+
}
|
|
238
|
+
const details = result.details;
|
|
239
|
+
return { violations: details?.totalViolations ?? 0 };
|
|
240
|
+
}
|
|
241
|
+
var init_a11y_airtable = __esm({
|
|
242
|
+
"src/audits/a11y-airtable.ts"() {
|
|
243
|
+
"use strict";
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// src/audits/deps-airtable.ts
|
|
248
|
+
function hasDepsCounts(result) {
|
|
249
|
+
if (result.audit !== "deps") return false;
|
|
250
|
+
return Array.isArray(result.details);
|
|
251
|
+
}
|
|
252
|
+
function depsCountsFromResult(result) {
|
|
253
|
+
if (result.audit !== "deps") {
|
|
254
|
+
throw new Error(`Expected a 'deps' AuditResult, got '${result.audit}'`);
|
|
255
|
+
}
|
|
256
|
+
const entries = result.details ?? [];
|
|
257
|
+
const drifted = entries.filter((e) => e.drift !== "same").length;
|
|
258
|
+
const majorBehind = entries.filter((e) => e.drift === "major").length;
|
|
259
|
+
return { drifted, majorBehind };
|
|
260
|
+
}
|
|
261
|
+
var init_deps_airtable = __esm({
|
|
262
|
+
"src/audits/deps-airtable.ts"() {
|
|
263
|
+
"use strict";
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// src/audits/security-airtable.ts
|
|
268
|
+
function hasSecurityCounts(result) {
|
|
269
|
+
if (result.audit !== "security") return false;
|
|
270
|
+
const details = result.details;
|
|
271
|
+
return !!details && typeof details.counts === "object";
|
|
272
|
+
}
|
|
273
|
+
function securityCountsFromResult(result) {
|
|
274
|
+
if (result.audit !== "security") {
|
|
275
|
+
throw new Error(`Expected a 'security' AuditResult, got '${result.audit}'`);
|
|
276
|
+
}
|
|
277
|
+
const details = result.details;
|
|
278
|
+
const c = details?.counts ?? { low: 0, moderate: 0, high: 0, critical: 0 };
|
|
279
|
+
return { critical: c.critical, high: c.high, moderate: c.moderate, low: c.low };
|
|
280
|
+
}
|
|
281
|
+
var init_security_airtable = __esm({
|
|
282
|
+
"src/audits/security-airtable.ts"() {
|
|
283
|
+
"use strict";
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// src/audits/write-audits-to-airtable.ts
|
|
288
|
+
var write_audits_to_airtable_exports = {};
|
|
289
|
+
__export(write_audits_to_airtable_exports, {
|
|
290
|
+
writeAuditsToAirtable: () => writeAuditsToAirtable
|
|
291
|
+
});
|
|
292
|
+
async function writeAuditsToAirtable(args) {
|
|
293
|
+
const { base, websites, slug, results } = args;
|
|
294
|
+
const lhResult = results.find((r) => r.audit === "lighthouse");
|
|
295
|
+
if (!lhResult) {
|
|
296
|
+
throw Object.assign(
|
|
297
|
+
new Error(
|
|
298
|
+
"--write-airtable requires a lighthouse result; did you pass --only without lighthouse?"
|
|
299
|
+
),
|
|
300
|
+
{ exitCode: 2 }
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
if (!hasRealScores(lhResult)) {
|
|
304
|
+
throw Object.assign(
|
|
305
|
+
new Error(
|
|
306
|
+
`Lighthouse audit produced no scores; refusing to write to Airtable. Summary: ${lhResult.summary}`
|
|
307
|
+
),
|
|
308
|
+
{ exitCode: 1 }
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
const target = websites.find((w) => siteSlug(w.name) === slug);
|
|
312
|
+
if (!target) {
|
|
313
|
+
throw Object.assign(new Error(`No Websites row matched slug "${slug}"`), { exitCode: 2 });
|
|
314
|
+
}
|
|
315
|
+
const writes = [];
|
|
316
|
+
const scores = lighthouseScoresFromResult(lhResult);
|
|
317
|
+
await updateScores(base, target.id, scores);
|
|
318
|
+
writes.push({ audit: "lighthouse", counts: scores });
|
|
319
|
+
const a11y = results.find((r) => r.audit === "a11y");
|
|
320
|
+
if (a11y && hasA11yCounts(a11y)) {
|
|
321
|
+
const counts = a11yCountsFromResult(a11y);
|
|
322
|
+
await updateA11yCounts(base, target.id, counts);
|
|
323
|
+
writes.push({ audit: "a11y", counts });
|
|
324
|
+
}
|
|
325
|
+
const deps = results.find((r) => r.audit === "deps");
|
|
326
|
+
if (deps && hasDepsCounts(deps)) {
|
|
327
|
+
const counts = depsCountsFromResult(deps);
|
|
328
|
+
await updateDepsCounts(base, target.id, counts);
|
|
329
|
+
writes.push({ audit: "deps", counts });
|
|
330
|
+
}
|
|
331
|
+
const sec = results.find((r) => r.audit === "security");
|
|
332
|
+
if (sec && hasSecurityCounts(sec)) {
|
|
333
|
+
const counts = securityCountsFromResult(sec);
|
|
334
|
+
await updateSecurityCounts(base, target.id, counts);
|
|
335
|
+
writes.push({ audit: "security", counts });
|
|
336
|
+
}
|
|
337
|
+
return { siteName: target.name, writes };
|
|
338
|
+
}
|
|
339
|
+
var init_write_audits_to_airtable = __esm({
|
|
340
|
+
"src/audits/write-audits-to-airtable.ts"() {
|
|
341
|
+
"use strict";
|
|
342
|
+
init_websites();
|
|
343
|
+
init_lighthouse_airtable();
|
|
344
|
+
init_a11y_airtable();
|
|
345
|
+
init_deps_airtable();
|
|
346
|
+
init_security_airtable();
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
196
350
|
// src/reports/airtable/reports.ts
|
|
197
351
|
function mapRow2(rec) {
|
|
198
352
|
const f = rec.fields;
|
|
@@ -1745,37 +1899,32 @@ async function runAuditCommand(site, opts) {
|
|
|
1745
1899
|
let output = opts.json ? JSON.stringify(results, null, 2) : formatTable(results);
|
|
1746
1900
|
if (opts.writeAirtable !== void 0) {
|
|
1747
1901
|
const { openBase: openBase2, readAirtableConfig: readAirtableConfig2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
1748
|
-
const { listWebsites: listWebsites2
|
|
1749
|
-
const {
|
|
1902
|
+
const { listWebsites: listWebsites2 } = await Promise.resolve().then(() => (init_websites(), websites_exports));
|
|
1903
|
+
const { resolveSlugFromCwd: resolveSlugFromCwd2 } = await Promise.resolve().then(() => (init_lighthouse_airtable(), lighthouse_airtable_exports));
|
|
1904
|
+
const { writeAuditsToAirtable: writeAuditsToAirtable2 } = await Promise.resolve().then(() => (init_write_audits_to_airtable(), write_audits_to_airtable_exports));
|
|
1750
1905
|
const slug = typeof opts.writeAirtable === "string" && opts.writeAirtable.length > 0 ? opts.writeAirtable : await resolveSlugFromCwd2(cwd);
|
|
1751
|
-
const lhResult = results.find((r) => r.audit === "lighthouse");
|
|
1752
|
-
if (!lhResult) {
|
|
1753
|
-
throw Object.assign(
|
|
1754
|
-
new Error(
|
|
1755
|
-
"--write-airtable requires a lighthouse result; did you pass --only without lighthouse?"
|
|
1756
|
-
),
|
|
1757
|
-
{ exitCode: 2 }
|
|
1758
|
-
);
|
|
1759
|
-
}
|
|
1760
|
-
if (!hasRealScores2(lhResult)) {
|
|
1761
|
-
throw Object.assign(
|
|
1762
|
-
new Error(
|
|
1763
|
-
`Lighthouse audit produced no scores; refusing to write to Airtable. Summary: ${lhResult.summary}`
|
|
1764
|
-
),
|
|
1765
|
-
{ exitCode: 1 }
|
|
1766
|
-
);
|
|
1767
|
-
}
|
|
1768
1906
|
const base = openBase2(readAirtableConfig2());
|
|
1769
1907
|
const websites = await listWebsites2(base);
|
|
1770
|
-
const
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1908
|
+
const summary = await writeAuditsToAirtable2({ base, websites, slug, results });
|
|
1909
|
+
const lines = summary.writes.map((w) => {
|
|
1910
|
+
if (w.audit === "lighthouse") {
|
|
1911
|
+
const s = w.counts;
|
|
1912
|
+
return ` lighthouse: P=${s.performance} A=${s.accessibility} BP=${s.bestPractices} SEO=${s.seo}`;
|
|
1913
|
+
}
|
|
1914
|
+
if (w.audit === "a11y") {
|
|
1915
|
+
return ` a11y: ${w.counts.violations} violations`;
|
|
1916
|
+
}
|
|
1917
|
+
if (w.audit === "deps") {
|
|
1918
|
+
const c2 = w.counts;
|
|
1919
|
+
return ` deps: ${c2.drifted} drifted (${c2.majorBehind} major)`;
|
|
1920
|
+
}
|
|
1921
|
+
const c = w.counts;
|
|
1922
|
+
return ` security: ${c.critical}C/${c.high}H/${c.moderate}M/${c.low}L`;
|
|
1923
|
+
});
|
|
1776
1924
|
output += `
|
|
1777
1925
|
|
|
1778
|
-
\u2192 wrote
|
|
1926
|
+
\u2192 wrote to Websites[${summary.siteName}]:
|
|
1927
|
+
${lines.join("\n")}`;
|
|
1779
1928
|
}
|
|
1780
1929
|
return { output, code: exitCode(results) };
|
|
1781
1930
|
}
|