@bensandee/tooling 0.40.4 → 0.40.5
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 +81 -14
- package/package.json +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -1549,7 +1549,7 @@ async function generatePackageJson(ctx) {
|
|
|
1549
1549
|
const devDeps = { ...ROOT_DEV_DEPS };
|
|
1550
1550
|
if (!isMonorepo) Object.assign(devDeps, PER_PACKAGE_DEV_DEPS);
|
|
1551
1551
|
devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "0.10.0";
|
|
1552
|
-
devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.40.
|
|
1552
|
+
devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.40.5";
|
|
1553
1553
|
if (ctx.config.useEslintPlugin) devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "0.12.0";
|
|
1554
1554
|
if (ctx.config.formatter === "oxfmt") devDeps["oxfmt"] = {
|
|
1555
1555
|
"@changesets/cli": "2.30.0",
|
|
@@ -1912,32 +1912,54 @@ async function generateVitest(ctx) {
|
|
|
1912
1912
|
}
|
|
1913
1913
|
//#endregion
|
|
1914
1914
|
//#region src/generators/oxlint.ts
|
|
1915
|
+
const IGNORE_PATTERNS_SPREAD = "...(recommended.ignorePatterns ?? [])";
|
|
1915
1916
|
const CONFIG_WITH_LINT_RULES = `import recommended from "@bensandee/config/oxlint/recommended";
|
|
1916
1917
|
import { defineConfig } from "oxlint";
|
|
1917
1918
|
|
|
1918
1919
|
export default defineConfig({
|
|
1919
1920
|
extends: [recommended],
|
|
1920
|
-
ignorePatterns: [
|
|
1921
|
+
ignorePatterns: [${IGNORE_PATTERNS_SPREAD}],
|
|
1921
1922
|
});
|
|
1922
1923
|
`;
|
|
1923
|
-
const CONFIG_PRESET_ONLY = `import { presetRules } from "@bensandee/config/oxlint";
|
|
1924
|
+
const CONFIG_PRESET_ONLY = `import { presetRules, recommended } from "@bensandee/config/oxlint";
|
|
1924
1925
|
import { defineConfig } from "oxlint";
|
|
1925
1926
|
|
|
1926
1927
|
export default defineConfig({
|
|
1927
1928
|
rules: presetRules,
|
|
1928
|
-
ignorePatterns: [
|
|
1929
|
+
ignorePatterns: [${IGNORE_PATTERNS_SPREAD}],
|
|
1929
1930
|
});
|
|
1930
1931
|
`;
|
|
1932
|
+
function addIgnorePatterns(content) {
|
|
1933
|
+
if (content.includes("ignorePatterns")) return void 0;
|
|
1934
|
+
const match = content.match(/defineConfig\(\{(\r?\n)/);
|
|
1935
|
+
if (!match) return void 0;
|
|
1936
|
+
const insertPos = (match.index ?? 0) + match[0].length;
|
|
1937
|
+
return content.slice(0, insertPos) + ` ignorePatterns: [${IGNORE_PATTERNS_SPREAD}],\n` + content.slice(insertPos);
|
|
1938
|
+
}
|
|
1931
1939
|
async function generateOxlint(ctx) {
|
|
1932
1940
|
const filePath = "oxlint.config.ts";
|
|
1933
1941
|
const content = ctx.config.useEslintPlugin ? CONFIG_WITH_LINT_RULES : CONFIG_PRESET_ONLY;
|
|
1934
1942
|
const existing = ctx.read(filePath);
|
|
1935
1943
|
if (existing) {
|
|
1936
|
-
if (existing === content
|
|
1944
|
+
if (existing === content) return {
|
|
1937
1945
|
filePath,
|
|
1938
1946
|
action: "skipped",
|
|
1939
1947
|
description: "Already configured"
|
|
1940
1948
|
};
|
|
1949
|
+
if (existing.includes("@bensandee/config/oxlint")) {
|
|
1950
|
+
const updated = addIgnorePatterns(existing);
|
|
1951
|
+
if (!updated) return {
|
|
1952
|
+
filePath,
|
|
1953
|
+
action: "skipped",
|
|
1954
|
+
description: "Already configured"
|
|
1955
|
+
};
|
|
1956
|
+
ctx.write(filePath, updated);
|
|
1957
|
+
return {
|
|
1958
|
+
filePath,
|
|
1959
|
+
action: "updated",
|
|
1960
|
+
description: "Added ignorePatterns"
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1941
1963
|
if (await ctx.confirmOverwrite(filePath) === "skip") return {
|
|
1942
1964
|
filePath,
|
|
1943
1965
|
action: "skipped",
|
|
@@ -2271,6 +2293,7 @@ export default {
|
|
|
2271
2293
|
},
|
|
2272
2294
|
} satisfies KnipConfig;
|
|
2273
2295
|
`;
|
|
2296
|
+
const REQUIRED_IGNORE = ".claude/hooks/**";
|
|
2274
2297
|
/** All known knip config file locations, in priority order. */
|
|
2275
2298
|
const KNIP_CONFIG_PATHS = [
|
|
2276
2299
|
"knip.config.ts",
|
|
@@ -2280,15 +2303,59 @@ const KNIP_CONFIG_PATHS = [
|
|
|
2280
2303
|
"knip.ts",
|
|
2281
2304
|
"knip.mts"
|
|
2282
2305
|
];
|
|
2306
|
+
const JSON_EXTENSIONS = new Set([".json", ".jsonc"]);
|
|
2307
|
+
function isJsonConfig(path) {
|
|
2308
|
+
const dot = path.lastIndexOf(".");
|
|
2309
|
+
return dot !== -1 && JSON_EXTENSIONS.has(path.slice(dot));
|
|
2310
|
+
}
|
|
2311
|
+
/**
|
|
2312
|
+
* Try to add the required ignore pattern to an existing knip config.
|
|
2313
|
+
* Returns the updated content, or undefined if no change was needed.
|
|
2314
|
+
*/
|
|
2315
|
+
function ensureIgnorePattern(content, path) {
|
|
2316
|
+
if (content.includes(".claude/hooks")) return void 0;
|
|
2317
|
+
if (isJsonConfig(path)) return ensureIgnoreInJson(content);
|
|
2318
|
+
return ensureIgnoreInTs(content);
|
|
2319
|
+
}
|
|
2320
|
+
const KnipJsonSchema = z.object({ ignore: z.array(z.string()).optional() }).passthrough();
|
|
2321
|
+
function ensureIgnoreInJson(content) {
|
|
2322
|
+
const result = KnipJsonSchema.safeParse(JSON.parse(content));
|
|
2323
|
+
if (!result.success) return void 0;
|
|
2324
|
+
const parsed = result.data;
|
|
2325
|
+
const ignore = parsed.ignore ?? [];
|
|
2326
|
+
ignore.push(REQUIRED_IGNORE);
|
|
2327
|
+
parsed.ignore = ignore;
|
|
2328
|
+
return JSON.stringify(parsed, null, 2) + "\n";
|
|
2329
|
+
}
|
|
2330
|
+
function ensureIgnoreInTs(content) {
|
|
2331
|
+
const ignoreArrayPattern = /(ignore:\s*\[)/;
|
|
2332
|
+
if (ignoreArrayPattern.exec(content)) return content.replace(ignoreArrayPattern, `$1"${REQUIRED_IGNORE}", `);
|
|
2333
|
+
const exportPattern = /(export default\s*\{)\n/;
|
|
2334
|
+
if (exportPattern.exec(content)) return content.replace(exportPattern, `$1\n ignore: ["${REQUIRED_IGNORE}"],\n`);
|
|
2335
|
+
}
|
|
2283
2336
|
async function generateKnip(ctx) {
|
|
2284
2337
|
const filePath = "knip.config.ts";
|
|
2285
2338
|
const isMonorepo = ctx.config.structure === "monorepo";
|
|
2286
2339
|
const existingPath = KNIP_CONFIG_PATHS.find((p) => ctx.exists(p));
|
|
2287
|
-
if (existingPath)
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2340
|
+
if (existingPath) {
|
|
2341
|
+
const content = ctx.read(existingPath);
|
|
2342
|
+
if (content) {
|
|
2343
|
+
const updated = ensureIgnorePattern(content, existingPath);
|
|
2344
|
+
if (updated) {
|
|
2345
|
+
ctx.write(existingPath, updated);
|
|
2346
|
+
return {
|
|
2347
|
+
filePath: existingPath,
|
|
2348
|
+
action: "updated",
|
|
2349
|
+
description: "Added \".claude/hooks/**\" to ignore"
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
return {
|
|
2354
|
+
filePath: existingPath,
|
|
2355
|
+
action: "skipped",
|
|
2356
|
+
description: existingPath === filePath ? "Already configured" : `Existing config found at ${existingPath}`
|
|
2357
|
+
};
|
|
2358
|
+
}
|
|
2292
2359
|
const config = isMonorepo ? KNIP_CONFIG_MONOREPO : KNIP_CONFIG_SINGLE;
|
|
2293
2360
|
ctx.write(filePath, config);
|
|
2294
2361
|
return {
|
|
@@ -3147,7 +3214,7 @@ async function generateVersionrc(ctx) {
|
|
|
3147
3214
|
action: "skipped",
|
|
3148
3215
|
description: "simple release not requested"
|
|
3149
3216
|
};
|
|
3150
|
-
if (ctx.exists(filePath)) return {
|
|
3217
|
+
if (ctx.exists(filePath) || ctx.exists(".versionrc")) return {
|
|
3151
3218
|
filePath,
|
|
3152
3219
|
action: "skipped",
|
|
3153
3220
|
description: "Existing versionrc config preserved"
|
|
@@ -3197,7 +3264,7 @@ async function runGenerators(ctx) {
|
|
|
3197
3264
|
function generateMigratePrompt(results, config, detected) {
|
|
3198
3265
|
const sections = [];
|
|
3199
3266
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3200
|
-
sections.push(`# Migration Prompt\n\n_Generated by \`@bensandee/tooling@0.40.
|
|
3267
|
+
sections.push(`# Migration Prompt\n\n_Generated by \`@bensandee/tooling@0.40.5 repo:sync\` on ${timestamp}_\n`);
|
|
3201
3268
|
const changed = results.filter((r) => r.action === "created" || r.action === "updated" || r.action === "archived");
|
|
3202
3269
|
if (changed.length > 0) {
|
|
3203
3270
|
const items = changed.map((r) => {
|
|
@@ -5333,7 +5400,7 @@ const hooksAuditCommand = defineCommand({
|
|
|
5333
5400
|
const main = defineCommand({
|
|
5334
5401
|
meta: {
|
|
5335
5402
|
name: "bst",
|
|
5336
|
-
version: "0.40.
|
|
5403
|
+
version: "0.40.5",
|
|
5337
5404
|
description: "Bootstrap and maintain standardized TypeScript project tooling"
|
|
5338
5405
|
},
|
|
5339
5406
|
subCommands: {
|
|
@@ -5350,7 +5417,7 @@ const main = defineCommand({
|
|
|
5350
5417
|
"hooks:audit": hooksAuditCommand
|
|
5351
5418
|
}
|
|
5352
5419
|
});
|
|
5353
|
-
console.log(`@bensandee/tooling v0.40.
|
|
5420
|
+
console.log(`@bensandee/tooling v0.40.5`);
|
|
5354
5421
|
async function run() {
|
|
5355
5422
|
await runMain(main);
|
|
5356
5423
|
process.exit(process.exitCode ?? 0);
|