@reddoorla/maintenance 0.9.0 → 0.10.1

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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as Site, b as AuditResult, a as AuditName, c as RecipeResult, R as RecipeName, I as InventoryProvider } from './sync-configs-pMPW4wTq.js';
2
- export { C as ConfigName, d as SyncConfigsOptions, s as syncConfigs } from './sync-configs-pMPW4wTq.js';
1
+ import { S as Site, b as AuditResult, a as AuditName, c as RecipeResult, R as RecipeName, I as InventoryProvider } from './sync-configs-Dn6KhjrW.js';
2
+ export { C as ConfigName, d as SyncConfigsOptions, s as syncConfigs } from './sync-configs-Dn6KhjrW.js';
3
3
  import * as airtable_lib_airtable_base_js from 'airtable/lib/airtable_base.js';
4
4
 
5
5
  type SpawnResult = {
@@ -82,6 +82,63 @@ type OnboardOptions = {
82
82
  };
83
83
  declare function onboard(site: Site, opts?: OnboardOptions): Promise<RecipeResult>;
84
84
 
85
+ /**
86
+ * Writes a starter `src/routes/dev/a11y-fixtures/+page.svelte` if the route
87
+ * doesn't already exist. The hardcoded URL in `src/configs/lighthouse.ts` +
88
+ * `src/configs/playwright-a11y.ts` targets this path — newly-onboarded sites
89
+ * need the route to exist for either audit to pass. Operator edits to an
90
+ * existing page are never clobbered (noop on existing file).
91
+ */
92
+ declare function a11yFixturesPage(site: Site): Promise<RecipeResult>;
93
+
94
+ type InitStepResult = {
95
+ kind: "recipe";
96
+ result: RecipeResult;
97
+ } | {
98
+ kind: "audit";
99
+ results: AuditResult[];
100
+ } | {
101
+ kind: "error";
102
+ message: string;
103
+ };
104
+ type InitStep = {
105
+ name: string;
106
+ run: (site: Site) => Promise<InitStepResult>;
107
+ };
108
+ type InitResult = {
109
+ site: string;
110
+ steps: Array<{
111
+ name: string;
112
+ result: InitStepResult;
113
+ }>;
114
+ /** True if every step ran; false if an `error` or `failed` recipe result
115
+ * short-circuited the chain. `noop` recipes do not break completeness. */
116
+ complete: boolean;
117
+ };
118
+ type InitOptions = {
119
+ /** Override the default step list. Tests inject mocked steps; production
120
+ * code relies on the default. */
121
+ steps?: InitStep[];
122
+ };
123
+ /** convert-to-pnpm → onboard → sync-configs → svelte-codemods →
124
+ * a11y-fixtures-page → audit. Order is deliberate — every step depends on
125
+ * the prior one's output (pnpm before onboard's installs, onboard's deps
126
+ * before sync-configs writes lighthouserc, fixtures page before audit
127
+ * actually has a route to hit). */
128
+ declare const DEFAULT_INIT_STEPS: InitStep[];
129
+ /**
130
+ * One-shot guided onboarding. Runs the default step sequence against a
131
+ * site, collecting per-step results into an InitResult. Each underlying
132
+ * recipe still creates its own branch — init is a thin orchestrator, not
133
+ * a branch-collapser; the operator ends up with one stack of branches per
134
+ * mutated step (recipes that noop don't branch).
135
+ *
136
+ * Stops the chain on the first uncaught error or `failed` recipe result.
137
+ * `noop` results are expected (e.g. running init twice) and continue the
138
+ * chain. The final audit pass runs if no prior step errored.
139
+ */
140
+ declare function init(site: Site, opts?: InitOptions): Promise<InitResult>;
141
+
85
142
  declare const ALL_RECIPE_NAMES: RecipeName[];
86
143
  declare function isRecipeName(value: string): value is RecipeName;
87
144
 
@@ -294,4 +351,4 @@ type DueItem = {
294
351
  */
295
352
  declare function findDueReports(websites: WebsiteRow[], reports: ReportRow[], today: Date): DueItem[];
296
353
 
297
- export { ALL_AUDIT_NAMES, ALL_RECIPE_NAMES, type AirtableInventoryOptions, AuditName, AuditResult, type BumpDepsOptions, type ConvertToPnpmOptions, type DraftOptions, type DraftResult, type DueItem, type HeaderImage, InventoryProvider, type LighthouseScores, type LocalPathOptions, type OnboardAudit, type OnboardOptions, type OrchestrateOptions, RecipeName, RecipeResult, type RenderResult, type ReportData, type ReportType, Site, type UpgradeSvelte4to5Options, a11yAudit, bumpDeps, convertToPnpm, depsAudit, draftReportForSite, findDueReports, fromAirtableBase, fromJsonFile, isRecipeName, lighthouseAudit, lintAudit, localPath, onboard, renderReportHtml, runAudits, runAuditsAcross, securityAudit, sendApprovedReports, svelteCodemods, upgradeSvelte4to5 };
354
+ export { ALL_AUDIT_NAMES, ALL_RECIPE_NAMES, type AirtableInventoryOptions, AuditName, AuditResult, type BumpDepsOptions, type ConvertToPnpmOptions, DEFAULT_INIT_STEPS, type DraftOptions, type DraftResult, type DueItem, type HeaderImage, type InitOptions, type InitResult, type InitStep, type InitStepResult, InventoryProvider, type LighthouseScores, type LocalPathOptions, type OnboardAudit, type OnboardOptions, type OrchestrateOptions, RecipeName, RecipeResult, type RenderResult, type ReportData, type ReportType, Site, type UpgradeSvelte4to5Options, a11yAudit, a11yFixturesPage, bumpDeps, convertToPnpm, depsAudit, draftReportForSite, findDueReports, fromAirtableBase, fromJsonFile, init, isRecipeName, lighthouseAudit, lintAudit, localPath, onboard, renderReportHtml, runAudits, runAuditsAcross, securityAudit, sendApprovedReports, svelteCodemods, upgradeSvelte4to5 };
package/dist/index.js CHANGED
@@ -1908,6 +1908,116 @@ async function onboard(site, opts = {}) {
1908
1908
  });
1909
1909
  }
