@getcoherent/cli 0.6.37 → 0.6.39

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/index.js +279 -148
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -6980,14 +6980,28 @@ function findPagesImporting(projectRoot, componentName, componentFile) {
6980
6980
  return results;
6981
6981
  }
6982
6982
  function isUsedInLayout(projectRoot, componentName) {
6983
- const layoutPath = join7(projectRoot, "app", "layout.tsx");
6984
- if (!existsSync12(layoutPath)) return false;
6985
- try {
6986
- const code = readFileSync9(layoutPath, "utf-8");
6987
- return code.includes(componentName);
6988
- } catch {
6989
- return false;
6983
+ const appDir = join7(projectRoot, "app");
6984
+ const layoutPaths = [join7(appDir, "layout.tsx")];
6985
+ if (existsSync12(appDir)) {
6986
+ try {
6987
+ for (const entry of readdirSync4(appDir, { withFileTypes: true })) {
6988
+ if (entry.isDirectory() && entry.name.startsWith("(") && entry.name.endsWith(")")) {
6989
+ layoutPaths.push(join7(appDir, entry.name, "layout.tsx"));
6990
+ }
6991
+ }
6992
+ } catch {
6993
+ }
6990
6994
  }
6995
+ const matched = [];
6996
+ for (const lp of [...new Set(layoutPaths)]) {
6997
+ try {
6998
+ if (readFileSync9(lp, "utf-8").includes(componentName)) {
6999
+ matched.push(relative3(projectRoot, lp));
7000
+ }
7001
+ } catch {
7002
+ }
7003
+ }
7004
+ return matched;
6991
7005
  }
6992
7006
  function findUnregisteredComponents(projectRoot, manifest) {
6993
7007
  const results = [];
@@ -7114,8 +7128,8 @@ function reconcileComponents(projectRoot, manifest) {
7114
7128
  result.updated.push({ id: entry.id, field: "name", from: oldName, to: entry.name });
7115
7129
  }
7116
7130
  const actualUsedIn = findPagesImporting(projectRoot, entry.name, entry.file);
7117
- const inLayout = isUsedInLayout(projectRoot, entry.name);
7118
- const fullUsedIn = inLayout ? [.../* @__PURE__ */ new Set([...actualUsedIn, "app/layout.tsx"])] : actualUsedIn;
7131
+ const layoutPaths = isUsedInLayout(projectRoot, entry.name);
7132
+ const fullUsedIn = [.../* @__PURE__ */ new Set([...actualUsedIn, ...layoutPaths])];
7119
7133
  if (!arraysEqual(fullUsedIn, entry.usedIn || [])) {
7120
7134
  result.updated.push({
7121
7135
  id: entry.id,
@@ -8308,8 +8322,8 @@ async function regenerateDocsCommand() {
8308
8322
 
8309
8323
  // src/commands/fix.ts
8310
8324
  import chalk15 from "chalk";
8311
- import { readdirSync as readdirSync7, readFileSync as readFileSync12, existsSync as existsSync16, writeFileSync as writeFileSync10, rmSync as rmSync5, mkdirSync as mkdirSync7 } from "fs";
8312
- import { resolve as resolve10, join as join11 } from "path";
8325
+ import { readdirSync as readdirSync7, readFileSync as readFileSync13, existsSync as existsSync17, rmSync as rmSync5, mkdirSync as mkdirSync7 } from "fs";
8326
+ import { resolve as resolve10, join as join12, relative as relative5 } from "path";
8313
8327
  import {
8314
8328
  DesignSystemManager as DesignSystemManager9,
8315
8329
  ComponentManager as ComponentManager5,
@@ -8318,6 +8332,54 @@ import {
8318
8332
  loadManifest as loadManifest9,
8319
8333
  saveManifest as saveManifest5
8320
8334
  } from "@getcoherent/core";
8335
+
8336
+ // src/commands/fix-validation.ts
8337
+ import { createRequire } from "module";
8338
+ import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
8339
+ import { join as join11 } from "path";
8340
+ var cachedTs = null;
8341
+ var cachedProjectRoot = null;
8342
+ function isValidTsx(code, projectRoot, ext = ".tsx") {
8343
+ if (ext !== ".tsx" && ext !== ".ts") return true;
8344
+ const pkgJson = join11(projectRoot, "package.json");
8345
+ if (!existsSync16(pkgJson)) return true;
8346
+ try {
8347
+ if (!cachedTs || cachedProjectRoot !== projectRoot) {
8348
+ const req = createRequire(pkgJson);
8349
+ cachedTs = req("typescript");
8350
+ cachedProjectRoot = projectRoot;
8351
+ }
8352
+ const sf = cachedTs.createSourceFile(
8353
+ "check.tsx",
8354
+ code,
8355
+ cachedTs.ScriptTarget.Latest,
8356
+ false,
8357
+ cachedTs.ScriptKind.TSX
8358
+ );
8359
+ const diagnostics = sf.parseDiagnostics;
8360
+ return !diagnostics || diagnostics.length === 0;
8361
+ } catch {
8362
+ return true;
8363
+ }
8364
+ }
8365
+ function safeWrite(filePath, newContent, projectRoot, backups) {
8366
+ if (!backups.has(filePath)) {
8367
+ try {
8368
+ backups.set(filePath, readFileSync12(filePath, "utf-8"));
8369
+ } catch {
8370
+ }
8371
+ }
8372
+ const ext = filePath.slice(filePath.lastIndexOf("."));
8373
+ writeFileSync10(filePath, newContent, "utf-8");
8374
+ if (!isValidTsx(newContent, projectRoot, ext)) {
8375
+ const original = backups.get(filePath);
8376
+ if (original) writeFileSync10(filePath, original, "utf-8");
8377
+ return { ok: false };
8378
+ }
8379
+ return { ok: true };
8380
+ }
8381
+
8382
+ // src/commands/fix.ts
8321
8383
  function extractComponentIdsFromCode2(code) {
8322
8384
  const ids = /* @__PURE__ */ new Set();
8323
8385
  const allMatches = code.matchAll(/@\/components\/((?:ui\/)?[a-z0-9-]+)/g);
@@ -8335,7 +8397,7 @@ function listTsxFiles(dir) {
8335
8397
  try {
8336
8398
  const entries = readdirSync7(dir, { withFileTypes: true });
8337
8399
  for (const e of entries) {
8338
- const full = join11(dir, e.name);
8400
+ const full = join12(dir, e.name);
8339
8401
  if (e.isDirectory() && e.name !== "node_modules" && !e.name.startsWith(".")) {
8340
8402
  files.push(...listTsxFiles(full));
8341
8403
  } else if (e.isFile() && e.name.endsWith(".tsx")) {
@@ -8358,14 +8420,16 @@ async function fixCommand(opts = {}) {
8358
8420
  const projectRoot = project.root;
8359
8421
  const fixes = [];
8360
8422
  const remaining = [];
8423
+ const backups = /* @__PURE__ */ new Map();
8424
+ const modifiedFiles = [];
8361
8425
  if (dryRun) {
8362
8426
  console.log(chalk15.cyan("\ncoherent fix --dry-run\n"));
8363
8427
  } else {
8364
8428
  console.log(chalk15.cyan("\ncoherent fix\n"));
8365
8429
  }
8366
8430
  if (!skipCache) {
8367
- const nextDir = join11(projectRoot, ".next");
8368
- if (existsSync16(nextDir)) {
8431
+ const nextDir = join12(projectRoot, ".next");
8432
+ if (existsSync17(nextDir)) {
8369
8433
  if (!dryRun) rmSync5(nextDir, { recursive: true, force: true });
8370
8434
  fixes.push("Cleared build cache");
8371
8435
  console.log(chalk15.green(" \u2714 Cleared build cache"));
@@ -8392,7 +8456,7 @@ async function fixCommand(opts = {}) {
8392
8456
  const componentsTsxFiles = listTsxFiles(resolve10(projectRoot, "components"));
8393
8457
  const allComponentIds = /* @__PURE__ */ new Set();
8394
8458
  for (const file of [...allTsxFiles, ...componentsTsxFiles]) {
8395
- const content = readFileSync12(file, "utf-8");
8459
+ const content = readFileSync13(file, "utf-8");
8396
8460
  extractComponentIdsFromCode2(content).forEach((id) => allComponentIds.add(id));
8397
8461
  }
8398
8462
  let dsm = null;
@@ -8412,7 +8476,7 @@ async function fixCommand(opts = {}) {
8412
8476
  } else {
8413
8477
  const fileName = toKebabCase(id) + ".tsx";
8414
8478
  const filePath = resolve10(projectRoot, "components", "ui", fileName);
8415
- if (!existsSync16(filePath)) missingFiles.push(id);
8479
+ if (!existsSync17(filePath)) missingFiles.push(id);
8416
8480
  }
8417
8481
  }
8418
8482
  const provider = getComponentProvider();
@@ -8464,13 +8528,22 @@ async function fixCommand(opts = {}) {
8464
8528
  const userTsxFiles = allTsxFiles.filter((f) => !f.includes("/design-system/"));
8465
8529
  let syntaxFixed = 0;
8466
8530
  for (const file of userTsxFiles) {
8467
- const content = readFileSync12(file, "utf-8");
8531
+ const content = readFileSync13(file, "utf-8");
8468
8532
  const fixed = fixUnescapedLtInJsx(
8469
8533
  fixEscapedClosingQuotes(sanitizeMetadataStrings(ensureUseClientIfNeeded(content)))
8470
8534
  );
8471
8535
  if (fixed !== content) {
8472
- if (!dryRun) writeFileSync10(file, fixed, "utf-8");
8473
- syntaxFixed++;
8536
+ if (!dryRun) {
8537
+ const result = safeWrite(file, fixed, projectRoot, backups);
8538
+ if (result.ok) {
8539
+ modifiedFiles.push(file);
8540
+ syntaxFixed++;
8541
+ } else {
8542
+ console.log(chalk15.yellow(` \u26A0 Syntax fix rolled back for ${relative5(projectRoot, file)} (parse error)`));
8543
+ }
8544
+ } else {
8545
+ syntaxFixed++;
8546
+ }
8474
8547
  }
8475
8548
  }
8476
8549
  if (syntaxFixed > 0) {
@@ -8493,7 +8566,7 @@ async function fixCommand(opts = {}) {
8493
8566
  console.log(chalk15.green(` \u2714 Verified group layouts: ${layoutTypes}`));
8494
8567
  const hasSidebar = plan.groups.some((g) => g.layout === "sidebar" || g.layout === "both");
8495
8568
  const sidebarPath = resolve10(projectRoot, "components", "shared", "sidebar.tsx");
8496
- if (hasSidebar && !existsSync16(sidebarPath) && !dryRun) {
8569
+ if (hasSidebar && !existsSync17(sidebarPath) && !dryRun) {
8497
8570
  if (!dsm) {
8498
8571
  dsm = new DesignSystemManager9(project.configPath);
8499
8572
  await dsm.load();
@@ -8502,14 +8575,18 @@ async function fixCommand(opts = {}) {
8502
8575
  const generator = new PageGenerator(dsm.getConfig());
8503
8576
  const sidebarCode = generator.generateSharedSidebarCode();
8504
8577
  mkdirSync7(resolve10(projectRoot, "components", "shared"), { recursive: true });
8505
- writeFileSync10(sidebarPath, sidebarCode, "utf-8");
8506
- fixes.push("Generated AppSidebar component (components/shared/sidebar.tsx)");
8507
- console.log(chalk15.green(" \u2714 Generated AppSidebar component"));
8578
+ const sidebarResult = safeWrite(sidebarPath, sidebarCode, projectRoot, backups);
8579
+ if (sidebarResult.ok) {
8580
+ fixes.push("Generated AppSidebar component (components/shared/sidebar.tsx)");
8581
+ console.log(chalk15.green(" \u2714 Generated AppSidebar component"));
8582
+ } else {
8583
+ console.log(chalk15.yellow(" \u26A0 AppSidebar generation failed validation"));
8584
+ }
8508
8585
  }
8509
8586
  if (hasSidebar && !dryRun) {
8510
8587
  const rootLayoutPath = resolve10(projectRoot, "app", "layout.tsx");
8511
- if (existsSync16(rootLayoutPath)) {
8512
- let rootCode = readFileSync12(rootLayoutPath, "utf-8");
8588
+ if (existsSync17(rootLayoutPath)) {
8589
+ let rootCode = readFileSync13(rootLayoutPath, "utf-8");
8513
8590
  if (rootCode.includes("<Header")) {
8514
8591
  rootCode = rootCode.replace(/import\s*\{[^}]*Header[^}]*\}[^;\n]*[;\n]?\s*/g, "").replace(/import\s*\{[^}]*Footer[^}]*\}[^;\n]*[;\n]?\s*/g, "").replace(/import\s+ShowWhenNotAuthRoute[^;\n]*[;\n]?\s*/g, "").replace(/<ShowWhenNotAuthRoute>[\s\S]*?<\/ShowWhenNotAuthRoute>/g, (match) => {
8515
8592
  const inner = match.replace(/<\/?ShowWhenNotAuthRoute>/g, "").trim();
@@ -8517,45 +8594,69 @@ async function fixCommand(opts = {}) {
8517
8594
  }).replace(/\s*<Header\s*\/>\s*/g, "\n").replace(/\s*<Footer\s*\/>\s*/g, "\n");
8518
8595
  rootCode = rootCode.replace(/min-h-screen flex flex-col/g, "min-h-svh");
8519
8596
  rootCode = rootCode.replace(/"flex-1 flex flex-col"/g, '"flex-1"');
8520
- writeFileSync10(rootLayoutPath, rootCode, "utf-8");
8521
- fixes.push("Stripped Header/Footer from root layout (sidebar mode)");
8522
- console.log(chalk15.green(" \u2714 Stripped Header/Footer from root layout (sidebar mode)"));
8597
+ const rootResult = safeWrite(rootLayoutPath, rootCode, projectRoot, backups);
8598
+ if (rootResult.ok) {
8599
+ fixes.push("Stripped Header/Footer from root layout (sidebar mode)");
8600
+ console.log(chalk15.green(" \u2714 Stripped Header/Footer from root layout (sidebar mode)"));
8601
+ } else {
8602
+ console.log(chalk15.yellow(" \u26A0 Root layout update rolled back (parse error)"));
8603
+ }
8523
8604
  }
8524
8605
  }
8525
8606
  const publicLayoutPath = resolve10(projectRoot, "app", "(public)", "layout.tsx");
8526
- const publicExists = existsSync16(publicLayoutPath);
8527
- const needsPublicLayout = !publicExists || !readFileSync12(publicLayoutPath, "utf-8").includes("<Header");
8607
+ const publicExists = existsSync17(publicLayoutPath);
8608
+ const needsPublicLayout = !publicExists || !readFileSync13(publicLayoutPath, "utf-8").includes("<Header");
8528
8609
  if (needsPublicLayout) {
8529
8610
  const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-D3ZHOO4M.js");
8530
8611
  mkdirSync7(resolve10(projectRoot, "app", "(public)"), { recursive: true });
8531
- writeFileSync10(publicLayoutPath, buildPublicLayoutCodeForSidebar(), "utf-8");
8532
- fixes.push("Added Header/Footer to (public) layout");
8533
- console.log(chalk15.green(" \u2714 Added Header/Footer to (public) layout"));
8612
+ const publicResult = safeWrite(publicLayoutPath, buildPublicLayoutCodeForSidebar(), projectRoot, backups);
8613
+ if (publicResult.ok) {
8614
+ fixes.push("Added Header/Footer to (public) layout");
8615
+ console.log(chalk15.green(" \u2714 Added Header/Footer to (public) layout"));
8616
+ } else {
8617
+ console.log(chalk15.yellow(" \u26A0 Public layout generation failed validation"));
8618
+ }
8534
8619
  }
8535
8620
  const appLayoutPath = resolve10(projectRoot, "app", "(app)", "layout.tsx");
8536
- if (existsSync16(appLayoutPath) && dsm) {
8537
- let appLayoutCode = readFileSync12(appLayoutPath, "utf-8");
8621
+ if (existsSync17(appLayoutPath) && dsm) {
8622
+ let appLayoutCode = readFileSync13(appLayoutPath, "utf-8");
8538
8623
  const configName = dsm.getConfig().name;
8539
8624
  if (configName && configName !== "My App" && appLayoutCode.includes("My App")) {
8540
8625
  appLayoutCode = appLayoutCode.replace(/My App/g, configName);
8541
- writeFileSync10(appLayoutPath, appLayoutCode, "utf-8");
8542
- fixes.push(`Replaced "My App" with "${configName}" in (app)/layout.tsx`);
8543
- console.log(chalk15.green(` \u2714 Replaced "My App" with "${configName}" in (app)/layout.tsx`));
8626
+ const appResult = safeWrite(appLayoutPath, appLayoutCode, projectRoot, backups);
8627
+ if (appResult.ok) {
8628
+ fixes.push(`Replaced "My App" with "${configName}" in (app)/layout.tsx`);
8629
+ console.log(chalk15.green(` \u2714 Replaced "My App" with "${configName}" in (app)/layout.tsx`));
8630
+ } else {
8631
+ console.log(chalk15.yellow(" \u26A0 (app)/layout.tsx update rolled back (parse error)"));
8632
+ }
8544
8633
  }
8545
8634
  }
8546
- const sidebarComponentPath = resolve10(projectRoot, "components", "shared", "sidebar.tsx");
8547
- if (existsSync16(sidebarComponentPath)) {
8548
- let sidebarCode = readFileSync12(sidebarComponentPath, "utf-8");
8549
- if (sidebarCode.includes("SidebarTrigger")) {
8550
- sidebarCode = sidebarCode.replace(/\s*SidebarTrigger,?\n?/g, "\n").replace(/\s*<SidebarTrigger\s*\/>\s*\n?/g, "\n").replace(/flex items-center justify-between/g, "flex items-center");
8551
- writeFileSync10(sidebarComponentPath, sidebarCode, "utf-8");
8552
- fixes.push("Removed duplicate SidebarTrigger from sidebar component");
8553
- console.log(chalk15.green(" \u2714 Removed duplicate SidebarTrigger from sidebar component"));
8635
+ const sidebarComponentPath2 = resolve10(projectRoot, "components", "shared", "sidebar.tsx");
8636
+ if (existsSync17(sidebarComponentPath2)) {
8637
+ const existingSidebarCode = readFileSync13(sidebarComponentPath2, "utf-8");
8638
+ const sidebarConfigName = dsm?.getConfig().name ?? "";
8639
+ const hasWrongName = existingSidebarCode.includes("My App") && sidebarConfigName !== "My App";
8640
+ const hasTrigger = existingSidebarCode.includes("SidebarTrigger");
8641
+ if (hasWrongName || hasTrigger) {
8642
+ if (!dsm) {
8643
+ dsm = new DesignSystemManager9(project.configPath);
8644
+ await dsm.load();
8645
+ }
8646
+ const { PageGenerator } = await import("@getcoherent/core");
8647
+ const gen = new PageGenerator(dsm.getConfig());
8648
+ const sidebarResult2 = safeWrite(sidebarComponentPath2, gen.generateSharedSidebarCode(), projectRoot, backups);
8649
+ if (sidebarResult2.ok) {
8650
+ fixes.push("Regenerated sidebar component");
8651
+ console.log(chalk15.green(" \u2714 Regenerated sidebar component"));
8652
+ } else {
8653
+ console.log(chalk15.yellow(" \u26A0 Sidebar regeneration failed validation \u2014 restored original"));
8654
+ }
8554
8655
  }
8555
8656
  }
8556
8657
  const rootPagePath = resolve10(projectRoot, "app", "page.tsx");
8557
8658
  const publicPagePath = resolve10(projectRoot, "app", "(public)", "page.tsx");
8558
- if (existsSync16(rootPagePath) && !existsSync16(publicPagePath)) {
8659
+ if (existsSync17(rootPagePath) && !existsSync17(publicPagePath)) {
8559
8660
  const { renameSync } = await import("fs");
8560
8661
  mkdirSync7(resolve10(projectRoot, "app", "(public)"), { recursive: true });
8561
8662
  renameSync(rootPagePath, publicPagePath);
@@ -8563,27 +8664,42 @@ async function fixCommand(opts = {}) {
8563
8664
  console.log(chalk15.green(" \u2714 Moved app/page.tsx \u2192 app/(public)/page.tsx (gets Header/Footer)"));
8564
8665
  }
8565
8666
  const themeTogglePath = resolve10(projectRoot, "components", "shared", "theme-toggle.tsx");
8566
- if (!existsSync16(themeTogglePath)) {
8667
+ if (!existsSync17(themeTogglePath)) {
8567
8668
  const { generateThemeToggleCode } = await import("./code-generator-D3ZHOO4M.js");
8568
8669
  mkdirSync7(resolve10(projectRoot, "components", "shared"), { recursive: true });
8569
- writeFileSync10(themeTogglePath, generateThemeToggleCode(), "utf-8");
8570
- fixes.push("Generated ThemeToggle component (components/shared/theme-toggle.tsx)");
8571
- console.log(chalk15.green(" \u2714 Generated ThemeToggle component"));
8670
+ const themeResult = safeWrite(themeTogglePath, generateThemeToggleCode(), projectRoot, backups);
8671
+ if (themeResult.ok) {
8672
+ fixes.push("Generated ThemeToggle component (components/shared/theme-toggle.tsx)");
8673
+ console.log(chalk15.green(" \u2714 Generated ThemeToggle component"));
8674
+ } else {
8675
+ console.log(chalk15.yellow(" \u26A0 ThemeToggle generation failed validation"));
8676
+ }
8572
8677
  }
8573
8678
  }
8574
8679
  }
8575
- } catch {
8680
+ } catch (err) {
8681
+ console.log(chalk15.yellow(` \u26A0 Layout repair skipped: ${err instanceof Error ? err.message : "unknown error"}`));
8576
8682
  }
8577
8683
  if (!skipQuality) {
8578
8684
  let qualityFixCount = 0;
8579
8685
  const qualityFixDetails = [];
8580
8686
  for (const file of userTsxFiles) {
8581
- const content = readFileSync12(file, "utf-8");
8687
+ const content = readFileSync13(file, "utf-8");
8582
8688
  const { code: autoFixed, fixes: fileFixes } = await autoFixCode(content);
8583
8689
  if (autoFixed !== content) {
8584
- if (!dryRun) writeFileSync10(file, autoFixed, "utf-8");
8585
- qualityFixCount++;
8586
- qualityFixDetails.push(...fileFixes);
8690
+ if (!dryRun) {
8691
+ const qResult = safeWrite(file, autoFixed, projectRoot, backups);
8692
+ if (qResult.ok) {
8693
+ modifiedFiles.push(file);
8694
+ qualityFixCount++;
8695
+ qualityFixDetails.push(...fileFixes);
8696
+ } else {
8697
+ console.log(chalk15.yellow(` \u26A0 Quality fix rolled back for ${relative5(projectRoot, file)} (parse error)`));
8698
+ }
8699
+ } else {
8700
+ qualityFixCount++;
8701
+ qualityFixDetails.push(...fileFixes);
8702
+ }
8587
8703
  }
8588
8704
  }
8589
8705
  if (qualityFixCount > 0) {
@@ -8593,11 +8709,22 @@ async function fixCommand(opts = {}) {
8593
8709
  console.log(chalk15.green(` \u2714 ${verb} ${uniqueFixes.length} quality issue type(s): ${uniqueFixes.join(", ")}`));
8594
8710
  }
8595
8711
  }
8712
+ for (const file of modifiedFiles) {
8713
+ if (!backups.has(file)) continue;
8714
+ const before = backups.get(file);
8715
+ const after = readFileSync13(file, "utf-8");
8716
+ const issues = verifyIncrementalEdit(before, after);
8717
+ if (issues.length > 0) {
8718
+ for (const issue of issues) {
8719
+ remaining.push(`${relative5(projectRoot, file)}: ${issue.message}`);
8720
+ }
8721
+ }
8722
+ }
8596
8723
  let totalErrors = 0;
8597
8724
  let totalWarnings = 0;
8598
8725
  const fileIssues = [];
8599
8726
  for (const file of allTsxFiles) {
8600
- const code = dryRun ? readFileSync12(file, "utf-8") : readFileSync12(file, "utf-8");
8727
+ const code = dryRun ? readFileSync13(file, "utf-8") : readFileSync13(file, "utf-8");
8601
8728
  const relativePath = file.replace(projectRoot + "/", "");
8602
8729
  const baseName = file.split("/").pop() || "";
8603
8730
  const isAuthPage = relativePath.includes("(auth)");
@@ -8648,8 +8775,8 @@ async function fixCommand(opts = {}) {
8648
8775
  }
8649
8776
  for (const entry of manifest.shared) {
8650
8777
  const actualUsedIn = findPagesImporting(project.root, entry.name, entry.file);
8651
- const inLayout = isUsedInLayout(project.root, entry.name);
8652
- const fullActual = inLayout ? [.../* @__PURE__ */ new Set([...actualUsedIn, "app/layout.tsx"])] : actualUsedIn;
8778
+ const layoutPaths = isUsedInLayout(project.root, entry.name);
8779
+ const fullActual = [.../* @__PURE__ */ new Set([...actualUsedIn, ...layoutPaths])];
8653
8780
  if (!arraysEqual(fullActual, entry.usedIn || [])) {
8654
8781
  entry.usedIn = fullActual;
8655
8782
  manifestModified = true;
@@ -8686,12 +8813,16 @@ async function fixCommand(opts = {}) {
8686
8813
  }
8687
8814
  for (const entry of manifest.shared) {
8688
8815
  const actualUsedIn = findPagesImporting(project.root, entry.name, entry.file);
8689
- const inLayout = isUsedInLayout(project.root, entry.name);
8690
- if (actualUsedIn.length === 0 && !inLayout) {
8816
+ const layoutPaths2 = isUsedInLayout(project.root, entry.name);
8817
+ if (actualUsedIn.length === 0 && layoutPaths2.length === 0) {
8691
8818
  remaining.push(`${entry.id} (${entry.name}) \u2014 unused. Remove: coherent components shared remove ${entry.id}`);
8692
8819
  }
8693
8820
  }
8694
- } catch {
8821
+ } catch (err) {
8822
+ const isNotFound = err instanceof Error && "code" in err && err.code === "ENOENT";
8823
+ if (!isNotFound) {
8824
+ console.log(chalk15.yellow(` \u26A0 Component manifest check skipped: ${err instanceof Error ? err.message : "unknown error"}`));
8825
+ }
8695
8826
  }
8696
8827
  if (fixes.length === 0 && totalErrors === 0 && totalWarnings === 0 && remaining.length === 0) {
8697
8828
  console.log(chalk15.green("\n \u2705 Everything looks good \u2014 no issues found\n"));
@@ -8722,7 +8853,7 @@ async function fixCommand(opts = {}) {
8722
8853
  // src/commands/check.ts
8723
8854
  import chalk16 from "chalk";
8724
8855
  import { resolve as resolve11 } from "path";
8725
- import { readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync3, existsSync as existsSync17 } from "fs";
8856
+ import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync3, existsSync as existsSync18 } from "fs";
8726
8857
  import { loadManifest as loadManifest10 } from "@getcoherent/core";
8727
8858
  var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["node_modules", "design-system"]);
8728
8859
  function findTsxFiles(dir) {
@@ -8779,7 +8910,7 @@ async function checkCommand(opts = {}) {
8779
8910
  "NATIVE_TABLE"
8780
8911
  ]);
8781
8912
  for (const file of files) {
8782
- const code = readFileSync13(file, "utf-8");
8913
+ const code = readFileSync14(file, "utf-8");
8783
8914
  const relativePath = file.replace(projectRoot + "/", "");
8784
8915
  const baseName = file.split("/").pop() || "";
8785
8916
  const isAuthPage = relativePath.includes("(auth)");
@@ -8821,7 +8952,7 @@ async function checkCommand(opts = {}) {
8821
8952
  routeSet.add("/");
8822
8953
  routeSet.add("#");
8823
8954
  for (const file of files) {
8824
- const code = readFileSync13(file, "utf-8");
8955
+ const code = readFileSync14(file, "utf-8");
8825
8956
  const relativePath = file.replace(projectRoot + "/", "");
8826
8957
  const lines = code.split("\n");
8827
8958
  const linkHrefRe = /href\s*=\s*["'](\/[a-z0-9/-]*)["']/gi;
@@ -8854,7 +8985,7 @@ async function checkCommand(opts = {}) {
8854
8985
  if (manifest.shared.length > 0) {
8855
8986
  for (const entry of manifest.shared) {
8856
8987
  const fullPath = resolve11(project.root, entry.file);
8857
- if (!existsSync17(fullPath)) {
8988
+ if (!existsSync18(fullPath)) {
8858
8989
  result.pages.withErrors++;
8859
8990
  if (!opts.json) console.log(chalk16.red(`
8860
8991
  \u2717 Missing shared component file: ${entry.id} (${entry.file})`));
@@ -8879,7 +9010,7 @@ async function checkCommand(opts = {}) {
8879
9010
  let _nameMismatch = 0;
8880
9011
  for (const entry of manifest.shared) {
8881
9012
  const filePath = resolve11(projectRoot, entry.file);
8882
- const fileExists = existsSync17(filePath);
9013
+ const fileExists = existsSync18(filePath);
8883
9014
  if (!fileExists) {
8884
9015
  _orphaned++;
8885
9016
  if (!opts.json) {
@@ -8889,7 +9020,7 @@ async function checkCommand(opts = {}) {
8889
9020
  continue;
8890
9021
  }
8891
9022
  try {
8892
- const code = readFileSync13(filePath, "utf-8");
9023
+ const code = readFileSync14(filePath, "utf-8");
8893
9024
  const actualExports = extractExportedComponentNames(code);
8894
9025
  if (actualExports.length > 0 && !actualExports.includes(entry.name)) {
8895
9026
  _nameMismatch++;
@@ -8905,10 +9036,10 @@ async function checkCommand(opts = {}) {
8905
9036
  } catch {
8906
9037
  }
8907
9038
  const actualUsedIn = findPagesImporting(projectRoot, entry.name, entry.file);
8908
- const inLayout = isUsedInLayout(projectRoot, entry.name);
8909
- const totalUsage = actualUsedIn.length + (inLayout ? 1 : 0);
9039
+ const layoutPaths = isUsedInLayout(projectRoot, entry.name);
9040
+ const totalUsage = actualUsedIn.length + layoutPaths.length;
8910
9041
  const manifestUsedIn = entry.usedIn || [];
8911
- const fullActual = inLayout ? [.../* @__PURE__ */ new Set([...actualUsedIn, "app/layout.tsx"])] : actualUsedIn;
9042
+ const fullActual = [.../* @__PURE__ */ new Set([...actualUsedIn, ...layoutPaths])];
8912
9043
  const isStale = manifestUsedIn.length !== fullActual.length || !manifestUsedIn.every((p) => fullActual.includes(p));
8913
9044
  if (isStale) _staleUsedIn++;
8914
9045
  if (totalUsage === 0) {
@@ -8919,7 +9050,7 @@ async function checkCommand(opts = {}) {
8919
9050
  }
8920
9051
  } else {
8921
9052
  consistent++;
8922
- const usageDesc = inLayout ? `layout + ${actualUsedIn.length} page(s)` : `${actualUsedIn.length} page(s)`;
9053
+ const usageDesc = layoutPaths.length > 0 ? `layout(${layoutPaths.length}) + ${actualUsedIn.length} page(s)` : `${actualUsedIn.length} page(s)`;
8923
9054
  if (!opts.json) {
8924
9055
  const staleNote = isStale ? chalk16.yellow(" [usedIn stale]") : "";
8925
9056
  console.log(chalk16.green(` \u2714 ${entry.id} (${entry.name})`) + chalk16.dim(` \u2014 ${usageDesc}`) + staleNote);
@@ -8957,7 +9088,7 @@ async function checkCommand(opts = {}) {
8957
9088
  id: e.id,
8958
9089
  name: e.name,
8959
9090
  type: e.type,
8960
- status: existsSync17(resolve11(projectRoot, e.file)) ? "ok" : "unused",
9091
+ status: existsSync18(resolve11(projectRoot, e.file)) ? "ok" : "unused",
8961
9092
  message: "",
8962
9093
  suggestions: void 0
8963
9094
  }))
@@ -8971,11 +9102,11 @@ async function checkCommand(opts = {}) {
8971
9102
  const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-EIP2XM7T.js");
8972
9103
  const manifest = await loadManifest10(projectRoot);
8973
9104
  const appDir = resolve11(projectRoot, "app");
8974
- const pageFiles = existsSync17(appDir) ? findTsxFiles(appDir) : [];
9105
+ const pageFiles = existsSync18(appDir) ? findTsxFiles(appDir) : [];
8975
9106
  if (manifest.shared.length > 0 && pageFiles.length > 0) {
8976
9107
  const reuseWarnings = [];
8977
9108
  for (const file of pageFiles) {
8978
- const code = readFileSync13(file, "utf-8");
9109
+ const code = readFileSync14(file, "utf-8");
8979
9110
  const relativePath = file.replace(projectRoot + "/", "");
8980
9111
  const route = "/" + relativePath.replace(/^app\//, "").replace(/\/page\.tsx$/, "").replace(/^\(.*?\)\//, "");
8981
9112
  const pageType = inferPageTypeFromRoute2(route);
@@ -9086,12 +9217,12 @@ import {
9086
9217
  generateSharedComponent as generateSharedComponent4,
9087
9218
  integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2
9088
9219
  } from "@getcoherent/core";
9089
- import { existsSync as existsSync18 } from "fs";
9220
+ import { existsSync as existsSync19 } from "fs";
9090
9221
  import { resolve as resolve12 } from "path";
9091
9222
 
9092
9223
  // src/utils/ds-files.ts
9093
9224
  import { mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
9094
- import { join as join12, dirname as dirname5 } from "path";
9225
+ import { join as join13, dirname as dirname5 } from "path";
9095
9226
  import { DesignSystemGenerator } from "@getcoherent/core";
9096
9227
  var SHARED_DS_KEYS = [
9097
9228
  "app/design-system/shared/page.tsx",
@@ -9105,7 +9236,7 @@ async function writeDesignSystemFiles(projectRoot, config2, options) {
9105
9236
  const toWrite = options?.sharedOnly ? new Map([...files].filter(([path3]) => SHARED_DS_KEYS.includes(path3))) : files;
9106
9237
  const written = [];
9107
9238
  for (const [relativePath, content] of toWrite) {
9108
- const fullPath = join12(projectRoot, relativePath);
9239
+ const fullPath = join13(projectRoot, relativePath);
9109
9240
  await mkdir3(dirname5(fullPath), { recursive: true });
9110
9241
  await writeFile4(fullPath, content, "utf-8");
9111
9242
  written.push(relativePath);
@@ -9241,7 +9372,7 @@ function createComponentsCommand() {
9241
9372
  if (updated) console.log(chalk22.cyan(" Updated app/layout.tsx to use shared layout components.\n"));
9242
9373
  }
9243
9374
  const sharedPagePath = resolve12(project.root, "app/design-system/shared/page.tsx");
9244
- if (!existsSync18(sharedPagePath)) {
9375
+ if (!existsSync19(sharedPagePath)) {
9245
9376
  try {
9246
9377
  const dsm = new DesignSystemManager10(project.configPath);
9247
9378
  await dsm.load();
@@ -9267,8 +9398,8 @@ function createComponentsCommand() {
9267
9398
  import chalk23 from "chalk";
9268
9399
  import ora6 from "ora";
9269
9400
  import { writeFile as writeFile5, mkdir as mkdir4 } from "fs/promises";
9270
- import { resolve as resolve13, join as join13, dirname as dirname6 } from "path";
9271
- import { existsSync as existsSync19 } from "fs";
9401
+ import { resolve as resolve13, join as join14, dirname as dirname6 } from "path";
9402
+ import { existsSync as existsSync20 } from "fs";
9272
9403
  import {
9273
9404
  FigmaClient,
9274
9405
  parseFigmaFileResponse,
@@ -9415,7 +9546,7 @@ async function importFigmaAction(urlOrKey, opts) {
9415
9546
  stats.filesWritten.push(filePath);
9416
9547
  return;
9417
9548
  }
9418
- const fullPath = join13(projectRoot, filePath);
9549
+ const fullPath = join14(projectRoot, filePath);
9419
9550
  await mkdir4(dirname6(fullPath), { recursive: true });
9420
9551
  await writeFile5(fullPath, content, "utf-8");
9421
9552
  stats.filesWritten.push(filePath);
@@ -9517,7 +9648,7 @@ async function importFigmaAction(urlOrKey, opts) {
9517
9648
  spinner.start("Updating design-system.config.ts...");
9518
9649
  const configPath = resolve13(projectRoot, DESIGN_SYSTEM_CONFIG_PATH);
9519
9650
  const dsm = new DesignSystemManager11(configPath);
9520
- if (existsSync19(configPath)) {
9651
+ if (existsSync20(configPath)) {
9521
9652
  await dsm.load();
9522
9653
  const existing = dsm.getConfig();
9523
9654
  dsm.updateConfig({
@@ -9546,8 +9677,8 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
9546
9677
  stats.configUpdated = true;
9547
9678
  spinner.succeed("design-system.config.ts updated");
9548
9679
  spinner.start("Ensuring root layout...");
9549
- const layoutPath = join13(projectRoot, "app/layout.tsx");
9550
- if (!existsSync19(layoutPath)) {
9680
+ const layoutPath = join14(projectRoot, "app/layout.tsx");
9681
+ if (!existsSync20(layoutPath)) {
9551
9682
  await mkdir4(dirname6(layoutPath), { recursive: true });
9552
9683
  await writeFile5(layoutPath, MINIMAL_ROOT_LAYOUT, "utf-8");
9553
9684
  stats.filesWritten.push("app/layout.tsx");
@@ -9637,8 +9768,8 @@ async function dsRegenerateCommand() {
9637
9768
  // src/commands/update.ts
9638
9769
  import chalk25 from "chalk";
9639
9770
  import ora8 from "ora";
9640
- import { readFileSync as readFileSync14, existsSync as existsSync20 } from "fs";
9641
- import { join as join14 } from "path";
9771
+ import { readFileSync as readFileSync15, existsSync as existsSync21 } from "fs";
9772
+ import { join as join15 } from "path";
9642
9773
  import { DesignSystemManager as DesignSystemManager13, CLI_VERSION as CLI_VERSION4 } from "@getcoherent/core";
9643
9774
 
9644
9775
  // src/utils/migrations.ts
@@ -9807,20 +9938,20 @@ var EXPECTED_CSS_VARS = [
9807
9938
  "--sidebar-ring"
9808
9939
  ];
9809
9940
  function checkMissingCssVars(projectRoot) {
9810
- const globalsPath = join14(projectRoot, "app", "globals.css");
9811
- if (!existsSync20(globalsPath)) return [];
9941
+ const globalsPath = join15(projectRoot, "app", "globals.css");
9942
+ if (!existsSync21(globalsPath)) return [];
9812
9943
  try {
9813
- const content = readFileSync14(globalsPath, "utf-8");
9944
+ const content = readFileSync15(globalsPath, "utf-8");
9814
9945
  return EXPECTED_CSS_VARS.filter((v) => !content.includes(v));
9815
9946
  } catch {
9816
9947
  return [];
9817
9948
  }
9818
9949
  }
9819
9950
  function patchGlobalsCss(projectRoot, missingVars) {
9820
- const globalsPath = join14(projectRoot, "app", "globals.css");
9821
- if (!existsSync20(globalsPath) || missingVars.length === 0) return;
9822
- const { writeFileSync: writeFileSync13 } = __require("fs");
9823
- let content = readFileSync14(globalsPath, "utf-8");
9951
+ const globalsPath = join15(projectRoot, "app", "globals.css");
9952
+ if (!existsSync21(globalsPath) || missingVars.length === 0) return;
9953
+ const { writeFileSync: writeFileSync14 } = __require("fs");
9954
+ let content = readFileSync15(globalsPath, "utf-8");
9824
9955
  const defaultValues = {
9825
9956
  "--chart-1": "220 70% 50%",
9826
9957
  "--chart-2": "160 60% 45%",
@@ -9848,7 +9979,7 @@ function patchGlobalsCss(projectRoot, missingVars) {
9848
9979
  const lightSectionEnd = content.indexOf("}");
9849
9980
  if (lightSectionEnd > 0) {
9850
9981
  content = content.slice(0, lightSectionEnd) + "\n" + injection + "\n" + content.slice(lightSectionEnd);
9851
- writeFileSync13(globalsPath, content, "utf-8");
9982
+ writeFileSync14(globalsPath, content, "utf-8");
9852
9983
  }
9853
9984
  }
9854
9985
 
@@ -9898,26 +10029,26 @@ async function undoCommand(options) {
9898
10029
  // src/commands/sync.ts
9899
10030
  import chalk27 from "chalk";
9900
10031
  import ora9 from "ora";
9901
- import { existsSync as existsSync21, readFileSync as readFileSync15 } from "fs";
9902
- import { join as join15, relative as relative5, dirname as dirname7 } from "path";
10032
+ import { existsSync as existsSync22, readFileSync as readFileSync16 } from "fs";
10033
+ import { join as join16, relative as relative6, dirname as dirname7 } from "path";
9903
10034
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
9904
10035
  import { DesignSystemManager as DesignSystemManager14 } from "@getcoherent/core";
9905
10036
  import { loadManifest as loadManifest12, saveManifest as saveManifest6, findSharedComponent } from "@getcoherent/core";
9906
10037
  function extractTokensFromProject(projectRoot) {
9907
10038
  const lightColors = {};
9908
10039
  const darkColors = {};
9909
- const globalsPath = join15(projectRoot, "app", "globals.css");
9910
- if (existsSync21(globalsPath)) {
9911
- const css = readFileSync15(globalsPath, "utf-8");
10040
+ const globalsPath = join16(projectRoot, "app", "globals.css");
10041
+ if (existsSync22(globalsPath)) {
10042
+ const css = readFileSync16(globalsPath, "utf-8");
9912
10043
  const rootMatch = css.match(/:root\s*\{([^}]+)\}/s);
9913
10044
  if (rootMatch) parseVarsInto(rootMatch[1], lightColors);
9914
10045
  const darkMatch = css.match(/\.dark\s*\{([^}]+)\}/s);
9915
10046
  if (darkMatch) parseVarsInto(darkMatch[1], darkColors);
9916
10047
  }
9917
- const layoutPath = join15(projectRoot, "app", "layout.tsx");
10048
+ const layoutPath = join16(projectRoot, "app", "layout.tsx");
9918
10049
  let layoutCode = "";
9919
- if (existsSync21(layoutPath)) {
9920
- layoutCode = readFileSync15(layoutPath, "utf-8");
10050
+ if (existsSync22(layoutPath)) {
10051
+ layoutCode = readFileSync16(layoutPath, "utf-8");
9921
10052
  const rootInline = layoutCode.match(/:root\s*\{([^}]+)\}/s);
9922
10053
  if (rootInline && Object.keys(lightColors).length === 0) {
9923
10054
  parseVarsInto(rootInline[1], lightColors);
@@ -9935,7 +10066,7 @@ function extractTokensFromProject(projectRoot) {
9935
10066
  defaultMode = "dark";
9936
10067
  }
9937
10068
  let radius;
9938
- const allCss = [existsSync21(globalsPath) ? readFileSync15(globalsPath, "utf-8") : "", layoutCode].join("\n");
10069
+ const allCss = [existsSync22(globalsPath) ? readFileSync16(globalsPath, "utf-8") : "", layoutCode].join("\n");
9939
10070
  const radiusMatch = allCss.match(/--radius:\s*([^;]+);/);
9940
10071
  if (radiusMatch) radius = radiusMatch[1].trim();
9941
10072
  return {
@@ -9958,14 +10089,14 @@ function parseVarsInto(block, target) {
9958
10089
  }
9959
10090
  async function detectCustomComponents(projectRoot, allPageCode) {
9960
10091
  const results = [];
9961
- const componentsDir = join15(projectRoot, "components");
9962
- if (!existsSync21(componentsDir)) return results;
10092
+ const componentsDir = join16(projectRoot, "components");
10093
+ if (!existsSync22(componentsDir)) return results;
9963
10094
  const files = [];
9964
10095
  await walkForTsx(componentsDir, files, ["ui"]);
9965
10096
  const fileResults = await Promise.all(
9966
10097
  files.map(async (filePath) => {
9967
10098
  const code = await readFile4(filePath, "utf-8");
9968
- const relFile = relative5(projectRoot, filePath);
10099
+ const relFile = relative6(projectRoot, filePath);
9969
10100
  const exportedNames = extractExportedComponentNames2(code);
9970
10101
  return exportedNames.map((name) => ({
9971
10102
  name,
@@ -9986,7 +10117,7 @@ async function walkForTsx(dir, files, skipDirs) {
9986
10117
  return;
9987
10118
  }
9988
10119
  for (const e of entries) {
9989
- const full = join15(dir, e.name);
10120
+ const full = join16(dir, e.name);
9990
10121
  if (e.isDirectory()) {
9991
10122
  if (skipDirs.includes(e.name) || e.name.startsWith(".")) continue;
9992
10123
  await walkForTsx(full, files, skipDirs);
@@ -10060,14 +10191,14 @@ async function discoverPages(appDir) {
10060
10191
  return;
10061
10192
  }
10062
10193
  for (const entry of entries) {
10063
- const full = join15(dir, entry.name);
10194
+ const full = join16(dir, entry.name);
10064
10195
  if (entry.isDirectory()) {
10065
10196
  if (["design-system", "api", "_not-found"].includes(entry.name)) continue;
10066
10197
  if (entry.name.startsWith(".")) continue;
10067
10198
  await walk(full);
10068
10199
  } else if (entry.name === "page.tsx" || entry.name === "page.jsx") {
10069
10200
  const code = await readFile4(full, "utf-8");
10070
- const routeDir = dirname7(relative5(appDir, full));
10201
+ const routeDir = dirname7(relative6(appDir, full));
10071
10202
  let route = routeDir === "." ? "/" : "/" + routeDir;
10072
10203
  route = route.replace(/\/\([^)]+\)/g, "");
10073
10204
  if (!route.startsWith("/")) route = "/" + route;
@@ -10149,8 +10280,8 @@ async function syncCommand(options = {}) {
10149
10280
  if (dryRun) console.log(chalk27.yellow(" [dry-run] No files will be written\n"));
10150
10281
  const spinner = ora9("Scanning project files...").start();
10151
10282
  try {
10152
- const appDir = join15(project.root, "app");
10153
- if (!existsSync21(appDir)) {
10283
+ const appDir = join16(project.root, "app");
10284
+ if (!existsSync22(appDir)) {
10154
10285
  spinner.fail("No app/ directory found");
10155
10286
  process.exit(1);
10156
10287
  }
@@ -10380,53 +10511,53 @@ async function syncCommand(options = {}) {
10380
10511
  // src/commands/migrate.ts
10381
10512
  import chalk28 from "chalk";
10382
10513
  import ora10 from "ora";
10383
- import { existsSync as existsSync22, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync11, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "fs";
10384
- import { join as join16 } from "path";
10514
+ import { existsSync as existsSync23, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync12, readFileSync as readFileSync17, readdirSync as readdirSync9 } from "fs";
10515
+ import { join as join17 } from "path";
10385
10516
  function backupDir(projectRoot) {
10386
10517
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
10387
- return join16(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10518
+ return join17(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10388
10519
  }
10389
10520
  function guardPath(projectRoot) {
10390
- return join16(projectRoot, ".coherent", "migration-in-progress");
10521
+ return join17(projectRoot, ".coherent", "migration-in-progress");
10391
10522
  }
10392
10523
  function createBackup2(projectRoot) {
10393
- const uiDir = join16(projectRoot, "components", "ui");
10524
+ const uiDir = join17(projectRoot, "components", "ui");
10394
10525
  const dest = backupDir(projectRoot);
10395
10526
  mkdirSync8(dest, { recursive: true });
10396
- if (existsSync22(uiDir)) {
10397
- cpSync(uiDir, join16(dest, "components-ui"), { recursive: true });
10527
+ if (existsSync23(uiDir)) {
10528
+ cpSync(uiDir, join17(dest, "components-ui"), { recursive: true });
10398
10529
  }
10399
- const configPath = join16(projectRoot, "design-system.config.ts");
10400
- if (existsSync22(configPath)) {
10401
- cpSync(configPath, join16(dest, "design-system.config.ts"));
10530
+ const configPath = join17(projectRoot, "design-system.config.ts");
10531
+ if (existsSync23(configPath)) {
10532
+ cpSync(configPath, join17(dest, "design-system.config.ts"));
10402
10533
  }
10403
10534
  return dest;
10404
10535
  }
10405
10536
  function setGuard(projectRoot, backupPath) {
10406
10537
  const guard = guardPath(projectRoot);
10407
- mkdirSync8(join16(projectRoot, ".coherent"), { recursive: true });
10408
- writeFileSync11(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10538
+ mkdirSync8(join17(projectRoot, ".coherent"), { recursive: true });
10539
+ writeFileSync12(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10409
10540
  }
10410
10541
  function clearGuard(projectRoot) {
10411
10542
  const guard = guardPath(projectRoot);
10412
- if (existsSync22(guard)) rmSync6(guard);
10543
+ if (existsSync23(guard)) rmSync6(guard);
10413
10544
  }
10414
10545
  function rollback(projectRoot) {
10415
10546
  const guard = guardPath(projectRoot);
10416
- if (!existsSync22(guard)) return false;
10547
+ if (!existsSync23(guard)) return false;
10417
10548
  try {
10418
- const data = JSON.parse(readFileSync16(guard, "utf-8"));
10549
+ const data = JSON.parse(readFileSync17(guard, "utf-8"));
10419
10550
  const backup = data.backup;
10420
- if (!existsSync22(backup)) return false;
10421
- const uiBackup = join16(backup, "components-ui");
10422
- const uiDir = join16(projectRoot, "components", "ui");
10423
- if (existsSync22(uiBackup)) {
10424
- if (existsSync22(uiDir)) rmSync6(uiDir, { recursive: true });
10551
+ if (!existsSync23(backup)) return false;
10552
+ const uiBackup = join17(backup, "components-ui");
10553
+ const uiDir = join17(projectRoot, "components", "ui");
10554
+ if (existsSync23(uiBackup)) {
10555
+ if (existsSync23(uiDir)) rmSync6(uiDir, { recursive: true });
10425
10556
  cpSync(uiBackup, uiDir, { recursive: true });
10426
10557
  }
10427
- const configBackup = join16(backup, "design-system.config.ts");
10428
- const configDest = join16(projectRoot, "design-system.config.ts");
10429
- if (existsSync22(configBackup)) {
10558
+ const configBackup = join17(backup, "design-system.config.ts");
10559
+ const configDest = join17(projectRoot, "design-system.config.ts");
10560
+ if (existsSync23(configBackup)) {
10430
10561
  cpSync(configBackup, configDest);
10431
10562
  }
10432
10563
  clearGuard(projectRoot);
@@ -10454,13 +10585,13 @@ async function migrateAction(options) {
10454
10585
  return;
10455
10586
  }
10456
10587
  const guard = guardPath(projectRoot);
10457
- if (existsSync22(guard)) {
10588
+ if (existsSync23(guard)) {
10458
10589
  console.log(chalk28.yellow("A migration is already in progress."));
10459
10590
  console.log(chalk28.dim("Run `coherent migrate --rollback` to undo, or delete .coherent/migration-in-progress"));
10460
10591
  return;
10461
10592
  }
10462
- const uiDir = join16(projectRoot, "components", "ui");
10463
- if (!existsSync22(uiDir)) {
10593
+ const uiDir = join17(projectRoot, "components", "ui");
10594
+ if (!existsSync23(uiDir)) {
10464
10595
  console.log(chalk28.yellow("No components/ui directory found. Nothing to migrate."));
10465
10596
  return;
10466
10597
  }
@@ -10486,8 +10617,8 @@ Found ${migratable.length} component(s) to migrate:`));
10486
10617
  setGuard(projectRoot, backup);
10487
10618
  try {
10488
10619
  for (const id of migratable) {
10489
- const filePath = join16(uiDir, `${id}.tsx`);
10490
- if (existsSync22(filePath)) rmSync6(filePath);
10620
+ const filePath = join17(uiDir, `${id}.tsx`);
10621
+ if (existsSync23(filePath)) rmSync6(filePath);
10491
10622
  }
10492
10623
  const results = await provider.installBatch(migratable, projectRoot, { force: true });
10493
10624
  let migrated = 0;
@@ -10509,20 +10640,20 @@ Found ${migratable.length} component(s) to migrate:`));
10509
10640
  }
10510
10641
 
10511
10642
  // src/utils/update-notifier.ts
10512
- import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync17, writeFileSync as writeFileSync12 } from "fs";
10513
- import { join as join17 } from "path";
10643
+ import { existsSync as existsSync24, mkdirSync as mkdirSync9, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "fs";
10644
+ import { join as join18 } from "path";
10514
10645
  import { homedir } from "os";
10515
10646
  import chalk29 from "chalk";
10516
10647
  import { CLI_VERSION as CLI_VERSION5 } from "@getcoherent/core";
10517
10648
  var DEBUG5 = process.env.COHERENT_DEBUG === "1";
10518
10649
  var PACKAGE_NAME = "@getcoherent/cli";
10519
- var CACHE_DIR = join17(homedir(), ".coherent");
10520
- var CACHE_FILE = join17(CACHE_DIR, "update-check.json");
10650
+ var CACHE_DIR = join18(homedir(), ".coherent");
10651
+ var CACHE_FILE = join18(CACHE_DIR, "update-check.json");
10521
10652
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10522
10653
  function readCache() {
10523
10654
  try {
10524
- if (!existsSync23(CACHE_FILE)) return null;
10525
- const raw = readFileSync17(CACHE_FILE, "utf-8");
10655
+ if (!existsSync24(CACHE_FILE)) return null;
10656
+ const raw = readFileSync18(CACHE_FILE, "utf-8");
10526
10657
  return JSON.parse(raw);
10527
10658
  } catch (e) {
10528
10659
  if (DEBUG5) console.error("Failed to read update cache:", e);
@@ -10531,8 +10662,8 @@ function readCache() {
10531
10662
  }
10532
10663
  function writeCache(data) {
10533
10664
  try {
10534
- if (!existsSync23(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10535
- writeFileSync12(CACHE_FILE, JSON.stringify(data), "utf-8");
10665
+ if (!existsSync24(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10666
+ writeFileSync13(CACHE_FILE, JSON.stringify(data), "utf-8");
10536
10667
  } catch (e) {
10537
10668
  if (DEBUG5) console.error("Failed to write update cache:", e);
10538
10669
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.6.37",
6
+ "version": "0.6.39",
7
7
  "description": "CLI interface for Coherent Design Method",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",
@@ -43,7 +43,7 @@
43
43
  "ora": "^7.0.1",
44
44
  "prompts": "^2.4.2",
45
45
  "zod": "^3.22.4",
46
- "@getcoherent/core": "0.6.37"
46
+ "@getcoherent/core": "0.6.39"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^20.11.0",