@bensandee/tooling 0.35.0 → 0.36.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.
Files changed (2) hide show
  1. package/dist/bin.mjs +84 -9
  2. package/package.json +1 -1
package/dist/bin.mjs CHANGED
@@ -956,7 +956,76 @@ function runDockerPublish(executor, config) {
956
956
  //#endregion
957
957
  //#region src/utils/yaml-merge.ts
958
958
  const IGNORE_PATTERN = "@bensandee/tooling:ignore";
959
+ const CUSTOM_START = "# @tooling:custom";
960
+ const CUSTOM_END = "# @tooling:endcustom";
959
961
  const FORGEJO_SCHEMA_COMMENT = "# yaml-language-server: $schema=../../.vscode/forgejo-workflow.schema.json\n";
962
+ /** Extract custom blocks from a workflow file, recording their anchor lines. */
963
+ function extractCustomBlocks(content) {
964
+ const lines = content.split("\n");
965
+ const blocks = [];
966
+ let i = 0;
967
+ while (i < lines.length) if (lines[i].trim() === CUSTOM_START) {
968
+ let anchor = "";
969
+ for (let j = i - 1; j >= 0; j--) if (lines[j].trim() !== "") {
970
+ anchor = lines[j].trim();
971
+ break;
972
+ }
973
+ const blockLines = [lines[i]];
974
+ i++;
975
+ while (i < lines.length && lines[i].trim() !== CUSTOM_END) {
976
+ blockLines.push(lines[i]);
977
+ i++;
978
+ }
979
+ if (i < lines.length) {
980
+ blockLines.push(lines[i]);
981
+ i++;
982
+ }
983
+ blocks.push({
984
+ anchor,
985
+ lines: blockLines
986
+ });
987
+ } else i++;
988
+ return blocks;
989
+ }
990
+ /** Remove custom blocks (markers + content) from a workflow string. */
991
+ function stripCustomBlocks(content) {
992
+ const lines = content.split("\n");
993
+ const result = [];
994
+ let inCustom = false;
995
+ for (const line of lines) {
996
+ if (line.trim() === CUSTOM_START) {
997
+ inCustom = true;
998
+ continue;
999
+ }
1000
+ if (inCustom && line.trim() === CUSTOM_END) {
1001
+ inCustom = false;
1002
+ continue;
1003
+ }
1004
+ if (!inCustom) result.push(line);
1005
+ }
1006
+ return result.join("\n");
1007
+ }
1008
+ /** Insert previously extracted custom blocks into freshly generated content, anchored by preceding line. */
1009
+ function insertCustomBlocks(generated, blocks) {
1010
+ if (blocks.length === 0) return generated;
1011
+ const lines = generated.split("\n");
1012
+ const insertions = [];
1013
+ for (const block of blocks) {
1014
+ let insertAfter = -1;
1015
+ for (let i = 0; i < lines.length; i++) if (lines[i].trim() === block.anchor) {
1016
+ insertAfter = i;
1017
+ break;
1018
+ }
1019
+ if (insertAfter < 0) insertAfter = lines.length - 1;
1020
+ insertions.push({
1021
+ afterIndex: insertAfter,
1022
+ block
1023
+ });
1024
+ }
1025
+ insertions.sort((a, b) => b.afterIndex - a.afterIndex);
1026
+ for (const { afterIndex, block } of insertions) lines.splice(afterIndex + 1, 0, ...block.lines);
1027
+ return lines.join("\n");
1028
+ }
960
1029
  /** Prepend the Forgejo schema comment if it's not already present. No-op for GitHub. */
961
1030
  function ensureSchemaComment(content, ci) {
962
1031
  if (ci !== "forgejo") return content;
@@ -1014,7 +1083,7 @@ function mergeLefthookCommands(existing, requiredCommands) {
1014
1083
  * don't cause unnecessary overwrites.
1015
1084
  */
1016
1085
  function normalizeWorkflow(content) {
1017
- const doc = parseDocument(content.replaceAll(/node\s+packages\/tooling-cli\/dist\/bin\.mjs/g, "pnpm exec bst"));
1086
+ const doc = parseDocument(stripCustomBlocks(content).replaceAll(/node\s+packages\/tooling-cli\/dist\/bin\.mjs/g, "pnpm exec bst"));
1018
1087
  doc.comment = null;
1019
1088
  doc.commentBefore = null;
1020
1089
  visit(doc, {
@@ -1156,7 +1225,9 @@ async function generateDeployCi(ctx) {
1156
1225
  description: "Publish workflow already up to date"
1157
1226
  };
1158
1227
  }
1159
- ctx.write(workflowPath, preserveDevBinaryPath(content, existing));
1228
+ const withDevPath = preserveDevBinaryPath(content, existing);
1229
+ const final = existing ? insertCustomBlocks(withDevPath, extractCustomBlocks(existing)) : withDevPath;
1230
+ ctx.write(workflowPath, final);
1160
1231
  return {
1161
1232
  filePath: workflowPath,
1162
1233
  action: alreadyExists ? "updated" : "created",
@@ -1427,7 +1498,7 @@ function getAddedDevDepNames(config) {
1427
1498
  const deps = { ...ROOT_DEV_DEPS };
1428
1499
  if (config.structure !== "monorepo") Object.assign(deps, PER_PACKAGE_DEV_DEPS);
1429
1500
  deps["@bensandee/config"] = "0.9.1";
1430
- deps["@bensandee/tooling"] = "0.35.0";
1501
+ deps["@bensandee/tooling"] = "0.36.0";
1431
1502
  if (config.formatter === "oxfmt") deps["oxfmt"] = {
1432
1503
  "@changesets/cli": "2.30.0",
1433
1504
  "@release-it/bumper": "7.0.5",
@@ -1482,7 +1553,7 @@ async function generatePackageJson(ctx) {
1482
1553
  const devDeps = { ...ROOT_DEV_DEPS };
1483
1554
  if (!isMonorepo) Object.assign(devDeps, PER_PACKAGE_DEV_DEPS);
1484
1555
  devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "0.9.1";
1485
- devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.35.0";
1556
+ devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.36.0";
1486
1557
  if (ctx.config.useEslintPlugin) devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "0.9.2";
1487
1558
  if (ctx.config.formatter === "oxfmt") devDeps["oxfmt"] = {
1488
1559
  "@changesets/cli": "2.30.0",
@@ -2116,7 +2187,9 @@ async function generateCi(ctx) {
2116
2187
  description: "CI workflow already up to date"
2117
2188
  };
2118
2189
  }
2119
- ctx.write(filePath, preserveDevBinaryPath(content, existing));
2190
+ const withDevPath = preserveDevBinaryPath(content, existing);
2191
+ const final = existing ? insertCustomBlocks(withDevPath, extractCustomBlocks(existing)) : withDevPath;
2192
+ ctx.write(filePath, final);
2120
2193
  return {
2121
2194
  filePath,
2122
2195
  action: alreadyExists ? "updated" : "created",
@@ -2743,7 +2816,9 @@ async function generateReleaseCi(ctx) {
2743
2816
  description: "Release workflow already up to date"
2744
2817
  };
2745
2818
  }
2746
- ctx.write(workflowPath, preserveDevBinaryPath(content, existing));
2819
+ const withDevPath = preserveDevBinaryPath(content, existing);
2820
+ const final = existing ? insertCustomBlocks(withDevPath, extractCustomBlocks(existing)) : withDevPath;
2821
+ ctx.write(workflowPath, final);
2747
2822
  return {
2748
2823
  filePath: workflowPath,
2749
2824
  action: alreadyExists ? "updated" : "created",
@@ -3042,7 +3117,7 @@ function generateMigratePrompt(results, config, detected) {
3042
3117
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
3043
3118
  sections.push("# Migration Prompt");
3044
3119
  sections.push("");
3045
- sections.push(`_Generated by \`@bensandee/tooling@0.35.0 repo:sync\` on ${timestamp}_`);
3120
+ sections.push(`_Generated by \`@bensandee/tooling@0.36.0 repo:sync\` on ${timestamp}_`);
3046
3121
  sections.push("");
3047
3122
  sections.push("The following prompt was generated by `@bensandee/tooling repo:sync`. Paste it into Claude Code or another AI assistant to finish migrating this repository.");
3048
3123
  sections.push("");
@@ -4915,7 +4990,7 @@ const dockerCheckCommand = defineCommand({
4915
4990
  const main = defineCommand({
4916
4991
  meta: {
4917
4992
  name: "bst",
4918
- version: "0.35.0",
4993
+ version: "0.36.0",
4919
4994
  description: "Bootstrap and maintain standardized TypeScript project tooling"
4920
4995
  },
4921
4996
  subCommands: {
@@ -4931,7 +5006,7 @@ const main = defineCommand({
4931
5006
  "docker:check": dockerCheckCommand
4932
5007
  }
4933
5008
  });
4934
- console.log(`@bensandee/tooling v0.35.0`);
5009
+ console.log(`@bensandee/tooling v0.36.0`);
4935
5010
  async function run() {
4936
5011
  await runMain(main);
4937
5012
  process.exit(process.exitCode ?? 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bensandee/tooling",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "CLI tool to bootstrap and maintain standardized TypeScript project tooling",
5
5
  "bin": {
6
6
  "bst": "./dist/bin.mjs"