@bensandee/tooling 0.7.3 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.mjs +268 -102
- package/dist/index.mjs +1 -1
- package/package.json +5 -5
package/dist/bin.mjs
CHANGED
|
@@ -8,7 +8,6 @@ import JSON5 from "json5";
|
|
|
8
8
|
import { parse } from "jsonc-parser";
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
import { FatalError, TransientError, UnexpectedError } from "@bensandee/common";
|
|
11
|
-
|
|
12
11
|
//#region src/types.ts
|
|
13
12
|
/** Default CI platform when not explicitly chosen. */
|
|
14
13
|
const DEFAULT_CI = "forgejo";
|
|
@@ -19,7 +18,6 @@ const LEGACY_TOOLS = [
|
|
|
19
18
|
"webpack",
|
|
20
19
|
"rollup"
|
|
21
20
|
];
|
|
22
|
-
|
|
23
21
|
//#endregion
|
|
24
22
|
//#region src/utils/json.ts
|
|
25
23
|
const StringRecord = z.record(z.string(), z.string());
|
|
@@ -83,7 +81,6 @@ function parsePackageJson(raw) {
|
|
|
83
81
|
return;
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
|
-
|
|
87
84
|
//#endregion
|
|
88
85
|
//#region src/utils/detect.ts
|
|
89
86
|
const LEGACY_PATTERNS = {
|
|
@@ -160,6 +157,32 @@ function detectProjectType(targetDir) {
|
|
|
160
157
|
if (pkg.exports || pkg.main || pkg.types || pkg.typings) return "library";
|
|
161
158
|
return "default";
|
|
162
159
|
}
|
|
160
|
+
const WEB_UI_DEPS = new Set([
|
|
161
|
+
"react",
|
|
162
|
+
"react-dom",
|
|
163
|
+
"vue",
|
|
164
|
+
"svelte",
|
|
165
|
+
"solid-js",
|
|
166
|
+
"next",
|
|
167
|
+
"nuxt",
|
|
168
|
+
"@angular/core",
|
|
169
|
+
"preact"
|
|
170
|
+
]);
|
|
171
|
+
/** Check whether a package.json depends on a web UI framework. */
|
|
172
|
+
function packageHasWebUIDeps(pkg) {
|
|
173
|
+
const deps = {
|
|
174
|
+
...pkg.dependencies,
|
|
175
|
+
...pkg.devDependencies
|
|
176
|
+
};
|
|
177
|
+
for (const dep of WEB_UI_DEPS) if (dep in deps) return true;
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
/** Check whether a package.json in the given directory depends on a web UI framework. */
|
|
181
|
+
function hasWebUIDeps(targetDir) {
|
|
182
|
+
const pkg = readPackageJson(targetDir);
|
|
183
|
+
if (!pkg) return false;
|
|
184
|
+
return packageHasWebUIDeps(pkg);
|
|
185
|
+
}
|
|
163
186
|
/** List packages in a monorepo's packages/ directory. */
|
|
164
187
|
function getMonorepoPackages(targetDir) {
|
|
165
188
|
const packagesDir = path.join(targetDir, "packages");
|
|
@@ -179,7 +202,6 @@ function getMonorepoPackages(targetDir) {
|
|
|
179
202
|
} catch (_error) {}
|
|
180
203
|
return results;
|
|
181
204
|
}
|
|
182
|
-
|
|
183
205
|
//#endregion
|
|
184
206
|
//#region src/prompts/init-prompts.ts
|
|
185
207
|
function isCancelled(value) {
|
|
@@ -390,7 +412,6 @@ function buildDefaultConfig(targetDir, flags) {
|
|
|
390
412
|
targetDir
|
|
391
413
|
};
|
|
392
414
|
}
|
|
393
|
-
|
|
394
415
|
//#endregion
|
|
395
416
|
//#region src/utils/fs.ts
|
|
396
417
|
/** Check whether a file exists at the given path. */
|
|
@@ -468,7 +489,6 @@ function createDryRunContext(config) {
|
|
|
468
489
|
pendingWrites
|
|
469
490
|
};
|
|
470
491
|
}
|
|
471
|
-
|
|
472
492
|
//#endregion
|
|
473
493
|
//#region src/generators/package-json.ts
|
|
474
494
|
const STANDARD_SCRIPTS_SINGLE = {
|
|
@@ -542,8 +562,8 @@ function addReleaseDeps(deps, config) {
|
|
|
542
562
|
function getAddedDevDepNames(config) {
|
|
543
563
|
const deps = { ...ROOT_DEV_DEPS };
|
|
544
564
|
if (config.structure !== "monorepo") Object.assign(deps, PER_PACKAGE_DEV_DEPS);
|
|
545
|
-
deps["@bensandee/config"] = "
|
|
546
|
-
deps["@bensandee/tooling"] = "
|
|
565
|
+
deps["@bensandee/config"] = "0.7.0";
|
|
566
|
+
deps["@bensandee/tooling"] = "0.8.1";
|
|
547
567
|
if (config.formatter === "oxfmt") deps["oxfmt"] = "0.35.0";
|
|
548
568
|
if (config.formatter === "prettier") deps["prettier"] = "3.8.1";
|
|
549
569
|
addReleaseDeps(deps, config);
|
|
@@ -563,9 +583,9 @@ async function generatePackageJson(ctx) {
|
|
|
563
583
|
if (ctx.config.releaseStrategy !== "none") allScripts["trigger-release"] = "pnpm exec tooling release:trigger";
|
|
564
584
|
const devDeps = { ...ROOT_DEV_DEPS };
|
|
565
585
|
if (!isMonorepo) Object.assign(devDeps, PER_PACKAGE_DEV_DEPS);
|
|
566
|
-
devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "
|
|
567
|
-
devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "
|
|
568
|
-
if (ctx.config.useEslintPlugin) devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "
|
|
586
|
+
devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "0.7.0";
|
|
587
|
+
devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.8.1";
|
|
588
|
+
if (ctx.config.useEslintPlugin) devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "0.9.0";
|
|
569
589
|
if (ctx.config.formatter === "oxfmt") devDeps["oxfmt"] = "0.35.0";
|
|
570
590
|
if (ctx.config.formatter === "prettier") devDeps["prettier"] = "3.8.1";
|
|
571
591
|
addReleaseDeps(devDeps, ctx.config);
|
|
@@ -591,9 +611,9 @@ async function generatePackageJson(ctx) {
|
|
|
591
611
|
for (const [key, value] of Object.entries(devDeps)) if (!(key in existingDevDeps)) {
|
|
592
612
|
existingDevDeps[key] = value;
|
|
593
613
|
changes.push(`added devDependency: ${key}`);
|
|
594
|
-
} else if (key.startsWith("@bensandee/") &&
|
|
595
|
-
existingDevDeps[key] =
|
|
596
|
-
changes.push(`updated devDependency: ${key} to
|
|
614
|
+
} else if (key.startsWith("@bensandee/") && existingDevDeps[key] !== value && existingDevDeps[key] !== "workspace:*") {
|
|
615
|
+
existingDevDeps[key] = value;
|
|
616
|
+
changes.push(`updated devDependency: ${key} to ${value}`);
|
|
597
617
|
}
|
|
598
618
|
pkg.devDependencies = existingDevDeps;
|
|
599
619
|
if (!pkg["engines"]) {
|
|
@@ -629,7 +649,6 @@ async function generatePackageJson(ctx) {
|
|
|
629
649
|
description: "Generated package.json"
|
|
630
650
|
};
|
|
631
651
|
}
|
|
632
|
-
|
|
633
652
|
//#endregion
|
|
634
653
|
//#region src/generators/migrate-prompt.ts
|
|
635
654
|
/**
|
|
@@ -799,19 +818,17 @@ function generateMigratePrompt(results, config, detected) {
|
|
|
799
818
|
sections.push("");
|
|
800
819
|
return sections.join("\n");
|
|
801
820
|
}
|
|
802
|
-
|
|
803
821
|
//#endregion
|
|
804
822
|
//#region src/generators/tsconfig.ts
|
|
805
823
|
async function generateTsconfig(ctx) {
|
|
806
824
|
const filePath = "tsconfig.json";
|
|
807
825
|
const existing = ctx.read(filePath);
|
|
808
|
-
if (ctx.config.structure === "monorepo") return [generateMonorepoRootTsconfig(ctx
|
|
826
|
+
if (ctx.config.structure === "monorepo") return [generateMonorepoRootTsconfig(ctx), ...ctx.config.detectPackageTypes ? generateMonorepoPackageTsconfigs(ctx) : []];
|
|
809
827
|
const extendsValue = `@bensandee/config/tsconfig/${ctx.config.projectType}`;
|
|
810
828
|
if (!existing) {
|
|
811
829
|
const config = {
|
|
812
830
|
extends: extendsValue,
|
|
813
|
-
...ctx.exists("src") ? { include: ["src"] } : {}
|
|
814
|
-
exclude: ["node_modules", "dist"]
|
|
831
|
+
...ctx.exists("src") ? { include: ["src"] } : {}
|
|
815
832
|
};
|
|
816
833
|
ctx.write(filePath, JSON.stringify(config, null, 2) + "\n");
|
|
817
834
|
return [{
|
|
@@ -885,31 +902,18 @@ function mergeSingleTsconfig(ctx, filePath, extendsValue) {
|
|
|
885
902
|
description: changes.join(", ")
|
|
886
903
|
};
|
|
887
904
|
}
|
|
888
|
-
function generateMonorepoRootTsconfig(ctx
|
|
905
|
+
function generateMonorepoRootTsconfig(ctx) {
|
|
889
906
|
const filePath = "tsconfig.json";
|
|
890
|
-
if (
|
|
891
|
-
const parsed = parseTsconfig(existing);
|
|
892
|
-
if (!parsed.references) {
|
|
893
|
-
parsed.files = [];
|
|
894
|
-
parsed.references = [];
|
|
895
|
-
ctx.write(filePath, JSON.stringify(parsed, null, 2) + "\n");
|
|
896
|
-
return {
|
|
897
|
-
filePath,
|
|
898
|
-
action: "updated",
|
|
899
|
-
description: "Added project references structure for monorepo"
|
|
900
|
-
};
|
|
901
|
-
}
|
|
902
|
-
return {
|
|
903
|
-
filePath,
|
|
904
|
-
action: "skipped",
|
|
905
|
-
description: "Already has project references"
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
|
-
return {
|
|
907
|
+
if (!ctx.read(filePath)) return {
|
|
909
908
|
filePath,
|
|
910
909
|
action: "skipped",
|
|
911
910
|
description: "No tsconfig.json found"
|
|
912
911
|
};
|
|
912
|
+
return {
|
|
913
|
+
filePath,
|
|
914
|
+
action: "skipped",
|
|
915
|
+
description: "Root tsconfig left as-is"
|
|
916
|
+
};
|
|
913
917
|
}
|
|
914
918
|
function generateMonorepoPackageTsconfigs(ctx) {
|
|
915
919
|
const packages = getMonorepoPackages(ctx.targetDir);
|
|
@@ -969,8 +973,7 @@ function generateMonorepoPackageTsconfigs(ctx) {
|
|
|
969
973
|
} else {
|
|
970
974
|
const config = {
|
|
971
975
|
extends: extendsValue,
|
|
972
|
-
...ctx.exists(path.join(relDir, "src")) ? { include: ["src"] } : {}
|
|
973
|
-
exclude: ["node_modules", "dist"]
|
|
976
|
+
...ctx.exists(path.join(relDir, "src")) ? { include: ["src"] } : {}
|
|
974
977
|
};
|
|
975
978
|
ctx.write(filePath, JSON.stringify(config, null, 2) + "\n");
|
|
976
979
|
results.push({
|
|
@@ -982,7 +985,6 @@ function generateMonorepoPackageTsconfigs(ctx) {
|
|
|
982
985
|
}
|
|
983
986
|
return results;
|
|
984
987
|
}
|
|
985
|
-
|
|
986
988
|
//#endregion
|
|
987
989
|
//#region src/generators/vitest.ts
|
|
988
990
|
const VITEST_CONFIG = `import { defineConfig } from "vitest/config";
|
|
@@ -1051,7 +1053,6 @@ async function generateVitest(ctx) {
|
|
|
1051
1053
|
}
|
|
1052
1054
|
return results;
|
|
1053
1055
|
}
|
|
1054
|
-
|
|
1055
1056
|
//#endregion
|
|
1056
1057
|
//#region src/generators/oxlint.ts
|
|
1057
1058
|
const CONFIG_WITH_LINT_RULES = `import recommended from "@bensandee/config/oxlint/recommended";
|
|
@@ -1091,7 +1092,6 @@ async function generateOxlint(ctx) {
|
|
|
1091
1092
|
description: "Generated oxlint.config.ts"
|
|
1092
1093
|
};
|
|
1093
1094
|
}
|
|
1094
|
-
|
|
1095
1095
|
//#endregion
|
|
1096
1096
|
//#region src/generators/formatter.ts
|
|
1097
1097
|
const OXFMT_CONFIG = `{}\n`;
|
|
@@ -1135,7 +1135,6 @@ async function generatePrettier(ctx) {
|
|
|
1135
1135
|
description: "Generated .prettierrc"
|
|
1136
1136
|
};
|
|
1137
1137
|
}
|
|
1138
|
-
|
|
1139
1138
|
//#endregion
|
|
1140
1139
|
//#region src/generators/tsdown.ts
|
|
1141
1140
|
const TSDOWN_CONFIG = `import { defineConfig } from "tsdown";
|
|
@@ -1171,7 +1170,6 @@ async function generateTsdown(ctx) {
|
|
|
1171
1170
|
description: "Generated tsdown.config.ts"
|
|
1172
1171
|
};
|
|
1173
1172
|
}
|
|
1174
|
-
|
|
1175
1173
|
//#endregion
|
|
1176
1174
|
//#region src/generators/gitignore.ts
|
|
1177
1175
|
/** Entries that every project should have — repo:check flags these as missing. */
|
|
@@ -1225,7 +1223,6 @@ async function generateGitignore(ctx) {
|
|
|
1225
1223
|
description: "Generated .gitignore"
|
|
1226
1224
|
};
|
|
1227
1225
|
}
|
|
1228
|
-
|
|
1229
1226
|
//#endregion
|
|
1230
1227
|
//#region src/generators/ci.ts
|
|
1231
1228
|
function hasEnginesNode$1(ctx) {
|
|
@@ -1233,9 +1230,9 @@ function hasEnginesNode$1(ctx) {
|
|
|
1233
1230
|
if (!raw) return false;
|
|
1234
1231
|
return typeof parsePackageJson(raw)?.engines?.["node"] === "string";
|
|
1235
1232
|
}
|
|
1236
|
-
function ciWorkflow(isMonorepo, nodeVersionYaml) {
|
|
1233
|
+
function ciWorkflow(isMonorepo, nodeVersionYaml, isForgejo) {
|
|
1237
1234
|
return `name: CI
|
|
1238
|
-
on:
|
|
1235
|
+
${isForgejo ? "\nenable-email-notifications: true\n" : ""}on:
|
|
1239
1236
|
push:
|
|
1240
1237
|
branches: [main]
|
|
1241
1238
|
pull_request:
|
|
@@ -1289,7 +1286,7 @@ async function generateCi(ctx) {
|
|
|
1289
1286
|
const isGitHub = ctx.config.ci === "github";
|
|
1290
1287
|
const nodeVersionYaml = hasEnginesNode$1(ctx) ? "node-version-file: package.json" : "node-version: \"24\"";
|
|
1291
1288
|
const filePath = isGitHub ? ".github/workflows/check.yml" : ".forgejo/workflows/check.yml";
|
|
1292
|
-
const content = ciWorkflow(isMonorepo, nodeVersionYaml);
|
|
1289
|
+
const content = ciWorkflow(isMonorepo, nodeVersionYaml, !isGitHub);
|
|
1293
1290
|
if (ctx.exists(filePath)) {
|
|
1294
1291
|
const existing = ctx.read(filePath);
|
|
1295
1292
|
if (existing && !existing.includes("repo:check")) {
|
|
@@ -1316,7 +1313,6 @@ async function generateCi(ctx) {
|
|
|
1316
1313
|
description: `Generated ${isGitHub ? "GitHub" : "Forgejo"} Actions CI workflow`
|
|
1317
1314
|
};
|
|
1318
1315
|
}
|
|
1319
|
-
|
|
1320
1316
|
//#endregion
|
|
1321
1317
|
//#region src/generators/knip.ts
|
|
1322
1318
|
const KNIP_CONFIG_SINGLE = `import type { KnipConfig } from "knip";
|
|
@@ -1369,7 +1365,6 @@ async function generateKnip(ctx) {
|
|
|
1369
1365
|
description: "Generated knip.config.ts for dead code analysis"
|
|
1370
1366
|
};
|
|
1371
1367
|
}
|
|
1372
|
-
|
|
1373
1368
|
//#endregion
|
|
1374
1369
|
//#region src/generators/renovate.ts
|
|
1375
1370
|
const SHARED_PRESET = "local>bensandee/tooling";
|
|
@@ -1436,7 +1431,6 @@ async function generateRenovate(ctx) {
|
|
|
1436
1431
|
description: "Generated renovate.json extending shared config"
|
|
1437
1432
|
};
|
|
1438
1433
|
}
|
|
1439
|
-
|
|
1440
1434
|
//#endregion
|
|
1441
1435
|
//#region src/generators/pnpm-workspace.ts
|
|
1442
1436
|
const WORKSPACE_YAML = `packages:
|
|
@@ -1461,7 +1455,6 @@ async function generatePnpmWorkspace(ctx) {
|
|
|
1461
1455
|
description: "Generated pnpm-workspace.yaml"
|
|
1462
1456
|
};
|
|
1463
1457
|
}
|
|
1464
|
-
|
|
1465
1458
|
//#endregion
|
|
1466
1459
|
//#region src/generators/claude-settings.ts
|
|
1467
1460
|
const ClaudeSettingsSchema = z.object({
|
|
@@ -1472,7 +1465,9 @@ const ClaudeSettingsSchema = z.object({
|
|
|
1472
1465
|
allow: [],
|
|
1473
1466
|
deny: []
|
|
1474
1467
|
}),
|
|
1475
|
-
instructions: z.array(z.string()).default([])
|
|
1468
|
+
instructions: z.array(z.string()).default([]),
|
|
1469
|
+
enabledPlugins: z.record(z.string(), z.boolean()).default({}),
|
|
1470
|
+
extraKnownMarketplaces: z.record(z.string(), z.record(z.string(), z.unknown())).default({})
|
|
1476
1471
|
});
|
|
1477
1472
|
function parseClaudeSettings(raw) {
|
|
1478
1473
|
try {
|
|
@@ -1536,11 +1531,17 @@ function buildSettings(ctx) {
|
|
|
1536
1531
|
"Bash(test *)",
|
|
1537
1532
|
"Bash([ *)",
|
|
1538
1533
|
"Bash(find *)",
|
|
1534
|
+
"Bash(grep *)",
|
|
1539
1535
|
"Bash(which *)",
|
|
1540
1536
|
"Bash(node -e *)",
|
|
1541
1537
|
"Bash(node -p *)"
|
|
1542
1538
|
];
|
|
1543
1539
|
if (ctx.config.structure === "monorepo") allow.push(`Bash(${pm} --filter *)`, `Bash(${pm} -r *)`);
|
|
1540
|
+
const enabledPlugins = { "code-simplifier@claude-plugins-official": true };
|
|
1541
|
+
const extraKnownMarketplaces = {};
|
|
1542
|
+
if (ctx.config.structure !== "monorepo") {
|
|
1543
|
+
if (ctx.packageJson ? packageHasWebUIDeps(ctx.packageJson) : false) enabledPlugins["frontend-design@claude-plugins-official"] = true;
|
|
1544
|
+
}
|
|
1544
1545
|
return {
|
|
1545
1546
|
permissions: {
|
|
1546
1547
|
allow,
|
|
@@ -1548,21 +1549,70 @@ function buildSettings(ctx) {
|
|
|
1548
1549
|
"Bash(npx *)",
|
|
1549
1550
|
"Bash(git push *)",
|
|
1550
1551
|
"Bash(git push)",
|
|
1551
|
-
"Bash(git
|
|
1552
|
-
"Bash(
|
|
1552
|
+
"Bash(git add *)",
|
|
1553
|
+
"Bash(git add)",
|
|
1554
|
+
"Bash(git commit *)",
|
|
1555
|
+
"Bash(git commit)",
|
|
1556
|
+
"Bash(git reset *)",
|
|
1557
|
+
"Bash(git merge *)",
|
|
1558
|
+
"Bash(git rebase *)",
|
|
1559
|
+
"Bash(git cherry-pick *)",
|
|
1560
|
+
"Bash(git checkout *)",
|
|
1561
|
+
"Bash(git switch *)",
|
|
1562
|
+
"Bash(git stash *)",
|
|
1563
|
+
"Bash(git tag *)",
|
|
1564
|
+
"Bash(git revert *)",
|
|
1565
|
+
"Bash(git clean *)",
|
|
1566
|
+
"Bash(git rm *)",
|
|
1567
|
+
"Bash(git mv *)",
|
|
1568
|
+
"Bash(rm -rf *)",
|
|
1569
|
+
"Bash(cat *.env)",
|
|
1570
|
+
"Bash(cat *.env.*)",
|
|
1571
|
+
"Bash(cat .env)",
|
|
1572
|
+
"Bash(cat .env.*)",
|
|
1573
|
+
"Bash(head *.env)",
|
|
1574
|
+
"Bash(head *.env.*)",
|
|
1575
|
+
"Bash(head .env)",
|
|
1576
|
+
"Bash(head .env.*)",
|
|
1577
|
+
"Bash(tail *.env)",
|
|
1578
|
+
"Bash(tail *.env.*)",
|
|
1579
|
+
"Bash(tail .env)",
|
|
1580
|
+
"Bash(tail .env.*)",
|
|
1581
|
+
"Bash(less *.env)",
|
|
1582
|
+
"Bash(less *.env.*)",
|
|
1583
|
+
"Bash(less .env)",
|
|
1584
|
+
"Bash(less .env.*)",
|
|
1585
|
+
"Bash(more *.env)",
|
|
1586
|
+
"Bash(more *.env.*)",
|
|
1587
|
+
"Bash(more .env)",
|
|
1588
|
+
"Bash(more .env.*)",
|
|
1589
|
+
"Bash(grep * .env)",
|
|
1590
|
+
"Bash(grep * .env.*)",
|
|
1591
|
+
"Read(.env)",
|
|
1592
|
+
"Read(.env.*)",
|
|
1593
|
+
"Read(*.env)",
|
|
1594
|
+
"Read(*.env.*)"
|
|
1553
1595
|
]
|
|
1554
1596
|
},
|
|
1555
1597
|
instructions: [
|
|
1556
1598
|
"Use pnpm, not npm/yarn/npx. Run binaries with `pnpm exec`.",
|
|
1557
1599
|
"No typecasts (as/any). Use zod schemas, type guards, or narrowing instead.",
|
|
1558
1600
|
"Fix lint violations instead of suppressing them. Only add disable comments when suppression is genuinely the best option."
|
|
1559
|
-
]
|
|
1601
|
+
],
|
|
1602
|
+
enabledPlugins,
|
|
1603
|
+
extraKnownMarketplaces
|
|
1560
1604
|
};
|
|
1561
1605
|
}
|
|
1562
|
-
|
|
1563
|
-
|
|
1606
|
+
/** Remove enabledPlugins/extraKnownMarketplaces when empty to keep the file clean. */
|
|
1607
|
+
function serializeSettings$1(settings) {
|
|
1608
|
+
const { enabledPlugins, extraKnownMarketplaces, ...rest } = settings;
|
|
1609
|
+
const out = { ...rest };
|
|
1610
|
+
if (Object.keys(enabledPlugins).length > 0) out["enabledPlugins"] = enabledPlugins;
|
|
1611
|
+
if (Object.keys(extraKnownMarketplaces).length > 0) out["extraKnownMarketplaces"] = extraKnownMarketplaces;
|
|
1612
|
+
return JSON.stringify(out, null, 2) + "\n";
|
|
1613
|
+
}
|
|
1614
|
+
function writeOrMergeSettings(ctx, filePath, generated) {
|
|
1564
1615
|
const existing = ctx.read(filePath);
|
|
1565
|
-
const generated = buildSettings(ctx);
|
|
1566
1616
|
if (existing) {
|
|
1567
1617
|
const parsed = parseClaudeSettings(existing);
|
|
1568
1618
|
if (!parsed) return {
|
|
@@ -1573,7 +1623,10 @@ async function generateClaudeSettings(ctx) {
|
|
|
1573
1623
|
const missingAllow = generated.permissions.allow.filter((rule) => !parsed.permissions.allow.includes(rule));
|
|
1574
1624
|
const missingDeny = generated.permissions.deny.filter((rule) => !parsed.permissions.deny.includes(rule));
|
|
1575
1625
|
const missingInstructions = generated.instructions.filter((inst) => !parsed.instructions.includes(inst));
|
|
1576
|
-
|
|
1626
|
+
const missingPlugins = Object.entries(generated.enabledPlugins).filter(([key]) => !(key in parsed.enabledPlugins));
|
|
1627
|
+
const missingMarketplaces = Object.entries(generated.extraKnownMarketplaces).filter(([key]) => !(key in parsed.extraKnownMarketplaces));
|
|
1628
|
+
const added = missingAllow.length + missingDeny.length + missingInstructions.length + missingPlugins.length + missingMarketplaces.length;
|
|
1629
|
+
if (added === 0) return {
|
|
1577
1630
|
filePath,
|
|
1578
1631
|
action: "skipped",
|
|
1579
1632
|
description: "Already has all rules and instructions"
|
|
@@ -1581,22 +1634,41 @@ async function generateClaudeSettings(ctx) {
|
|
|
1581
1634
|
parsed.permissions.allow = [...parsed.permissions.allow, ...missingAllow];
|
|
1582
1635
|
parsed.permissions.deny = [...parsed.permissions.deny, ...missingDeny];
|
|
1583
1636
|
parsed.instructions = [...parsed.instructions, ...missingInstructions];
|
|
1584
|
-
const
|
|
1585
|
-
|
|
1637
|
+
for (const [key, value] of missingPlugins) parsed.enabledPlugins[key] = value;
|
|
1638
|
+
for (const [key, value] of missingMarketplaces) parsed.extraKnownMarketplaces[key] = value;
|
|
1639
|
+
ctx.write(filePath, serializeSettings$1(parsed));
|
|
1586
1640
|
return {
|
|
1587
1641
|
filePath,
|
|
1588
1642
|
action: "updated",
|
|
1589
1643
|
description: `Added ${String(added)} rules/instructions`
|
|
1590
1644
|
};
|
|
1591
1645
|
}
|
|
1592
|
-
ctx.write(filePath,
|
|
1646
|
+
ctx.write(filePath, serializeSettings$1(generated));
|
|
1593
1647
|
return {
|
|
1594
1648
|
filePath,
|
|
1595
1649
|
action: "created",
|
|
1596
|
-
description:
|
|
1650
|
+
description: `Generated ${filePath}`
|
|
1597
1651
|
};
|
|
1598
1652
|
}
|
|
1599
|
-
|
|
1653
|
+
async function generateClaudeSettings(ctx) {
|
|
1654
|
+
const results = [];
|
|
1655
|
+
results.push(writeOrMergeSettings(ctx, ".claude/settings.json", buildSettings(ctx)));
|
|
1656
|
+
if (ctx.config.structure === "monorepo") for (const pkg of getMonorepoPackages(ctx.targetDir)) {
|
|
1657
|
+
if (!hasWebUIDeps(pkg.dir)) continue;
|
|
1658
|
+
const pkgRelDir = path.relative(ctx.targetDir, pkg.dir);
|
|
1659
|
+
const pkgSettingsPath = path.join(pkgRelDir, ".claude/settings.json");
|
|
1660
|
+
results.push(writeOrMergeSettings(ctx, pkgSettingsPath, {
|
|
1661
|
+
permissions: {
|
|
1662
|
+
allow: [],
|
|
1663
|
+
deny: []
|
|
1664
|
+
},
|
|
1665
|
+
instructions: [],
|
|
1666
|
+
enabledPlugins: { "frontend-design@claude-plugins-official": true },
|
|
1667
|
+
extraKnownMarketplaces: {}
|
|
1668
|
+
}));
|
|
1669
|
+
}
|
|
1670
|
+
return results;
|
|
1671
|
+
}
|
|
1600
1672
|
//#endregion
|
|
1601
1673
|
//#region src/generators/release-it.ts
|
|
1602
1674
|
function buildConfig$2(ci, isMonorepo) {
|
|
@@ -1648,7 +1720,6 @@ async function generateReleaseIt(ctx) {
|
|
|
1648
1720
|
description: "Generated .release-it.json"
|
|
1649
1721
|
};
|
|
1650
1722
|
}
|
|
1651
|
-
|
|
1652
1723
|
//#endregion
|
|
1653
1724
|
//#region src/generators/changesets.ts
|
|
1654
1725
|
function buildConfig$1() {
|
|
@@ -1685,7 +1756,6 @@ async function generateChangesets(ctx) {
|
|
|
1685
1756
|
description: "Generated .changeset/config.json"
|
|
1686
1757
|
};
|
|
1687
1758
|
}
|
|
1688
|
-
|
|
1689
1759
|
//#endregion
|
|
1690
1760
|
//#region src/generators/release-ci.ts
|
|
1691
1761
|
function hasEnginesNode(ctx) {
|
|
@@ -1855,7 +1925,6 @@ async function generateReleaseCi(ctx) {
|
|
|
1855
1925
|
description: `Generated ${isGitHub ? "GitHub" : "Forgejo"} Actions release workflow`
|
|
1856
1926
|
};
|
|
1857
1927
|
}
|
|
1858
|
-
|
|
1859
1928
|
//#endregion
|
|
1860
1929
|
//#region src/generators/lefthook.ts
|
|
1861
1930
|
function buildConfig(formatter) {
|
|
@@ -1984,7 +2053,103 @@ async function generateLefthook(ctx) {
|
|
|
1984
2053
|
});
|
|
1985
2054
|
return results;
|
|
1986
2055
|
}
|
|
1987
|
-
|
|
2056
|
+
//#endregion
|
|
2057
|
+
//#region src/generators/vscode-settings.ts
|
|
2058
|
+
const SCHEMA_NPM_PATH = "@bensandee/config/schemas/forgejo-workflow.schema.json";
|
|
2059
|
+
const SCHEMA_LOCAL_PATH = ".vscode/forgejo-workflow.schema.json";
|
|
2060
|
+
const SETTINGS_PATH = ".vscode/settings.json";
|
|
2061
|
+
const VscodeSettingsSchema = z.object({ "yaml.schemas": z.record(z.string(), z.unknown()).default({}) }).passthrough();
|
|
2062
|
+
function readSchemaFromNodeModules(targetDir) {
|
|
2063
|
+
const candidate = path.join(targetDir, "node_modules", SCHEMA_NPM_PATH);
|
|
2064
|
+
if (!existsSync(candidate)) return void 0;
|
|
2065
|
+
return readFileSync(candidate, "utf-8");
|
|
2066
|
+
}
|
|
2067
|
+
function serializeSettings(settings) {
|
|
2068
|
+
return JSON.stringify(settings, null, 2) + "\n";
|
|
2069
|
+
}
|
|
2070
|
+
async function generateVscodeSettings(ctx) {
|
|
2071
|
+
const results = [];
|
|
2072
|
+
if (ctx.config.ci !== "forgejo") {
|
|
2073
|
+
results.push({
|
|
2074
|
+
filePath: SETTINGS_PATH,
|
|
2075
|
+
action: "skipped",
|
|
2076
|
+
description: "Not a Forgejo project"
|
|
2077
|
+
});
|
|
2078
|
+
return results;
|
|
2079
|
+
}
|
|
2080
|
+
const schemaContent = readSchemaFromNodeModules(ctx.targetDir);
|
|
2081
|
+
if (!schemaContent) {
|
|
2082
|
+
results.push({
|
|
2083
|
+
filePath: SCHEMA_LOCAL_PATH,
|
|
2084
|
+
action: "skipped",
|
|
2085
|
+
description: "Could not find @bensandee/config schema in node_modules"
|
|
2086
|
+
});
|
|
2087
|
+
return results;
|
|
2088
|
+
}
|
|
2089
|
+
const existingSchema = ctx.read(SCHEMA_LOCAL_PATH);
|
|
2090
|
+
if (existingSchema === schemaContent) results.push({
|
|
2091
|
+
filePath: SCHEMA_LOCAL_PATH,
|
|
2092
|
+
action: "skipped",
|
|
2093
|
+
description: "Schema already up to date"
|
|
2094
|
+
});
|
|
2095
|
+
else {
|
|
2096
|
+
ctx.write(SCHEMA_LOCAL_PATH, schemaContent);
|
|
2097
|
+
results.push({
|
|
2098
|
+
filePath: SCHEMA_LOCAL_PATH,
|
|
2099
|
+
action: existingSchema ? "updated" : "created",
|
|
2100
|
+
description: "Copied Forgejo workflow schema from @bensandee/config"
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
const schemaGlob = ".forgejo/workflows/*.yml";
|
|
2104
|
+
if (ctx.exists(SETTINGS_PATH)) {
|
|
2105
|
+
const raw = ctx.read(SETTINGS_PATH);
|
|
2106
|
+
if (!raw) {
|
|
2107
|
+
results.push({
|
|
2108
|
+
filePath: SETTINGS_PATH,
|
|
2109
|
+
action: "skipped",
|
|
2110
|
+
description: "Could not read existing settings"
|
|
2111
|
+
});
|
|
2112
|
+
return results;
|
|
2113
|
+
}
|
|
2114
|
+
const parsed = VscodeSettingsSchema.safeParse(JSON.parse(raw));
|
|
2115
|
+
if (!parsed.success) {
|
|
2116
|
+
results.push({
|
|
2117
|
+
filePath: SETTINGS_PATH,
|
|
2118
|
+
action: "skipped",
|
|
2119
|
+
description: "Could not parse existing settings"
|
|
2120
|
+
});
|
|
2121
|
+
return results;
|
|
2122
|
+
}
|
|
2123
|
+
const existing = parsed.data;
|
|
2124
|
+
const yamlSchemas = existing["yaml.schemas"];
|
|
2125
|
+
if (SCHEMA_LOCAL_PATH in yamlSchemas) {
|
|
2126
|
+
results.push({
|
|
2127
|
+
filePath: SETTINGS_PATH,
|
|
2128
|
+
action: "skipped",
|
|
2129
|
+
description: "Already has Forgejo schema mapping"
|
|
2130
|
+
});
|
|
2131
|
+
return results;
|
|
2132
|
+
}
|
|
2133
|
+
yamlSchemas[SCHEMA_LOCAL_PATH] = schemaGlob;
|
|
2134
|
+
ctx.write(SETTINGS_PATH, serializeSettings({
|
|
2135
|
+
...existing,
|
|
2136
|
+
"yaml.schemas": yamlSchemas
|
|
2137
|
+
}));
|
|
2138
|
+
results.push({
|
|
2139
|
+
filePath: SETTINGS_PATH,
|
|
2140
|
+
action: "updated",
|
|
2141
|
+
description: "Added Forgejo workflow schema mapping"
|
|
2142
|
+
});
|
|
2143
|
+
} else {
|
|
2144
|
+
ctx.write(SETTINGS_PATH, serializeSettings({ "yaml.schemas": { [SCHEMA_LOCAL_PATH]: schemaGlob } }));
|
|
2145
|
+
results.push({
|
|
2146
|
+
filePath: SETTINGS_PATH,
|
|
2147
|
+
action: "created",
|
|
2148
|
+
description: "Generated .vscode/settings.json with Forgejo workflow schema"
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2151
|
+
return results;
|
|
2152
|
+
}
|
|
1988
2153
|
//#endregion
|
|
1989
2154
|
//#region src/generators/pipeline.ts
|
|
1990
2155
|
/** Run all generators sequentially and return their results. */
|
|
@@ -2001,14 +2166,14 @@ async function runGenerators(ctx) {
|
|
|
2001
2166
|
results.push(await generateKnip(ctx));
|
|
2002
2167
|
results.push(await generateRenovate(ctx));
|
|
2003
2168
|
results.push(await generateCi(ctx));
|
|
2004
|
-
results.push(await generateClaudeSettings(ctx));
|
|
2169
|
+
results.push(...await generateClaudeSettings(ctx));
|
|
2005
2170
|
results.push(await generateReleaseIt(ctx));
|
|
2006
2171
|
results.push(await generateChangesets(ctx));
|
|
2007
2172
|
results.push(await generateReleaseCi(ctx));
|
|
2008
2173
|
results.push(...await generateVitest(ctx));
|
|
2174
|
+
results.push(...await generateVscodeSettings(ctx));
|
|
2009
2175
|
return results;
|
|
2010
2176
|
}
|
|
2011
|
-
|
|
2012
2177
|
//#endregion
|
|
2013
2178
|
//#region src/utils/tooling-config.ts
|
|
2014
2179
|
const CONFIG_FILE = ".tooling.json";
|
|
@@ -2063,11 +2228,16 @@ function saveToolingConfig(ctx, config) {
|
|
|
2063
2228
|
detectPackageTypes: config.detectPackageTypes
|
|
2064
2229
|
};
|
|
2065
2230
|
const content = JSON.stringify(saved, null, 2) + "\n";
|
|
2066
|
-
const
|
|
2231
|
+
const existing = ctx.exists(CONFIG_FILE) ? ctx.read(CONFIG_FILE) : void 0;
|
|
2232
|
+
if (existing === content) return {
|
|
2233
|
+
filePath: CONFIG_FILE,
|
|
2234
|
+
action: "skipped",
|
|
2235
|
+
description: "Already up to date"
|
|
2236
|
+
};
|
|
2067
2237
|
ctx.write(CONFIG_FILE, content);
|
|
2068
2238
|
return {
|
|
2069
2239
|
filePath: CONFIG_FILE,
|
|
2070
|
-
action:
|
|
2240
|
+
action: existing ? "updated" : "created",
|
|
2071
2241
|
description: "Saved tooling configuration"
|
|
2072
2242
|
};
|
|
2073
2243
|
}
|
|
@@ -2088,7 +2258,6 @@ function mergeWithSavedConfig(detected, saved) {
|
|
|
2088
2258
|
detectPackageTypes: saved.detectPackageTypes ?? detected.detectPackageTypes
|
|
2089
2259
|
};
|
|
2090
2260
|
}
|
|
2091
|
-
|
|
2092
2261
|
//#endregion
|
|
2093
2262
|
//#region src/commands/repo-init.ts
|
|
2094
2263
|
const initCommand = defineCommand({
|
|
@@ -2160,6 +2329,14 @@ async function runInit(config, options = {}) {
|
|
|
2160
2329
|
action: "archived",
|
|
2161
2330
|
description: `Original saved to .tooling-archived/${rel}`
|
|
2162
2331
|
});
|
|
2332
|
+
const created = results.filter((r) => r.action === "created");
|
|
2333
|
+
const updated = results.filter((r) => r.action === "updated");
|
|
2334
|
+
const skipped = results.filter((r) => r.action === "skipped");
|
|
2335
|
+
const archived = results.filter((r) => r.action === "archived");
|
|
2336
|
+
if (!(created.length > 0 || updated.length > 0 || archived.length > 0) && options.noPrompt) {
|
|
2337
|
+
s.stop("Repository is up to date.");
|
|
2338
|
+
return results;
|
|
2339
|
+
}
|
|
2163
2340
|
s.stop("Done!");
|
|
2164
2341
|
if (results.some((r) => r.action === "archived" && r.filePath.startsWith(".husky/"))) try {
|
|
2165
2342
|
execSync("git config --unset core.hooksPath", {
|
|
@@ -2167,10 +2344,6 @@ async function runInit(config, options = {}) {
|
|
|
2167
2344
|
stdio: "ignore"
|
|
2168
2345
|
});
|
|
2169
2346
|
} catch (_error) {}
|
|
2170
|
-
const created = results.filter((r) => r.action === "created");
|
|
2171
|
-
const updated = results.filter((r) => r.action === "updated");
|
|
2172
|
-
const skipped = results.filter((r) => r.action === "skipped");
|
|
2173
|
-
const archived = results.filter((r) => r.action === "archived");
|
|
2174
2347
|
const summaryLines = [];
|
|
2175
2348
|
if (created.length > 0) summaryLines.push(`Created: ${created.map((r) => r.filePath).join(", ")}`);
|
|
2176
2349
|
if (updated.length > 0) summaryLines.push(`Updated: ${updated.map((r) => r.filePath).join(", ")}`);
|
|
@@ -2207,7 +2380,6 @@ async function runInit(config, options = {}) {
|
|
|
2207
2380
|
].join("\n"), "Next steps");
|
|
2208
2381
|
return results;
|
|
2209
2382
|
}
|
|
2210
|
-
|
|
2211
2383
|
//#endregion
|
|
2212
2384
|
//#region src/commands/repo-update.ts
|
|
2213
2385
|
const updateCommand = defineCommand({
|
|
@@ -2233,7 +2405,6 @@ async function runUpdate(targetDir) {
|
|
|
2233
2405
|
confirmOverwrite: async () => "overwrite"
|
|
2234
2406
|
});
|
|
2235
2407
|
}
|
|
2236
|
-
|
|
2237
2408
|
//#endregion
|
|
2238
2409
|
//#region src/commands/repo-check.ts
|
|
2239
2410
|
const checkCommand = defineCommand({
|
|
@@ -2292,14 +2463,12 @@ function lineDiff(oldText, newText) {
|
|
|
2292
2463
|
for (const l of added) lines.push(`+ ${l.trim()}`);
|
|
2293
2464
|
return lines;
|
|
2294
2465
|
}
|
|
2295
|
-
|
|
2296
2466
|
//#endregion
|
|
2297
2467
|
//#region src/utils/exec.ts
|
|
2298
2468
|
/** Type guard for `execSync` errors that carry stdout/stderr/status. */
|
|
2299
2469
|
function isExecSyncError(err) {
|
|
2300
2470
|
return err instanceof Error && "stdout" in err && typeof err.stdout === "string" && "stderr" in err && typeof err.stderr === "string" && "status" in err && typeof err.status === "number";
|
|
2301
2471
|
}
|
|
2302
|
-
|
|
2303
2472
|
//#endregion
|
|
2304
2473
|
//#region src/release/executor.ts
|
|
2305
2474
|
/** Create an executor that runs real commands, fetches, and reads the filesystem. */
|
|
@@ -2410,18 +2579,25 @@ function reconcileTags(expectedTags, remoteTags, stdoutTags) {
|
|
|
2410
2579
|
for (const tag of stdoutTags) result.add(tag);
|
|
2411
2580
|
return [...result];
|
|
2412
2581
|
}
|
|
2413
|
-
|
|
2414
2582
|
//#endregion
|
|
2415
2583
|
//#region src/release/forgejo.ts
|
|
2416
|
-
const PullRequestSchema = z.array(z.object({
|
|
2417
|
-
|
|
2584
|
+
const PullRequestSchema = z.array(z.object({
|
|
2585
|
+
number: z.number(),
|
|
2586
|
+
head: z.object({ ref: z.string() })
|
|
2587
|
+
}));
|
|
2588
|
+
/**
|
|
2589
|
+
* Find an open PR with the given head branch. Returns the PR number or null.
|
|
2590
|
+
*
|
|
2591
|
+
* Fetches all open PRs and filters client-side by head.ref rather than relying
|
|
2592
|
+
* on Forgejo's query parameter filtering, which behaves inconsistently.
|
|
2593
|
+
*/
|
|
2418
2594
|
async function findOpenPr(executor, conn, head) {
|
|
2419
|
-
const url = `${conn.serverUrl}/api/v1/repos/${conn.repository}/pulls?state=open
|
|
2595
|
+
const url = `${conn.serverUrl}/api/v1/repos/${conn.repository}/pulls?state=open`;
|
|
2420
2596
|
const res = await executor.fetch(url, { headers: { Authorization: `token ${conn.token}` } });
|
|
2421
2597
|
if (!res.ok) throw new TransientError(`Failed to list PRs: ${res.status} ${res.statusText}`);
|
|
2422
2598
|
const parsed = PullRequestSchema.safeParse(await res.json());
|
|
2423
2599
|
if (!parsed.success) throw new UnexpectedError(`Unexpected PR list response: ${parsed.error.message}`);
|
|
2424
|
-
return parsed.data
|
|
2600
|
+
return parsed.data.find((pr) => pr.head.ref === head)?.number ?? null;
|
|
2425
2601
|
}
|
|
2426
2602
|
/** Create a new pull request. */
|
|
2427
2603
|
async function createPr(executor, conn, options) {
|
|
@@ -2500,7 +2676,6 @@ async function createRelease(executor, conn, tag) {
|
|
|
2500
2676
|
});
|
|
2501
2677
|
if (!res.ok) throw new TransientError(`Failed to create release for ${tag}: ${res.status} ${res.statusText}`);
|
|
2502
2678
|
}
|
|
2503
|
-
|
|
2504
2679
|
//#endregion
|
|
2505
2680
|
//#region src/release/log.ts
|
|
2506
2681
|
/** Log a debug message when verbose mode is enabled. */
|
|
@@ -2515,7 +2690,6 @@ function debugExec(config, label, result) {
|
|
|
2515
2690
|
if (result.stderr.trim()) lines.push(` stderr: ${result.stderr.trim()}`);
|
|
2516
2691
|
p.log.info(lines.join("\n"));
|
|
2517
2692
|
}
|
|
2518
|
-
|
|
2519
2693
|
//#endregion
|
|
2520
2694
|
//#region src/release/version.ts
|
|
2521
2695
|
const BRANCH = "changeset-release/main";
|
|
@@ -2660,7 +2834,6 @@ async function runVersionMode(executor, config) {
|
|
|
2660
2834
|
pr: "updated"
|
|
2661
2835
|
};
|
|
2662
2836
|
}
|
|
2663
|
-
|
|
2664
2837
|
//#endregion
|
|
2665
2838
|
//#region src/release/publish.ts
|
|
2666
2839
|
const RETRY_ATTEMPTS = 3;
|
|
@@ -2750,7 +2923,6 @@ async function runPublishMode(executor, config) {
|
|
|
2750
2923
|
tags: allTags
|
|
2751
2924
|
};
|
|
2752
2925
|
}
|
|
2753
|
-
|
|
2754
2926
|
//#endregion
|
|
2755
2927
|
//#region src/release/connection.ts
|
|
2756
2928
|
const RepositorySchema = z.union([z.string(), z.object({ url: z.string() })]);
|
|
@@ -2824,7 +2996,6 @@ function parseGitUrl(urlStr) {
|
|
|
2824
2996
|
return null;
|
|
2825
2997
|
}
|
|
2826
2998
|
}
|
|
2827
|
-
|
|
2828
2999
|
//#endregion
|
|
2829
3000
|
//#region src/commands/release-changesets.ts
|
|
2830
3001
|
const releaseForgejoCommand = defineCommand({
|
|
@@ -2871,7 +3042,6 @@ async function runRelease(config, executor) {
|
|
|
2871
3042
|
debug(config, "Entering publish mode");
|
|
2872
3043
|
return runPublishMode(executor, config);
|
|
2873
3044
|
}
|
|
2874
|
-
|
|
2875
3045
|
//#endregion
|
|
2876
3046
|
//#region src/commands/release-trigger.ts
|
|
2877
3047
|
const releaseTriggerCommand = defineCommand({
|
|
@@ -2908,7 +3078,6 @@ function triggerGitHub(ref) {
|
|
|
2908
3078
|
createRealExecutor().exec(`gh workflow run release.yml --ref ${ref}`, { cwd: process.cwd() });
|
|
2909
3079
|
p.log.info(`Triggered release workflow on GitHub (ref: ${ref})`);
|
|
2910
3080
|
}
|
|
2911
|
-
|
|
2912
3081
|
//#endregion
|
|
2913
3082
|
//#region src/commands/release-create-forgejo-release.ts
|
|
2914
3083
|
const createForgejoReleaseCommand = defineCommand({
|
|
@@ -2934,7 +3103,6 @@ const createForgejoReleaseCommand = defineCommand({
|
|
|
2934
3103
|
p.log.info(`Created Forgejo release for ${args.tag}`);
|
|
2935
3104
|
}
|
|
2936
3105
|
});
|
|
2937
|
-
|
|
2938
3106
|
//#endregion
|
|
2939
3107
|
//#region src/commands/release-merge.ts
|
|
2940
3108
|
const HEAD_BRANCH = "changeset-release/main";
|
|
@@ -2979,13 +3147,12 @@ function mergeGitHub(dryRun) {
|
|
|
2979
3147
|
executor.exec(`gh pr merge ${HEAD_BRANCH} --merge --delete-branch`, { cwd: process.cwd() });
|
|
2980
3148
|
p.log.info(`Merged changesets PR and deleted branch ${HEAD_BRANCH}`);
|
|
2981
3149
|
}
|
|
2982
|
-
|
|
2983
3150
|
//#endregion
|
|
2984
3151
|
//#region src/bin.ts
|
|
2985
3152
|
const main = defineCommand({
|
|
2986
3153
|
meta: {
|
|
2987
3154
|
name: "tooling",
|
|
2988
|
-
version: "0.
|
|
3155
|
+
version: "0.8.1",
|
|
2989
3156
|
description: "Bootstrap and maintain standardized TypeScript project tooling"
|
|
2990
3157
|
},
|
|
2991
3158
|
subCommands: {
|
|
@@ -2998,8 +3165,7 @@ const main = defineCommand({
|
|
|
2998
3165
|
"release:merge": releaseMergeCommand
|
|
2999
3166
|
}
|
|
3000
3167
|
});
|
|
3001
|
-
console.log(`@bensandee/tooling v0.
|
|
3168
|
+
console.log(`@bensandee/tooling v0.8.1`);
|
|
3002
3169
|
runMain(main);
|
|
3003
|
-
|
|
3004
3170
|
//#endregion
|
|
3005
|
-
export {
|
|
3171
|
+
export {};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bensandee/tooling",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "CLI tool to bootstrap and maintain standardized TypeScript project tooling",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tooling": "./dist/bin.mjs"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@clack/prompts": "^1.0
|
|
24
|
+
"@clack/prompts": "^1.1.0",
|
|
25
25
|
"citty": "^0.2.1",
|
|
26
26
|
"json5": "^2.2.3",
|
|
27
27
|
"jsonc-parser": "^3.3.1",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"@bensandee/common": "0.1.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@types/node": "24.
|
|
33
|
-
"tsdown": "0.
|
|
32
|
+
"@types/node": "24.12.0",
|
|
33
|
+
"tsdown": "0.21.0",
|
|
34
34
|
"typescript": "5.9.3",
|
|
35
35
|
"vitest": "4.0.18",
|
|
36
|
-
"@bensandee/config": "0.
|
|
36
|
+
"@bensandee/config": "0.7.0"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsdown",
|