@bensandee/tooling 0.8.0 → 0.9.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/dist/bin.mjs +263 -120
- 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 = {
|
|
@@ -205,7 +202,6 @@ function getMonorepoPackages(targetDir) {
|
|
|
205
202
|
} catch (_error) {}
|
|
206
203
|
return results;
|
|
207
204
|
}
|
|
208
|
-
|
|
209
205
|
//#endregion
|
|
210
206
|
//#region src/prompts/init-prompts.ts
|
|
211
207
|
function isCancelled(value) {
|
|
@@ -416,7 +412,6 @@ function buildDefaultConfig(targetDir, flags) {
|
|
|
416
412
|
targetDir
|
|
417
413
|
};
|
|
418
414
|
}
|
|
419
|
-
|
|
420
415
|
//#endregion
|
|
421
416
|
//#region src/utils/fs.ts
|
|
422
417
|
/** Check whether a file exists at the given path. */
|
|
@@ -442,29 +437,31 @@ function writeFile(targetDir, relativePath, content) {
|
|
|
442
437
|
function createContext(config, confirmOverwrite) {
|
|
443
438
|
const archivedFiles = [];
|
|
444
439
|
const pkgRaw = readFile(config.targetDir, "package.json");
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
archivedFiles.push(rel);
|
|
458
|
-
}
|
|
440
|
+
const ctx = {
|
|
441
|
+
config,
|
|
442
|
+
targetDir: config.targetDir,
|
|
443
|
+
packageJson: pkgRaw ? parsePackageJson(pkgRaw) : void 0,
|
|
444
|
+
exists: (rel) => fileExists(config.targetDir, rel),
|
|
445
|
+
read: (rel) => readFile(config.targetDir, rel),
|
|
446
|
+
write: (rel, content) => {
|
|
447
|
+
if (!rel.startsWith(".tooling-archived/")) {
|
|
448
|
+
const existing = readFile(config.targetDir, rel);
|
|
449
|
+
if (existing !== void 0 && existing !== content) {
|
|
450
|
+
writeFile(config.targetDir, `.tooling-archived/${rel}`, existing);
|
|
451
|
+
archivedFiles.push(rel);
|
|
459
452
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
const fullPath = path.join(config.targetDir, rel);
|
|
464
|
-
if (existsSync(fullPath)) rmSync(fullPath);
|
|
465
|
-
},
|
|
466
|
-
confirmOverwrite
|
|
453
|
+
}
|
|
454
|
+
writeFile(config.targetDir, rel, content);
|
|
455
|
+
if (rel === "package.json") ctx.packageJson = parsePackageJson(content);
|
|
467
456
|
},
|
|
457
|
+
remove: (rel) => {
|
|
458
|
+
const fullPath = path.join(config.targetDir, rel);
|
|
459
|
+
if (existsSync(fullPath)) rmSync(fullPath);
|
|
460
|
+
},
|
|
461
|
+
confirmOverwrite
|
|
462
|
+
};
|
|
463
|
+
return {
|
|
464
|
+
ctx,
|
|
468
465
|
archivedFiles
|
|
469
466
|
};
|
|
470
467
|
}
|
|
@@ -477,24 +474,25 @@ function createDryRunContext(config) {
|
|
|
477
474
|
const pkgRaw = readFile(config.targetDir, "package.json");
|
|
478
475
|
const pendingWrites = /* @__PURE__ */ new Map();
|
|
479
476
|
const shadow = /* @__PURE__ */ new Map();
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
},
|
|
491
|
-
remove: () => {},
|
|
492
|
-
confirmOverwrite: async () => "overwrite"
|
|
477
|
+
const ctx = {
|
|
478
|
+
config,
|
|
479
|
+
targetDir: config.targetDir,
|
|
480
|
+
packageJson: pkgRaw ? parsePackageJson(pkgRaw) : void 0,
|
|
481
|
+
exists: (rel) => shadow.has(rel) || fileExists(config.targetDir, rel),
|
|
482
|
+
read: (rel) => shadow.get(rel) ?? readFile(config.targetDir, rel),
|
|
483
|
+
write: (rel, content) => {
|
|
484
|
+
pendingWrites.set(rel, content);
|
|
485
|
+
shadow.set(rel, content);
|
|
486
|
+
if (rel === "package.json") ctx.packageJson = parsePackageJson(content);
|
|
493
487
|
},
|
|
488
|
+
remove: () => {},
|
|
489
|
+
confirmOverwrite: async () => "overwrite"
|
|
490
|
+
};
|
|
491
|
+
return {
|
|
492
|
+
ctx,
|
|
494
493
|
pendingWrites
|
|
495
494
|
};
|
|
496
495
|
}
|
|
497
|
-
|
|
498
496
|
//#endregion
|
|
499
497
|
//#region src/generators/package-json.ts
|
|
500
498
|
const STANDARD_SCRIPTS_SINGLE = {
|
|
@@ -568,8 +566,8 @@ function addReleaseDeps(deps, config) {
|
|
|
568
566
|
function getAddedDevDepNames(config) {
|
|
569
567
|
const deps = { ...ROOT_DEV_DEPS };
|
|
570
568
|
if (config.structure !== "monorepo") Object.assign(deps, PER_PACKAGE_DEV_DEPS);
|
|
571
|
-
deps["@bensandee/config"] = "
|
|
572
|
-
deps["@bensandee/tooling"] = "
|
|
569
|
+
deps["@bensandee/config"] = "0.7.1";
|
|
570
|
+
deps["@bensandee/tooling"] = "0.9.0";
|
|
573
571
|
if (config.formatter === "oxfmt") deps["oxfmt"] = "0.35.0";
|
|
574
572
|
if (config.formatter === "prettier") deps["prettier"] = "3.8.1";
|
|
575
573
|
addReleaseDeps(deps, config);
|
|
@@ -589,9 +587,9 @@ async function generatePackageJson(ctx) {
|
|
|
589
587
|
if (ctx.config.releaseStrategy !== "none") allScripts["trigger-release"] = "pnpm exec tooling release:trigger";
|
|
590
588
|
const devDeps = { ...ROOT_DEV_DEPS };
|
|
591
589
|
if (!isMonorepo) Object.assign(devDeps, PER_PACKAGE_DEV_DEPS);
|
|
592
|
-
devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "
|
|
593
|
-
devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "
|
|
594
|
-
if (ctx.config.useEslintPlugin) devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "
|
|
590
|
+
devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "0.7.1";
|
|
591
|
+
devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.9.0";
|
|
592
|
+
if (ctx.config.useEslintPlugin) devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "0.9.0";
|
|
595
593
|
if (ctx.config.formatter === "oxfmt") devDeps["oxfmt"] = "0.35.0";
|
|
596
594
|
if (ctx.config.formatter === "prettier") devDeps["prettier"] = "3.8.1";
|
|
597
595
|
addReleaseDeps(devDeps, ctx.config);
|
|
@@ -617,9 +615,9 @@ async function generatePackageJson(ctx) {
|
|
|
617
615
|
for (const [key, value] of Object.entries(devDeps)) if (!(key in existingDevDeps)) {
|
|
618
616
|
existingDevDeps[key] = value;
|
|
619
617
|
changes.push(`added devDependency: ${key}`);
|
|
620
|
-
} else if (key.startsWith("@bensandee/") &&
|
|
621
|
-
existingDevDeps[key] =
|
|
622
|
-
changes.push(`updated devDependency: ${key} to
|
|
618
|
+
} else if (key.startsWith("@bensandee/") && existingDevDeps[key] !== value && existingDevDeps[key] !== "workspace:*") {
|
|
619
|
+
existingDevDeps[key] = value;
|
|
620
|
+
changes.push(`updated devDependency: ${key} to ${value}`);
|
|
623
621
|
}
|
|
624
622
|
pkg.devDependencies = existingDevDeps;
|
|
625
623
|
if (!pkg["engines"]) {
|
|
@@ -655,7 +653,6 @@ async function generatePackageJson(ctx) {
|
|
|
655
653
|
description: "Generated package.json"
|
|
656
654
|
};
|
|
657
655
|
}
|
|
658
|
-
|
|
659
656
|
//#endregion
|
|
660
657
|
//#region src/generators/migrate-prompt.ts
|
|
661
658
|
/**
|
|
@@ -825,7 +822,6 @@ function generateMigratePrompt(results, config, detected) {
|
|
|
825
822
|
sections.push("");
|
|
826
823
|
return sections.join("\n");
|
|
827
824
|
}
|
|
828
|
-
|
|
829
825
|
//#endregion
|
|
830
826
|
//#region src/generators/tsconfig.ts
|
|
831
827
|
async function generateTsconfig(ctx) {
|
|
@@ -993,7 +989,6 @@ function generateMonorepoPackageTsconfigs(ctx) {
|
|
|
993
989
|
}
|
|
994
990
|
return results;
|
|
995
991
|
}
|
|
996
|
-
|
|
997
992
|
//#endregion
|
|
998
993
|
//#region src/generators/vitest.ts
|
|
999
994
|
const VITEST_CONFIG = `import { defineConfig } from "vitest/config";
|
|
@@ -1062,7 +1057,6 @@ async function generateVitest(ctx) {
|
|
|
1062
1057
|
}
|
|
1063
1058
|
return results;
|
|
1064
1059
|
}
|
|
1065
|
-
|
|
1066
1060
|
//#endregion
|
|
1067
1061
|
//#region src/generators/oxlint.ts
|
|
1068
1062
|
const CONFIG_WITH_LINT_RULES = `import recommended from "@bensandee/config/oxlint/recommended";
|
|
@@ -1102,7 +1096,6 @@ async function generateOxlint(ctx) {
|
|
|
1102
1096
|
description: "Generated oxlint.config.ts"
|
|
1103
1097
|
};
|
|
1104
1098
|
}
|
|
1105
|
-
|
|
1106
1099
|
//#endregion
|
|
1107
1100
|
//#region src/generators/formatter.ts
|
|
1108
1101
|
const OXFMT_CONFIG = `{}\n`;
|
|
@@ -1146,7 +1139,6 @@ async function generatePrettier(ctx) {
|
|
|
1146
1139
|
description: "Generated .prettierrc"
|
|
1147
1140
|
};
|
|
1148
1141
|
}
|
|
1149
|
-
|
|
1150
1142
|
//#endregion
|
|
1151
1143
|
//#region src/generators/tsdown.ts
|
|
1152
1144
|
const TSDOWN_CONFIG = `import { defineConfig } from "tsdown";
|
|
@@ -1182,7 +1174,6 @@ async function generateTsdown(ctx) {
|
|
|
1182
1174
|
description: "Generated tsdown.config.ts"
|
|
1183
1175
|
};
|
|
1184
1176
|
}
|
|
1185
|
-
|
|
1186
1177
|
//#endregion
|
|
1187
1178
|
//#region src/generators/gitignore.ts
|
|
1188
1179
|
/** Entries that every project should have — repo:check flags these as missing. */
|
|
@@ -1236,7 +1227,6 @@ async function generateGitignore(ctx) {
|
|
|
1236
1227
|
description: "Generated .gitignore"
|
|
1237
1228
|
};
|
|
1238
1229
|
}
|
|
1239
|
-
|
|
1240
1230
|
//#endregion
|
|
1241
1231
|
//#region src/generators/ci.ts
|
|
1242
1232
|
function hasEnginesNode$1(ctx) {
|
|
@@ -1244,9 +1234,9 @@ function hasEnginesNode$1(ctx) {
|
|
|
1244
1234
|
if (!raw) return false;
|
|
1245
1235
|
return typeof parsePackageJson(raw)?.engines?.["node"] === "string";
|
|
1246
1236
|
}
|
|
1247
|
-
function ciWorkflow(isMonorepo, nodeVersionYaml) {
|
|
1237
|
+
function ciWorkflow(isMonorepo, nodeVersionYaml, isForgejo) {
|
|
1248
1238
|
return `name: CI
|
|
1249
|
-
on:
|
|
1239
|
+
${isForgejo ? "\nenable-email-notifications: true\n" : ""}on:
|
|
1250
1240
|
push:
|
|
1251
1241
|
branches: [main]
|
|
1252
1242
|
pull_request:
|
|
@@ -1300,7 +1290,7 @@ async function generateCi(ctx) {
|
|
|
1300
1290
|
const isGitHub = ctx.config.ci === "github";
|
|
1301
1291
|
const nodeVersionYaml = hasEnginesNode$1(ctx) ? "node-version-file: package.json" : "node-version: \"24\"";
|
|
1302
1292
|
const filePath = isGitHub ? ".github/workflows/check.yml" : ".forgejo/workflows/check.yml";
|
|
1303
|
-
const content = ciWorkflow(isMonorepo, nodeVersionYaml);
|
|
1293
|
+
const content = ciWorkflow(isMonorepo, nodeVersionYaml, !isGitHub);
|
|
1304
1294
|
if (ctx.exists(filePath)) {
|
|
1305
1295
|
const existing = ctx.read(filePath);
|
|
1306
1296
|
if (existing && !existing.includes("repo:check")) {
|
|
@@ -1327,7 +1317,6 @@ async function generateCi(ctx) {
|
|
|
1327
1317
|
description: `Generated ${isGitHub ? "GitHub" : "Forgejo"} Actions CI workflow`
|
|
1328
1318
|
};
|
|
1329
1319
|
}
|
|
1330
|
-
|
|
1331
1320
|
//#endregion
|
|
1332
1321
|
//#region src/generators/knip.ts
|
|
1333
1322
|
const KNIP_CONFIG_SINGLE = `import type { KnipConfig } from "knip";
|
|
@@ -1380,7 +1369,6 @@ async function generateKnip(ctx) {
|
|
|
1380
1369
|
description: "Generated knip.config.ts for dead code analysis"
|
|
1381
1370
|
};
|
|
1382
1371
|
}
|
|
1383
|
-
|
|
1384
1372
|
//#endregion
|
|
1385
1373
|
//#region src/generators/renovate.ts
|
|
1386
1374
|
const SHARED_PRESET = "local>bensandee/tooling";
|
|
@@ -1447,7 +1435,6 @@ async function generateRenovate(ctx) {
|
|
|
1447
1435
|
description: "Generated renovate.json extending shared config"
|
|
1448
1436
|
};
|
|
1449
1437
|
}
|
|
1450
|
-
|
|
1451
1438
|
//#endregion
|
|
1452
1439
|
//#region src/generators/pnpm-workspace.ts
|
|
1453
1440
|
const WORKSPACE_YAML = `packages:
|
|
@@ -1472,7 +1459,6 @@ async function generatePnpmWorkspace(ctx) {
|
|
|
1472
1459
|
description: "Generated pnpm-workspace.yaml"
|
|
1473
1460
|
};
|
|
1474
1461
|
}
|
|
1475
|
-
|
|
1476
1462
|
//#endregion
|
|
1477
1463
|
//#region src/generators/claude-settings.ts
|
|
1478
1464
|
const ClaudeSettingsSchema = z.object({
|
|
@@ -1557,12 +1543,8 @@ function buildSettings(ctx) {
|
|
|
1557
1543
|
if (ctx.config.structure === "monorepo") allow.push(`Bash(${pm} --filter *)`, `Bash(${pm} -r *)`);
|
|
1558
1544
|
const enabledPlugins = { "code-simplifier@claude-plugins-official": true };
|
|
1559
1545
|
const extraKnownMarketplaces = {};
|
|
1560
|
-
if (ctx.config.structure
|
|
1561
|
-
enabledPlugins["
|
|
1562
|
-
extraKnownMarketplaces["anthropic-agent-skills"] = { source: {
|
|
1563
|
-
source: "github",
|
|
1564
|
-
repo: "anthropics/skills"
|
|
1565
|
-
} };
|
|
1546
|
+
if (ctx.config.structure !== "monorepo") {
|
|
1547
|
+
if (ctx.packageJson ? packageHasWebUIDeps(ctx.packageJson) : false) enabledPlugins["frontend-design@claude-plugins-official"] = true;
|
|
1566
1548
|
}
|
|
1567
1549
|
return {
|
|
1568
1550
|
permissions: {
|
|
@@ -1626,17 +1608,15 @@ function buildSettings(ctx) {
|
|
|
1626
1608
|
};
|
|
1627
1609
|
}
|
|
1628
1610
|
/** Remove enabledPlugins/extraKnownMarketplaces when empty to keep the file clean. */
|
|
1629
|
-
function serializeSettings(settings) {
|
|
1611
|
+
function serializeSettings$1(settings) {
|
|
1630
1612
|
const { enabledPlugins, extraKnownMarketplaces, ...rest } = settings;
|
|
1631
1613
|
const out = { ...rest };
|
|
1632
1614
|
if (Object.keys(enabledPlugins).length > 0) out["enabledPlugins"] = enabledPlugins;
|
|
1633
1615
|
if (Object.keys(extraKnownMarketplaces).length > 0) out["extraKnownMarketplaces"] = extraKnownMarketplaces;
|
|
1634
1616
|
return JSON.stringify(out, null, 2) + "\n";
|
|
1635
1617
|
}
|
|
1636
|
-
|
|
1637
|
-
const filePath = ".claude/settings.json";
|
|
1618
|
+
function writeOrMergeSettings(ctx, filePath, generated) {
|
|
1638
1619
|
const existing = ctx.read(filePath);
|
|
1639
|
-
const generated = buildSettings(ctx);
|
|
1640
1620
|
if (existing) {
|
|
1641
1621
|
const parsed = parseClaudeSettings(existing);
|
|
1642
1622
|
if (!parsed) return {
|
|
@@ -1660,21 +1640,39 @@ async function generateClaudeSettings(ctx) {
|
|
|
1660
1640
|
parsed.instructions = [...parsed.instructions, ...missingInstructions];
|
|
1661
1641
|
for (const [key, value] of missingPlugins) parsed.enabledPlugins[key] = value;
|
|
1662
1642
|
for (const [key, value] of missingMarketplaces) parsed.extraKnownMarketplaces[key] = value;
|
|
1663
|
-
ctx.write(filePath, serializeSettings(parsed));
|
|
1643
|
+
ctx.write(filePath, serializeSettings$1(parsed));
|
|
1664
1644
|
return {
|
|
1665
1645
|
filePath,
|
|
1666
1646
|
action: "updated",
|
|
1667
1647
|
description: `Added ${String(added)} rules/instructions`
|
|
1668
1648
|
};
|
|
1669
1649
|
}
|
|
1670
|
-
ctx.write(filePath, serializeSettings(generated));
|
|
1650
|
+
ctx.write(filePath, serializeSettings$1(generated));
|
|
1671
1651
|
return {
|
|
1672
1652
|
filePath,
|
|
1673
1653
|
action: "created",
|
|
1674
|
-
description:
|
|
1654
|
+
description: `Generated ${filePath}`
|
|
1675
1655
|
};
|
|
1676
1656
|
}
|
|
1677
|
-
|
|
1657
|
+
async function generateClaudeSettings(ctx) {
|
|
1658
|
+
const results = [];
|
|
1659
|
+
results.push(writeOrMergeSettings(ctx, ".claude/settings.json", buildSettings(ctx)));
|
|
1660
|
+
if (ctx.config.structure === "monorepo") for (const pkg of getMonorepoPackages(ctx.targetDir)) {
|
|
1661
|
+
if (!hasWebUIDeps(pkg.dir)) continue;
|
|
1662
|
+
const pkgRelDir = path.relative(ctx.targetDir, pkg.dir);
|
|
1663
|
+
const pkgSettingsPath = path.join(pkgRelDir, ".claude/settings.json");
|
|
1664
|
+
results.push(writeOrMergeSettings(ctx, pkgSettingsPath, {
|
|
1665
|
+
permissions: {
|
|
1666
|
+
allow: [],
|
|
1667
|
+
deny: []
|
|
1668
|
+
},
|
|
1669
|
+
instructions: [],
|
|
1670
|
+
enabledPlugins: { "frontend-design@claude-plugins-official": true },
|
|
1671
|
+
extraKnownMarketplaces: {}
|
|
1672
|
+
}));
|
|
1673
|
+
}
|
|
1674
|
+
return results;
|
|
1675
|
+
}
|
|
1678
1676
|
//#endregion
|
|
1679
1677
|
//#region src/generators/release-it.ts
|
|
1680
1678
|
function buildConfig$2(ci, isMonorepo) {
|
|
@@ -1726,7 +1724,6 @@ async function generateReleaseIt(ctx) {
|
|
|
1726
1724
|
description: "Generated .release-it.json"
|
|
1727
1725
|
};
|
|
1728
1726
|
}
|
|
1729
|
-
|
|
1730
1727
|
//#endregion
|
|
1731
1728
|
//#region src/generators/changesets.ts
|
|
1732
1729
|
function buildConfig$1() {
|
|
@@ -1763,7 +1760,6 @@ async function generateChangesets(ctx) {
|
|
|
1763
1760
|
description: "Generated .changeset/config.json"
|
|
1764
1761
|
};
|
|
1765
1762
|
}
|
|
1766
|
-
|
|
1767
1763
|
//#endregion
|
|
1768
1764
|
//#region src/generators/release-ci.ts
|
|
1769
1765
|
function hasEnginesNode(ctx) {
|
|
@@ -1933,7 +1929,6 @@ async function generateReleaseCi(ctx) {
|
|
|
1933
1929
|
description: `Generated ${isGitHub ? "GitHub" : "Forgejo"} Actions release workflow`
|
|
1934
1930
|
};
|
|
1935
1931
|
}
|
|
1936
|
-
|
|
1937
1932
|
//#endregion
|
|
1938
1933
|
//#region src/generators/lefthook.ts
|
|
1939
1934
|
function buildConfig(formatter) {
|
|
@@ -2062,7 +2057,149 @@ async function generateLefthook(ctx) {
|
|
|
2062
2057
|
});
|
|
2063
2058
|
return results;
|
|
2064
2059
|
}
|
|
2065
|
-
|
|
2060
|
+
//#endregion
|
|
2061
|
+
//#region src/generators/vscode-settings.ts
|
|
2062
|
+
const SCHEMA_NPM_PATH = "@bensandee/config/schemas/forgejo-workflow.schema.json";
|
|
2063
|
+
const SCHEMA_LOCAL_PATH = ".vscode/forgejo-workflow.schema.json";
|
|
2064
|
+
const SETTINGS_PATH = ".vscode/settings.json";
|
|
2065
|
+
const SCHEMA_GLOB = ".forgejo/workflows/*.yml";
|
|
2066
|
+
const VscodeSettingsSchema = z.object({ "yaml.schemas": z.record(z.string(), z.unknown()).default({}) }).passthrough();
|
|
2067
|
+
const FullWorkspaceFileSchema = z.object({ settings: z.record(z.string(), z.unknown()).default({}) }).passthrough();
|
|
2068
|
+
function readSchemaFromNodeModules(targetDir) {
|
|
2069
|
+
const candidate = path.join(targetDir, "node_modules", SCHEMA_NPM_PATH);
|
|
2070
|
+
if (!existsSync(candidate)) return void 0;
|
|
2071
|
+
return readFileSync(candidate, "utf-8");
|
|
2072
|
+
}
|
|
2073
|
+
/** Find a *.code-workspace file in the target directory. */
|
|
2074
|
+
function findWorkspaceFile(targetDir) {
|
|
2075
|
+
try {
|
|
2076
|
+
return readdirSync(targetDir).find((e) => e.endsWith(".code-workspace"));
|
|
2077
|
+
} catch {
|
|
2078
|
+
return;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
function serializeSettings(settings) {
|
|
2082
|
+
return JSON.stringify(settings, null, 2) + "\n";
|
|
2083
|
+
}
|
|
2084
|
+
const YamlSchemasSchema = z.record(z.string(), z.unknown());
|
|
2085
|
+
/** Merge yaml.schemas into a settings object. Returns the result and whether anything changed. */
|
|
2086
|
+
function mergeYamlSchemas(settings) {
|
|
2087
|
+
const parsed = YamlSchemasSchema.safeParse(settings["yaml.schemas"]);
|
|
2088
|
+
const yamlSchemas = parsed.success ? { ...parsed.data } : {};
|
|
2089
|
+
if (SCHEMA_LOCAL_PATH in yamlSchemas) return {
|
|
2090
|
+
merged: settings,
|
|
2091
|
+
changed: false
|
|
2092
|
+
};
|
|
2093
|
+
yamlSchemas[SCHEMA_LOCAL_PATH] = SCHEMA_GLOB;
|
|
2094
|
+
return {
|
|
2095
|
+
merged: {
|
|
2096
|
+
...settings,
|
|
2097
|
+
"yaml.schemas": yamlSchemas
|
|
2098
|
+
},
|
|
2099
|
+
changed: true
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
function writeSchemaToWorkspaceFile(ctx, wsFileName) {
|
|
2103
|
+
const raw = ctx.read(wsFileName);
|
|
2104
|
+
if (!raw) return {
|
|
2105
|
+
filePath: wsFileName,
|
|
2106
|
+
action: "skipped",
|
|
2107
|
+
description: "Could not read workspace file"
|
|
2108
|
+
};
|
|
2109
|
+
const fullParsed = FullWorkspaceFileSchema.safeParse(parse(raw));
|
|
2110
|
+
if (!fullParsed.success) return {
|
|
2111
|
+
filePath: wsFileName,
|
|
2112
|
+
action: "skipped",
|
|
2113
|
+
description: "Could not parse workspace file"
|
|
2114
|
+
};
|
|
2115
|
+
const { merged, changed } = mergeYamlSchemas(fullParsed.data.settings);
|
|
2116
|
+
if (!changed) return {
|
|
2117
|
+
filePath: wsFileName,
|
|
2118
|
+
action: "skipped",
|
|
2119
|
+
description: "Already has Forgejo schema mapping"
|
|
2120
|
+
};
|
|
2121
|
+
const updated = {
|
|
2122
|
+
...fullParsed.data,
|
|
2123
|
+
settings: merged
|
|
2124
|
+
};
|
|
2125
|
+
ctx.write(wsFileName, JSON.stringify(updated, null, 2) + "\n");
|
|
2126
|
+
return {
|
|
2127
|
+
filePath: wsFileName,
|
|
2128
|
+
action: "updated",
|
|
2129
|
+
description: "Added Forgejo workflow schema mapping to workspace settings"
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
function writeSchemaToSettings(ctx) {
|
|
2133
|
+
if (ctx.exists(SETTINGS_PATH)) {
|
|
2134
|
+
const raw = ctx.read(SETTINGS_PATH);
|
|
2135
|
+
if (!raw) return {
|
|
2136
|
+
filePath: SETTINGS_PATH,
|
|
2137
|
+
action: "skipped",
|
|
2138
|
+
description: "Could not read existing settings"
|
|
2139
|
+
};
|
|
2140
|
+
const parsed = VscodeSettingsSchema.safeParse(parse(raw));
|
|
2141
|
+
if (!parsed.success) return {
|
|
2142
|
+
filePath: SETTINGS_PATH,
|
|
2143
|
+
action: "skipped",
|
|
2144
|
+
description: "Could not parse existing settings"
|
|
2145
|
+
};
|
|
2146
|
+
const { merged, changed } = mergeYamlSchemas(parsed.data);
|
|
2147
|
+
if (!changed) return {
|
|
2148
|
+
filePath: SETTINGS_PATH,
|
|
2149
|
+
action: "skipped",
|
|
2150
|
+
description: "Already has Forgejo schema mapping"
|
|
2151
|
+
};
|
|
2152
|
+
ctx.write(SETTINGS_PATH, serializeSettings(merged));
|
|
2153
|
+
return {
|
|
2154
|
+
filePath: SETTINGS_PATH,
|
|
2155
|
+
action: "updated",
|
|
2156
|
+
description: "Added Forgejo workflow schema mapping"
|
|
2157
|
+
};
|
|
2158
|
+
}
|
|
2159
|
+
ctx.write(SETTINGS_PATH, serializeSettings({ "yaml.schemas": { [SCHEMA_LOCAL_PATH]: SCHEMA_GLOB } }));
|
|
2160
|
+
return {
|
|
2161
|
+
filePath: SETTINGS_PATH,
|
|
2162
|
+
action: "created",
|
|
2163
|
+
description: "Generated .vscode/settings.json with Forgejo workflow schema"
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
async function generateVscodeSettings(ctx) {
|
|
2167
|
+
const results = [];
|
|
2168
|
+
if (ctx.config.ci !== "forgejo") {
|
|
2169
|
+
results.push({
|
|
2170
|
+
filePath: SETTINGS_PATH,
|
|
2171
|
+
action: "skipped",
|
|
2172
|
+
description: "Not a Forgejo project"
|
|
2173
|
+
});
|
|
2174
|
+
return results;
|
|
2175
|
+
}
|
|
2176
|
+
const schemaContent = readSchemaFromNodeModules(ctx.targetDir);
|
|
2177
|
+
if (!schemaContent) {
|
|
2178
|
+
results.push({
|
|
2179
|
+
filePath: SCHEMA_LOCAL_PATH,
|
|
2180
|
+
action: "skipped",
|
|
2181
|
+
description: "Could not find @bensandee/config schema in node_modules"
|
|
2182
|
+
});
|
|
2183
|
+
return results;
|
|
2184
|
+
}
|
|
2185
|
+
const existingSchema = ctx.read(SCHEMA_LOCAL_PATH);
|
|
2186
|
+
if (existingSchema === schemaContent) results.push({
|
|
2187
|
+
filePath: SCHEMA_LOCAL_PATH,
|
|
2188
|
+
action: "skipped",
|
|
2189
|
+
description: "Schema already up to date"
|
|
2190
|
+
});
|
|
2191
|
+
else {
|
|
2192
|
+
ctx.write(SCHEMA_LOCAL_PATH, schemaContent);
|
|
2193
|
+
results.push({
|
|
2194
|
+
filePath: SCHEMA_LOCAL_PATH,
|
|
2195
|
+
action: existingSchema ? "updated" : "created",
|
|
2196
|
+
description: "Copied Forgejo workflow schema from @bensandee/config"
|
|
2197
|
+
});
|
|
2198
|
+
}
|
|
2199
|
+
const wsFile = findWorkspaceFile(ctx.targetDir);
|
|
2200
|
+
results.push(wsFile ? writeSchemaToWorkspaceFile(ctx, wsFile) : writeSchemaToSettings(ctx));
|
|
2201
|
+
return results;
|
|
2202
|
+
}
|
|
2066
2203
|
//#endregion
|
|
2067
2204
|
//#region src/generators/pipeline.ts
|
|
2068
2205
|
/** Run all generators sequentially and return their results. */
|
|
@@ -2079,14 +2216,14 @@ async function runGenerators(ctx) {
|
|
|
2079
2216
|
results.push(await generateKnip(ctx));
|
|
2080
2217
|
results.push(await generateRenovate(ctx));
|
|
2081
2218
|
results.push(await generateCi(ctx));
|
|
2082
|
-
results.push(await generateClaudeSettings(ctx));
|
|
2219
|
+
results.push(...await generateClaudeSettings(ctx));
|
|
2083
2220
|
results.push(await generateReleaseIt(ctx));
|
|
2084
2221
|
results.push(await generateChangesets(ctx));
|
|
2085
2222
|
results.push(await generateReleaseCi(ctx));
|
|
2086
2223
|
results.push(...await generateVitest(ctx));
|
|
2224
|
+
results.push(...await generateVscodeSettings(ctx));
|
|
2087
2225
|
return results;
|
|
2088
2226
|
}
|
|
2089
|
-
|
|
2090
2227
|
//#endregion
|
|
2091
2228
|
//#region src/utils/tooling-config.ts
|
|
2092
2229
|
const CONFIG_FILE = ".tooling.json";
|
|
@@ -2141,11 +2278,16 @@ function saveToolingConfig(ctx, config) {
|
|
|
2141
2278
|
detectPackageTypes: config.detectPackageTypes
|
|
2142
2279
|
};
|
|
2143
2280
|
const content = JSON.stringify(saved, null, 2) + "\n";
|
|
2144
|
-
const
|
|
2281
|
+
const existing = ctx.exists(CONFIG_FILE) ? ctx.read(CONFIG_FILE) : void 0;
|
|
2282
|
+
if (existing === content) return {
|
|
2283
|
+
filePath: CONFIG_FILE,
|
|
2284
|
+
action: "skipped",
|
|
2285
|
+
description: "Already up to date"
|
|
2286
|
+
};
|
|
2145
2287
|
ctx.write(CONFIG_FILE, content);
|
|
2146
2288
|
return {
|
|
2147
2289
|
filePath: CONFIG_FILE,
|
|
2148
|
-
action:
|
|
2290
|
+
action: existing ? "updated" : "created",
|
|
2149
2291
|
description: "Saved tooling configuration"
|
|
2150
2292
|
};
|
|
2151
2293
|
}
|
|
@@ -2166,7 +2308,6 @@ function mergeWithSavedConfig(detected, saved) {
|
|
|
2166
2308
|
detectPackageTypes: saved.detectPackageTypes ?? detected.detectPackageTypes
|
|
2167
2309
|
};
|
|
2168
2310
|
}
|
|
2169
|
-
|
|
2170
2311
|
//#endregion
|
|
2171
2312
|
//#region src/commands/repo-init.ts
|
|
2172
2313
|
const initCommand = defineCommand({
|
|
@@ -2238,6 +2379,14 @@ async function runInit(config, options = {}) {
|
|
|
2238
2379
|
action: "archived",
|
|
2239
2380
|
description: `Original saved to .tooling-archived/${rel}`
|
|
2240
2381
|
});
|
|
2382
|
+
const created = results.filter((r) => r.action === "created");
|
|
2383
|
+
const updated = results.filter((r) => r.action === "updated");
|
|
2384
|
+
const skipped = results.filter((r) => r.action === "skipped");
|
|
2385
|
+
const archived = results.filter((r) => r.action === "archived");
|
|
2386
|
+
if (!(created.length > 0 || updated.length > 0 || archived.length > 0) && options.noPrompt) {
|
|
2387
|
+
s.stop("Repository is up to date.");
|
|
2388
|
+
return results;
|
|
2389
|
+
}
|
|
2241
2390
|
s.stop("Done!");
|
|
2242
2391
|
if (results.some((r) => r.action === "archived" && r.filePath.startsWith(".husky/"))) try {
|
|
2243
2392
|
execSync("git config --unset core.hooksPath", {
|
|
@@ -2245,10 +2394,6 @@ async function runInit(config, options = {}) {
|
|
|
2245
2394
|
stdio: "ignore"
|
|
2246
2395
|
});
|
|
2247
2396
|
} catch (_error) {}
|
|
2248
|
-
const created = results.filter((r) => r.action === "created");
|
|
2249
|
-
const updated = results.filter((r) => r.action === "updated");
|
|
2250
|
-
const skipped = results.filter((r) => r.action === "skipped");
|
|
2251
|
-
const archived = results.filter((r) => r.action === "archived");
|
|
2252
2397
|
const summaryLines = [];
|
|
2253
2398
|
if (created.length > 0) summaryLines.push(`Created: ${created.map((r) => r.filePath).join(", ")}`);
|
|
2254
2399
|
if (updated.length > 0) summaryLines.push(`Updated: ${updated.map((r) => r.filePath).join(", ")}`);
|
|
@@ -2260,7 +2405,7 @@ async function runInit(config, options = {}) {
|
|
|
2260
2405
|
const promptPath = ".tooling-migrate.md";
|
|
2261
2406
|
ctx.write(promptPath, prompt);
|
|
2262
2407
|
p.log.info(`Migration prompt written to ${promptPath}`);
|
|
2263
|
-
p.log.info("
|
|
2408
|
+
p.log.info("In Claude Code, run: \"Execute the steps in .tooling-migrate.md\"");
|
|
2264
2409
|
}
|
|
2265
2410
|
const bensandeeDeps = getAddedDevDepNames(config).filter((name) => name.startsWith("@bensandee/"));
|
|
2266
2411
|
const hasLockfile = ctx.exists("pnpm-lock.yaml");
|
|
@@ -2281,11 +2426,10 @@ async function runInit(config, options = {}) {
|
|
|
2281
2426
|
"2. Run: pnpm typecheck",
|
|
2282
2427
|
"3. Run: pnpm build",
|
|
2283
2428
|
"4. Run: pnpm test",
|
|
2284
|
-
...options.noPrompt ? [] : ["5.
|
|
2429
|
+
...options.noPrompt ? [] : ["5. In Claude Code, run: \"Execute the steps in .tooling-migrate.md\""]
|
|
2285
2430
|
].join("\n"), "Next steps");
|
|
2286
2431
|
return results;
|
|
2287
2432
|
}
|
|
2288
|
-
|
|
2289
2433
|
//#endregion
|
|
2290
2434
|
//#region src/commands/repo-update.ts
|
|
2291
2435
|
const updateCommand = defineCommand({
|
|
@@ -2304,14 +2448,16 @@ const updateCommand = defineCommand({
|
|
|
2304
2448
|
});
|
|
2305
2449
|
async function runUpdate(targetDir) {
|
|
2306
2450
|
const saved = loadToolingConfig(targetDir);
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2451
|
+
if (!saved) {
|
|
2452
|
+
p.log.error("No .tooling.json found. Run `tooling repo:init` first to initialize the project.");
|
|
2453
|
+
process.exitCode = 1;
|
|
2454
|
+
return [];
|
|
2455
|
+
}
|
|
2456
|
+
return runInit(mergeWithSavedConfig(buildDefaultConfig(targetDir, {}), saved), {
|
|
2310
2457
|
noPrompt: true,
|
|
2311
2458
|
confirmOverwrite: async () => "overwrite"
|
|
2312
2459
|
});
|
|
2313
2460
|
}
|
|
2314
|
-
|
|
2315
2461
|
//#endregion
|
|
2316
2462
|
//#region src/commands/repo-check.ts
|
|
2317
2463
|
const checkCommand = defineCommand({
|
|
@@ -2331,9 +2477,11 @@ const checkCommand = defineCommand({
|
|
|
2331
2477
|
});
|
|
2332
2478
|
async function runCheck(targetDir) {
|
|
2333
2479
|
const saved = loadToolingConfig(targetDir);
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2480
|
+
if (!saved) {
|
|
2481
|
+
p.log.error("No .tooling.json found. Run `tooling repo:init` first to initialize the project.");
|
|
2482
|
+
return 1;
|
|
2483
|
+
}
|
|
2484
|
+
const { ctx, pendingWrites } = createDryRunContext(mergeWithSavedConfig(buildDefaultConfig(targetDir, {}), saved));
|
|
2337
2485
|
const actionable = (await runGenerators(ctx)).filter((r) => r.action === "created" || r.action === "updated");
|
|
2338
2486
|
if (actionable.length === 0) {
|
|
2339
2487
|
p.log.success("Repository is up to date.");
|
|
@@ -2370,14 +2518,12 @@ function lineDiff(oldText, newText) {
|
|
|
2370
2518
|
for (const l of added) lines.push(`+ ${l.trim()}`);
|
|
2371
2519
|
return lines;
|
|
2372
2520
|
}
|
|
2373
|
-
|
|
2374
2521
|
//#endregion
|
|
2375
2522
|
//#region src/utils/exec.ts
|
|
2376
2523
|
/** Type guard for `execSync` errors that carry stdout/stderr/status. */
|
|
2377
2524
|
function isExecSyncError(err) {
|
|
2378
2525
|
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";
|
|
2379
2526
|
}
|
|
2380
|
-
|
|
2381
2527
|
//#endregion
|
|
2382
2528
|
//#region src/release/executor.ts
|
|
2383
2529
|
/** Create an executor that runs real commands, fetches, and reads the filesystem. */
|
|
@@ -2488,18 +2634,25 @@ function reconcileTags(expectedTags, remoteTags, stdoutTags) {
|
|
|
2488
2634
|
for (const tag of stdoutTags) result.add(tag);
|
|
2489
2635
|
return [...result];
|
|
2490
2636
|
}
|
|
2491
|
-
|
|
2492
2637
|
//#endregion
|
|
2493
2638
|
//#region src/release/forgejo.ts
|
|
2494
|
-
const PullRequestSchema = z.array(z.object({
|
|
2495
|
-
|
|
2639
|
+
const PullRequestSchema = z.array(z.object({
|
|
2640
|
+
number: z.number(),
|
|
2641
|
+
head: z.object({ ref: z.string() })
|
|
2642
|
+
}));
|
|
2643
|
+
/**
|
|
2644
|
+
* Find an open PR with the given head branch. Returns the PR number or null.
|
|
2645
|
+
*
|
|
2646
|
+
* Fetches all open PRs and filters client-side by head.ref rather than relying
|
|
2647
|
+
* on Forgejo's query parameter filtering, which behaves inconsistently.
|
|
2648
|
+
*/
|
|
2496
2649
|
async function findOpenPr(executor, conn, head) {
|
|
2497
|
-
const url = `${conn.serverUrl}/api/v1/repos/${conn.repository}/pulls?state=open
|
|
2650
|
+
const url = `${conn.serverUrl}/api/v1/repos/${conn.repository}/pulls?state=open`;
|
|
2498
2651
|
const res = await executor.fetch(url, { headers: { Authorization: `token ${conn.token}` } });
|
|
2499
2652
|
if (!res.ok) throw new TransientError(`Failed to list PRs: ${res.status} ${res.statusText}`);
|
|
2500
2653
|
const parsed = PullRequestSchema.safeParse(await res.json());
|
|
2501
2654
|
if (!parsed.success) throw new UnexpectedError(`Unexpected PR list response: ${parsed.error.message}`);
|
|
2502
|
-
return parsed.data
|
|
2655
|
+
return parsed.data.find((pr) => pr.head.ref === head)?.number ?? null;
|
|
2503
2656
|
}
|
|
2504
2657
|
/** Create a new pull request. */
|
|
2505
2658
|
async function createPr(executor, conn, options) {
|
|
@@ -2578,7 +2731,6 @@ async function createRelease(executor, conn, tag) {
|
|
|
2578
2731
|
});
|
|
2579
2732
|
if (!res.ok) throw new TransientError(`Failed to create release for ${tag}: ${res.status} ${res.statusText}`);
|
|
2580
2733
|
}
|
|
2581
|
-
|
|
2582
2734
|
//#endregion
|
|
2583
2735
|
//#region src/release/log.ts
|
|
2584
2736
|
/** Log a debug message when verbose mode is enabled. */
|
|
@@ -2593,7 +2745,6 @@ function debugExec(config, label, result) {
|
|
|
2593
2745
|
if (result.stderr.trim()) lines.push(` stderr: ${result.stderr.trim()}`);
|
|
2594
2746
|
p.log.info(lines.join("\n"));
|
|
2595
2747
|
}
|
|
2596
|
-
|
|
2597
2748
|
//#endregion
|
|
2598
2749
|
//#region src/release/version.ts
|
|
2599
2750
|
const BRANCH = "changeset-release/main";
|
|
@@ -2738,7 +2889,6 @@ async function runVersionMode(executor, config) {
|
|
|
2738
2889
|
pr: "updated"
|
|
2739
2890
|
};
|
|
2740
2891
|
}
|
|
2741
|
-
|
|
2742
2892
|
//#endregion
|
|
2743
2893
|
//#region src/release/publish.ts
|
|
2744
2894
|
const RETRY_ATTEMPTS = 3;
|
|
@@ -2828,7 +2978,6 @@ async function runPublishMode(executor, config) {
|
|
|
2828
2978
|
tags: allTags
|
|
2829
2979
|
};
|
|
2830
2980
|
}
|
|
2831
|
-
|
|
2832
2981
|
//#endregion
|
|
2833
2982
|
//#region src/release/connection.ts
|
|
2834
2983
|
const RepositorySchema = z.union([z.string(), z.object({ url: z.string() })]);
|
|
@@ -2902,7 +3051,6 @@ function parseGitUrl(urlStr) {
|
|
|
2902
3051
|
return null;
|
|
2903
3052
|
}
|
|
2904
3053
|
}
|
|
2905
|
-
|
|
2906
3054
|
//#endregion
|
|
2907
3055
|
//#region src/commands/release-changesets.ts
|
|
2908
3056
|
const releaseForgejoCommand = defineCommand({
|
|
@@ -2949,7 +3097,6 @@ async function runRelease(config, executor) {
|
|
|
2949
3097
|
debug(config, "Entering publish mode");
|
|
2950
3098
|
return runPublishMode(executor, config);
|
|
2951
3099
|
}
|
|
2952
|
-
|
|
2953
3100
|
//#endregion
|
|
2954
3101
|
//#region src/commands/release-trigger.ts
|
|
2955
3102
|
const releaseTriggerCommand = defineCommand({
|
|
@@ -2986,7 +3133,6 @@ function triggerGitHub(ref) {
|
|
|
2986
3133
|
createRealExecutor().exec(`gh workflow run release.yml --ref ${ref}`, { cwd: process.cwd() });
|
|
2987
3134
|
p.log.info(`Triggered release workflow on GitHub (ref: ${ref})`);
|
|
2988
3135
|
}
|
|
2989
|
-
|
|
2990
3136
|
//#endregion
|
|
2991
3137
|
//#region src/commands/release-create-forgejo-release.ts
|
|
2992
3138
|
const createForgejoReleaseCommand = defineCommand({
|
|
@@ -3012,7 +3158,6 @@ const createForgejoReleaseCommand = defineCommand({
|
|
|
3012
3158
|
p.log.info(`Created Forgejo release for ${args.tag}`);
|
|
3013
3159
|
}
|
|
3014
3160
|
});
|
|
3015
|
-
|
|
3016
3161
|
//#endregion
|
|
3017
3162
|
//#region src/commands/release-merge.ts
|
|
3018
3163
|
const HEAD_BRANCH = "changeset-release/main";
|
|
@@ -3057,13 +3202,12 @@ function mergeGitHub(dryRun) {
|
|
|
3057
3202
|
executor.exec(`gh pr merge ${HEAD_BRANCH} --merge --delete-branch`, { cwd: process.cwd() });
|
|
3058
3203
|
p.log.info(`Merged changesets PR and deleted branch ${HEAD_BRANCH}`);
|
|
3059
3204
|
}
|
|
3060
|
-
|
|
3061
3205
|
//#endregion
|
|
3062
3206
|
//#region src/bin.ts
|
|
3063
3207
|
const main = defineCommand({
|
|
3064
3208
|
meta: {
|
|
3065
3209
|
name: "tooling",
|
|
3066
|
-
version: "0.
|
|
3210
|
+
version: "0.9.0",
|
|
3067
3211
|
description: "Bootstrap and maintain standardized TypeScript project tooling"
|
|
3068
3212
|
},
|
|
3069
3213
|
subCommands: {
|
|
@@ -3076,8 +3220,7 @@ const main = defineCommand({
|
|
|
3076
3220
|
"release:merge": releaseMergeCommand
|
|
3077
3221
|
}
|
|
3078
3222
|
});
|
|
3079
|
-
console.log(`@bensandee/tooling v0.
|
|
3223
|
+
console.log(`@bensandee/tooling v0.9.0`);
|
|
3080
3224
|
runMain(main);
|
|
3081
|
-
|
|
3082
3225
|
//#endregion
|
|
3083
|
-
export {
|
|
3226
|
+
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.9.0",
|
|
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.1"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsdown",
|