@bensandee/tooling 0.7.0 → 0.7.2
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 +122 -54
- package/package.json +2 -2
package/dist/bin.mjs
CHANGED
|
@@ -64,6 +64,16 @@ function parseRenovateJson(raw) {
|
|
|
64
64
|
return {};
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
+
const ChangesetConfigSchema = z.object({ commit: z.union([z.boolean(), z.string()]).optional() }).loose();
|
|
68
|
+
/** Parse a JSON string as a .changeset/config.json. Returns `undefined` on failure. */
|
|
69
|
+
function parseChangesetConfig(raw) {
|
|
70
|
+
try {
|
|
71
|
+
const result = ChangesetConfigSchema.safeParse(JSON.parse(raw));
|
|
72
|
+
return result.success ? result.data : void 0;
|
|
73
|
+
} catch {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
67
77
|
/** Parse a JSON string as a package.json. Returns `undefined` on failure. */
|
|
68
78
|
function parsePackageJson(raw) {
|
|
69
79
|
try {
|
|
@@ -519,7 +529,6 @@ function addReleaseDeps(deps, config) {
|
|
|
519
529
|
case "release-it":
|
|
520
530
|
deps["release-it"] = "18.1.2";
|
|
521
531
|
if (config.structure === "monorepo") deps["@release-it/bumper"] = "7.0.2";
|
|
522
|
-
if (config.ci === "forgejo") deps["@bensandee/release-it-forgejo"] = "0.1.1";
|
|
523
532
|
break;
|
|
524
533
|
case "commit-and-tag-version":
|
|
525
534
|
deps["commit-and-tag-version"] = "12.5.0";
|
|
@@ -582,6 +591,9 @@ async function generatePackageJson(ctx) {
|
|
|
582
591
|
for (const [key, value] of Object.entries(devDeps)) if (!(key in existingDevDeps)) {
|
|
583
592
|
existingDevDeps[key] = value;
|
|
584
593
|
changes.push(`added devDependency: ${key}`);
|
|
594
|
+
} else if (key.startsWith("@bensandee/") && value === "latest" && existingDevDeps[key] !== "latest" && existingDevDeps[key] !== "workspace:*") {
|
|
595
|
+
existingDevDeps[key] = "latest";
|
|
596
|
+
changes.push(`updated devDependency: ${key} to latest`);
|
|
585
597
|
}
|
|
586
598
|
pkg.devDependencies = existingDevDeps;
|
|
587
599
|
if (!pkg["engines"]) {
|
|
@@ -793,47 +805,81 @@ async function generateTsconfig(ctx) {
|
|
|
793
805
|
const existing = ctx.read(filePath);
|
|
794
806
|
if (ctx.config.structure === "monorepo") return [generateMonorepoRootTsconfig(ctx, existing), ...ctx.config.detectPackageTypes ? generateMonorepoPackageTsconfigs(ctx) : []];
|
|
795
807
|
const extendsValue = `@bensandee/config/tsconfig/${ctx.config.projectType}`;
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
808
|
+
if (!existing) {
|
|
809
|
+
const config = {
|
|
810
|
+
extends: extendsValue,
|
|
811
|
+
include: ["src"],
|
|
812
|
+
exclude: ["node_modules", "dist"]
|
|
813
|
+
};
|
|
814
|
+
ctx.write(filePath, JSON.stringify(config, null, 2) + "\n");
|
|
815
|
+
return [{
|
|
803
816
|
filePath,
|
|
804
|
-
action: "
|
|
805
|
-
description:
|
|
817
|
+
action: "created",
|
|
818
|
+
description: `Generated tsconfig.json with ${extendsValue}`
|
|
806
819
|
}];
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
changes.push(`added "${entry}" to include`);
|
|
817
|
-
}
|
|
818
|
-
parsed.include = existingInclude;
|
|
819
|
-
if (changes.length === 0) return [{
|
|
820
|
+
}
|
|
821
|
+
if (existing.includes("// @bensandee/tooling:ignore")) return [{
|
|
822
|
+
filePath,
|
|
823
|
+
action: "skipped",
|
|
824
|
+
description: "Ignored via tooling:ignore comment"
|
|
825
|
+
}];
|
|
826
|
+
const parsed = parseTsconfig(existing);
|
|
827
|
+
if (isSolutionStyle(parsed)) {
|
|
828
|
+
const results = [{
|
|
820
829
|
filePath,
|
|
821
830
|
action: "skipped",
|
|
822
|
-
description: "
|
|
823
|
-
}];
|
|
824
|
-
ctx.write(filePath, JSON.stringify(parsed, null, 2) + "\n");
|
|
825
|
-
return [{
|
|
826
|
-
filePath,
|
|
827
|
-
action: "updated",
|
|
828
|
-
description: changes.join(", ")
|
|
831
|
+
description: "Solution-style tsconfig — traversing references"
|
|
829
832
|
}];
|
|
833
|
+
for (const ref of parsed.references ?? []) {
|
|
834
|
+
const refPath = resolveReferencePath(ref.path);
|
|
835
|
+
results.push(mergeSingleTsconfig(ctx, refPath, extendsValue));
|
|
836
|
+
}
|
|
837
|
+
return results;
|
|
838
|
+
}
|
|
839
|
+
return [mergeSingleTsconfig(ctx, filePath, extendsValue)];
|
|
840
|
+
}
|
|
841
|
+
function isSolutionStyle(parsed) {
|
|
842
|
+
return Array.isArray(parsed.references) && parsed.references.length > 0 && Array.isArray(parsed.files) && parsed.files.length === 0;
|
|
843
|
+
}
|
|
844
|
+
function resolveReferencePath(refPath) {
|
|
845
|
+
const resolved = refPath.endsWith(".json") ? refPath : path.join(refPath, "tsconfig.json");
|
|
846
|
+
return path.normalize(resolved);
|
|
847
|
+
}
|
|
848
|
+
function mergeSingleTsconfig(ctx, filePath, extendsValue) {
|
|
849
|
+
const existing = ctx.read(filePath);
|
|
850
|
+
if (!existing) return {
|
|
851
|
+
filePath,
|
|
852
|
+
action: "skipped",
|
|
853
|
+
description: "File not found"
|
|
854
|
+
};
|
|
855
|
+
if (existing.includes("// @bensandee/tooling:ignore")) return {
|
|
856
|
+
filePath,
|
|
857
|
+
action: "skipped",
|
|
858
|
+
description: "Ignored via tooling:ignore comment"
|
|
859
|
+
};
|
|
860
|
+
const parsed = parseTsconfig(existing);
|
|
861
|
+
const changes = [];
|
|
862
|
+
if (!parsed.extends) {
|
|
863
|
+
parsed.extends = extendsValue;
|
|
864
|
+
changes.push(`added extends: ${extendsValue}`);
|
|
830
865
|
}
|
|
831
|
-
|
|
832
|
-
|
|
866
|
+
const existingInclude = parsed.include ?? [];
|
|
867
|
+
if (!existingInclude.includes("src")) {
|
|
868
|
+
existingInclude.push("src");
|
|
869
|
+
changes.push("added \"src\" to include");
|
|
870
|
+
}
|
|
871
|
+
parsed.include = existingInclude;
|
|
872
|
+
if (changes.length === 0) return {
|
|
833
873
|
filePath,
|
|
834
|
-
action: "
|
|
835
|
-
description:
|
|
836
|
-
}
|
|
874
|
+
action: "skipped",
|
|
875
|
+
description: "Already up to spec"
|
|
876
|
+
};
|
|
877
|
+
ctx.write(filePath, JSON.stringify(parsed, null, 2) + "\n");
|
|
878
|
+
return {
|
|
879
|
+
filePath,
|
|
880
|
+
action: "updated",
|
|
881
|
+
description: changes.join(", ")
|
|
882
|
+
};
|
|
837
883
|
}
|
|
838
884
|
function generateMonorepoRootTsconfig(ctx, existing) {
|
|
839
885
|
const filePath = "tsconfig.json";
|
|
@@ -855,14 +901,10 @@ function generateMonorepoRootTsconfig(ctx, existing) {
|
|
|
855
901
|
description: "Already has project references"
|
|
856
902
|
};
|
|
857
903
|
}
|
|
858
|
-
ctx.write(filePath, JSON.stringify({
|
|
859
|
-
files: [],
|
|
860
|
-
references: []
|
|
861
|
-
}, null, 2) + "\n");
|
|
862
904
|
return {
|
|
863
905
|
filePath,
|
|
864
|
-
action: "
|
|
865
|
-
description: "
|
|
906
|
+
action: "skipped",
|
|
907
|
+
description: "No tsconfig.json found"
|
|
866
908
|
};
|
|
867
909
|
}
|
|
868
910
|
function generateMonorepoPackageTsconfigs(ctx) {
|
|
@@ -884,6 +926,18 @@ function generateMonorepoPackageTsconfigs(ctx) {
|
|
|
884
926
|
continue;
|
|
885
927
|
}
|
|
886
928
|
const parsed = parseTsconfig(existing);
|
|
929
|
+
if (isSolutionStyle(parsed)) {
|
|
930
|
+
results.push({
|
|
931
|
+
filePath,
|
|
932
|
+
action: "skipped",
|
|
933
|
+
description: "Solution-style tsconfig — traversing references"
|
|
934
|
+
});
|
|
935
|
+
for (const ref of parsed.references ?? []) {
|
|
936
|
+
const refPath = path.join(relDir, resolveReferencePath(ref.path));
|
|
937
|
+
results.push(mergeSingleTsconfig(ctx, refPath, extendsValue));
|
|
938
|
+
}
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
887
941
|
const changes = [];
|
|
888
942
|
if (parsed.extends !== extendsValue) {
|
|
889
943
|
const prev = parsed.extends;
|
|
@@ -1542,7 +1596,6 @@ function buildConfig$2(ci, isMonorepo) {
|
|
|
1542
1596
|
};
|
|
1543
1597
|
if (ci === "github") config["github"] = { release: true };
|
|
1544
1598
|
const plugins = {};
|
|
1545
|
-
if (ci === "forgejo") plugins["@bensandee/release-it-forgejo"] = { release: true };
|
|
1546
1599
|
if (isMonorepo) {
|
|
1547
1600
|
config["npm"] = {
|
|
1548
1601
|
publish: true,
|
|
@@ -2117,14 +2170,26 @@ async function runInit(config, options = {}) {
|
|
|
2117
2170
|
p.log.info(`Migration prompt written to ${promptPath}`);
|
|
2118
2171
|
p.log.info("Paste its contents into Claude Code to finish the migration.");
|
|
2119
2172
|
}
|
|
2120
|
-
const
|
|
2173
|
+
const bensandeeDeps = getAddedDevDepNames(config).filter((name) => name.startsWith("@bensandee/"));
|
|
2174
|
+
const hasLockfile = ctx.exists("pnpm-lock.yaml");
|
|
2175
|
+
if (bensandeeDeps.length > 0 && hasLockfile) {
|
|
2176
|
+
s.start("Updating @bensandee/* packages...");
|
|
2177
|
+
try {
|
|
2178
|
+
execSync(`pnpm update --latest ${bensandeeDeps.join(" ")}`, {
|
|
2179
|
+
cwd: config.targetDir,
|
|
2180
|
+
stdio: "ignore"
|
|
2181
|
+
});
|
|
2182
|
+
s.stop("Updated @bensandee/* packages");
|
|
2183
|
+
} catch (_error) {
|
|
2184
|
+
s.stop("Could not update @bensandee/* packages — run pnpm install first");
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2121
2187
|
p.note([
|
|
2122
2188
|
"1. Run: pnpm install",
|
|
2123
|
-
|
|
2124
|
-
"3. Run: pnpm
|
|
2125
|
-
"4. Run: pnpm
|
|
2126
|
-
"5.
|
|
2127
|
-
...options.noPrompt ? [] : ["6. Paste .tooling-migrate.md into Claude Code for cleanup"]
|
|
2189
|
+
"2. Run: pnpm typecheck",
|
|
2190
|
+
"3. Run: pnpm build",
|
|
2191
|
+
"4. Run: pnpm test",
|
|
2192
|
+
...options.noPrompt ? [] : ["5. Paste .tooling-migrate.md into Claude Code for cleanup"]
|
|
2128
2193
|
].join("\n"), "Next steps");
|
|
2129
2194
|
return results;
|
|
2130
2195
|
}
|
|
@@ -2513,10 +2578,13 @@ async function runVersionMode(executor, config) {
|
|
|
2513
2578
|
const changesetConfigPath = path.join(config.cwd, ".changeset", "config.json");
|
|
2514
2579
|
const originalConfig = executor.readFile(changesetConfigPath);
|
|
2515
2580
|
if (originalConfig) {
|
|
2516
|
-
const parsed =
|
|
2517
|
-
if (parsed
|
|
2518
|
-
|
|
2519
|
-
|
|
2581
|
+
const parsed = parseChangesetConfig(originalConfig);
|
|
2582
|
+
if (parsed?.commit) {
|
|
2583
|
+
const patched = {
|
|
2584
|
+
...parsed,
|
|
2585
|
+
commit: false
|
|
2586
|
+
};
|
|
2587
|
+
executor.writeFile(changesetConfigPath, JSON.stringify(patched, null, 2) + "\n");
|
|
2520
2588
|
debug(config, "Temporarily disabled changeset commit:true");
|
|
2521
2589
|
}
|
|
2522
2590
|
}
|
|
@@ -2903,7 +2971,7 @@ function mergeGitHub(dryRun) {
|
|
|
2903
2971
|
const main = defineCommand({
|
|
2904
2972
|
meta: {
|
|
2905
2973
|
name: "tooling",
|
|
2906
|
-
version: "0.7.
|
|
2974
|
+
version: "0.7.2",
|
|
2907
2975
|
description: "Bootstrap and maintain standardized TypeScript project tooling"
|
|
2908
2976
|
},
|
|
2909
2977
|
subCommands: {
|
|
@@ -2916,7 +2984,7 @@ const main = defineCommand({
|
|
|
2916
2984
|
"release:merge": releaseMergeCommand
|
|
2917
2985
|
}
|
|
2918
2986
|
});
|
|
2919
|
-
console.log(`@bensandee/tooling v0.7.
|
|
2987
|
+
console.log(`@bensandee/tooling v0.7.2`);
|
|
2920
2988
|
runMain(main);
|
|
2921
2989
|
|
|
2922
2990
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bensandee/tooling",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "CLI tool to bootstrap and maintain standardized TypeScript project tooling",
|
|
5
5
|
"bin": {
|
|
6
6
|
"tooling": "./dist/bin.mjs"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"tsdown": "0.20.3",
|
|
34
34
|
"typescript": "5.9.3",
|
|
35
35
|
"vitest": "4.0.18",
|
|
36
|
-
"@bensandee/config": "0.6.
|
|
36
|
+
"@bensandee/config": "0.6.3"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsdown",
|