@reddoorla/maintenance 0.6.4 → 0.6.6

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, a as AuditResult, A as AuditName, b as RecipeResult, R as RecipeName, I as InventoryProvider } from './sync-configs-DRmSAnfV.js';
2
- export { C as ConfigName, c as SyncConfigsOptions, s as syncConfigs } from './sync-configs-DRmSAnfV.js';
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';
3
3
 
4
4
  type SpawnResult = {
5
5
  code: number;
package/dist/index.js CHANGED
@@ -931,9 +931,19 @@ async function syncConfigs(site, opts = {}) {
931
931
  }
932
932
 
933
933
  // src/recipes/bump-deps.ts
934
+ import { stat } from "fs/promises";
935
+ import { join as join6 } from "path";
934
936
  function siteLabel7(site) {
935
937
  return site.name ?? site.path;
936
938
  }
939
+ async function exists(path) {
940
+ try {
941
+ await stat(path);
942
+ return true;
943
+ } catch {
944
+ return false;
945
+ }
946
+ }
937
947
  function outdatedFlagsForGroup(group) {
938
948
  if (group === "major") return ["--latest"];
939
949
  if (group === "minor") return [];
@@ -947,6 +957,24 @@ async function bumpDeps(site, opts = {}) {
947
957
  const label = siteLabel7(site);
948
958
  const group = opts.group ?? "minor";
949
959
  const spawn2 = opts.spawn ?? defaultSpawn;
960
+ const hasPnpmLock = await exists(join6(site.path, "pnpm-lock.yaml"));
961
+ if (!hasPnpmLock) {
962
+ const hasNpmLock = await exists(join6(site.path, "package-lock.json"));
963
+ const hasYarnLock = await exists(join6(site.path, "yarn.lock"));
964
+ if (hasNpmLock || hasYarnLock) {
965
+ const competing = hasNpmLock ? "package-lock.json" : "yarn.lock";
966
+ return {
967
+ recipe: "bump-deps",
968
+ site: label,
969
+ status: "failed",
970
+ commits: [],
971
+ notes: `site has ${competing} but no pnpm-lock.yaml \u2014 run convert-to-pnpm first`
972
+ };
973
+ }
974
+ }
975
+ if (!await isWorkingTreeClean(site.path)) {
976
+ throw new Error(`refusing to run: working tree is not clean at ${site.path}`);
977
+ }
950
978
  await spawn2("pnpm", ["install"], { cwd: site.path, streaming: true });
951
979
  const outdated = await spawn2("pnpm", ["outdated", "--json", ...outdatedFlagsForGroup(group)], {
952
980
  cwd: site.path
@@ -967,9 +995,6 @@ async function bumpDeps(site, opts = {}) {
967
995
  notes: `pnpm outdated reported nothing for group=${group}`
968
996
  };
969
997
  }
970
- if (!await isWorkingTreeClean(site.path)) {
971
- throw new Error(`refusing to run: working tree is not clean at ${site.path}`);
972
- }
973
998
  const branch = branchName("bump-deps");
974
999
  await createBranch(site.path, branch);
975
1000
  await spawn2("pnpm", ["up", ...upFlagsForGroup(group)], {
@@ -988,7 +1013,7 @@ async function bumpDeps(site, opts = {}) {
988
1013
  }
989
1014
 
990
1015
  // src/recipes/svelte-5/index.ts
991
- import { join as join11 } from "path";
1016
+ import { join as join12 } from "path";
992
1017
 
993
1018
  // src/util/pkg.ts
994
1019
  import { readFile as readFile6, writeFile as writeFile4 } from "fs/promises";
@@ -996,8 +1021,18 @@ async function readPackageJson(path) {
996
1021
  const raw = await readFile6(path, "utf-8");
997
1022
  return JSON.parse(raw);
998
1023
  }
1024
+ function detectIndentFromContent(raw) {
1025
+ const match = raw.match(/\n([ \t]+)"/);
1026
+ return match ? match[1] ?? " " : " ";
1027
+ }
999
1028
  async function writePackageJson(path, pkg) {
1000
- const content = JSON.stringify(pkg, null, 2) + "\n";
1029
+ let indent = " ";
1030
+ try {
1031
+ const existing = await readFile6(path, "utf-8");
1032
+ indent = detectIndentFromContent(existing);
1033
+ } catch {
1034
+ }
1035
+ const content = JSON.stringify(pkg, null, indent) + "\n";
1001
1036
  await writeFile4(path, content, "utf-8");
1002
1037
  }
1003
1038
  function bumpDep(pkg, name, version, opts = {}) {
@@ -1027,7 +1062,7 @@ function bumpDep(pkg, name, version, opts = {}) {
1027
1062
  }
1028
1063
 
1029
1064
  // src/recipes/svelte-5/step-bump-versions.ts
1030
- import { join as join6 } from "path";
1065
+ import { join as join7 } from "path";
1031
1066
  var SVELTE_5_VERSIONS = {
1032
1067
  svelte: "^5.55.5",
1033
1068
  "@sveltejs/kit": "^2.59.0",
@@ -1040,7 +1075,7 @@ var SVELTE_5_VERSIONS = {
1040
1075
  "typescript-svelte-plugin": "^0.3.52"
1041
1076
  };
1042
1077
  async function bumpToSvelte5Versions(cwd) {
1043
- const pkgPath = join6(cwd, "package.json");
1078
+ const pkgPath = join7(cwd, "package.json");
1044
1079
  const pkg = await readPackageJson(pkgPath);
1045
1080
  let next = pkg;
1046
1081
  for (const [name, version] of Object.entries(SVELTE_5_VERSIONS)) {
@@ -1053,7 +1088,7 @@ async function bumpToSvelte5Versions(cwd) {
1053
1088
 
1054
1089
  // src/recipes/svelte-5/step-svelte-config.ts
1055
1090
  import { readFile as readFile7, writeFile as writeFile5 } from "fs/promises";
1056
- import { join as join7 } from "path";
1091
+ import { join as join8 } from "path";
1057
1092
  var VITE_PLUGIN_PKG = "@sveltejs/vite-plugin-svelte";
1058
1093
  var IMPORT_FROM_VITE_PLUGIN = new RegExp(
1059
1094
  String.raw`^import\s+\{\s*([^}]+?)\s*\}\s+from\s+["']` + VITE_PLUGIN_PKG.replace(/[/]/g, "\\/") + String.raw`["'];?[ \t]*\n`,
@@ -1094,7 +1129,7 @@ function dropPreprocessKey(source) {
1094
1129
  return source.slice(0, m.index) + source.slice(tailIdx).replace(new RegExp(`^${indent}\\n`), "");
1095
1130
  }
1096
1131
  async function migrateSvelteConfig(cwd) {
1097
- const path = join7(cwd, "svelte.config.js");
1132
+ const path = join8(cwd, "svelte.config.js");
1098
1133
  let src;
1099
1134
  try {
1100
1135
  src = await readFile7(path, "utf-8");
@@ -1131,9 +1166,9 @@ async function runSvelteMigrate(cwd, spawn2 = defaultSpawn) {
1131
1166
  }
1132
1167
 
1133
1168
  // src/recipes/svelte-5/step-tailwind-upgrade.ts
1134
- import { join as join8 } from "path";
1169
+ import { join as join9 } from "path";
1135
1170
  async function upgradeTailwind(cwd, spawn2 = defaultSpawn) {
1136
- const pkg = await readPackageJson(join8(cwd, "package.json"));
1171
+ const pkg = await readPackageJson(join9(cwd, "package.json"));
1137
1172
  const tailwindVersion = pkg.devDependencies?.tailwindcss ?? pkg.dependencies?.tailwindcss;
1138
1173
  if (!tailwindVersion) return { ran: false, reason: "tailwindcss not installed" };
1139
1174
  if (/^\^?4\./.test(tailwindVersion)) return { ran: false, reason: "already on tailwind 4.x" };
@@ -1155,7 +1190,7 @@ async function upgradeTailwind(cwd, spawn2 = defaultSpawn) {
1155
1190
 
1156
1191
  // src/recipes/svelte-5/step-gotchas.ts
1157
1192
  import { readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
1158
- import { join as join9 } from "path";
1193
+ import { join as join10 } from "path";
1159
1194
  import { glob as glob2 } from "tinyglobby";
1160
1195
 
1161
1196
  // src/recipes/svelte-5/codemods/on-event-to-handler.ts
@@ -1416,6 +1451,7 @@ function findStringClose(source, openIdx) {
1416
1451
  }
1417
1452
  return -1;
1418
1453
  }
1454
+ var MIGRATION_MARKER = "// @migration-task: $effect won't trigger UI updates on plain `let` bindings \u2014 refine mutated locals to $state or split into per-variable $derived.";
1419
1455
  function transformBlocks(body) {
1420
1456
  const out = [];
1421
1457
  let last = 0;
@@ -1431,6 +1467,8 @@ function transformBlocks(body) {
1431
1467
  out.push(body.slice(last, m.index));
1432
1468
  out.push(leadingNewline);
1433
1469
  const blockBody = body.slice(openBraceIdx + 1, closeBraceIdx);
1470
+ out.push(`${indent}${MIGRATION_MARKER}
1471
+ `);
1434
1472
  out.push(`${indent}$effect(() => {${blockBody}});`);
1435
1473
  last = closeBraceIdx + 1;
1436
1474
  BLOCK_REACTIVE_HEAD.lastIndex = last;
@@ -1467,7 +1505,7 @@ async function planGotchaCodemods(cwd) {
1467
1505
  const changes = [];
1468
1506
  const relPaths = await glob2(SVELTE_GLOBS, { cwd, ignore: IGNORE2, absolute: false });
1469
1507
  for (const rel of relPaths) {
1470
- const path = join9(cwd, rel);
1508
+ const path = join10(cwd, rel);
1471
1509
  const before = await readFile8(path, "utf-8");
1472
1510
  const after = CODEMODS.reduce((s, fn) => fn(s), before);
1473
1511
  if (after !== before) changes.push({ rel, after });
@@ -1477,7 +1515,7 @@ async function planGotchaCodemods(cwd) {
1477
1515
  async function applyGotchaCodemods(cwd) {
1478
1516
  const changes = await planGotchaCodemods(cwd);
1479
1517
  for (const c of changes) {
1480
- await writeFile6(join9(cwd, c.rel), c.after, "utf-8");
1518
+ await writeFile6(join10(cwd, c.rel), c.after, "utf-8");
1481
1519
  }
1482
1520
  return { filesChanged: changes.length };
1483
1521
  }
@@ -1501,7 +1539,7 @@ async function verifyMigration(cwd, spawn2 = defaultSpawn) {
1501
1539
 
1502
1540
  // src/recipes/svelte-5/step-summary.ts
1503
1541
  import { writeFile as writeFile7 } from "fs/promises";
1504
- import { join as join10 } from "path";
1542
+ import { join as join11 } from "path";
1505
1543
  async function writeMigrationSummary(input) {
1506
1544
  const lines = [
1507
1545
  `# Svelte 4 \u2192 5 migration summary`,
@@ -1518,7 +1556,7 @@ async function writeMigrationSummary(input) {
1518
1556
  `- Verify Playwright a11y tests still pass.`
1519
1557
  ];
1520
1558
  const content = lines.join("\n") + "\n";
1521
- const path = join10(input.cwd, "MIGRATION_SVELTE_5.md");
1559
+ const path = join11(input.cwd, "MIGRATION_SVELTE_5.md");
1522
1560
  await writeFile7(path, content, "utf-8");
1523
1561
  return path;
1524
1562
  }
@@ -1529,7 +1567,7 @@ function siteLabel8(site) {
1529
1567
  }
1530
1568
  async function alreadyOnSvelte5(cwd) {
1531
1569
  try {
1532
- const pkg = await readPackageJson(join11(cwd, "package.json"));
1570
+ const pkg = await readPackageJson(join12(cwd, "package.json"));
1533
1571
  const v = pkg.devDependencies?.svelte ?? pkg.dependencies?.svelte;
1534
1572
  return !!v && /^\^?5\./.test(v);
1535
1573
  } catch {
@@ -1607,7 +1645,7 @@ async function upgradeSvelte4to5(site, opts = {}) {
1607
1645
 
1608
1646
  // src/recipes/svelte-codemods.ts
1609
1647
  import { writeFile as writeFile8 } from "fs/promises";
1610
- import { join as join12 } from "path";
1648
+ import { join as join13 } from "path";
1611
1649
  function siteLabel9(site) {
1612
1650
  return site.name ?? site.path;
1613
1651
  }
@@ -1629,7 +1667,7 @@ async function svelteCodemods(site) {
1629
1667
  const branch = branchName("svelte-codemods");
1630
1668
  await createBranch(site.path, branch);
1631
1669
  for (const c of changes) {
1632
- await writeFile8(join12(site.path, c.rel), c.after, "utf-8");
1670
+ await writeFile8(join13(site.path, c.rel), c.after, "utf-8");
1633
1671
  }
1634
1672
  const sha = await commit(
1635
1673
  site.path,
@@ -1645,8 +1683,8 @@ async function svelteCodemods(site) {
1645
1683
  }
1646
1684
 
1647
1685
  // src/recipes/convert-to-pnpm.ts
1648
- import { rm as rm3, stat } from "fs/promises";
1649
- import { join as join13 } from "path";
1686
+ import { rm as rm3, stat as stat2 } from "fs/promises";
1687
+ import { join as join14 } from "path";
1650
1688
 
1651
1689
  // src/recipes/convert-to-pnpm/script-rewrites.ts
1652
1690
  function rewriteScriptForPnpm(script) {
@@ -1668,9 +1706,9 @@ function rewriteScriptsForPnpm(scripts) {
1668
1706
 
1669
1707
  // src/recipes/convert-to-pnpm.ts
1670
1708
  var DEFAULT_PNPM_VERSION = "10.33.1";
1671
- async function exists(path) {
1709
+ async function exists2(path) {
1672
1710
  try {
1673
- await stat(path);
1711
+ await stat2(path);
1674
1712
  return true;
1675
1713
  } catch {
1676
1714
  return false;
@@ -1683,10 +1721,10 @@ async function convertToPnpm(site, opts = {}) {
1683
1721
  const label = siteLabel10(site);
1684
1722
  const spawn2 = opts.spawn ?? defaultSpawn;
1685
1723
  const pnpmVersion = opts.pnpmVersion ?? DEFAULT_PNPM_VERSION;
1686
- const pnpmLockPath = join13(site.path, "pnpm-lock.yaml");
1687
- const npmLockPath = join13(site.path, "package-lock.json");
1688
- const yarnLockPath = join13(site.path, "yarn.lock");
1689
- if (await exists(pnpmLockPath)) {
1724
+ const pnpmLockPath = join14(site.path, "pnpm-lock.yaml");
1725
+ const npmLockPath = join14(site.path, "package-lock.json");
1726
+ const yarnLockPath = join14(site.path, "yarn.lock");
1727
+ if (await exists2(pnpmLockPath)) {
1690
1728
  return {
1691
1729
  recipe: "convert-to-pnpm",
1692
1730
  site: label,
@@ -1695,8 +1733,8 @@ async function convertToPnpm(site, opts = {}) {
1695
1733
  notes: "site already has pnpm-lock.yaml"
1696
1734
  };
1697
1735
  }
1698
- const hasNpmLock = await exists(npmLockPath);
1699
- const hasYarnLock = await exists(yarnLockPath);
1736
+ const hasNpmLock = await exists2(npmLockPath);
1737
+ const hasYarnLock = await exists2(yarnLockPath);
1700
1738
  if (!hasNpmLock && !hasYarnLock) {
1701
1739
  return {
1702
1740
  recipe: "convert-to-pnpm",
@@ -1717,7 +1755,7 @@ async function convertToPnpm(site, opts = {}) {
1717
1755
  const sourceLock = hasNpmLock ? "package-lock.json" : "yarn.lock";
1718
1756
  const lockSha = await commit(site.path, `chore(pnpm): remove ${sourceLock}`);
1719
1757
  if (lockSha) shas.push(lockSha);
1720
- const pkgPath = join13(site.path, "package.json");
1758
+ const pkgPath = join14(site.path, "package.json");
1721
1759
  const pkg = await readPackageJson(pkgPath);
1722
1760
  const next = { ...pkg, packageManager: `pnpm@${pnpmVersion}` };
1723
1761
  if (pkg.scripts && typeof pkg.scripts === "object") {
@@ -1731,6 +1769,7 @@ async function convertToPnpm(site, opts = {}) {
1731
1769
  await writePackageJson(pkgPath, next);
1732
1770
  const pkgSha = await commit(site.path, "chore(pnpm): pin packageManager + rewrite npm scripts");
1733
1771
  if (pkgSha) shas.push(pkgSha);
1772
+ await rm3(join14(site.path, "node_modules"), { recursive: true, force: true });
1734
1773
  const installResult = await spawn2("pnpm", ["install"], {
1735
1774
  cwd: site.path,
1736
1775
  streaming: true
@@ -1756,17 +1795,17 @@ async function convertToPnpm(site, opts = {}) {
1756
1795
  }
1757
1796
 
1758
1797
  // src/recipes/onboard.ts
1759
- import { stat as stat2 } from "fs/promises";
1760
- import { join as join15 } from "path";
1798
+ import { stat as stat3 } from "fs/promises";
1799
+ import { join as join16 } from "path";
1761
1800
 
1762
1801
  // src/util/self-version.ts
1763
1802
  import { readFileSync } from "fs";
1764
1803
  import { fileURLToPath } from "url";
1765
- import { dirname, join as join14 } from "path";
1804
+ import { dirname, join as join15 } from "path";
1766
1805
  function selfPackageVersion(callerImportMetaUrl) {
1767
1806
  try {
1768
1807
  const here = dirname(fileURLToPath(callerImportMetaUrl));
1769
- const raw = readFileSync(join14(here, "..", "..", "package.json"), "utf-8");
1808
+ const raw = readFileSync(join15(here, "..", "..", "package.json"), "utf-8");
1770
1809
  const pkg = JSON.parse(raw);
1771
1810
  return pkg.version ?? "0.0.0";
1772
1811
  } catch {
@@ -1779,16 +1818,27 @@ function selfCaretRange(callerImportMetaUrl) {
1779
1818
 
1780
1819
  // src/recipes/onboard.ts
1781
1820
  var PACKAGE_NAME = "@reddoorla/maintenance";
1782
- var AUDIT_DEPS = {
1783
- lighthouse: [{ name: "@lhci/cli", version: "^0.15.1" }],
1784
- a11y: [
1785
- { name: "@playwright/test", version: "^1.59.1" },
1786
- { name: "@axe-core/playwright", version: "^4.11.3" }
1787
- ]
1821
+ var AUDIT_DEP_NAMES = {
1822
+ lighthouse: ["@lhci/cli"],
1823
+ a11y: ["@playwright/test", "@axe-core/playwright"]
1788
1824
  };
1789
- async function exists2(path) {
1825
+ var AUDIT_DEPS = Object.fromEntries(
1826
+ Object.entries(AUDIT_DEP_NAMES).map(([audit, names]) => [
1827
+ audit,
1828
+ names.map((name) => {
1829
+ const version = baselineVersions[name];
1830
+ if (!version) {
1831
+ throw new Error(
1832
+ `baseline-versions is missing audit dep "${name}" \u2014 add it to src/configs/baseline-versions.ts`
1833
+ );
1834
+ }
1835
+ return { name, version };
1836
+ })
1837
+ ])
1838
+ );
1839
+ async function exists3(path) {
1790
1840
  try {
1791
- await stat2(path);
1841
+ await stat3(path);
1792
1842
  return true;
1793
1843
  } catch {
1794
1844
  return false;
@@ -1805,7 +1855,7 @@ async function onboard(site, opts = {}) {
1805
1855
  const spawn2 = opts.spawn ?? defaultSpawn;
1806
1856
  const audits = opts.audits ?? ["lighthouse", "a11y"];
1807
1857
  const packageVersion = opts.packageVersion ?? selfCaretRange(import.meta.url);
1808
- if (!await exists2(join15(site.path, "pnpm-lock.yaml"))) {
1858
+ if (!await exists3(join16(site.path, "pnpm-lock.yaml"))) {
1809
1859
  return {
1810
1860
  recipe: "onboard",
1811
1861
  site: label,
@@ -1814,7 +1864,7 @@ async function onboard(site, opts = {}) {
1814
1864
  notes: "no pnpm-lock.yaml at site root \u2014 run convert-to-pnpm first"
1815
1865
  };
1816
1866
  }
1817
- const pkgPath = join15(site.path, "package.json");
1867
+ const pkgPath = join16(site.path, "package.json");
1818
1868
  const pkg = await readPackageJson(pkgPath);
1819
1869
  const toAdd = [];
1820
1870
  if (!isDeclared(pkg, PACKAGE_NAME)) {