@betterstart/cli 0.1.25 → 0.1.26

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/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-SAPJG4NO.js";
5
5
 
6
6
  // src/cli.ts
7
- import { Command as Command7 } from "commander";
7
+ import { Command as Command8 } from "commander";
8
8
 
9
9
  // src/commands/generate.ts
10
10
  import path22 from "path";
@@ -901,8 +901,8 @@ function toPascalCase3(str) {
901
901
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
902
902
  }
903
903
  function toCamelCase(str) {
904
- const p5 = toPascalCase3(str);
905
- return p5.charAt(0).toLowerCase() + p5.slice(1);
904
+ const p6 = toPascalCase3(str);
905
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
906
906
  }
907
907
  function toKebabCase(str) {
908
908
  return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
@@ -993,7 +993,7 @@ function generateFormAdminPages(schema, cwd, pagesDir, options) {
993
993
  const adminDir = path4.join(cwd, pagesDir, "forms", kebab);
994
994
  if (!fs4.existsSync(adminDir)) fs4.mkdirSync(adminDir, { recursive: true });
995
995
  const files = [];
996
- const rel = (p5) => path4.relative(cwd, p5);
996
+ const rel = (p6) => path4.relative(cwd, p6);
997
997
  const pagePath = path4.join(adminDir, "page.tsx");
998
998
  if (!fs4.existsSync(pagePath) || options.force) {
999
999
  fs4.writeFileSync(pagePath, generatePage(pascal, kebab), "utf-8");
@@ -1981,8 +1981,8 @@ function toPascalCase4(str) {
1981
1981
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
1982
1982
  }
1983
1983
  function toCamelCase2(str) {
1984
- const p5 = toPascalCase4(str);
1985
- return p5.charAt(0).toLowerCase() + p5.slice(1);
1984
+ const p6 = toPascalCase4(str);
1985
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
1986
1986
  }
1987
1987
  function toKebabCase3(str) {
1988
1988
  return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
@@ -2697,8 +2697,8 @@ function toPascalCase5(str) {
2697
2697
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
2698
2698
  }
2699
2699
  function toCamelCase3(str) {
2700
- const p5 = toPascalCase5(str);
2701
- return p5.charAt(0).toLowerCase() + p5.slice(1);
2700
+ const p6 = toPascalCase5(str);
2701
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
2702
2702
  }
2703
2703
  function singularize2(str) {
2704
2704
  if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
@@ -2758,11 +2758,11 @@ function generateActions(schema, cwd, actionsDir, options = {}) {
2758
2758
  const listFieldsWithRels = findListFieldsWithRelationships(dbFields);
2759
2759
  const hasListRels = listFieldsWithRels.length > 0;
2760
2760
  const allListRelQueries = [];
2761
- for (const { field: listField, path: path41 } of listFieldsWithRels) {
2761
+ for (const { field: listField, path: path42 } of listFieldsWithRels) {
2762
2762
  const rels = (listField.fields || []).filter((f) => f.type === "relationship" && f.relationship);
2763
2763
  for (const relField of rels) {
2764
2764
  allListRelQueries.push({
2765
- fieldPath: path41.join("_"),
2765
+ fieldPath: path42.join("_"),
2766
2766
  relField,
2767
2767
  relTable: toCamelCase3(relField.relationship),
2768
2768
  listFieldName: listField.name
@@ -3421,8 +3421,8 @@ function toPascalCase6(str) {
3421
3421
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
3422
3422
  }
3423
3423
  function toCamelCase4(str) {
3424
- const p5 = toPascalCase6(str);
3425
- return p5.charAt(0).toLowerCase() + p5.slice(1);
3424
+ const p6 = toPascalCase6(str);
3425
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
3426
3426
  }
3427
3427
  function singularize3(str) {
3428
3428
  if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
@@ -4564,8 +4564,8 @@ function toPascalCase9(str) {
4564
4564
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
4565
4565
  }
4566
4566
  function toCamelCase5(str) {
4567
- const p5 = toPascalCase9(str);
4568
- return p5.charAt(0).toLowerCase() + p5.slice(1);
4567
+ const p6 = toPascalCase9(str);
4568
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
4569
4569
  }
4570
4570
  function singularize6(str) {
4571
4571
  if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
@@ -4813,8 +4813,8 @@ function toPascalCase10(str) {
4813
4813
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
4814
4814
  }
4815
4815
  function toCamelCase6(str) {
4816
- const p5 = toPascalCase10(str);
4817
- return p5.charAt(0).toLowerCase() + p5.slice(1);
4816
+ const p6 = toPascalCase10(str);
4817
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
4818
4818
  }
4819
4819
  function singularize7(str) {
4820
4820
  if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
@@ -7045,8 +7045,8 @@ function toPascalCase16(str) {
7045
7045
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
7046
7046
  }
7047
7047
  function toCamelCase7(str) {
7048
- const p5 = toPascalCase16(str);
7049
- return p5.charAt(0).toLowerCase() + p5.slice(1);
7048
+ const p6 = toPascalCase16(str);
7049
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
7050
7050
  }
7051
7051
  function singularize12(str) {
7052
7052
  if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
@@ -7640,6 +7640,9 @@ function detectPackageManager(cwd) {
7640
7640
  }
7641
7641
  return "npm";
7642
7642
  }
7643
+ function installCommand(pm) {
7644
+ return pm === "yarn" ? "yarn" : `${pm} install`;
7645
+ }
7643
7646
  function runCommand(pm, script) {
7644
7647
  switch (pm) {
7645
7648
  case "pnpm":
@@ -14097,8 +14100,8 @@ function toPascalCase17(str) {
14097
14100
  return str.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
14098
14101
  }
14099
14102
  function toCamelCase8(str) {
14100
- const p5 = toPascalCase17(str);
14101
- return p5.charAt(0).toLowerCase() + p5.slice(1);
14103
+ const p6 = toPascalCase17(str);
14104
+ return p6.charAt(0).toLowerCase() + p6.slice(1);
14102
14105
  }
14103
14106
  function singularize13(str) {
14104
14107
  if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
@@ -14339,33 +14342,418 @@ var updateDepsCommand = new Command5("update-deps").description("Install or upda
14339
14342
  clack2.outro("Dependencies updated");
14340
14343
  });
14341
14344
 
14342
- // src/commands/update-styles.ts
14343
- import fs34 from "fs";
14345
+ // src/commands/uninstall.ts
14346
+ import fs35 from "fs";
14344
14347
  import path40 from "path";
14345
- import * as clack3 from "@clack/prompts";
14348
+ import * as p5 from "@clack/prompts";
14349
+ import pc3 from "picocolors";
14346
14350
  import { Command as Command6 } from "commander";
14347
- var updateStylesCommand = new Command6("update-styles").description("Replace cms-globals.css with the latest version from the CLI").option("--cwd <path>", "Project root path").action(async (options) => {
14351
+
14352
+ // src/commands/uninstall-cleaners.ts
14353
+ import fs34 from "fs";
14354
+ function stripJsonComments2(input) {
14355
+ let result = "";
14356
+ let i = 0;
14357
+ while (i < input.length) {
14358
+ if (input[i] === '"') {
14359
+ let j = i + 1;
14360
+ while (j < input.length) {
14361
+ if (input[j] === "\\") {
14362
+ j += 2;
14363
+ continue;
14364
+ }
14365
+ if (input[j] === '"') {
14366
+ j++;
14367
+ break;
14368
+ }
14369
+ j++;
14370
+ }
14371
+ result += input.slice(i, j);
14372
+ i = j;
14373
+ } else if (input[i] === "/" && input[i + 1] === "/") {
14374
+ const nl = input.indexOf("\n", i);
14375
+ i = nl === -1 ? input.length : nl;
14376
+ } else if (input[i] === "/" && input[i + 1] === "*") {
14377
+ const end = input.indexOf("*/", i + 2);
14378
+ i = end === -1 ? input.length : end + 2;
14379
+ } else {
14380
+ result += input[i];
14381
+ i++;
14382
+ }
14383
+ }
14384
+ return result;
14385
+ }
14386
+ function cleanTsconfig(tsconfigPath) {
14387
+ if (!fs34.existsSync(tsconfigPath)) return [];
14388
+ const raw = fs34.readFileSync(tsconfigPath, "utf-8");
14389
+ const stripped = stripJsonComments2(raw).replace(/,\s*([\]}])/g, "$1");
14390
+ let tsconfig;
14391
+ try {
14392
+ tsconfig = JSON.parse(stripped);
14393
+ } catch {
14394
+ return [];
14395
+ }
14396
+ const compilerOptions = tsconfig.compilerOptions ?? {};
14397
+ const paths = compilerOptions.paths ?? {};
14398
+ const removed = [];
14399
+ for (const key of Object.keys(paths)) {
14400
+ if (key.startsWith("@cms/") || key === "@cms/*") {
14401
+ removed.push(key);
14402
+ delete paths[key];
14403
+ }
14404
+ }
14405
+ if (removed.length === 0) return [];
14406
+ if (Object.keys(paths).length === 0) {
14407
+ delete compilerOptions.paths;
14408
+ } else {
14409
+ compilerOptions.paths = paths;
14410
+ }
14411
+ tsconfig.compilerOptions = compilerOptions;
14412
+ fs34.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
14413
+ `, "utf-8");
14414
+ return removed;
14415
+ }
14416
+ function cleanCss(cssPath) {
14417
+ if (!fs34.existsSync(cssPath)) return [];
14418
+ const content = fs34.readFileSync(cssPath, "utf-8");
14419
+ const lines = content.split("\n");
14420
+ const sourcePattern = /^@source\s+"[^"]*cms[^"]*";\s*$/;
14421
+ const removed = [];
14422
+ const kept = [];
14423
+ for (const line of lines) {
14424
+ if (sourcePattern.test(line)) {
14425
+ removed.push(line.trim());
14426
+ } else {
14427
+ kept.push(line);
14428
+ }
14429
+ }
14430
+ if (removed.length === 0) return [];
14431
+ const cleaned = kept.join("\n").replace(/\n{3,}/g, "\n\n");
14432
+ fs34.writeFileSync(cssPath, cleaned, "utf-8");
14433
+ return removed;
14434
+ }
14435
+ function cleanEnvFile(envPath) {
14436
+ if (!fs34.existsSync(envPath)) return [];
14437
+ const content = fs34.readFileSync(envPath, "utf-8");
14438
+ const lines = content.split("\n");
14439
+ const removed = [];
14440
+ const kept = [];
14441
+ const headerPattern = /^# =+$/;
14442
+ const headerTextPattern = /^# BetterStart CMS$/;
14443
+ for (let i = 0; i < lines.length; i++) {
14444
+ const line = lines[i];
14445
+ const trimmed = line.trim();
14446
+ if (trimmed.match(/^BETTERSTART_\w+=/)) {
14447
+ const key = trimmed.split("=")[0];
14448
+ removed.push(key);
14449
+ continue;
14450
+ }
14451
+ if (headerPattern.test(trimmed)) {
14452
+ const next = lines[i + 1]?.trim();
14453
+ const afterNext = lines[i + 2]?.trim();
14454
+ if (next && headerTextPattern.test(next) && afterNext && headerPattern.test(afterNext)) {
14455
+ i += 2;
14456
+ continue;
14457
+ }
14458
+ }
14459
+ if (trimmed.startsWith("#") && !headerPattern.test(trimmed)) {
14460
+ const nextNonEmpty = findNextNonEmptyLine(lines, i + 1);
14461
+ if (nextNonEmpty !== null && nextNonEmpty.match(/^BETTERSTART_\w+=/)) {
14462
+ continue;
14463
+ }
14464
+ }
14465
+ kept.push(line);
14466
+ }
14467
+ if (removed.length === 0) return [];
14468
+ let result = kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
14469
+ if (result === "") {
14470
+ fs34.unlinkSync(envPath);
14471
+ } else {
14472
+ fs34.writeFileSync(envPath, `${result}
14473
+ `, "utf-8");
14474
+ }
14475
+ return removed;
14476
+ }
14477
+ function findNextNonEmptyLine(lines, startIndex) {
14478
+ for (let i = startIndex; i < lines.length; i++) {
14479
+ const trimmed = lines[i].trim();
14480
+ if (trimmed !== "") return trimmed;
14481
+ }
14482
+ return null;
14483
+ }
14484
+ function cleanPackageJsonDeps(pkgPath, allDeps, allDevDeps) {
14485
+ if (!fs34.existsSync(pkgPath)) return { removed: [], removedDev: [] };
14486
+ const content = fs34.readFileSync(pkgPath, "utf-8");
14487
+ let pkg;
14488
+ try {
14489
+ pkg = JSON.parse(content);
14490
+ } catch {
14491
+ return { removed: [], removedDev: [] };
14492
+ }
14493
+ const deps = pkg.dependencies ?? {};
14494
+ const devDeps = pkg.devDependencies ?? {};
14495
+ const depNames = new Set(allDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@")));
14496
+ const devDepNames = new Set(
14497
+ allDevDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@"))
14498
+ );
14499
+ const removed = [];
14500
+ for (const name of Object.keys(deps)) {
14501
+ if (depNames.has(name)) {
14502
+ delete deps[name];
14503
+ removed.push(name);
14504
+ }
14505
+ }
14506
+ const removedDev = [];
14507
+ for (const name of Object.keys(devDeps)) {
14508
+ if (devDepNames.has(name)) {
14509
+ delete devDeps[name];
14510
+ removedDev.push(name);
14511
+ }
14512
+ }
14513
+ if (removed.length === 0 && removedDev.length === 0) {
14514
+ return { removed: [], removedDev: [] };
14515
+ }
14516
+ pkg.dependencies = deps;
14517
+ pkg.devDependencies = devDeps;
14518
+ fs34.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
14519
+ `, "utf-8");
14520
+ return { removed, removedDev };
14521
+ }
14522
+
14523
+ // src/commands/uninstall.ts
14524
+ function findMainCss2(cwd) {
14525
+ const candidates = [
14526
+ "src/app/globals.css",
14527
+ "app/globals.css",
14528
+ "src/app/global.css",
14529
+ "app/global.css",
14530
+ "src/app/app.css",
14531
+ "app/app.css",
14532
+ "src/globals.css",
14533
+ "globals.css"
14534
+ ];
14535
+ for (const candidate of candidates) {
14536
+ const filePath = path40.join(cwd, candidate);
14537
+ if (fs35.existsSync(filePath)) return filePath;
14538
+ }
14539
+ return void 0;
14540
+ }
14541
+ function isCLICreatedBiome(biomePath) {
14542
+ if (!fs35.existsSync(biomePath)) return false;
14543
+ try {
14544
+ const content = JSON.parse(fs35.readFileSync(biomePath, "utf-8"));
14545
+ return content.$schema?.includes("biomejs.dev") && content.formatter?.indentStyle === "space" && content.javascript?.formatter?.quoteStyle === "single" && Array.isArray(content.files?.ignore) && content.files.ignore.includes(".next");
14546
+ } catch {
14547
+ return false;
14548
+ }
14549
+ }
14550
+ function buildUninstallPlan(cwd) {
14551
+ const steps = [];
14552
+ const hasSrc = fs35.existsSync(path40.join(cwd, "src"));
14553
+ const appBase = hasSrc ? "src/app" : "app";
14554
+ const dirs = [];
14555
+ const cmsDir = path40.join(cwd, "cms");
14556
+ const cmsRouteGroup = path40.join(cwd, appBase, "(cms)");
14557
+ if (fs35.existsSync(cmsDir)) dirs.push("cms/");
14558
+ if (fs35.existsSync(cmsRouteGroup)) dirs.push(`${appBase}/(cms)/`);
14559
+ if (dirs.length > 0) {
14560
+ steps.push({
14561
+ label: "CMS directories",
14562
+ items: dirs,
14563
+ execute() {
14564
+ if (fs35.existsSync(cmsDir)) fs35.rmSync(cmsDir, { recursive: true, force: true });
14565
+ if (fs35.existsSync(cmsRouteGroup)) fs35.rmSync(cmsRouteGroup, { recursive: true, force: true });
14566
+ }
14567
+ });
14568
+ }
14569
+ const configFiles = [];
14570
+ const configPaths = [];
14571
+ const candidates = [
14572
+ ["cms.config.ts", path40.join(cwd, "cms.config.ts")],
14573
+ ["drizzle.config.ts", path40.join(cwd, "drizzle.config.ts")],
14574
+ ["CMS.md", path40.join(cwd, "CMS.md")]
14575
+ ];
14576
+ for (const [label, fullPath] of candidates) {
14577
+ if (fs35.existsSync(fullPath)) {
14578
+ configFiles.push(label);
14579
+ configPaths.push(fullPath);
14580
+ }
14581
+ }
14582
+ const biomePath = path40.join(cwd, "biome.json");
14583
+ if (isCLICreatedBiome(biomePath)) {
14584
+ configFiles.push("biome.json (CLI-created)");
14585
+ configPaths.push(biomePath);
14586
+ }
14587
+ if (configFiles.length > 0) {
14588
+ steps.push({
14589
+ label: "Config files",
14590
+ items: configFiles,
14591
+ execute() {
14592
+ for (const p6 of configPaths) {
14593
+ if (fs35.existsSync(p6)) fs35.unlinkSync(p6);
14594
+ }
14595
+ }
14596
+ });
14597
+ }
14598
+ const tsconfigPath = path40.join(cwd, "tsconfig.json");
14599
+ if (fs35.existsSync(tsconfigPath)) {
14600
+ const content = fs35.readFileSync(tsconfigPath, "utf-8");
14601
+ if (content.includes("@cms/")) {
14602
+ steps.push({
14603
+ label: "tsconfig.json path aliases",
14604
+ items: ["Remove all @cms/* paths from compilerOptions.paths"],
14605
+ execute() {
14606
+ cleanTsconfig(tsconfigPath);
14607
+ }
14608
+ });
14609
+ }
14610
+ }
14611
+ const cssFile = findMainCss2(cwd);
14612
+ if (cssFile) {
14613
+ const cssContent = fs35.readFileSync(cssFile, "utf-8");
14614
+ const sourcePattern = /^@source\s+"[^"]*cms[^"]*";\s*$/m;
14615
+ if (sourcePattern.test(cssContent)) {
14616
+ const relCss = path40.relative(cwd, cssFile);
14617
+ steps.push({
14618
+ label: `CSS @source lines (${relCss})`,
14619
+ items: ["Remove @source lines referencing cms/"],
14620
+ execute() {
14621
+ cleanCss(cssFile);
14622
+ }
14623
+ });
14624
+ }
14625
+ }
14626
+ const envPath = path40.join(cwd, ".env.local");
14627
+ if (fs35.existsSync(envPath)) {
14628
+ const envContent = fs35.readFileSync(envPath, "utf-8");
14629
+ const bsVars = envContent.split("\n").filter((l) => l.trim().match(/^BETTERSTART_\w+=/)).map((l) => l.split("=")[0]);
14630
+ if (bsVars.length > 0) {
14631
+ steps.push({
14632
+ label: ".env.local variables",
14633
+ items: bsVars,
14634
+ execute() {
14635
+ cleanEnvFile(envPath);
14636
+ }
14637
+ });
14638
+ }
14639
+ }
14640
+ const pkgPath = path40.join(cwd, "package.json");
14641
+ if (fs35.existsSync(pkgPath)) {
14642
+ const allCoreDeps = [...CORE_DEPS, ...EMAIL_DEPS];
14643
+ const allDevDeps = [...DEV_DEPS, ...BIOME_DEV_DEPS];
14644
+ const coreNames = new Set(
14645
+ allCoreDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@"))
14646
+ );
14647
+ const devNames = new Set(
14648
+ allDevDeps.map((d) => d.split("@").slice(0, d.startsWith("@") ? 2 : 1).join("@"))
14649
+ );
14650
+ const pkgContent = JSON.parse(fs35.readFileSync(pkgPath, "utf-8"));
14651
+ const deps = Object.keys(pkgContent.dependencies ?? {}).filter((n) => coreNames.has(n));
14652
+ const devDeps = Object.keys(pkgContent.devDependencies ?? {}).filter((n) => devNames.has(n));
14653
+ if (deps.length > 0 || devDeps.length > 0) {
14654
+ const items = [];
14655
+ if (deps.length > 0) items.push(`${deps.length} dependencies`);
14656
+ if (devDeps.length > 0) items.push(`${devDeps.length} devDependencies`);
14657
+ steps.push({
14658
+ label: "package.json dependencies",
14659
+ items,
14660
+ execute() {
14661
+ cleanPackageJsonDeps(pkgPath, allCoreDeps, allDevDeps);
14662
+ }
14663
+ });
14664
+ }
14665
+ }
14666
+ return steps;
14667
+ }
14668
+ var uninstallCommand = new Command6("uninstall").description("Remove all CMS files and undo modifications made by betterstart init").option("-f, --force", "Skip all confirmation prompts", false).option("--cwd <path>", "Project root path").action(async (options) => {
14348
14669
  const cwd = options.cwd ? path40.resolve(options.cwd) : process.cwd();
14670
+ p5.intro(pc3.bgRed(pc3.white(" BetterStart Uninstall ")));
14671
+ const steps = buildUninstallPlan(cwd);
14672
+ if (steps.length === 0) {
14673
+ p5.log.info("Nothing to remove \u2014 project is already clean.");
14674
+ p5.outro("Done");
14675
+ return;
14676
+ }
14677
+ p5.log.warn(
14678
+ `Found ${steps.length} ${steps.length === 1 ? "area" : "areas"} to clean up:`
14679
+ );
14680
+ let completedCount = 0;
14681
+ for (const step of steps) {
14682
+ p5.log.message("");
14683
+ p5.log.step(pc3.bold(step.label));
14684
+ for (const item of step.items) {
14685
+ p5.log.message(` ${pc3.dim("\u2022")} ${item}`);
14686
+ }
14687
+ if (!options.force) {
14688
+ const confirmed = await p5.confirm({
14689
+ message: `Remove ${step.label}?`,
14690
+ initialValue: true
14691
+ });
14692
+ if (p5.isCancel(confirmed)) {
14693
+ p5.cancel("Uninstall cancelled.");
14694
+ process.exit(0);
14695
+ }
14696
+ if (!confirmed) {
14697
+ p5.log.info(pc3.dim(`Skipped: ${step.label}`));
14698
+ continue;
14699
+ }
14700
+ }
14701
+ step.execute();
14702
+ completedCount++;
14703
+ p5.log.success(`Removed: ${step.label}`);
14704
+ }
14705
+ p5.log.message("");
14706
+ if (completedCount === 0) {
14707
+ p5.log.info("No changes were made.");
14708
+ } else {
14709
+ const pm = detectPackageManager(cwd);
14710
+ p5.note(
14711
+ [
14712
+ `Run ${pc3.cyan(installCommand(pm))} to clean up node_modules.`,
14713
+ "",
14714
+ pc3.dim("Database tables were NOT dropped \u2014 drop them manually if needed.")
14715
+ ].join("\n"),
14716
+ "Next steps"
14717
+ );
14718
+ }
14719
+ if (findMainCss2(cwd)) {
14720
+ p5.log.info(
14721
+ pc3.dim(
14722
+ "Note: @theme tokens were left in your CSS \u2014 they're harmless and may be shared with your own styles."
14723
+ )
14724
+ );
14725
+ }
14726
+ p5.outro(completedCount > 0 ? "Uninstall complete" : "Done");
14727
+ });
14728
+
14729
+ // src/commands/update-styles.ts
14730
+ import fs36 from "fs";
14731
+ import path41 from "path";
14732
+ import * as clack3 from "@clack/prompts";
14733
+ import { Command as Command7 } from "commander";
14734
+ var updateStylesCommand = new Command7("update-styles").description("Replace cms-globals.css with the latest version from the CLI").option("--cwd <path>", "Project root path").action(async (options) => {
14735
+ const cwd = options.cwd ? path41.resolve(options.cwd) : process.cwd();
14349
14736
  clack3.intro("BetterStart Update Styles");
14350
14737
  const config = await resolveConfig(cwd);
14351
14738
  const cmsDir = config.paths?.cms ?? "./cms";
14352
- const targetPath = path40.join(cwd, cmsDir, "cms-globals.css");
14353
- if (!fs34.existsSync(targetPath)) {
14354
- clack3.cancel(`cms-globals.css not found at ${path40.relative(cwd, targetPath)}`);
14739
+ const targetPath = path41.join(cwd, cmsDir, "cms-globals.css");
14740
+ if (!fs36.existsSync(targetPath)) {
14741
+ clack3.cancel(`cms-globals.css not found at ${path41.relative(cwd, targetPath)}`);
14355
14742
  process.exit(1);
14356
14743
  }
14357
- fs34.writeFileSync(targetPath, cmsGlobalsCssTemplate(), "utf-8");
14358
- clack3.log.success(`Updated ${path40.relative(cwd, targetPath)}`);
14744
+ fs36.writeFileSync(targetPath, cmsGlobalsCssTemplate(), "utf-8");
14745
+ clack3.log.success(`Updated ${path41.relative(cwd, targetPath)}`);
14359
14746
  clack3.outro("Styles updated");
14360
14747
  });
14361
14748
 
14362
14749
  // src/cli.ts
14363
- var program = new Command7();
14750
+ var program = new Command8();
14364
14751
  program.name("betterstart").description("Scaffold a full-featured CMS into any Next.js 16 application").version("0.1.0");
14365
14752
  program.addCommand(initCommand);
14366
14753
  program.addCommand(generateCommand);
14367
14754
  program.addCommand(removeCommand);
14368
14755
  program.addCommand(seedCommand);
14756
+ program.addCommand(uninstallCommand);
14369
14757
  program.addCommand(updateDepsCommand);
14370
14758
  program.addCommand(updateStylesCommand);
14371
14759
  program.parse();