@reddoorla/maintenance 0.6.1 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/bin.js +118 -16
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.js +9 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/index.d.ts +17 -3
- package/dist/index.js +151 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/bin.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/bin.ts
|
|
4
|
-
import { dirname } from "path";
|
|
5
|
-
import { fileURLToPath } from "url";
|
|
4
|
+
import { dirname as dirname2 } from "path";
|
|
5
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6
6
|
import { cac } from "cac";
|
|
7
7
|
|
|
8
8
|
// src/cli/commands/audit.ts
|
|
@@ -761,6 +761,13 @@ function assertSafeName(name) {
|
|
|
761
761
|
throw new Error(`unsafe site name (traversal segment not allowed): ${name}`);
|
|
762
762
|
}
|
|
763
763
|
}
|
|
764
|
+
function assertSafeRepoUrl(repoUrl) {
|
|
765
|
+
if (!/^(https?|ssh|git|file):\/\//.test(repoUrl) && !/^[A-Za-z0-9._-]+@[A-Za-z0-9._-]+:/.test(repoUrl)) {
|
|
766
|
+
throw new Error(
|
|
767
|
+
`unsafe repoUrl: must start with a scheme (https://, ssh://, git://, file://) or use scp-style "user@host:path" (got: ${JSON.stringify(repoUrl)})`
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
764
771
|
async function isNonEmptyDir(path) {
|
|
765
772
|
try {
|
|
766
773
|
const s = await stat(path);
|
|
@@ -778,13 +785,14 @@ async function cloneIfNeeded(site, opts) {
|
|
|
778
785
|
}
|
|
779
786
|
const name = site.name ?? deriveNameFromRepoUrl(site.repoUrl);
|
|
780
787
|
assertSafeName(name);
|
|
788
|
+
assertSafeRepoUrl(site.repoUrl);
|
|
781
789
|
const target = join5(opts.workdir, name);
|
|
782
790
|
await mkdir(opts.workdir, { recursive: true });
|
|
783
791
|
if (await isNonEmptyDir(target)) {
|
|
784
792
|
return { ...site, name, path: target };
|
|
785
793
|
}
|
|
786
794
|
const spawn2 = opts.spawn ?? defaultSpawn;
|
|
787
|
-
const result = await spawn2("git", ["clone", site.repoUrl, target], {
|
|
795
|
+
const result = await spawn2("git", ["clone", "--", site.repoUrl, target], {
|
|
788
796
|
cwd: opts.workdir,
|
|
789
797
|
timeoutMs: 5 * 6e4
|
|
790
798
|
});
|
|
@@ -1516,7 +1524,7 @@ function removeDollarRestProps(source) {
|
|
|
1516
1524
|
}
|
|
1517
1525
|
|
|
1518
1526
|
// src/recipes/svelte-5/codemods/state-effect-sync.ts
|
|
1519
|
-
var PATTERN = /let\s+(\w+)\s*=\s*\$state\(\s*([^)]+?)\s*\)\s*;[ \t\r\n]*\$effect\(\s*\(\s*\)\s*=>\s*\{\s*\w+\s*;\s*\1\s*=\s*([^;}]+?)\s*\}\s*\)\s*;?/g;
|
|
1527
|
+
var PATTERN = /let\s+(\w+)\s*=\s*\$state\(\s*([^)]+?)\s*\)\s*;[ \t\r\n]*\$effect\(\s*\(\s*\)\s*=>\s*\{\s*\w+\s*;\s*\1\s*=\s*([^;}]+?)\s*;?\s*\}\s*\)\s*;?/g;
|
|
1520
1528
|
function stateEffectSyncToDerived(source) {
|
|
1521
1529
|
return source.replace(PATTERN, (full, name, initExpr, effectExpr) => {
|
|
1522
1530
|
if (initExpr.trim() !== effectExpr.trim()) return full;
|
|
@@ -1572,6 +1580,80 @@ function dollarPropsClass(source) {
|
|
|
1572
1580
|
return updated;
|
|
1573
1581
|
}
|
|
1574
1582
|
|
|
1583
|
+
// src/recipes/svelte-5/codemods/legacy-reactive.ts
|
|
1584
|
+
var SCRIPT_BLOCK4 = /<script\b([^>]*)>([\s\S]*?)<\/script>/g;
|
|
1585
|
+
var SIMPLE_REACTIVE = /^([ \t]*)\$:\s*(\w+)\s*=\s*([^;\n]+);?[ \t]*$/gm;
|
|
1586
|
+
var BLOCK_REACTIVE_HEAD = /(^|\n)([ \t]*)\$:\s*\{/g;
|
|
1587
|
+
function findMatchingClose(source, openIdx) {
|
|
1588
|
+
let depth = 0;
|
|
1589
|
+
let i = openIdx;
|
|
1590
|
+
while (i < source.length) {
|
|
1591
|
+
const ch = source[i];
|
|
1592
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
1593
|
+
const closeStr = findStringClose(source, i);
|
|
1594
|
+
if (closeStr === -1) return -1;
|
|
1595
|
+
i = closeStr + 1;
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
if (ch === "{") depth++;
|
|
1599
|
+
else if (ch === "}") {
|
|
1600
|
+
depth--;
|
|
1601
|
+
if (depth === 0) return i;
|
|
1602
|
+
}
|
|
1603
|
+
i++;
|
|
1604
|
+
}
|
|
1605
|
+
return -1;
|
|
1606
|
+
}
|
|
1607
|
+
function findStringClose(source, openIdx) {
|
|
1608
|
+
const quote = source[openIdx];
|
|
1609
|
+
let i = openIdx + 1;
|
|
1610
|
+
while (i < source.length) {
|
|
1611
|
+
const ch = source[i];
|
|
1612
|
+
if (ch === "\\") {
|
|
1613
|
+
i += 2;
|
|
1614
|
+
continue;
|
|
1615
|
+
}
|
|
1616
|
+
if (ch === quote) return i;
|
|
1617
|
+
i++;
|
|
1618
|
+
}
|
|
1619
|
+
return -1;
|
|
1620
|
+
}
|
|
1621
|
+
function transformBlocks(body) {
|
|
1622
|
+
const out = [];
|
|
1623
|
+
let last = 0;
|
|
1624
|
+
BLOCK_REACTIVE_HEAD.lastIndex = 0;
|
|
1625
|
+
let m;
|
|
1626
|
+
while ((m = BLOCK_REACTIVE_HEAD.exec(body)) !== null) {
|
|
1627
|
+
const leadingNewline = m[1] ?? "";
|
|
1628
|
+
const indent = m[2] ?? "";
|
|
1629
|
+
const headEnd = m.index + m[0].length;
|
|
1630
|
+
const openBraceIdx = headEnd - 1;
|
|
1631
|
+
const closeBraceIdx = findMatchingClose(body, openBraceIdx);
|
|
1632
|
+
if (closeBraceIdx === -1) continue;
|
|
1633
|
+
out.push(body.slice(last, m.index));
|
|
1634
|
+
out.push(leadingNewline);
|
|
1635
|
+
const blockBody = body.slice(openBraceIdx + 1, closeBraceIdx);
|
|
1636
|
+
out.push(`${indent}$effect(() => {${blockBody}});`);
|
|
1637
|
+
last = closeBraceIdx + 1;
|
|
1638
|
+
BLOCK_REACTIVE_HEAD.lastIndex = last;
|
|
1639
|
+
}
|
|
1640
|
+
out.push(body.slice(last));
|
|
1641
|
+
return out.join("");
|
|
1642
|
+
}
|
|
1643
|
+
function transformSimple(body) {
|
|
1644
|
+
return body.replace(SIMPLE_REACTIVE, (_full, indent, name, expr) => {
|
|
1645
|
+
return `${indent}let ${name} = $derived(${expr.trim()});`;
|
|
1646
|
+
});
|
|
1647
|
+
}
|
|
1648
|
+
function legacyReactiveToRunes(source) {
|
|
1649
|
+
return source.replace(SCRIPT_BLOCK4, (full, _attrs, body) => {
|
|
1650
|
+
let next = transformBlocks(body);
|
|
1651
|
+
next = transformSimple(next);
|
|
1652
|
+
if (next === body) return full;
|
|
1653
|
+
return full.replace(body, next);
|
|
1654
|
+
});
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1575
1657
|
// src/recipes/svelte-5/step-gotchas.ts
|
|
1576
1658
|
var SVELTE_GLOBS = ["src/**/*.svelte"];
|
|
1577
1659
|
var IGNORE2 = ["node_modules/**", ".svelte-kit/**", "build/**"];
|
|
@@ -1580,7 +1662,8 @@ var CODEMODS = [
|
|
|
1580
1662
|
exportLetToProps,
|
|
1581
1663
|
removeDollarRestProps,
|
|
1582
1664
|
stateEffectSyncToDerived,
|
|
1583
|
-
dollarPropsClass
|
|
1665
|
+
dollarPropsClass,
|
|
1666
|
+
legacyReactiveToRunes
|
|
1584
1667
|
];
|
|
1585
1668
|
async function planGotchaCodemods(cwd) {
|
|
1586
1669
|
const changes = [];
|
|
@@ -1905,9 +1988,28 @@ import { resolve as resolve7 } from "path";
|
|
|
1905
1988
|
|
|
1906
1989
|
// src/recipes/onboard.ts
|
|
1907
1990
|
import { stat as stat3 } from "fs/promises";
|
|
1908
|
-
import { join as
|
|
1991
|
+
import { join as join16 } from "path";
|
|
1992
|
+
|
|
1993
|
+
// src/util/self-version.ts
|
|
1994
|
+
import { readFileSync } from "fs";
|
|
1995
|
+
import { fileURLToPath } from "url";
|
|
1996
|
+
import { dirname, join as join15 } from "path";
|
|
1997
|
+
function selfPackageVersion(callerImportMetaUrl) {
|
|
1998
|
+
try {
|
|
1999
|
+
const here2 = dirname(fileURLToPath(callerImportMetaUrl));
|
|
2000
|
+
const raw = readFileSync(join15(here2, "..", "..", "package.json"), "utf-8");
|
|
2001
|
+
const pkg = JSON.parse(raw);
|
|
2002
|
+
return pkg.version ?? "0.0.0";
|
|
2003
|
+
} catch {
|
|
2004
|
+
return "0.0.0";
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
function selfCaretRange(callerImportMetaUrl) {
|
|
2008
|
+
return `^${selfPackageVersion(callerImportMetaUrl)}`;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
// src/recipes/onboard.ts
|
|
1909
2012
|
var PACKAGE_NAME = "@reddoorla/maintenance";
|
|
1910
|
-
var DEFAULT_PACKAGE_VERSION = "^0.2.0";
|
|
1911
2013
|
var AUDIT_DEPS = {
|
|
1912
2014
|
lighthouse: [{ name: "@lhci/cli", version: "^0.15.1" }],
|
|
1913
2015
|
a11y: [
|
|
@@ -1933,8 +2035,8 @@ async function onboard(site, opts = {}) {
|
|
|
1933
2035
|
const label = siteLabel10(site);
|
|
1934
2036
|
const spawn2 = opts.spawn ?? defaultSpawn;
|
|
1935
2037
|
const audits = opts.audits ?? ["lighthouse", "a11y"];
|
|
1936
|
-
const packageVersion = opts.packageVersion ??
|
|
1937
|
-
if (!await exists2(
|
|
2038
|
+
const packageVersion = opts.packageVersion ?? selfCaretRange(import.meta.url);
|
|
2039
|
+
if (!await exists2(join16(site.path, "pnpm-lock.yaml"))) {
|
|
1938
2040
|
return {
|
|
1939
2041
|
recipe: "onboard",
|
|
1940
2042
|
site: label,
|
|
@@ -1943,7 +2045,7 @@ async function onboard(site, opts = {}) {
|
|
|
1943
2045
|
notes: "no pnpm-lock.yaml at site root \u2014 run convert-to-pnpm first"
|
|
1944
2046
|
};
|
|
1945
2047
|
}
|
|
1946
|
-
const pkgPath =
|
|
2048
|
+
const pkgPath = join16(site.path, "package.json");
|
|
1947
2049
|
const pkg = await readPackageJson(pkgPath);
|
|
1948
2050
|
const toAdd = [];
|
|
1949
2051
|
if (!isDeclared(pkg, PACKAGE_NAME)) {
|
|
@@ -2047,7 +2149,7 @@ import { resolve as resolve8 } from "path";
|
|
|
2047
2149
|
|
|
2048
2150
|
// src/recipes/svelte-codemods.ts
|
|
2049
2151
|
import { writeFile as writeFile8 } from "fs/promises";
|
|
2050
|
-
import { join as
|
|
2152
|
+
import { join as join17 } from "path";
|
|
2051
2153
|
function siteLabel11(site) {
|
|
2052
2154
|
return site.name ?? site.path;
|
|
2053
2155
|
}
|
|
@@ -2069,7 +2171,7 @@ async function svelteCodemods(site) {
|
|
|
2069
2171
|
const branch = branchName("svelte-codemods");
|
|
2070
2172
|
await createBranch(site.path, branch);
|
|
2071
2173
|
for (const c of changes) {
|
|
2072
|
-
await writeFile8(
|
|
2174
|
+
await writeFile8(join17(site.path, c.rel), c.after, "utf-8");
|
|
2073
2175
|
}
|
|
2074
2176
|
const sha = await commit(
|
|
2075
2177
|
site.path,
|
|
@@ -2110,11 +2212,11 @@ async function runSvelteCodemodsCommand(site, opts) {
|
|
|
2110
2212
|
}
|
|
2111
2213
|
|
|
2112
2214
|
// src/cli/version.ts
|
|
2113
|
-
import { readFileSync } from "fs";
|
|
2114
|
-
import { join as
|
|
2215
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
2216
|
+
import { join as join18 } from "path";
|
|
2115
2217
|
function resolvePackageVersion(fromDir) {
|
|
2116
2218
|
try {
|
|
2117
|
-
const raw =
|
|
2219
|
+
const raw = readFileSync2(join18(fromDir, "..", "..", "package.json"), "utf-8");
|
|
2118
2220
|
const pkg = JSON.parse(raw);
|
|
2119
2221
|
return pkg.version ?? "unknown";
|
|
2120
2222
|
} catch {
|
|
@@ -2123,7 +2225,7 @@ function resolvePackageVersion(fromDir) {
|
|
|
2123
2225
|
}
|
|
2124
2226
|
|
|
2125
2227
|
// src/cli/bin.ts
|
|
2126
|
-
var here =
|
|
2228
|
+
var here = dirname2(fileURLToPath2(import.meta.url));
|
|
2127
2229
|
var version = resolvePackageVersion(here);
|
|
2128
2230
|
var AUDIT_DESCRIPTIONS = {
|
|
2129
2231
|
deps: "Diff site package.json against the bundled baseline version map.",
|