@bettercms-ai/convert 0.24.1 → 0.25.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @bettercms-ai/convert
2
2
 
3
+ ## 0.25.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 832e08a: A converted repository whose `build` runs checks before the build (`astro check && astro build`, `tsc --noEmit && vite build`, `npm run lint && next build`) gets a `build:bcms` script beside it with the same build minus those checks, `prebuild`/`postbuild` folded in. BetterCMS builds with `build:bcms` when a project declares one, so a deploy no longer pays for the project's CI checks; `build` is left unchanged. Every writing run adds it once (a repository that already has one is never touched), and only for a plain `&&` chain. Exported as `bcmsBuildScript`.
8
+
9
+ ### Patch Changes
10
+
11
+ - c6fd790: The codemod never walks into a directory holding its own `.git` (a git worktree, submodule or vendored clone), so a tool's worktree copy of the repo is no longer converted alongside the real source.
12
+
3
13
  ## 0.24.1
4
14
 
5
15
  ### Patch Changes
package/dist/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  // src/cli.ts
4
4
  import { execFileSync } from "child_process";
5
+ import { existsSync } from "fs";
5
6
  import { readdir, readFile, writeFile, mkdir, stat } from "fs/promises";
6
7
  import { dirname, join as join2, relative, resolve, sep } from "path";
7
8
 
@@ -7664,6 +7665,54 @@ function moduleScope(parsed, content) {
7664
7665
  return out;
7665
7666
  }
7666
7667
 