1910
1910
 
1911
+ // src/recipes/a11y-fixtures-page/index.ts
1912
+ import { access, mkdir, writeFile as writeFile9 } from "fs/promises";
1913
+ import { dirname as dirname2, join as join18 } from "path";
1914
+
1915
+ // src/recipes/a11y-fixtures-page/template.ts
1916
+ var A11Y_FIXTURES_PAGE_RELATIVE = "src/routes/dev/a11y-fixtures/+page.svelte";
1917
+ var A11Y_FIXTURES_PAGE_TEMPLATE = `<svelte:head>
1918
+ <title>a11y fixtures \u2014 Reddoor</title>
1919
+ <meta
1920
+ name="description"
1921
+ content="Reddoor accessibility fixtures \u2014 semantic landmarks, heading hierarchy, and a stable target for @lhci/cli and Playwright + axe-core coverage. Not linked from the public site."
1922
+ />
1923
+ </svelte:head>
1924
+
1925
+ <main>
1926
+ <header>
1927
+ <h1>Accessibility fixtures</h1>
1928
+ <p>
1929
+ This page exists so <code>@lhci/cli</code> and Playwright + axe-core have a
1930
+ stable target with predictable a11y characteristics. It is not linked from
1931
+ the public site.
1932
+ </p>
1933
+ </header>
1934
+
1935
+ <section aria-labelledby="landmarks-heading">
1936
+ <h2 id="landmarks-heading">Landmarks</h2>
1937
+ <p>
1938
+ A single <code>main</code> wraps the page; sections each declare
1939
+ <code>aria-labelledby</code> matched to their heading id so screen readers
1940
+ and axe both see a clean outline.
1941
+ </p>
1942
+ </section>
1943
+
1944
+ <section aria-labelledby="links-heading">
1945
+ <h2 id="links-heading">Links</h2>
1946
+ <p>
1947
+ <a href="/">Back to home</a> \u2014 relative link with descriptive visible text,
1948
+ so no <code>aria-label</code> override is needed.
1949
+ </p>
1950
+ </section>
1951
+ </main>
1952
+ `;
1953
+
1954
+ // src/recipes/a11y-fixtures-page/index.ts
1955
+ async function fileExists(path) {
1956
+ try {
1957
+ await access(path);
1958
+ return true;
1959
+ } catch {
1960
+ return false;
1961
+ }
1962
+ }
1963
+ async function a11yFixturesPage(site) {
1964
+ const target = join18(site.path, A11Y_FIXTURES_PAGE_RELATIVE);
1965
+ return withRecipe({
1966
+ name: "a11y-fixtures-page",
1967
+ site,
1968
+ plan: async () => {
1969
+ if (await fileExists(target)) {
1970
+ return { kind: "noop", notes: `${A11Y_FIXTURES_PAGE_RELATIVE} already exists` };
1971
+ }
1972
+ return { kind: "apply", plan: { target } };
1973
+ },
1974
+ apply: async (planned, { commit: commit2 }) => {
1975
+ await mkdir(dirname2(planned.target), { recursive: true });
1976
+ await writeFile9(planned.target, A11Y_FIXTURES_PAGE_TEMPLATE, "utf-8");
1977
+ await commit2("feat: add /dev/a11y-fixtures starter route");
1978
+ return { kind: "ok" };
1979
+ }
1980
+ });
1981
+ }
1982
+
1983
+ // src/recipes/init.ts
1984
+ function recipeStep(name, fn) {
1985
+ return {
1986
+ name,
1987
+ run: async (site) => ({ kind: "recipe", result: await fn(site) })
1988
+ };
1989
+ }
1990
+ var DEFAULT_INIT_STEPS = [
1991
+ recipeStep("convert-to-pnpm", convertToPnpm),
1992
+ recipeStep("onboard", onboard),
1993
+ recipeStep("sync-configs", syncConfigs),
1994
+ recipeStep("svelte-codemods", svelteCodemods),
1995
+ recipeStep("a11y-fixtures-page", a11yFixturesPage),
1996
+ {
1997
+ name: "audit",
1998
+ run: async (site) => ({ kind: "audit", results: await runAudits(site) })
1999
+ }
2000
+ ];
2001
+ async function init(site, opts = {}) {
2002
+ const steps = opts.steps ?? DEFAULT_INIT_STEPS;
2003
+ const out = [];
2004
+ for (const step of steps) {
2005
+ let result;
2006
+ try {
2007
+ result = await step.run(site);
2008
+ } catch (err) {
2009
+ const message = err instanceof Error ? err.message : String(err);
2010
+ out.push({ name: step.name, result: { kind: "error", message } });
2011
+ return { site: siteLabel(site), steps: out, complete: false };
2012
+ }
2013
+ out.push({ name: step.name, result });
2014
+ if (result.kind === "recipe" && result.result.status === "failed") {
2015
+ return { site: siteLabel(site), steps: out, complete: false };
2016
+ }
2017
+ }
2018
+ return { site: siteLabel(site), steps: out, complete: true };
2019
+ }
2020
+
1911
2021
  // src/recipes/index.ts
