@reddoorla/maintenance 0.1.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/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +1408 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/audit.d.ts +13 -0
- package/dist/cli/commands/audit.js +666 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/configs/eslint.d.ts +8 -0
- package/dist/configs/eslint.js +67 -0
- package/dist/configs/eslint.js.map +1 -0
- package/dist/configs/lighthouse.d.ts +36 -0
- package/dist/configs/lighthouse.js +33 -0
- package/dist/configs/lighthouse.js.map +1 -0
- package/dist/configs/playwright-a11y.d.ts +10 -0
- package/dist/configs/playwright-a11y.js +37 -0
- package/dist/configs/playwright-a11y.js.map +1 -0
- package/dist/configs/prettier.d.ts +5 -0
- package/dist/configs/prettier.js +14 -0
- package/dist/configs/prettier.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +1098 -0
- package/dist/index.js.map +1 -0
- package/dist/recipes/sync-configs.d.ts +1 -0
- package/dist/recipes/sync-configs.js +138 -0
- package/dist/recipes/sync-configs.js.map +1 -0
- package/dist/sync-configs-Z5a0iaDd.d.ts +31 -0
- package/dist/util/git.d.ts +12 -0
- package/dist/util/git.js +43 -0
- package/dist/util/git.js.map +1 -0
- package/dist/util/pkg.d.ts +12 -0
- package/dist/util/pkg.js +39 -0
- package/dist/util/pkg.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/audits/util/spawn.ts","../src/audits/deps.ts","../src/configs/baseline-versions.ts","../src/audits/lint.ts","../src/audits/security.ts","../src/audits/lighthouse.ts","../src/configs/lighthouse.ts","../src/audits/a11y.ts","../src/configs/playwright-a11y.ts","../src/audits/index.ts","../src/recipes/sync-configs.ts","../src/recipes/sync-configs/templates.ts","../src/util/git.ts","../src/recipes/bump-deps.ts","../src/recipes/svelte-5/index.ts","../src/util/pkg.ts","../src/recipes/svelte-5/step-bump-versions.ts","../src/recipes/svelte-5/step-svelte-config.ts","../src/recipes/svelte-5/step-svelte-migrate.ts","../src/recipes/svelte-5/step-tailwind-upgrade.ts","../src/recipes/svelte-5/step-gotchas.ts","../src/recipes/svelte-5/codemods/on-event-to-handler.ts","../src/recipes/svelte-5/codemods/dollar-props.ts","../src/recipes/svelte-5/codemods/dollar-restprops.ts","../src/recipes/svelte-5/step-verify.ts","../src/recipes/svelte-5/step-summary.ts","../src/recipes/index.ts","../src/inventory/local.ts","../src/inventory/json.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\n\nexport type SpawnResult = { code: number; stdout: string; stderr: string };\n\nexport type SpawnFn = (\n cmd: string,\n args: readonly string[],\n opts?: { cwd?: string; env?: NodeJS.ProcessEnv; timeoutMs?: number },\n) => Promise<SpawnResult>;\n\nexport const defaultSpawn: SpawnFn = (cmd, args, opts = {}) =>\n new Promise((resolve, reject) => {\n const child = spawn(cmd, [...args], {\n cwd: opts.cwd,\n env: opts.env ?? process.env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk) => (stdout += String(chunk)));\n child.stderr.on(\"data\", (chunk) => (stderr += String(chunk)));\n\n const timer = opts.timeoutMs\n ? setTimeout(() => {\n child.kill(\"SIGTERM\");\n reject(new Error(`spawn timeout after ${opts.timeoutMs}ms: ${cmd}`));\n }, opts.timeoutMs)\n : undefined;\n\n child.on(\"error\", (err) => {\n if (timer) clearTimeout(timer);\n reject(err);\n });\n child.on(\"close\", (code) => {\n if (timer) clearTimeout(timer);\n resolve({ code: code ?? -1, stdout, stderr });\n });\n });\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { AuditResult, Site } from \"../types.js\";\nimport { baselineVersions } from \"../configs/baseline-versions.js\";\nimport type { AuditContext } from \"./util/inject.js\";\n\nexport type Drift = \"same\" | \"patch\" | \"minor\" | \"major\" | \"newer\";\n\nexport type DepsDriftEntry = {\n pkg: string;\n baseline: string;\n actual: string;\n drift: Drift;\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nfunction stripCaret(range: string): string {\n return range.replace(/^[\\^~]/, \"\");\n}\n\nfunction parseSemver(v: string): [number, number, number] {\n const cleaned = stripCaret(v).split(\"-\")[0] ?? \"0.0.0\";\n const parts = cleaned.split(\".\").map((n) => Number.parseInt(n, 10));\n return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];\n}\n\nfunction compareSemver(actual: string, baseline: string): Drift {\n const [aMajor, aMinor, aPatch] = parseSemver(actual);\n const [bMajor, bMinor, bPatch] = parseSemver(baseline);\n if (aMajor > bMajor) return \"newer\";\n if (aMajor < bMajor) return \"major\";\n if (aMinor > bMinor) return \"newer\";\n if (aMinor < bMinor) return \"minor\";\n if (aPatch > bPatch) return \"newer\";\n if (aPatch < bPatch) return \"patch\";\n return \"same\";\n}\n\nexport async function depsAudit(ctx: AuditContext): Promise<AuditResult> {\n const pkgPath = join(ctx.site.path, \"package.json\");\n let pkgRaw: string;\n try {\n pkgRaw = await readFile(pkgPath, \"utf-8\");\n } catch (err) {\n return {\n audit: \"deps\",\n site: siteLabel(ctx.site),\n status: \"skip\",\n summary: `no package.json at ${pkgPath}`,\n details: { error: String(err) },\n };\n }\n\n const pkg = JSON.parse(pkgRaw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const installed: Record<string, string> = {\n ...(pkg.dependencies ?? {}),\n ...(pkg.devDependencies ?? {}),\n };\n\n const details: DepsDriftEntry[] = [];\n for (const [name, baseline] of Object.entries(baselineVersions)) {\n const actual = installed[name];\n if (!actual) continue;\n details.push({\n pkg: name,\n baseline,\n actual,\n drift: compareSemver(actual, baseline),\n });\n }\n\n const anyMajor = details.some((d) => d.drift === \"major\");\n const anyMinor = details.some((d) => d.drift === \"minor\");\n const anyNewer = details.some((d) => d.drift === \"newer\");\n\n const status: AuditResult[\"status\"] = anyMajor ? \"fail\" : anyMinor || anyNewer ? \"warn\" : \"pass\";\n\n const summary =\n status === \"pass\"\n ? `all ${details.length} tracked deps in line with baseline`\n : status === \"warn\"\n ? `${details.filter((d) => d.drift !== \"same\").length} of ${details.length} tracked deps drifted`\n : `${details.filter((d) => d.drift === \"major\").length} deps lagging by a major version`;\n\n return {\n audit: \"deps\",\n site: siteLabel(ctx.site),\n status,\n summary,\n details,\n };\n}\n","// Curated map of the framework deps reddoor sites should stay close to.\n// Refreshed at each package release from reddoor-starter's package.json.\n// Versions are caret ranges to mirror what `pnpm add` would produce.\n\nexport const baselineVersions: Record<string, string> = {\n // SvelteKit core\n svelte: \"^5.55.5\",\n \"@sveltejs/kit\": \"^2.59.0\",\n \"@sveltejs/adapter-netlify\": \"^6.0.4\",\n \"@sveltejs/adapter-auto\": \"^7.0.0\",\n \"@sveltejs/vite-plugin-svelte\": \"^7.0.0\",\n \"svelte-check\": \"^4.4.7\",\n\n // Build tooling\n vite: \"^8.0.10\",\n vitest: \"^4.1.1\",\n typescript: \"^6.0.3\",\n\n // Tailwind 4\n tailwindcss: \"^4.0.14\",\n \"@tailwindcss/vite\": \"^4.3.0\",\n\n // Prismic\n \"@prismicio/client\": \"^7.3.1\",\n \"@prismicio/svelte\": \"^2.0.0\",\n \"@slicemachine/adapter-sveltekit\": \"^0.3.36\",\n \"slice-machine-ui\": \"^2.11.1\",\n\n // Test tooling\n \"@playwright/test\": \"^1.59.1\",\n \"@axe-core/playwright\": \"^4.11.3\",\n \"@lhci/cli\": \"^0.15.1\",\n\n // Lint\n eslint: \"^10.3.0\",\n \"eslint-plugin-svelte\": \"^3.1.0\",\n \"eslint-config-prettier\": \"^10.1.1\",\n prettier: \"^3.1.1\",\n \"prettier-plugin-svelte\": \"^3.2.6\",\n \"typescript-eslint\": \"^8.59.1\",\n \"@eslint/js\": \"^10.0.1\",\n globals: \"^17.6.0\",\n\n // Misc\n \"@lucide/svelte\": \"^1.14.0\",\n \"@zerodevx/svelte-img\": \"^2.1.2\",\n};\n\nexport default baselineVersions;\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { ESLint } from \"eslint\";\nimport { check as prettierCheck, resolveConfig as prettierResolveConfig } from \"prettier\";\nimport { glob } from \"tinyglobby\";\nimport type { AuditResult, Site } from \"../types.js\";\nimport type { AuditContext } from \"./util/inject.js\";\n\nconst TARGET_GLOBS = [\"**/*.{ts,js,svelte}\"];\nconst IGNORE = [\"node_modules/**\", \"dist/**\", \".svelte-kit/**\", \"build/**\", \".netlify/**\"];\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nasync function listFiles(cwd: string): Promise<string[]> {\n return glob(TARGET_GLOBS, { cwd, ignore: IGNORE, absolute: false });\n}\n\nexport async function lintAudit(ctx: AuditContext): Promise<AuditResult> {\n const { site } = ctx;\n const configPath = join(site.path, \"eslint.config.js\");\n\n if (!existsSync(configPath)) {\n return {\n audit: \"lint\",\n site: siteLabel(site),\n status: \"skip\",\n summary: \"no eslint config at site root\",\n };\n }\n\n const eslint = new ESLint({\n cwd: site.path,\n overrideConfigFile: configPath,\n errorOnUnmatchedPattern: false,\n });\n\n const relFiles = await listFiles(site.path);\n const filesToLint = relFiles.map((f) => join(site.path, f));\n\n const eslintResults = await eslint.lintFiles(filesToLint);\n const eslintErrors = eslintResults.reduce((n, r) => n + r.errorCount, 0);\n const eslintWarnings = eslintResults.reduce((n, r) => n + r.warningCount, 0);\n\n const prettierUnformatted: string[] = [];\n for (const file of filesToLint) {\n const source = await readFile(file, \"utf-8\");\n const options = (await prettierResolveConfig(file)) ?? {};\n const ok = await prettierCheck(source, { ...options, filepath: file });\n if (!ok) prettierUnformatted.push(relative(site.path, file));\n }\n\n const status: AuditResult[\"status\"] =\n eslintErrors > 0 || prettierUnformatted.length > 0\n ? \"fail\"\n : eslintWarnings > 0\n ? \"warn\"\n : \"pass\";\n\n const summary =\n status === \"pass\"\n ? `lint clean across ${filesToLint.length} files`\n : `${eslintErrors} eslint errors, ${eslintWarnings} warnings, ${prettierUnformatted.length} unformatted`;\n\n return {\n audit: \"lint\",\n site: siteLabel(site),\n status,\n summary,\n details: {\n eslintErrors,\n eslintWarnings,\n prettierUnformatted,\n files: filesToLint.length,\n },\n };\n}\n","import type { AuditResult, Site } from \"../types.js\";\nimport { defaultSpawn, type SpawnResult } from \"./util/spawn.js\";\nimport type { AuditContext } from \"./util/inject.js\";\n\ntype AuditJson = {\n metadata?: {\n vulnerabilities?: {\n low?: number;\n moderate?: number;\n high?: number;\n critical?: number;\n };\n };\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nfunction classify(v: { low: number; moderate: number; high: number; critical: number }) {\n if (v.critical > 0 || v.high > 0) return \"fail\" as const;\n if (v.moderate > 0 || v.low > 0) return \"warn\" as const;\n return \"pass\" as const;\n}\n\nasync function tryRun(\n spawn: (cmd: string, args: readonly string[], opts?: { cwd?: string }) => Promise<SpawnResult>,\n cmd: string,\n args: readonly string[],\n cwd: string,\n): Promise<SpawnResult | { missing: true }> {\n try {\n return await spawn(cmd, args, { cwd });\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\" || /ENOENT/.test(String(err))) return { missing: true };\n throw err;\n }\n}\n\nexport async function securityAudit(ctx: AuditContext): Promise<AuditResult> {\n const spawn = ctx.spawn ?? defaultSpawn;\n const site = ctx.site;\n const label = siteLabel(site);\n\n let used = \"pnpm audit\";\n let raw: SpawnResult | { missing: true } = await tryRun(\n spawn,\n \"pnpm\",\n [\"audit\", \"--json\", \"--prod\"],\n site.path,\n );\n\n if (\"missing\" in raw) {\n used = \"npm audit\";\n raw = await tryRun(spawn, \"npm\", [\"audit\", \"--json\", \"--omit=dev\"], site.path);\n }\n\n if (\"missing\" in raw) {\n return {\n audit: \"security\",\n site: label,\n status: \"skip\",\n summary: \"neither pnpm nor npm is available on PATH\",\n };\n }\n\n // pnpm/npm audit exit codes: 0 = clean, 1 = vulns found. Anything else is a real error.\n if (raw.code !== 0 && raw.code !== 1) {\n return {\n audit: \"security\",\n site: label,\n status: \"skip\",\n summary: `${used} exited with code ${raw.code}`,\n details: { stderr: raw.stderr },\n };\n }\n\n let parsed: AuditJson;\n try {\n parsed = JSON.parse(raw.stdout) as AuditJson;\n } catch (err) {\n return {\n audit: \"security\",\n site: label,\n status: \"skip\",\n summary: `${used} produced unparseable JSON`,\n details: { error: String(err), stdout: raw.stdout.slice(0, 500) },\n };\n }\n\n const vuln = {\n low: parsed.metadata?.vulnerabilities?.low ?? 0,\n moderate: parsed.metadata?.vulnerabilities?.moderate ?? 0,\n high: parsed.metadata?.vulnerabilities?.high ?? 0,\n critical: parsed.metadata?.vulnerabilities?.critical ?? 0,\n };\n\n const status = classify(vuln);\n const total = vuln.low + vuln.moderate + vuln.high + vuln.critical;\n const summary =\n status === \"pass\"\n ? `${used}: 0 vulnerabilities`\n : `${used}: ${total} vulnerabilities (${vuln.critical}C/${vuln.high}H/${vuln.moderate}M/${vuln.low}L)`;\n\n return {\n audit: \"security\",\n site: label,\n status,\n summary,\n details: vuln,\n };\n}\n","import { writeFile, mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AuditResult, Site } from \"../types.js\";\nimport { lighthouseConfig } from \"../configs/lighthouse.js\";\nimport { defaultSpawn } from \"./util/spawn.js\";\nimport type { AuditContext } from \"./util/inject.js\";\n\ntype NormalizedLhciResult = {\n summary: Record<string, number>;\n assertionsFailed: number;\n assertions?: Array<{ category: string; level: \"warn\" | \"error\"; message: string }>;\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nfunction isFakeShape(stdout: string): NormalizedLhciResult | null {\n // Tests inject a pre-normalized JSON blob; detect that and pass through.\n try {\n const parsed = JSON.parse(stdout) as NormalizedLhciResult;\n if (typeof parsed.assertionsFailed === \"number\" && parsed.summary) return parsed;\n } catch {\n return null;\n }\n return null;\n}\n\nexport async function lighthouseAudit(ctx: AuditContext): Promise<AuditResult> {\n const spawn = ctx.spawn ?? defaultSpawn;\n const site = ctx.site;\n const label = siteLabel(site);\n\n const dir = await mkdtemp(join(tmpdir(), \"reddoor-lhci-\"));\n const configPath = join(dir, \"lighthouserc.json\");\n await writeFile(configPath, JSON.stringify(lighthouseConfig), \"utf-8\");\n\n let raw;\n try {\n raw = await spawn(\"npx\", [\"--yes\", \"@lhci/cli\", \"autorun\", `--config=${configPath}`], {\n cwd: site.path,\n });\n } catch (err) {\n await rm(dir, { recursive: true, force: true });\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\" || /ENOENT/.test(String(err))) {\n return {\n audit: \"lighthouse\",\n site: label,\n status: \"skip\",\n summary: \"npx/@lhci/cli not available\",\n };\n }\n throw err;\n }\n await rm(dir, { recursive: true, force: true });\n\n const fake = isFakeShape(raw.stdout);\n const normalized: NormalizedLhciResult = fake ?? {\n summary: {},\n assertionsFailed: raw.code === 0 ? 0 : 1,\n assertions:\n raw.code === 0\n ? []\n : [{ category: \"unknown\", level: \"error\", message: raw.stderr.slice(0, 200) }],\n };\n\n const anyError = (normalized.assertions ?? []).some((a) => a.level === \"error\");\n const anyWarn = (normalized.assertions ?? []).some((a) => a.level === \"warn\");\n\n const status: AuditResult[\"status\"] = anyError ? \"fail\" : anyWarn ? \"warn\" : \"pass\";\n\n const summary =\n status === \"pass\"\n ? \"lighthouse: all categories passing\"\n : `lighthouse: ${normalized.assertionsFailed} assertion(s) failed`;\n\n return {\n audit: \"lighthouse\",\n site: label,\n status,\n summary,\n details: normalized,\n };\n}\n","export const lighthouseConfig = {\n ci: {\n collect: {\n url: [\"http://localhost:5173/dev/a11y-fixtures\"],\n startServerCommand: \"pnpm vite:dev\",\n startServerReadyPattern: \"ready in\",\n startServerReadyTimeout: 120_000,\n numberOfRuns: 1,\n settings: {\n preset: \"desktop\",\n skipAudits: [\"uses-http2\"],\n },\n },\n assert: {\n assertions: {\n \"categories:accessibility\": [\"error\", { minScore: 0.95 }],\n \"categories:best-practices\": [\"error\", { minScore: 0.9 }],\n \"categories:seo\": [\"error\", { minScore: 0.9 }],\n \"categories:performance\": [\"warn\", { minScore: 0.7 }],\n },\n },\n upload: {\n target: \"temporary-public-storage\",\n },\n },\n} as const;\n\nexport default lighthouseConfig;\n","import { writeFile, mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AuditResult, Site } from \"../types.js\";\nimport { a11yRoutes } from \"../configs/playwright-a11y.js\";\nimport { defaultSpawn } from \"./util/spawn.js\";\nimport type { AuditContext } from \"./util/inject.js\";\n\ntype NormalizedA11y = {\n totalViolations: number;\n byImpact: Partial<Record<\"minor\" | \"moderate\" | \"serious\" | \"critical\", number>>;\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nfunction isFakeShape(stdout: string): NormalizedA11y | null {\n try {\n const parsed = JSON.parse(stdout) as NormalizedA11y;\n if (typeof parsed.totalViolations === \"number\" && parsed.byImpact) return parsed;\n } catch {\n return null;\n }\n return null;\n}\n\nfunction buildSpec(): string {\n return `\nimport { test, expect } from \"@playwright/test\";\nimport AxeBuilder from \"@axe-core/playwright\";\nconst pages = ${JSON.stringify(a11yRoutes)};\nfor (const { path, name } of pages) {\n test(\\`\\${name} has no axe violations\\`, async ({ page }) => {\n await page.goto(path);\n const results = await new AxeBuilder({ page })\n .withTags([\"wcag2a\",\"wcag2aa\",\"wcag21a\",\"wcag21aa\",\"wcag22aa\"])\n .analyze();\n expect(results.violations).toEqual([]);\n });\n}\n`;\n}\n\nexport async function a11yAudit(ctx: AuditContext): Promise<AuditResult> {\n const spawn = ctx.spawn ?? defaultSpawn;\n const site = ctx.site;\n const label = siteLabel(site);\n\n const dir = await mkdtemp(join(tmpdir(), \"reddoor-a11y-\"));\n const specPath = join(dir, \"a11y.spec.ts\");\n await writeFile(specPath, buildSpec(), \"utf-8\");\n\n let raw;\n try {\n raw = await spawn(\"npx\", [\"--yes\", \"playwright\", \"test\", \"--reporter=json\", specPath], {\n cwd: site.path,\n });\n } catch (err) {\n await rm(dir, { recursive: true, force: true });\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\" || /ENOENT/.test(String(err))) {\n return {\n audit: \"a11y\",\n site: label,\n status: \"skip\",\n summary: \"npx/playwright not available\",\n };\n }\n throw err;\n }\n await rm(dir, { recursive: true, force: true });\n\n const fake = isFakeShape(raw.stdout);\n const normalized: NormalizedA11y = fake ?? {\n totalViolations: raw.code === 0 ? 0 : 1,\n byImpact: raw.code === 0 ? {} : { moderate: 1 },\n };\n\n const hasSerious =\n (normalized.byImpact.serious ?? 0) > 0 || (normalized.byImpact.critical ?? 0) > 0;\n const hasAny = normalized.totalViolations > 0;\n\n const status: AuditResult[\"status\"] = hasSerious ? \"fail\" : hasAny ? \"warn\" : \"pass\";\n const summary =\n status === \"pass\"\n ? `a11y: 0 violations across ${a11yRoutes.length} routes`\n : `a11y: ${normalized.totalViolations} violations`;\n\n return {\n audit: \"a11y\",\n site: label,\n status,\n summary,\n details: normalized,\n };\n}\n","import { defineConfig, devices, type PlaywrightTestConfig } from \"@playwright/test\";\n\nexport type A11yRoute = { path: string; name: string };\n\nexport const a11yRoutes: A11yRoute[] = [\n { path: \"/dev/a11y-fixtures\", name: \"a11y fixtures\" },\n { path: \"/dev/animate-in\", name: \"animate-in demo\" },\n];\n\nexport const playwrightA11yConfig: PlaywrightTestConfig = defineConfig({\n testDir: \"tests\",\n testMatch: /.*\\.spec\\.ts$/,\n fullyParallel: true,\n forbidOnly: !!process.env.CI,\n retries: process.env.CI ? 2 : 0,\n reporter: process.env.CI ? \"github\" : \"list\",\n use: {\n baseURL: \"http://localhost:5173\",\n trace: \"on-first-retry\",\n },\n projects: [\n {\n name: \"chromium\",\n use: { ...devices[\"Desktop Chrome\"] },\n },\n ],\n webServer: {\n command: \"pnpm vite:dev\",\n url: \"http://localhost:5173/dev/a11y-fixtures\",\n reuseExistingServer: !process.env.CI,\n timeout: 120_000,\n },\n});\n\nexport default playwrightA11yConfig;\n","import type { AuditName, AuditResult, Site } from \"../types.js\";\nimport type { AuditContext } from \"./util/inject.js\";\nimport { defaultSpawn } from \"./util/spawn.js\";\nimport type { SpawnFn } from \"./util/spawn.js\";\nimport { depsAudit } from \"./deps.js\";\nimport { lintAudit } from \"./lint.js\";\nimport { securityAudit } from \"./security.js\";\nimport { lighthouseAudit } from \"./lighthouse.js\";\nimport { a11yAudit } from \"./a11y.js\";\n\nconst REGISTRY: Record<AuditName, (ctx: AuditContext) => Promise<AuditResult>> = {\n deps: depsAudit,\n lint: lintAudit,\n security: securityAudit,\n lighthouse: lighthouseAudit,\n a11y: a11yAudit,\n};\n\nexport const ALL_AUDIT_NAMES = Object.keys(REGISTRY) as AuditName[];\n\n/** Default per-audit spawn timeout when running via runAudits (30 s). */\nconst DEFAULT_AUDIT_TIMEOUT_MS = 30_000;\n\nfunction timedSpawn(timeoutMs: number): SpawnFn {\n return (cmd, args, opts = {}) =>\n defaultSpawn(cmd, args, { ...opts, timeoutMs: opts.timeoutMs ?? timeoutMs });\n}\n\nexport async function runAudits(site: Site, which?: AuditName[]): Promise<AuditResult[]> {\n const names = which ?? ALL_AUDIT_NAMES;\n for (const n of names) {\n if (!(n in REGISTRY)) throw new Error(`unknown audit: ${n}`);\n }\n const spawn = timedSpawn(DEFAULT_AUDIT_TIMEOUT_MS);\n const label = site.name ?? site.path;\n return Promise.all(\n names.map((n) =>\n REGISTRY[n]({ site, spawn }).catch(\n (err): AuditResult => ({\n audit: n,\n site: label,\n status: \"fail\",\n summary: `${n}: unexpected error — ${String(err)}`,\n }),\n ),\n ),\n );\n}\n\nexport async function runAuditsAcross(sites: Site[], which?: AuditName[]): Promise<AuditResult[]> {\n const all = await Promise.all(sites.map((s) => runAudits(s, which)));\n return all.flat();\n}\n\nexport { depsAudit, lintAudit, securityAudit, lighthouseAudit, a11yAudit };\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { RecipeResult, Site, ConfigName } from \"../types.js\";\nimport { ALL_TEMPLATES, templatesByName, type ConfigTemplate } from \"./sync-configs/templates.js\";\nimport { branchName, commit, createBranch, isWorkingTreeClean } from \"../util/git.js\";\n\nexport type SyncConfigsOptions = {\n which?: ConfigName[];\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nasync function readMaybe(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nasync function planDiffs(cwd: string, templates: ConfigTemplate[]): Promise<ConfigTemplate[]> {\n const diffs: ConfigTemplate[] = [];\n for (const t of templates) {\n const existing = await readMaybe(join(cwd, t.path));\n if (existing !== t.contents) diffs.push(t);\n }\n return diffs;\n}\n\nexport async function syncConfigs(\n site: Site,\n opts: SyncConfigsOptions = {},\n): Promise<RecipeResult> {\n const label = siteLabel(site);\n const targets = opts.which ? templatesByName(opts.which) : ALL_TEMPLATES;\n\n const diffs = await planDiffs(site.path, targets);\n if (diffs.length === 0) {\n return {\n recipe: \"sync-configs\",\n site: label,\n status: \"noop\",\n commits: [],\n notes: \"all targeted configs already match\",\n };\n }\n\n if (!(await isWorkingTreeClean(site.path))) {\n throw new Error(`refusing to run: working tree is not clean at ${site.path}`);\n }\n\n const branch = branchName(\"sync-configs\");\n await createBranch(site.path, branch);\n\n const shas: string[] = [];\n for (const t of diffs) {\n await writeFile(join(site.path, t.path), t.contents, \"utf-8\");\n const sha = await commit(\n site.path,\n `chore: sync ${t.config} config from @reddoorla/maintenance`,\n );\n if (sha) shas.push(sha);\n }\n\n return {\n recipe: \"sync-configs\",\n site: label,\n status: \"applied\",\n commits: shas,\n notes: `branch: ${branch}`,\n };\n}\n","import type { ConfigName } from \"../../types.js\";\n\nexport type ConfigTemplate = {\n config: ConfigName;\n path: string;\n contents: string;\n};\n\nconst eslint: ConfigTemplate = {\n config: \"eslint\",\n path: \"eslint.config.js\",\n contents: `import { createEslintConfig } from \"@reddoorla/maintenance/configs/eslint\";\nimport svelteConfig from \"./svelte.config.js\";\n\nexport default createEslintConfig({ svelteConfig });\n`,\n};\n\nconst prettier: ConfigTemplate = {\n config: \"prettier\",\n path: \".prettierrc.json\",\n contents: `{\n \"trailingComma\": \"all\",\n \"singleQuote\": false,\n \"printWidth\": 100,\n \"plugins\": [\"prettier-plugin-svelte\"]\n}\n`,\n};\n\nconst lighthouse: ConfigTemplate = {\n config: \"lighthouse\",\n path: \"lighthouserc.json\",\n contents: `${JSON.stringify(\n {\n $note:\n \"Generated by @reddoorla/maintenance sync-configs; edit src/configs/lighthouse.ts in the package instead.\",\n extends: \"@reddoorla/maintenance/configs/lighthouse\",\n },\n null,\n 2,\n )}\n`,\n};\n\nconst playwrightA11y: ConfigTemplate = {\n config: \"playwright-a11y\",\n path: \"playwright.config.ts\",\n contents: `export { default } from \"@reddoorla/maintenance/configs/playwright-a11y\";\n`,\n};\n\nexport const ALL_TEMPLATES: ConfigTemplate[] = [eslint, prettier, lighthouse, playwrightA11y];\n\nexport function templatesByName(which: ConfigName[]): ConfigTemplate[] {\n return ALL_TEMPLATES.filter((t) => which.includes(t.config));\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst exec = promisify(execFile);\n\nasync function git(cwd: string, args: string[]): Promise<{ stdout: string; stderr: string }> {\n return exec(\"git\", args, { cwd, env: process.env });\n}\n\nexport function branchName(recipe: string, when: Date = new Date()): string {\n const iso = when.toISOString().replace(/[-:.]/g, \"\").replace(/Z$/, \"Z\");\n // 2026-05-20T10:30:00.000Z → 20260520T103000000Z; trim millis:\n const trimmed = iso.replace(/(\\d{8}T\\d{6})\\d+(Z)$/, \"$1$2\");\n return `maint/${recipe}-${trimmed}`;\n}\n\nexport async function currentBranch(cwd: string): Promise<string> {\n const { stdout } = await git(cwd, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n return stdout.trim();\n}\n\nexport async function isWorkingTreeClean(cwd: string): Promise<boolean> {\n const { stdout } = await git(cwd, [\"status\", \"--porcelain\"]);\n return stdout.trim().length === 0;\n}\n\nexport async function createBranch(cwd: string, name: string): Promise<void> {\n await git(cwd, [\"checkout\", \"-b\", name]);\n}\n\nexport async function stageAll(cwd: string): Promise<void> {\n await git(cwd, [\"add\", \"-A\"]);\n}\n\n/**\n * Stages all current changes and commits with `message`. Returns the commit SHA,\n * or `null` if there was nothing to commit.\n */\nexport async function commit(cwd: string, message: string): Promise<string | null> {\n await stageAll(cwd);\n const { stdout: status } = await git(cwd, [\"status\", \"--porcelain\"]);\n if (status.trim().length === 0) return null;\n await git(cwd, [\"commit\", \"-m\", message]);\n const { stdout: sha } = await git(cwd, [\"rev-parse\", \"HEAD\"]);\n return sha.trim();\n}\n","import type { RecipeResult, Site } from \"../types.js\";\nimport { branchName, commit, createBranch, isWorkingTreeClean } from \"../util/git.js\";\nimport { defaultSpawn, type SpawnFn } from \"../audits/util/spawn.js\";\n\nexport type BumpDepsGroup = \"patch\" | \"minor\" | \"major\";\n\nexport type BumpDepsOptions = {\n group?: BumpDepsGroup;\n spawn?: SpawnFn;\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nfunction outdatedFlagsForGroup(group: BumpDepsGroup): string[] {\n if (group === \"major\") return [\"--latest\"];\n if (group === \"minor\") return [];\n return [\"--depth\", \"0\"];\n}\n\nfunction upFlagsForGroup(group: BumpDepsGroup): string[] {\n if (group === \"major\") return [\"--latest\"];\n return [];\n}\n\nexport async function bumpDeps(site: Site, opts: BumpDepsOptions = {}): Promise<RecipeResult> {\n const label = siteLabel(site);\n const group: BumpDepsGroup = opts.group ?? \"minor\";\n const spawn = opts.spawn ?? defaultSpawn;\n\n const outdated = await spawn(\"pnpm\", [\"outdated\", \"--json\", ...outdatedFlagsForGroup(group)], {\n cwd: site.path,\n });\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(outdated.stdout || \"{}\") as Record<string, unknown>;\n } catch {\n parsed = {};\n }\n const nothingToDo = Object.keys(parsed).length === 0;\n\n if (nothingToDo) {\n return {\n recipe: \"bump-deps\",\n site: label,\n status: \"noop\",\n commits: [],\n notes: `pnpm outdated reported nothing for group=${group}`,\n };\n }\n\n if (!(await isWorkingTreeClean(site.path))) {\n throw new Error(`refusing to run: working tree is not clean at ${site.path}`);\n }\n\n const branch = branchName(\"bump-deps\");\n await createBranch(site.path, branch);\n\n await spawn(\"pnpm\", [\"up\", ...upFlagsForGroup(group)], { cwd: site.path });\n\n const sha = await commit(site.path, `chore(deps): bump dependencies (${group})`);\n const shas = sha ? [sha] : [];\n\n return {\n recipe: \"bump-deps\",\n site: label,\n status: shas.length > 0 ? \"applied\" : \"noop\",\n commits: shas,\n notes: `branch: ${branch}`,\n };\n}\n","import { join } from \"node:path\";\nimport type { RecipeResult, Site } from \"../../types.js\";\nimport { branchName, commit, createBranch, isWorkingTreeClean } from \"../../util/git.js\";\nimport { readPackageJson } from \"../../util/pkg.js\";\nimport { defaultSpawn, type SpawnFn } from \"../../audits/util/spawn.js\";\nimport { bumpToSvelte5Versions } from \"./step-bump-versions.js\";\nimport { migrateSvelteConfig } from \"./step-svelte-config.js\";\nimport { runSvelteMigrate } from \"./step-svelte-migrate.js\";\nimport { upgradeTailwind } from \"./step-tailwind-upgrade.js\";\nimport { applyGotchaCodemods } from \"./step-gotchas.js\";\nimport { verifyMigration } from \"./step-verify.js\";\nimport { writeMigrationSummary } from \"./step-summary.js\";\n\nexport type UpgradeSvelte4to5Options = {\n spawn?: SpawnFn;\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nasync function alreadyOnSvelte5(cwd: string): Promise<boolean> {\n try {\n const pkg = await readPackageJson(join(cwd, \"package.json\"));\n const v = pkg.devDependencies?.svelte ?? pkg.dependencies?.svelte;\n return !!v && /^\\^?5\\./.test(v);\n } catch {\n return false;\n }\n}\n\nexport async function upgradeSvelte4to5(\n site: Site,\n opts: UpgradeSvelte4to5Options = {},\n): Promise<RecipeResult> {\n const label = siteLabel(site);\n const spawn = opts.spawn ?? defaultSpawn;\n\n if (await alreadyOnSvelte5(site.path)) {\n return {\n recipe: \"svelte-4-to-5\",\n site: label,\n status: \"noop\",\n commits: [],\n notes: \"site already declares svelte ^5.x\",\n };\n }\n\n if (!(await isWorkingTreeClean(site.path))) {\n throw new Error(`refusing to run: working tree is not clean at ${site.path}`);\n }\n\n const branch = branchName(\"svelte-4-to-5\");\n await createBranch(site.path, branch);\n\n const shas: string[] = [];\n\n const bumped = await bumpToSvelte5Versions(site.path);\n if (bumped) {\n const sha = await commit(site.path, \"chore(svelte5): bump svelte/kit/vite/vite-plugin-svelte\");\n if (sha) shas.push(sha);\n }\n\n const configChanged = await migrateSvelteConfig(site.path);\n if (configChanged) {\n const sha = await commit(\n site.path,\n \"refactor(svelte5): migrate svelte.config.js (drop vitePreprocess)\",\n );\n if (sha) shas.push(sha);\n }\n\n const migrate = await runSvelteMigrate(site.path, spawn);\n if (migrate.ran) {\n const sha = await commit(site.path, \"refactor(svelte5): run official svelte-migrate codemod\");\n if (sha) shas.push(sha);\n }\n\n const tw = await upgradeTailwind(site.path, spawn);\n if (tw.ran) {\n const sha = await commit(site.path, \"chore(svelte5): tailwindcss 3 → 4 upgrade\");\n if (sha) shas.push(sha);\n }\n\n const codemods = await applyGotchaCodemods(site.path);\n if (codemods.filesChanged > 0) {\n const sha = await commit(\n site.path,\n `refactor(svelte5): apply gotcha codemods (${codemods.filesChanged} files)`,\n );\n if (sha) shas.push(sha);\n }\n\n await verifyMigration(site.path, spawn);\n const verifySha = await commit(site.path, \"chore(svelte5): pnpm install + check\");\n if (verifySha) shas.push(verifySha);\n\n await writeMigrationSummary({\n cwd: site.path,\n filesChangedByCodemods: codemods.filesChanged,\n svelteMigrateRan: migrate.ran,\n tailwindUpgraded: tw.ran,\n });\n const summarySha = await commit(site.path, \"docs(svelte5): add MIGRATION_SVELTE_5.md summary\");\n if (summarySha) shas.push(summarySha);\n\n return {\n recipe: \"svelte-4-to-5\",\n site: label,\n status: shas.length > 0 ? \"applied\" : \"noop\",\n commits: shas,\n notes: `branch: ${branch}`,\n };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\n\nexport type PackageJsonLike = {\n name?: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n};\n\nexport async function readPackageJson(path: string): Promise<PackageJsonLike> {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw) as PackageJsonLike;\n}\n\nexport async function writePackageJson(path: string, pkg: PackageJsonLike): Promise<void> {\n const content = JSON.stringify(pkg, null, 2) + \"\\n\";\n await writeFile(path, content, \"utf-8\");\n}\n\nexport function bumpDep(pkg: PackageJsonLike, name: string, version: string): PackageJsonLike {\n const next: PackageJsonLike = {\n ...pkg,\n };\n\n if (pkg.dependencies) {\n next.dependencies = { ...pkg.dependencies };\n }\n if (pkg.devDependencies) {\n next.devDependencies = { ...pkg.devDependencies };\n }\n\n if (next.dependencies && name in next.dependencies) {\n if (next.dependencies[name] === version) return pkg;\n next.dependencies[name] = version;\n return next;\n }\n if (next.devDependencies && name in next.devDependencies) {\n if (next.devDependencies[name] === version) return pkg;\n next.devDependencies[name] = version;\n return next;\n }\n // Not present in either: add to devDependencies.\n next.devDependencies = { ...(next.devDependencies ?? {}), [name]: version };\n return next;\n}\n","import { join } from \"node:path\";\nimport { readPackageJson, writePackageJson, bumpDep } from \"../../util/pkg.js\";\n\nconst SVELTE_5_VERSIONS: Record<string, string> = {\n svelte: \"^5.55.5\",\n \"@sveltejs/kit\": \"^2.59.0\",\n \"@sveltejs/vite-plugin-svelte\": \"^7.0.0\",\n \"@sveltejs/adapter-netlify\": \"^6.0.4\",\n \"@sveltejs/adapter-auto\": \"^7.0.0\",\n vite: \"^8.0.10\",\n \"svelte-check\": \"^4.4.7\",\n typescript: \"^6.0.3\",\n \"typescript-svelte-plugin\": \"^0.3.52\",\n};\n\nexport async function bumpToSvelte5Versions(cwd: string): Promise<boolean> {\n const pkgPath = join(cwd, \"package.json\");\n const pkg = await readPackageJson(pkgPath);\n let next = pkg;\n for (const [name, version] of Object.entries(SVELTE_5_VERSIONS)) {\n next = bumpDep(next, name, version);\n }\n if (next === pkg) return false;\n await writePackageJson(pkgPath, next);\n return true;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function migrateSvelteConfig(cwd: string): Promise<boolean> {\n const path = join(cwd, \"svelte.config.js\");\n let src: string;\n try {\n src = await readFile(path, \"utf-8\");\n } catch {\n return false;\n }\n\n let next = src;\n next = next.replace(\n /^import\\s+\\{\\s*vitePreprocess\\s*\\}\\s+from\\s+[\"']@sveltejs\\/vite-plugin-svelte[\"'];\\n/m,\n \"\",\n );\n next = next.replace(/^\\s*preprocess:\\s*vitePreprocess\\(\\)\\s*,?\\s*\\n/m, \"\");\n\n if (next === src) return false;\n await writeFile(path, next, \"utf-8\");\n return true;\n}\n","import { defaultSpawn, type SpawnFn } from \"../../audits/util/spawn.js\";\n\nexport async function runSvelteMigrate(\n cwd: string,\n spawn: SpawnFn = defaultSpawn,\n): Promise<{ ran: boolean; stderr: string }> {\n try {\n const { code, stderr } = await spawn(\n \"npx\",\n [\"--yes\", \"svelte-migrate\", \"svelte-5\", \"--no-install\"],\n { cwd, timeoutMs: 5 * 60_000 },\n );\n if (code !== 0) {\n return { ran: false, stderr };\n }\n return { ran: true, stderr };\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\" || /ENOENT/.test(String(err))) {\n return { ran: false, stderr: \"npx unavailable\" };\n }\n throw err;\n }\n}\n","import { readPackageJson } from \"../../util/pkg.js\";\nimport { join } from \"node:path\";\nimport { defaultSpawn, type SpawnFn } from \"../../audits/util/spawn.js\";\n\nexport async function upgradeTailwind(\n cwd: string,\n spawn: SpawnFn = defaultSpawn,\n): Promise<{ ran: boolean; reason?: string }> {\n const pkg = await readPackageJson(join(cwd, \"package.json\"));\n const tailwindVersion = pkg.devDependencies?.tailwindcss ?? pkg.dependencies?.tailwindcss;\n if (!tailwindVersion) return { ran: false, reason: \"tailwindcss not installed\" };\n if (/^\\^?4\\./.test(tailwindVersion)) return { ran: false, reason: \"already on tailwind 4.x\" };\n\n try {\n const { code, stderr } = await spawn(\"npx\", [\"--yes\", \"@tailwindcss/upgrade\", \"--force\"], {\n cwd,\n timeoutMs: 5 * 60_000,\n });\n if (code !== 0) return { ran: false, reason: stderr.slice(0, 200) };\n return { ran: true };\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\" || /ENOENT/.test(String(err))) {\n return { ran: false, reason: \"npx unavailable\" };\n }\n throw err;\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { glob } from \"tinyglobby\";\nimport { onEventToHandler } from \"./codemods/on-event-to-handler.js\";\nimport { exportLetToProps } from \"./codemods/dollar-props.js\";\nimport { removeDollarRestProps } from \"./codemods/dollar-restprops.js\";\n\nconst SVELTE_GLOBS = [\"src/**/*.svelte\"];\nconst IGNORE = [\"node_modules/**\", \".svelte-kit/**\", \"build/**\"];\n\ntype Codemod = (src: string) => string;\n\nconst CODEMODS: Codemod[] = [onEventToHandler, exportLetToProps, removeDollarRestProps];\n\nexport async function applyGotchaCodemods(cwd: string): Promise<{ filesChanged: number }> {\n let filesChanged = 0;\n const relPaths = await glob(SVELTE_GLOBS, { cwd, ignore: IGNORE, absolute: false });\n for (const rel of relPaths) {\n const path = join(cwd, rel);\n const before = await readFile(path, \"utf-8\");\n const after = CODEMODS.reduce((s, fn) => fn(s), before);\n if (after !== before) {\n await writeFile(path, after, \"utf-8\");\n filesChanged += 1;\n }\n }\n return { filesChanged };\n}\n","const SCRIPT_BLOCK = /<script\\b[^>]*>[\\s\\S]*?<\\/script>/g;\nconst SIMPLE_ON_EVENT = /\\bon:([a-z]+)(?=\\s*=)/g;\n\nexport function onEventToHandler(source: string): string {\n const masked: string[] = [];\n const placeholder = (i: number): string => ` SCRIPT_${i} `;\n const intermediate = source.replace(SCRIPT_BLOCK, (match) => {\n masked.push(match);\n return placeholder(masked.length - 1);\n });\n\n const rewritten = intermediate.replace(SIMPLE_ON_EVENT, (_full, name: string) => `on${name}`);\n\n let out = rewritten;\n masked.forEach((blk, i) => {\n out = out.replace(placeholder(i), blk);\n });\n\n return out;\n}\n","const SCRIPT_TS = /<script\\b[^>]*lang=[\"']ts[\"'][^>]*>([\\s\\S]*?)<\\/script>/;\nconst EXPORT_LET = /^\\s*export\\s+let\\s+(\\w+)\\s*(?::\\s*([^=;\\n]+))?\\s*(?:=\\s*([^;\\n]+))?;?\\s*$/gm;\n\ntype Prop = { name: string; type?: string | undefined; defaultExpr?: string | undefined };\n\nfunction transformScript(scriptBody: string): { body: string; changed: boolean } {\n const props: Prop[] = [];\n const cleaned = scriptBody.replace(\n EXPORT_LET,\n (_full, name: string, type?: string, defaultExpr?: string) => {\n props.push({\n name,\n type: type?.trim(),\n defaultExpr: defaultExpr?.trim(),\n });\n return \"\";\n },\n );\n if (props.length === 0) return { body: scriptBody, changed: false };\n\n const typeSig = props\n .map((p) => {\n const optional = p.defaultExpr ? \"?\" : \"\";\n return `${p.name}${optional}: ${p.type ?? \"unknown\"}`;\n })\n .join(\"; \");\n const destructured = props\n .map((p) => (p.defaultExpr ? `${p.name} = ${p.defaultExpr}` : p.name))\n .join(\", \");\n const decl = ` let { ${destructured} }: { ${typeSig} } = $props();`;\n\n const next = cleaned.replace(/^(\\s*)/, (m) => `${m}${decl}\\n`);\n return { body: next, changed: true };\n}\n\nexport function exportLetToProps(source: string): string {\n const match = source.match(SCRIPT_TS);\n if (!match) return source;\n const inner = match[1] ?? \"\";\n const { body, changed } = transformScript(inner);\n if (!changed) return source;\n return source.replace(SCRIPT_TS, (full) => full.replace(inner, body));\n}\n","export function removeDollarRestProps(source: string): string {\n let next = source;\n next = next.replace(/\\$\\$restProps/g, \"rest\");\n next = next.replace(/^\\s*interface\\s+\\$\\$Props\\s*\\{[^}]*\\}\\s*\\n/gm, \"\");\n return next;\n}\n","import { defaultSpawn, type SpawnFn, type SpawnResult } from \"../../audits/util/spawn.js\";\n\nexport type VerifyResult = {\n install: SpawnResult | { skipped: true };\n check: SpawnResult | { skipped: true };\n};\n\nexport async function verifyMigration(\n cwd: string,\n spawn: SpawnFn = defaultSpawn,\n): Promise<VerifyResult> {\n let install: VerifyResult[\"install\"];\n try {\n install = await spawn(\"pnpm\", [\"install\"], { cwd, timeoutMs: 10 * 60_000 });\n } catch {\n install = { skipped: true };\n }\n\n let check: VerifyResult[\"check\"];\n try {\n check = await spawn(\"pnpm\", [\"run\", \"check\"], { cwd, timeoutMs: 5 * 60_000 });\n } catch {\n check = { skipped: true };\n }\n\n return { install, check };\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type SummaryInput = {\n cwd: string;\n filesChangedByCodemods: number;\n svelteMigrateRan: boolean;\n tailwindUpgraded: boolean;\n};\n\nexport async function writeMigrationSummary(input: SummaryInput): Promise<string> {\n const lines = [\n `# Svelte 4 → 5 migration summary`,\n ``,\n `Generated by @reddoorla/maintenance.`,\n ``,\n `- svelte-migrate run: ${input.svelteMigrateRan ? \"yes\" : \"no\"}`,\n `- @tailwindcss/upgrade run: ${input.tailwindUpgraded ? \"yes\" : \"no\"}`,\n `- .svelte files touched by gotcha codemods: ${input.filesChangedByCodemods}`,\n ``,\n `Next steps:`,\n `- Run \\`pnpm run check\\` and resolve any remaining warnings.`,\n `- Spot-check rune migrations in components that use \\`reactive\\` statements.`,\n `- Verify Playwright a11y tests still pass.`,\n ];\n const content = lines.join(\"\\n\") + \"\\n\";\n const path = join(input.cwd, \"MIGRATION_SVELTE_5.md\");\n await writeFile(path, content, \"utf-8\");\n return path;\n}\n","import type { RecipeName } from \"../types.js\";\nimport { syncConfigs, type SyncConfigsOptions } from \"./sync-configs.js\";\nimport { bumpDeps, type BumpDepsOptions } from \"./bump-deps.js\";\nimport { upgradeSvelte4to5, type UpgradeSvelte4to5Options } from \"./svelte-5/index.js\";\n\nexport { syncConfigs, bumpDeps, upgradeSvelte4to5 };\nexport type { SyncConfigsOptions, BumpDepsOptions, UpgradeSvelte4to5Options };\n\nexport const ALL_RECIPE_NAMES: RecipeName[] = [\"sync-configs\", \"bump-deps\", \"svelte-4-to-5\"];\n\nexport function isRecipeName(value: string): value is RecipeName {\n return (ALL_RECIPE_NAMES as string[]).includes(value);\n}\n","import { basename } from \"node:path\";\nimport type { InventoryProvider, Site } from \"../types.js\";\n\nexport type LocalPathOptions = {\n name?: string;\n};\n\nexport function localPath(path: string, opts: LocalPathOptions = {}): InventoryProvider {\n const site: Site = { path, name: opts.name ?? basename(path) };\n return async () => [site];\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { InventoryProvider, Site } from \"../types.js\";\n\nfunction validate(raw: unknown): Site[] {\n if (!Array.isArray(raw)) {\n throw new Error(\"inventory JSON must be an array of sites\");\n }\n return raw.map((entry, i) => {\n if (!entry || typeof entry !== \"object\") {\n throw new Error(`inventory entry ${i} is not an object`);\n }\n const e = entry as Record<string, unknown>;\n if (typeof e.path !== \"string\" || e.path.length === 0) {\n throw new Error(`inventory entry ${i} is missing required field: path`);\n }\n const site: Site = { path: e.path };\n if (typeof e.name === \"string\") site.name = e.name;\n if (typeof e.repoUrl === \"string\") site.repoUrl = e.repoUrl;\n if (typeof e.meta === \"object\" && e.meta !== null) {\n site.meta = e.meta as Record<string, unknown>;\n }\n return site;\n });\n}\n\nexport function fromJsonFile(path: string): InventoryProvider {\n return async () => {\n const raw = JSON.parse(await readFile(path, \"utf-8\")) as unknown;\n return validate(raw);\n };\n}\n"],"mappings":"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","names":["readFile","join","siteLabel","eslint","siteLabel","spawn","join","siteLabel","spawn","join","writeFile","mkdtemp","rm","tmpdir","join","siteLabel","isFakeShape","spawn","mkdtemp","join","tmpdir","writeFile","rm","spawn","readFile","writeFile","join","siteLabel","readFile","join","writeFile","siteLabel","spawn","join","readFile","writeFile","join","join","readFile","writeFile","join","spawn","join","spawn","join","readFile","writeFile","join","glob","IGNORE","glob","join","readFile","writeFile","spawn","writeFile","join","siteLabel","join","spawn","readFile"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { c as SyncConfigsOptions, s as syncConfigs } from '../sync-configs-Z5a0iaDd.js';
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// src/recipes/sync-configs.ts
|
|
2
|
+
import { readFile, writeFile } from "fs/promises";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
|
|
5
|
+
// src/recipes/sync-configs/templates.ts
|
|
6
|
+
var eslint = {
|
|
7
|
+
config: "eslint",
|
|
8
|
+
path: "eslint.config.js",
|
|
9
|
+
contents: `import { createEslintConfig } from "@reddoorla/maintenance/configs/eslint";
|
|
10
|
+
import svelteConfig from "./svelte.config.js";
|
|
11
|
+
|
|
12
|
+
export default createEslintConfig({ svelteConfig });
|
|
13
|
+
`
|
|
14
|
+
};
|
|
15
|
+
var prettier = {
|
|
16
|
+
config: "prettier",
|
|
17
|
+
path: ".prettierrc.json",
|
|
18
|
+
contents: `{
|
|
19
|
+
"trailingComma": "all",
|
|
20
|
+
"singleQuote": false,
|
|
21
|
+
"printWidth": 100,
|
|
22
|
+
"plugins": ["prettier-plugin-svelte"]
|
|
23
|
+
}
|
|
24
|
+
`
|
|
25
|
+
};
|
|
26
|
+
var lighthouse = {
|
|
27
|
+
config: "lighthouse",
|
|
28
|
+
path: "lighthouserc.json",
|
|
29
|
+
contents: `${JSON.stringify(
|
|
30
|
+
{
|
|
31
|
+
$note: "Generated by @reddoorla/maintenance sync-configs; edit src/configs/lighthouse.ts in the package instead.",
|
|
32
|
+
extends: "@reddoorla/maintenance/configs/lighthouse"
|
|
33
|
+
},
|
|
34
|
+
null,
|
|
35
|
+
2
|
|
36
|
+
)}
|
|
37
|
+
`
|
|
38
|
+
};
|
|
39
|
+
var playwrightA11y = {
|
|
40
|
+
config: "playwright-a11y",
|
|
41
|
+
path: "playwright.config.ts",
|
|
42
|
+
contents: `export { default } from "@reddoorla/maintenance/configs/playwright-a11y";
|
|
43
|
+
`
|
|
44
|
+
};
|
|
45
|
+
var ALL_TEMPLATES = [eslint, prettier, lighthouse, playwrightA11y];
|
|
46
|
+
function templatesByName(which) {
|
|
47
|
+
return ALL_TEMPLATES.filter((t) => which.includes(t.config));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/util/git.ts
|
|
51
|
+
import { execFile } from "child_process";
|
|
52
|
+
import { promisify } from "util";
|
|
53
|
+
var exec = promisify(execFile);
|
|
54
|
+
async function git(cwd, args) {
|
|
55
|
+
return exec("git", args, { cwd, env: process.env });
|
|
56
|
+
}
|
|
57
|
+
function branchName(recipe, when = /* @__PURE__ */ new Date()) {
|
|
58
|
+
const iso = when.toISOString().replace(/[-:.]/g, "").replace(/Z$/, "Z");
|
|
59
|
+
const trimmed = iso.replace(/(\d{8}T\d{6})\d+(Z)$/, "$1$2");
|
|
60
|
+
return `maint/${recipe}-${trimmed}`;
|
|
61
|
+
}
|
|
62
|
+
async function isWorkingTreeClean(cwd) {
|
|
63
|
+
const { stdout } = await git(cwd, ["status", "--porcelain"]);
|
|
64
|
+
return stdout.trim().length === 0;
|
|
65
|
+
}
|
|
66
|
+
async function createBranch(cwd, name) {
|
|
67
|
+
await git(cwd, ["checkout", "-b", name]);
|
|
68
|
+
}
|
|
69
|
+
async function stageAll(cwd) {
|
|
70
|
+
await git(cwd, ["add", "-A"]);
|
|
71
|
+
}
|
|
72
|
+
async function commit(cwd, message) {
|
|
73
|
+
await stageAll(cwd);
|
|
74
|
+
const { stdout: status } = await git(cwd, ["status", "--porcelain"]);
|
|
75
|
+
if (status.trim().length === 0) return null;
|
|
76
|
+
await git(cwd, ["commit", "-m", message]);
|
|
77
|
+
const { stdout: sha } = await git(cwd, ["rev-parse", "HEAD"]);
|
|
78
|
+
return sha.trim();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/recipes/sync-configs.ts
|
|
82
|
+
function siteLabel(site) {
|
|
83
|
+
return site.name ?? site.path;
|
|
84
|
+
}
|
|
85
|
+
async function readMaybe(path) {
|
|
86
|
+
try {
|
|
87
|
+
return await readFile(path, "utf-8");
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function planDiffs(cwd, templates) {
|
|
93
|
+
const diffs = [];
|
|
94
|
+
for (const t of templates) {
|
|
95
|
+
const existing = await readMaybe(join(cwd, t.path));
|
|
96
|
+
if (existing !== t.contents) diffs.push(t);
|
|
97
|
+
}
|
|
98
|
+
return diffs;
|
|
99
|
+
}
|
|
100
|
+
async function syncConfigs(site, opts = {}) {
|
|
101
|
+
const label = siteLabel(site);
|
|
102
|
+
const targets = opts.which ? templatesByName(opts.which) : ALL_TEMPLATES;
|
|
103
|
+
const diffs = await planDiffs(site.path, targets);
|
|
104
|
+
if (diffs.length === 0) {
|
|
105
|
+
return {
|
|
106
|
+
recipe: "sync-configs",
|
|
107
|
+
site: label,
|
|
108
|
+
status: "noop",
|
|
109
|
+
commits: [],
|
|
110
|
+
notes: "all targeted configs already match"
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (!await isWorkingTreeClean(site.path)) {
|
|
114
|
+
throw new Error(`refusing to run: working tree is not clean at ${site.path}`);
|
|
115
|
+
}
|
|
116
|
+
const branch = branchName("sync-configs");
|
|
117
|
+
await createBranch(site.path, branch);
|
|
118
|
+
const shas = [];
|
|
119
|
+
for (const t of diffs) {
|
|
120
|
+
await writeFile(join(site.path, t.path), t.contents, "utf-8");
|
|
121
|
+
const sha = await commit(
|
|
122
|
+
site.path,
|
|
123
|
+
`chore: sync ${t.config} config from @reddoorla/maintenance`
|
|
124
|
+
);
|
|
125
|
+
if (sha) shas.push(sha);
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
recipe: "sync-configs",
|
|
129
|
+
site: label,
|
|
130
|
+
status: "applied",
|
|
131
|
+
commits: shas,
|
|
132
|
+
notes: `branch: ${branch}`
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
export {
|
|
136
|
+
syncConfigs
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=sync-configs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/recipes/sync-configs.ts","../../src/recipes/sync-configs/templates.ts","../../src/util/git.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { RecipeResult, Site, ConfigName } from \"../types.js\";\nimport { ALL_TEMPLATES, templatesByName, type ConfigTemplate } from \"./sync-configs/templates.js\";\nimport { branchName, commit, createBranch, isWorkingTreeClean } from \"../util/git.js\";\n\nexport type SyncConfigsOptions = {\n which?: ConfigName[];\n};\n\nfunction siteLabel(site: Site): string {\n return site.name ?? site.path;\n}\n\nasync function readMaybe(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nasync function planDiffs(cwd: string, templates: ConfigTemplate[]): Promise<ConfigTemplate[]> {\n const diffs: ConfigTemplate[] = [];\n for (const t of templates) {\n const existing = await readMaybe(join(cwd, t.path));\n if (existing !== t.contents) diffs.push(t);\n }\n return diffs;\n}\n\nexport async function syncConfigs(\n site: Site,\n opts: SyncConfigsOptions = {},\n): Promise<RecipeResult> {\n const label = siteLabel(site);\n const targets = opts.which ? templatesByName(opts.which) : ALL_TEMPLATES;\n\n const diffs = await planDiffs(site.path, targets);\n if (diffs.length === 0) {\n return {\n recipe: \"sync-configs\",\n site: label,\n status: \"noop\",\n commits: [],\n notes: \"all targeted configs already match\",\n };\n }\n\n if (!(await isWorkingTreeClean(site.path))) {\n throw new Error(`refusing to run: working tree is not clean at ${site.path}`);\n }\n\n const branch = branchName(\"sync-configs\");\n await createBranch(site.path, branch);\n\n const shas: string[] = [];\n for (const t of diffs) {\n await writeFile(join(site.path, t.path), t.contents, \"utf-8\");\n const sha = await commit(\n site.path,\n `chore: sync ${t.config} config from @reddoorla/maintenance`,\n );\n if (sha) shas.push(sha);\n }\n\n return {\n recipe: \"sync-configs\",\n site: label,\n status: \"applied\",\n commits: shas,\n notes: `branch: ${branch}`,\n };\n}\n","import type { ConfigName } from \"../../types.js\";\n\nexport type ConfigTemplate = {\n config: ConfigName;\n path: string;\n contents: string;\n};\n\nconst eslint: ConfigTemplate = {\n config: \"eslint\",\n path: \"eslint.config.js\",\n contents: `import { createEslintConfig } from \"@reddoorla/maintenance/configs/eslint\";\nimport svelteConfig from \"./svelte.config.js\";\n\nexport default createEslintConfig({ svelteConfig });\n`,\n};\n\nconst prettier: ConfigTemplate = {\n config: \"prettier\",\n path: \".prettierrc.json\",\n contents: `{\n \"trailingComma\": \"all\",\n \"singleQuote\": false,\n \"printWidth\": 100,\n \"plugins\": [\"prettier-plugin-svelte\"]\n}\n`,\n};\n\nconst lighthouse: ConfigTemplate = {\n config: \"lighthouse\",\n path: \"lighthouserc.json\",\n contents: `${JSON.stringify(\n {\n $note:\n \"Generated by @reddoorla/maintenance sync-configs; edit src/configs/lighthouse.ts in the package instead.\",\n extends: \"@reddoorla/maintenance/configs/lighthouse\",\n },\n null,\n 2,\n )}\n`,\n};\n\nconst playwrightA11y: ConfigTemplate = {\n config: \"playwright-a11y\",\n path: \"playwright.config.ts\",\n contents: `export { default } from \"@reddoorla/maintenance/configs/playwright-a11y\";\n`,\n};\n\nexport const ALL_TEMPLATES: ConfigTemplate[] = [eslint, prettier, lighthouse, playwrightA11y];\n\nexport function templatesByName(which: ConfigName[]): ConfigTemplate[] {\n return ALL_TEMPLATES.filter((t) => which.includes(t.config));\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst exec = promisify(execFile);\n\nasync function git(cwd: string, args: string[]): Promise<{ stdout: string; stderr: string }> {\n return exec(\"git\", args, { cwd, env: process.env });\n}\n\nexport function branchName(recipe: string, when: Date = new Date()): string {\n const iso = when.toISOString().replace(/[-:.]/g, \"\").replace(/Z$/, \"Z\");\n // 2026-05-20T10:30:00.000Z → 20260520T103000000Z; trim millis:\n const trimmed = iso.replace(/(\\d{8}T\\d{6})\\d+(Z)$/, \"$1$2\");\n return `maint/${recipe}-${trimmed}`;\n}\n\nexport async function currentBranch(cwd: string): Promise<string> {\n const { stdout } = await git(cwd, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n return stdout.trim();\n}\n\nexport async function isWorkingTreeClean(cwd: string): Promise<boolean> {\n const { stdout } = await git(cwd, [\"status\", \"--porcelain\"]);\n return stdout.trim().length === 0;\n}\n\nexport async function createBranch(cwd: string, name: string): Promise<void> {\n await git(cwd, [\"checkout\", \"-b\", name]);\n}\n\nexport async function stageAll(cwd: string): Promise<void> {\n await git(cwd, [\"add\", \"-A\"]);\n}\n\n/**\n * Stages all current changes and commits with `message`. Returns the commit SHA,\n * or `null` if there was nothing to commit.\n */\nexport async function commit(cwd: string, message: string): Promise<string | null> {\n await stageAll(cwd);\n const { stdout: status } = await git(cwd, [\"status\", \"--porcelain\"]);\n if (status.trim().length === 0) return null;\n await git(cwd, [\"commit\", \"-m\", message]);\n const { stdout: sha } = await git(cwd, [\"rev-parse\", \"HEAD\"]);\n return sha.trim();\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
type Site = {
|
|
2
|
+
path: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
repoUrl?: string;
|
|
5
|
+
meta?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
type AuditName = "deps" | "lighthouse" | "a11y" | "security" | "lint";
|
|
8
|
+
type RecipeName = "sync-configs" | "bump-deps" | "svelte-4-to-5";
|
|
9
|
+
type ConfigName = "lighthouse" | "eslint" | "prettier" | "playwright-a11y";
|
|
10
|
+
type AuditResult = {
|
|
11
|
+
audit: AuditName;
|
|
12
|
+
site: string;
|
|
13
|
+
status: "pass" | "warn" | "fail" | "skip";
|
|
14
|
+
summary: string;
|
|
15
|
+
details?: unknown;
|
|
16
|
+
};
|
|
17
|
+
type RecipeResult = {
|
|
18
|
+
recipe: RecipeName;
|
|
19
|
+
site: string;
|
|
20
|
+
status: "applied" | "noop" | "failed";
|
|
21
|
+
commits: string[];
|
|
22
|
+
notes?: string;
|
|
23
|
+
};
|
|
24
|
+
type InventoryProvider = () => Promise<Site[]>;
|
|
25
|
+
|
|
26
|
+
type SyncConfigsOptions = {
|
|
27
|
+
which?: ConfigName[];
|
|
28
|
+
};
|
|
29
|
+
declare function syncConfigs(site: Site, opts?: SyncConfigsOptions): Promise<RecipeResult>;
|
|
30
|
+
|
|
31
|
+
export { type AuditName as A, type ConfigName as C, type InventoryProvider as I, type RecipeName as R, type Site as S, type AuditResult as a, type RecipeResult as b, type SyncConfigsOptions as c, syncConfigs as s };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare function branchName(recipe: string, when?: Date): string;
|
|
2
|
+
declare function currentBranch(cwd: string): Promise<string>;
|
|
3
|
+
declare function isWorkingTreeClean(cwd: string): Promise<boolean>;
|
|
4
|
+
declare function createBranch(cwd: string, name: string): Promise<void>;
|
|
5
|
+
declare function stageAll(cwd: string): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Stages all current changes and commits with `message`. Returns the commit SHA,
|
|
8
|
+
* or `null` if there was nothing to commit.
|
|
9
|
+
*/
|
|
10
|
+
declare function commit(cwd: string, message: string): Promise<string | null>;
|
|
11
|
+
|
|
12
|
+
export { branchName, commit, createBranch, currentBranch, isWorkingTreeClean, stageAll };
|
package/dist/util/git.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/util/git.ts
|
|
2
|
+
import { execFile } from "child_process";
|
|
3
|
+
import { promisify } from "util";
|
|
4
|
+
var exec = promisify(execFile);
|
|
5
|
+
async function git(cwd, args) {
|
|
6
|
+
return exec("git", args, { cwd, env: process.env });
|
|
7
|
+
}
|
|
8
|
+
function branchName(recipe, when = /* @__PURE__ */ new Date()) {
|
|
9
|
+
const iso = when.toISOString().replace(/[-:.]/g, "").replace(/Z$/, "Z");
|
|
10
|
+
const trimmed = iso.replace(/(\d{8}T\d{6})\d+(Z)$/, "$1$2");
|
|
11
|
+
return `maint/${recipe}-${trimmed}`;
|
|
12
|
+
}
|
|
13
|
+
async function currentBranch(cwd) {
|
|
14
|
+
const { stdout } = await git(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
15
|
+
return stdout.trim();
|
|
16
|
+
}
|
|
17
|
+
async function isWorkingTreeClean(cwd) {
|
|
18
|
+
const { stdout } = await git(cwd, ["status", "--porcelain"]);
|
|
19
|
+
return stdout.trim().length === 0;
|
|
20
|
+
}
|
|
21
|
+
async function createBranch(cwd, name) {
|
|
22
|
+
await git(cwd, ["checkout", "-b", name]);
|
|
23
|
+
}
|
|
24
|
+
async function stageAll(cwd) {
|
|
25
|
+
await git(cwd, ["add", "-A"]);
|
|
26
|
+
}
|
|
27
|
+
async function commit(cwd, message) {
|
|
28
|
+
await stageAll(cwd);
|
|
29
|
+
const { stdout: status } = await git(cwd, ["status", "--porcelain"]);
|
|
30
|
+
if (status.trim().length === 0) return null;
|
|
31
|
+
await git(cwd, ["commit", "-m", message]);
|
|
32
|
+
const { stdout: sha } = await git(cwd, ["rev-parse", "HEAD"]);
|
|
33
|
+
return sha.trim();
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
branchName,
|
|
37
|
+
commit,
|
|
38
|
+
createBranch,
|
|
39
|
+
currentBranch,
|
|
40
|
+
isWorkingTreeClean,
|
|
41
|
+
stageAll
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/util/git.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst exec = promisify(execFile);\n\nasync function git(cwd: string, args: string[]): Promise<{ stdout: string; stderr: string }> {\n return exec(\"git\", args, { cwd, env: process.env });\n}\n\nexport function branchName(recipe: string, when: Date = new Date()): string {\n const iso = when.toISOString().replace(/[-:.]/g, \"\").replace(/Z$/, \"Z\");\n // 2026-05-20T10:30:00.000Z → 20260520T103000000Z; trim millis:\n const trimmed = iso.replace(/(\\d{8}T\\d{6})\\d+(Z)$/, \"$1$2\");\n return `maint/${recipe}-${trimmed}`;\n}\n\nexport async function currentBranch(cwd: string): Promise<string> {\n const { stdout } = await git(cwd, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n return stdout.trim();\n}\n\nexport async function isWorkingTreeClean(cwd: string): Promise<boolean> {\n const { stdout } = await git(cwd, [\"status\", \"--porcelain\"]);\n return stdout.trim().length === 0;\n}\n\nexport async function createBranch(cwd: string, name: string): Promise<void> {\n await git(cwd, [\"checkout\", \"-b\", name]);\n}\n\nexport async function stageAll(cwd: string): Promise<void> {\n await git(cwd, [\"add\", \"-A\"]);\n}\n\n/**\n * Stages all current changes and commits with `message`. Returns the commit SHA,\n * or `null` if there was nothing to commit.\n */\nexport async function commit(cwd: string, message: string): Promise<string | null> {\n await stageAll(cwd);\n const { stdout: status } = await git(cwd, [\"status\", \"--porcelain\"]);\n if (status.trim().length === 0) return null;\n await git(cwd, [\"commit\", \"-m\", message]);\n const { stdout: sha } = await git(cwd, [\"rev-parse\", \"HEAD\"]);\n return sha.trim();\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAE1B,IAAM,OAAO,UAAU,QAAQ;AAE/B,eAAe,IAAI,KAAa,MAA6D;AAC3F,SAAO,KAAK,OAAO,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAI,CAAC;AACpD;AAEO,SAAS,WAAW,QAAgB,OAAa,oBAAI,KAAK,GAAW;AAC1E,QAAM,MAAM,KAAK,YAAY,EAAE,QAAQ,UAAU,EAAE,EAAE,QAAQ,MAAM,GAAG;AAEtE,QAAM,UAAU,IAAI,QAAQ,wBAAwB,MAAM;AAC1D,SAAO,SAAS,MAAM,IAAI,OAAO;AACnC;AAEA,eAAsB,cAAc,KAA8B;AAChE,QAAM,EAAE,OAAO,IAAI,MAAM,IAAI,KAAK,CAAC,aAAa,gBAAgB,MAAM,CAAC;AACvE,SAAO,OAAO,KAAK;AACrB;AAEA,eAAsB,mBAAmB,KAA+B;AACtE,QAAM,EAAE,OAAO,IAAI,MAAM,IAAI,KAAK,CAAC,UAAU,aAAa,CAAC;AAC3D,SAAO,OAAO,KAAK,EAAE,WAAW;AAClC;AAEA,eAAsB,aAAa,KAAa,MAA6B;AAC3E,QAAM,IAAI,KAAK,CAAC,YAAY,MAAM,IAAI,CAAC;AACzC;AAEA,eAAsB,SAAS,KAA4B;AACzD,QAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC;AAC9B;AAMA,eAAsB,OAAO,KAAa,SAAyC;AACjF,QAAM,SAAS,GAAG;AAClB,QAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,IAAI,KAAK,CAAC,UAAU,aAAa,CAAC;AACnE,MAAI,OAAO,KAAK,EAAE,WAAW,EAAG,QAAO;AACvC,QAAM,IAAI,KAAK,CAAC,UAAU,MAAM,OAAO,CAAC;AACxC,QAAM,EAAE,QAAQ,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC,aAAa,MAAM,CAAC;AAC5D,SAAO,IAAI,KAAK;AAClB;","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type PackageJsonLike = {
|
|
2
|
+
name?: string;
|
|
3
|
+
version?: string;
|
|
4
|
+
dependencies?: Record<string, string>;
|
|
5
|
+
devDependencies?: Record<string, string>;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
declare function readPackageJson(path: string): Promise<PackageJsonLike>;
|
|
9
|
+
declare function writePackageJson(path: string, pkg: PackageJsonLike): Promise<void>;
|
|
10
|
+
declare function bumpDep(pkg: PackageJsonLike, name: string, version: string): PackageJsonLike;
|
|
11
|
+
|
|
12
|
+
export { type PackageJsonLike, bumpDep, readPackageJson, writePackageJson };
|
package/dist/util/pkg.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/util/pkg.ts
|
|
2
|
+
import { readFile, writeFile } from "fs/promises";
|
|
3
|
+
async function readPackageJson(path) {
|
|
4
|
+
const raw = await readFile(path, "utf-8");
|
|
5
|
+
return JSON.parse(raw);
|
|
6
|
+
}
|
|
7
|
+
async function writePackageJson(path, pkg) {
|
|
8
|
+
const content = JSON.stringify(pkg, null, 2) + "\n";
|
|
9
|
+
await writeFile(path, content, "utf-8");
|
|
10
|
+
}
|
|
11
|
+
function bumpDep(pkg, name, version) {
|
|
12
|
+
const next = {
|
|
13
|
+
...pkg
|
|
14
|
+
};
|
|
15
|
+
if (pkg.dependencies) {
|
|
16
|
+
next.dependencies = { ...pkg.dependencies };
|
|
17
|
+
}
|
|
18
|
+
if (pkg.devDependencies) {
|
|
19
|
+
next.devDependencies = { ...pkg.devDependencies };
|
|
20
|
+
}
|
|
21
|
+
if (next.dependencies && name in next.dependencies) {
|
|
22
|
+
if (next.dependencies[name] === version) return pkg;
|
|
23
|
+
next.dependencies[name] = version;
|
|
24
|
+
return next;
|
|
25
|
+
}
|
|
26
|
+
if (next.devDependencies && name in next.devDependencies) {
|
|
27
|
+
if (next.devDependencies[name] === version) return pkg;
|
|
28
|
+
next.devDependencies[name] = version;
|
|
29
|
+
return next;
|
|
30
|
+
}
|
|
31
|
+
next.devDependencies = { ...next.devDependencies ?? {}, [name]: version };
|
|
32
|
+
return next;
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
bumpDep,
|
|
36
|
+
readPackageJson,
|
|
37
|
+
writePackageJson
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=pkg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/util/pkg.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\n\nexport type PackageJsonLike = {\n name?: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n};\n\nexport async function readPackageJson(path: string): Promise<PackageJsonLike> {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw) as PackageJsonLike;\n}\n\nexport async function writePackageJson(path: string, pkg: PackageJsonLike): Promise<void> {\n const content = JSON.stringify(pkg, null, 2) + \"\\n\";\n await writeFile(path, content, \"utf-8\");\n}\n\nexport function bumpDep(pkg: PackageJsonLike, name: string, version: string): PackageJsonLike {\n const next: PackageJsonLike = {\n ...pkg,\n };\n\n if (pkg.dependencies) {\n next.dependencies = { ...pkg.dependencies };\n }\n if (pkg.devDependencies) {\n next.devDependencies = { ...pkg.devDependencies };\n }\n\n if (next.dependencies && name in next.dependencies) {\n if (next.dependencies[name] === version) return pkg;\n next.dependencies[name] = version;\n return next;\n }\n if (next.devDependencies && name in next.devDependencies) {\n if (next.devDependencies[name] === version) return pkg;\n next.devDependencies[name] = version;\n return next;\n }\n // Not present in either: add to devDependencies.\n next.devDependencies = { ...(next.devDependencies ?? {}), [name]: version };\n return next;\n}\n"],"mappings":";AAAA,SAAS,UAAU,iBAAiB;AAUpC,eAAsB,gBAAgB,MAAwC;AAC5E,QAAM,MAAM,MAAM,SAAS,MAAM,OAAO;AACxC,SAAO,KAAK,MAAM,GAAG;AACvB;AAEA,eAAsB,iBAAiB,MAAc,KAAqC;AACxF,QAAM,UAAU,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI;AAC/C,QAAM,UAAU,MAAM,SAAS,OAAO;AACxC;AAEO,SAAS,QAAQ,KAAsB,MAAc,SAAkC;AAC5F,QAAM,OAAwB;AAAA,IAC5B,GAAG;AAAA,EACL;AAEA,MAAI,IAAI,cAAc;AACpB,SAAK,eAAe,EAAE,GAAG,IAAI,aAAa;AAAA,EAC5C;AACA,MAAI,IAAI,iBAAiB;AACvB,SAAK,kBAAkB,EAAE,GAAG,IAAI,gBAAgB;AAAA,EAClD;AAEA,MAAI,KAAK,gBAAgB,QAAQ,KAAK,cAAc;AAClD,QAAI,KAAK,aAAa,IAAI,MAAM,QAAS,QAAO;AAChD,SAAK,aAAa,IAAI,IAAI;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,KAAK,mBAAmB,QAAQ,KAAK,iBAAiB;AACxD,QAAI,KAAK,gBAAgB,IAAI,MAAM,QAAS,QAAO;AACnD,SAAK,gBAAgB,IAAI,IAAI;AAC7B,WAAO;AAAA,EACT;AAEA,OAAK,kBAAkB,EAAE,GAAI,KAAK,mBAAmB,CAAC,GAAI,CAAC,IAAI,GAAG,QAAQ;AAC1E,SAAO;AACT;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reddoorla/maintenance",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Canonical maintenance configs, audits, and recipes for the reddoor stack.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Tucker Lemos",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/tucksravin/reddoor-maintenance.git"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./configs/lighthouse": {
|
|
25
|
+
"types": "./dist/configs/lighthouse.d.ts",
|
|
26
|
+
"import": "./dist/configs/lighthouse.js"
|
|
27
|
+
},
|
|
28
|
+
"./configs/eslint": {
|
|
29
|
+
"types": "./dist/configs/eslint.d.ts",
|
|
30
|
+
"import": "./dist/configs/eslint.js"
|
|
31
|
+
},
|
|
32
|
+
"./configs/prettier": {
|
|
33
|
+
"types": "./dist/configs/prettier.d.ts",
|
|
34
|
+
"import": "./dist/configs/prettier.js"
|
|
35
|
+
},
|
|
36
|
+
"./configs/playwright-a11y": {
|
|
37
|
+
"types": "./dist/configs/playwright-a11y.d.ts",
|
|
38
|
+
"import": "./dist/configs/playwright-a11y.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"bin": {
|
|
42
|
+
"reddoor-maint": "./dist/cli/bin.js"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"dev": "tsup --watch",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"lint": "eslint . && prettier --check .",
|
|
50
|
+
"format": "prettier --write .",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"prepublishOnly": "pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run build",
|
|
53
|
+
"changeset": "changeset",
|
|
54
|
+
"version-packages": "changeset version",
|
|
55
|
+
"release": "pnpm run prepublishOnly && changeset publish"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@axe-core/playwright": "^4.11.3",
|
|
59
|
+
"@eslint/js": "^10.0.1",
|
|
60
|
+
"@lhci/cli": "^0.15.1",
|
|
61
|
+
"@playwright/test": "^1.59.1",
|
|
62
|
+
"cac": "^6.7.14",
|
|
63
|
+
"eslint": "^10.3.0",
|
|
64
|
+
"eslint-config-prettier": "^10.1.1",
|
|
65
|
+
"eslint-plugin-svelte": "^3.1.0",
|
|
66
|
+
"globals": "^17.6.0",
|
|
67
|
+
"prettier": "^3.1.1",
|
|
68
|
+
"prettier-plugin-svelte": "^3.2.6",
|
|
69
|
+
"tinyglobby": "^0.2.10",
|
|
70
|
+
"typescript-eslint": "^8.59.1"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@changesets/cli": "^2.31.0",
|
|
74
|
+
"@types/node": "^22.0.0",
|
|
75
|
+
"tsup": "^8.3.0",
|
|
76
|
+
"tsx": "^4.19.0",
|
|
77
|
+
"typescript": "^6.0.3",
|
|
78
|
+
"vitest": "^4.1.1"
|
|
79
|
+
},
|
|
80
|
+
"packageManager": "pnpm@10.33.1"
|
|
81
|
+
}
|