@reddoorla/maintenance 0.12.1 → 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 CHANGED
@@ -40,7 +40,10 @@ __export(websites_exports, {
40
40
  listWebsites: () => listWebsites,
41
41
  mapRow: () => mapRow,
42
42
  siteSlug: () => siteSlug,
43
- updateScores: () => updateScores
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;
@@ -826,39 +980,39 @@ function siteLabel(site) {
826
980
  // src/configs/baseline-versions.ts
827
981
  var baselineVersions = {
828
982
  // SvelteKit core
829
- svelte: "^5.55.5",
830
- "@sveltejs/kit": "^2.59.0",
983
+ svelte: "^5.55.10",
984
+ "@sveltejs/kit": "^2.61.1",
831
985
  "@sveltejs/adapter-netlify": "^6.0.4",
832
- "@sveltejs/adapter-auto": "^7.0.0",
833
- "@sveltejs/vite-plugin-svelte": "^7.0.0",
834
- "svelte-check": "^4.4.7",
986
+ "@sveltejs/adapter-auto": "^7.0.1",
987
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
988
+ "svelte-check": "^4.4.8",
835
989
  // Build tooling
836
- vite: "^8.0.10",
837
- vitest: "^4.1.1",
990
+ vite: "^8.0.14",
991
+ vitest: "^4.1.7",
838
992
  typescript: "^6.0.3",
839
993
  // Tailwind 4
840
- tailwindcss: "^4.0.14",
994
+ tailwindcss: "^4.3.0",
841
995
  "@tailwindcss/vite": "^4.3.0",
842
996
  // Prismic
843
- "@prismicio/client": "^7.3.1",
844
- "@prismicio/svelte": "^2.0.0",
845
- "@slicemachine/adapter-sveltekit": "^0.3.36",
846
- "slice-machine-ui": "^2.11.1",
997
+ "@prismicio/client": "^7.21.8",
998
+ "@prismicio/svelte": "^2.2.1",
999
+ "@slicemachine/adapter-sveltekit": "^0.3.96",
1000
+ "slice-machine-ui": "^2.21.3",
847
1001
  // Test tooling
848
- "@playwright/test": "^1.59.1",
1002
+ "@playwright/test": "^1.60.0",
849
1003
  "@axe-core/playwright": "^4.11.3",
850
1004
  "@lhci/cli": "^0.15.1",
851
1005
  // Lint
852
- eslint: "^10.3.0",
853
- "eslint-plugin-svelte": "^3.1.0",
854
- "eslint-config-prettier": "^10.1.1",
855
- prettier: "^3.1.1",
856
- "prettier-plugin-svelte": "^3.2.6",
857
- "typescript-eslint": "^8.59.1",
1006
+ eslint: "^10.4.0",
1007
+ "eslint-plugin-svelte": "^3.18.0",
1008
+ "eslint-config-prettier": "^10.1.8",
1009
+ prettier: "^3.8.3",
1010
+ "prettier-plugin-svelte": "^4.0.1",
1011
+ "typescript-eslint": "^8.60.0",
858
1012
  "@eslint/js": "^10.0.1",
859
1013
  globals: "^17.6.0",
860
1014
  // Misc
861
- "@lucide/svelte": "^1.14.0",
1015
+ "@lucide/svelte": "^1.17.0",
862
1016
  "@zerodevx/svelte-img": "^2.1.2"
863
1017
  };
864
1018
 
@@ -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, updateScores: updateScores2, siteSlug: siteSlug2 } = await Promise.resolve().then(() => (init_websites(), websites_exports));
1749
- const { lighthouseScoresFromResult: lighthouseScoresFromResult2, hasRealScores: hasRealScores2, resolveSlugFromCwd: resolveSlugFromCwd2 } = await Promise.resolve().then(() => (init_lighthouse_airtable(), lighthouse_airtable_exports));
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 target = websites.find((w) => siteSlug2(w.name) === slug);
1771
- if (!target) {
1772
- throw Object.assign(new Error(`No Websites row matched slug "${slug}"`), { exitCode: 2 });
1773
- }
1774
- const scores = lighthouseScoresFromResult2(lhResult);
1775
- await updateScores2(base, target.id, scores);
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 scores to Websites[${target.name}]: P=${scores.performance} A=${scores.accessibility} BP=${scores.bestPractices} SEO=${scores.seo}`;
1926
+ \u2192 wrote to Websites[${summary.siteName}]:
1927
+ ${lines.join("\n")}`;
1779
1928
  }
1780
1929
  return { output, code: exitCode(results) };
1781
1930
  }
@@ -1870,7 +2019,8 @@ var CANONICAL_GITIGNORE_ENTRIES = [
1870
2019
  ".DS_Store",
1871
2020
  "*.log",
1872
2021
  ".vercel/",
1873
- ".netlify/"
2022
+ ".netlify/",
2023
+ ".reddoor-a11y/"
1874
2024
  ];
1875
2025
  function stripLeadingSlash(s) {
1876
2026
  return s.startsWith("/") ? s.slice(1) : s;