7668
+ // src/build-script.ts
7669
+ var CHECK = /^(?:npx\s+|pnpm\s+(?:exec\s+)?|yarn\s+|bunx\s+)?(?:astro\s+check|svelte-check|vue-tsc|tsc(?:\s|$)|eslint|next\s+lint|biome\s+(?:check|lint|ci)|prettier\s+(?:--check|-c)\b|stylelint|oxlint)/;
7670
+ var RUN_CHECK = /^(?:npm\s+run|pnpm(?:\s+run)?|yarn(?:\s+run)?|bun\s+run)\s+(?:lint|typecheck|type-check|check|check:types|types|format:check|test)(?::[\w-]+)?\s*$/;
7671
+ var UNSAFE = /;|\|\||\||(?:^|[^&])&(?:[^&]|$)|\$\(|`|\n/;
7672
+ var isCheck = (step) => CHECK.test(step) || RUN_CHECK.test(step);
7673
+ function steps(script) {
7674
+ if (UNSAFE.test(script)) return null;
7675
+ const out = script.split("&&").map((s) => s.trim());
7676
+ return out.some((s) => s === "") ? null : out;
7677
+ }
7678
+ function bcmsBuildScript(packageJson) {
7679
+ let pkg;
7680
+ try {
7681
+ pkg = JSON.parse(packageJson);
7682
+ } catch {
7683
+ return null;
7684
+ }
7685
+ const scripts = pkg?.scripts;
7686
+ if (!scripts || typeof scripts !== "object" || "build:bcms" in scripts) return null;
7687
+ const build = scripts.build;
7688
+ if (typeof build !== "string") return null;
7689
+ const parts = [];
7690
+ for (const name of ["prebuild", "build", "postbuild"]) {
7691
+ const value = scripts[name];
7692
+ if (value === void 0) continue;
7693
+ if (typeof value !== "string") return null;
7694
+ const s = steps(value);
7695
+ if (!s) return null;
7696
+ parts.push(s);
7697
+ }
7698
+ const all = parts.flat();
7699
+ const dropped = all.filter(isCheck);
7700
+ const kept = all.filter((s) => !isCheck(s));
7701
+ if (dropped.length === 0 || kept.length === 0) return null;
7702
+ const script = kept.join(" && ");
7703
+ const next = {};
7704
+ for (const [key, value] of Object.entries(scripts)) {
7705
+ next[key] = value;
7706
+ if (key === "build") next["build:bcms"] = script;
7707
+ }
7708
+ const indent = /^[ \t]+(?=")/m.exec(packageJson)?.[0] ?? " ";
7709
+ const eol = packageJson.includes("\r\n") ? "\r\n" : "\n";
7710
+ let content = JSON.stringify({ ...pkg, scripts: next }, null, indent);
7711
+ if (eol !== "\n") content = content.replace(/\n/g, eol);
7712
+ if (/\r?\n$/.test(packageJson)) content += eol;
7713
+ return { content, script, dropped };
7714
+ }
7715
+
7667
7716
  // src/componentize.ts
7668
7717
  import MagicString5 from "magic-string";
7669
7718
  var SectionInvariantError = class extends Error {
@@ -10784,7 +10833,7 @@ function styleEdits(before, after) {
10784
10833
  // package.json
10785
10834
  var package_default = {
10786
10835
  name: "@bettercms-ai/convert",
10787
- version: "0.24.1",
10836
+ version: "0.25.0",
10788
10837
  type: "module",
10789
10838
  description: "Deterministic codemod that turns an imported site's text-matched bindings into declared ones \u2014 parser offsets in, one magic-string pass out, plus a receipt of everything it could not do.",
10790
10839
  bin: {
@@ -10961,7 +11010,7 @@ async function readTree(root, verbose) {
10961
11010
  const full = join2(dir, entry.name);
10962
11011
  const rel = relative(root, full).split(sep).join("/");
10963
11012
  if (entry.isDirectory()) {
10964
- if (isSourceCandidate(`${rel}/x.html`)) await walk(full);
11013
+ if (isSourceCandidate(`${rel}/x.html`) && !existsSync(join2(full, ".git"))) await walk(full);
10965
11014
  continue;
10966
11015
  }
10967
11016
  if (!entry.isFile() || !isSourceCandidate(rel)) continue;
@@ -11142,6 +11191,21 @@ async function verifyStyles(root, base, verbose) {
11142
11191
  );
11143
11192
  return 1;
11144
11193
  }
11194
+ async function addBcmsBuild(root, dryRun) {
11195
+ let packageJson;
11196
+ try {
11197
+ packageJson = await readFile(join2(root, "package.json"), "utf-8");
11198
+ } catch {
11199
+ return;
11200
+ }
11201
+ const added = bcmsBuildScript(packageJson);
11202
+ if (!added) return;
11203
+ if (!dryRun) await writeFile(join2(root, "package.json"), added.content, "utf-8");
11204
+ process.stderr.write(
11205
+ `package.json: ${dryRun ? "would add" : "added"} "build:bcms": "${added.script}" \u2014 BetterCMS builds with it, without ${added.dropped.join(", ")}; "build" is unchanged.
11206
+ `
11207
+ );
11208
+ }
11145
11209
  async function main() {
11146
11210
  const args = parseArgs(process.argv.slice(2));
11147
11211
  if (args.help) {
@@ -11173,6 +11237,7 @@ async function main() {
11173
11237
  await writeFile(target, file.content, "utf-8");
11174
11238
  }
11175
11239
  }
11240
+ await addBcmsBuild(root2, args.dryRun);
11176
11241
  if (args.receipt) await writeFile(resolve(args.receipt), `${JSON.stringify(receipt2, null, 2)}
11177
11242
  `, "utf-8");
11178
11243
  reportUpgrade(files2, receipt2, args.dryRun);
@@ -11200,12 +11265,14 @@ async function main() {
11200
11265
  if (args.verbose) process.stderr.write(`read ${sources.length} candidate files under ${root}
11201
11266
  `);
11202
11267
  const written = async (files2) => {
11203
- if (args.dryRun) return;
11204
- for (const file of files2) {
11205
- const target = under(root, file.path);
11206
- await mkdir(dirname(target), { recursive: true });
11207
- await writeFile(target, file.content, "utf-8");
11268
+ if (!args.dryRun) {
11269
+ for (const file of files2) {
11270
+ const target = under(root, file.path);
11271
+ await mkdir(dirname(target), { recursive: true });
11272
+ await writeFile(target, file.content, "utf-8");
11273
+ }
11208
11274
  }
11275
+ await addBcmsBuild(root, args.dryRun);
11209
11276
  };
11210
11277
  const saveReceipt = async (receipt2) => {
11211
11278
  if (!args.receipt) return;