1912
2022
  var ALL_RECIPE_NAMES = [
1913
2023
  "sync-configs",
@@ -1915,7 +2025,9 @@ var ALL_RECIPE_NAMES = [
1915
2025
  "svelte-4-to-5",
1916
2026
  "svelte-codemods",
1917
2027
  "convert-to-pnpm",
1918
- "onboard"
2028
+ "onboard",
2029
+ "a11y-fixtures-page",
2030
+ "init"
1919
2031
  ];
1920
2032
  function isRecipeName(value) {
1921
2033
  return ALL_RECIPE_NAMES.includes(value);
@@ -2027,23 +2139,23 @@ function fromAirtableBase(base, opts = {}) {
2027
2139
  }
2028
2140
 
2029
2141
  // src/reports/draft.ts
2030
- import { mkdir, writeFile as writeFile9 } from "fs/promises";
2031
- import { dirname as dirname3 } from "path";
2142
+ import { mkdir as mkdir2, writeFile as writeFile10 } from "fs/promises";
2143
+ import { dirname as dirname4 } from "path";
2032
2144
 
2033
2145
  // src/reports/render.ts
2034
2146
  import mjml2html from "mjml";
2035
2147
 
2036
2148
  // src/reports/maintenance-email/assets/index.ts
2037
2149
  import { readFile as readFile11 } from "fs/promises";
2038
- import { dirname as dirname2, join as join18 } from "path";
2150
+ import { dirname as dirname3, join as join19 } from "path";
2039
2151
  import { fileURLToPath as fileURLToPath2 } from "url";
2040
- var here = dirname2(fileURLToPath2(import.meta.url));
2152
+ var here = dirname3(fileURLToPath2(import.meta.url));
2041
2153
  var CHECK_CID = "rd-check-png";
2042
2154
  var BLURRED_CID = "rd-blurred-tests-jpg";
2043
2155
  async function loadBundledImages() {
2044
2156
  const [check, blurred] = await Promise.all([
2045
- readFile11(join18(here, "check.png")),
2046
- readFile11(join18(here, "blurredTests.jpg"))
2157
+ readFile11(join19(here, "check.png")),
2158
+ readFile11(join19(here, "blurredTests.jpg"))
2047
2159
  ]);
2048
2160
  return {
2049
2161
  check: {
@@ -2407,8 +2519,8 @@ async function draftReportForSite(base, siteRow, reportType, options = {}) {
2407
2519
  });
2408
2520
  if (options.previewOnly) {
2409
2521
  const path = options.previewPath ?? `reports/${slug}/draft.html`;
2410
- await mkdir(dirname3(path), { recursive: true });
2411
- await writeFile9(path, html, "utf-8");
2522
+ await mkdir2(dirname4(path), { recursive: true });
2523
+ await writeFile10(path, html, "utf-8");
2412
2524
  return { reportRow: null, htmlPath: path, html };
2413
2525
  }
2414
2526
  if (base === null) throw new Error("base required when previewOnly=false");
@@ -2674,7 +2786,9 @@ function findDueReports(websites, reports, today) {
2674
2786
  export {
2675
2787
  ALL_AUDIT_NAMES,
2676
2788
  ALL_RECIPE_NAMES,
2789
+ DEFAULT_INIT_STEPS,
2677
2790
  a11yAudit,
2791
+ a11yFixturesPage,
2678
2792
  bumpDeps,
2679
2793
  convertToPnpm,
2680
2794
  depsAudit,
@@ -2682,6 +2796,7 @@ export {
2682
2796
  findDueReports,
2683
2797
  fromAirtableBase,
2684
2798
  fromJsonFile,
2799
+ init,
2685
2800
  isRecipeName,
2686
2801
  lighthouseAudit,
2687
2802
  lintAudit,