@getcoherent/cli 0.6.38 → 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 +272 -146
  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,50 +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
8635
  const sidebarComponentPath2 = resolve10(projectRoot, "components", "shared", "sidebar.tsx");
8547
- if (existsSync16(sidebarComponentPath2)) {
8548
- const sidebarCode = readFileSync12(sidebarComponentPath2, "utf-8");
8549
- if (sidebarCode.includes("SidebarTrigger")) {
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) {
8550
8642
  if (!dsm) {
8551
8643
  dsm = new DesignSystemManager9(project.configPath);
8552
8644
  await dsm.load();
8553
8645
  }
8554
8646
  const { PageGenerator } = await import("@getcoherent/core");
8555
8647
  const gen = new PageGenerator(dsm.getConfig());
8556
- writeFileSync10(sidebarComponentPath2, gen.generateSharedSidebarCode(), "utf-8");
8557
- fixes.push("Regenerated sidebar component (removed duplicate SidebarTrigger)");
8558
- console.log(chalk15.green(" \u2714 Regenerated sidebar component (removed duplicate SidebarTrigger)"));
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
+ }
8559
8655
  }
8560
8656
  }
8561
8657
  const rootPagePath = resolve10(projectRoot, "app", "page.tsx");
8562
8658
  const publicPagePath = resolve10(projectRoot, "app", "(public)", "page.tsx");
8563
- if (existsSync16(rootPagePath) && !existsSync16(publicPagePath)) {
8659
+ if (existsSync17(rootPagePath) && !existsSync17(publicPagePath)) {
8564
8660
  const { renameSync } = await import("fs");
8565
8661
  mkdirSync7(resolve10(projectRoot, "app", "(public)"), { recursive: true });
8566
8662
  renameSync(rootPagePath, publicPagePath);
@@ -8568,27 +8664,42 @@ async function fixCommand(opts = {}) {
8568
8664
  console.log(chalk15.green(" \u2714 Moved app/page.tsx \u2192 app/(public)/page.tsx (gets Header/Footer)"));
8569
8665
  }
8570
8666
  const themeTogglePath = resolve10(projectRoot, "components", "shared", "theme-toggle.tsx");
8571
- if (!existsSync16(themeTogglePath)) {
8667
+ if (!existsSync17(themeTogglePath)) {
8572
8668
  const { generateThemeToggleCode } = await import("./code-generator-D3ZHOO4M.js");
8573
8669
  mkdirSync7(resolve10(projectRoot, "components", "shared"), { recursive: true });
8574
- writeFileSync10(themeTogglePath, generateThemeToggleCode(), "utf-8");
8575
- fixes.push("Generated ThemeToggle component (components/shared/theme-toggle.tsx)");
8576
- 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
+ }
8577
8677
  }
8578
8678
  }
8579
8679
  }
8580
- } catch {
8680
+ } catch (err) {
8681
+ console.log(chalk15.yellow(` \u26A0 Layout repair skipped: ${err instanceof Error ? err.message : "unknown error"}`));
8581
8682
  }
8582
8683
  if (!skipQuality) {
8583
8684
  let qualityFixCount = 0;
8584
8685
  const qualityFixDetails = [];
8585
8686
  for (const file of userTsxFiles) {
8586
- const content = readFileSync12(file, "utf-8");
8687
+ const content = readFileSync13(file, "utf-8");
8587
8688
  const { code: autoFixed, fixes: fileFixes } = await autoFixCode(content);
8588
8689
  if (autoFixed !== content) {
8589
- if (!dryRun) writeFileSync10(file, autoFixed, "utf-8");
8590
- qualityFixCount++;
8591
- 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
+ }
8592
8703
  }
8593
8704
  }
8594
8705
  if (qualityFixCount > 0) {
@@ -8598,11 +8709,22 @@ async function fixCommand(opts = {}) {
8598
8709
  console.log(chalk15.green(` \u2714 ${verb} ${uniqueFixes.length} quality issue type(s): ${uniqueFixes.join(", ")}`));
8599
8710
  }
8600
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
+ }
8601
8723
  let totalErrors = 0;
8602
8724
  let totalWarnings = 0;
8603
8725
  const fileIssues = [];
8604
8726
  for (const file of allTsxFiles) {
8605
- const code = dryRun ? readFileSync12(file, "utf-8") : readFileSync12(file, "utf-8");
8727
+ const code = dryRun ? readFileSync13(file, "utf-8") : readFileSync13(file, "utf-8");
8606
8728
  const relativePath = file.replace(projectRoot + "/", "");
8607
8729
  const baseName = file.split("/").pop() || "";
8608
8730
  const isAuthPage = relativePath.includes("(auth)");
@@ -8653,8 +8775,8 @@ async function fixCommand(opts = {}) {
8653
8775
  }
8654
8776
  for (const entry of manifest.shared) {
8655
8777
  const actualUsedIn = findPagesImporting(project.root, entry.name, entry.file);
8656
- const inLayout = isUsedInLayout(project.root, entry.name);
8657
- 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])];
8658
8780
  if (!arraysEqual(fullActual, entry.usedIn || [])) {
8659
8781
  entry.usedIn = fullActual;
8660
8782
  manifestModified = true;
@@ -8691,12 +8813,16 @@ async function fixCommand(opts = {}) {
8691
8813
  }
8692
8814
  for (const entry of manifest.shared) {
8693
8815
  const actualUsedIn = findPagesImporting(project.root, entry.name, entry.file);
8694
- const inLayout = isUsedInLayout(project.root, entry.name);
8695
- if (actualUsedIn.length === 0 && !inLayout) {
8816
+ const layoutPaths2 = isUsedInLayout(project.root, entry.name);
8817
+ if (actualUsedIn.length === 0 && layoutPaths2.length === 0) {
8696
8818
  remaining.push(`${entry.id} (${entry.name}) \u2014 unused. Remove: coherent components shared remove ${entry.id}`);
8697
8819
  }
8698
8820
  }
8699
- } 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
+ }
8700
8826
  }
8701
8827
  if (fixes.length === 0 && totalErrors === 0 && totalWarnings === 0 && remaining.length === 0) {
8702
8828
  console.log(chalk15.green("\n \u2705 Everything looks good \u2014 no issues found\n"));
@@ -8727,7 +8853,7 @@ async function fixCommand(opts = {}) {
8727
8853
  // src/commands/check.ts
8728
8854
  import chalk16 from "chalk";
8729
8855
  import { resolve as resolve11 } from "path";
8730
- 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";
8731
8857
  import { loadManifest as loadManifest10 } from "@getcoherent/core";
8732
8858
  var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["node_modules", "design-system"]);
8733
8859
  function findTsxFiles(dir) {
@@ -8784,7 +8910,7 @@ async function checkCommand(opts = {}) {
8784
8910
  "NATIVE_TABLE"
8785
8911
  ]);
8786
8912
  for (const file of files) {
8787
- const code = readFileSync13(file, "utf-8");
8913
+ const code = readFileSync14(file, "utf-8");
8788
8914
  const relativePath = file.replace(projectRoot + "/", "");
8789
8915
  const baseName = file.split("/").pop() || "";
8790
8916
  const isAuthPage = relativePath.includes("(auth)");
@@ -8826,7 +8952,7 @@ async function checkCommand(opts = {}) {
8826
8952
  routeSet.add("/");
8827
8953
  routeSet.add("#");
8828
8954
  for (const file of files) {
8829
- const code = readFileSync13(file, "utf-8");
8955
+ const code = readFileSync14(file, "utf-8");
8830
8956
  const relativePath = file.replace(projectRoot + "/", "");
8831
8957
  const lines = code.split("\n");
8832
8958
  const linkHrefRe = /href\s*=\s*["'](\/[a-z0-9/-]*)["']/gi;
@@ -8859,7 +8985,7 @@ async function checkCommand(opts = {}) {
8859
8985
  if (manifest.shared.length > 0) {
8860
8986
  for (const entry of manifest.shared) {
8861
8987
  const fullPath = resolve11(project.root, entry.file);
8862
- if (!existsSync17(fullPath)) {
8988
+ if (!existsSync18(fullPath)) {
8863
8989
  result.pages.withErrors++;
8864
8990
  if (!opts.json) console.log(chalk16.red(`
8865
8991
  \u2717 Missing shared component file: ${entry.id} (${entry.file})`));
@@ -8884,7 +9010,7 @@ async function checkCommand(opts = {}) {
8884
9010
  let _nameMismatch = 0;
8885
9011
  for (const entry of manifest.shared) {
8886
9012
  const filePath = resolve11(projectRoot, entry.file);
8887
- const fileExists = existsSync17(filePath);
9013
+ const fileExists = existsSync18(filePath);
8888
9014
  if (!fileExists) {
8889
9015
  _orphaned++;
8890
9016
  if (!opts.json) {
@@ -8894,7 +9020,7 @@ async function checkCommand(opts = {}) {
8894
9020
  continue;
8895
9021
  }
8896
9022
  try {
8897
- const code = readFileSync13(filePath, "utf-8");
9023
+ const code = readFileSync14(filePath, "utf-8");
8898
9024
  const actualExports = extractExportedComponentNames(code);
8899
9025
  if (actualExports.length > 0 && !actualExports.includes(entry.name)) {
8900
9026
  _nameMismatch++;
@@ -8910,10 +9036,10 @@ async function checkCommand(opts = {}) {
8910
9036
  } catch {
8911
9037
  }
8912
9038
  const actualUsedIn = findPagesImporting(projectRoot, entry.name, entry.file);
8913
- const inLayout = isUsedInLayout(projectRoot, entry.name);
8914
- const totalUsage = actualUsedIn.length + (inLayout ? 1 : 0);
9039
+ const layoutPaths = isUsedInLayout(projectRoot, entry.name);
9040
+ const totalUsage = actualUsedIn.length + layoutPaths.length;
8915
9041
  const manifestUsedIn = entry.usedIn || [];
8916
- const fullActual = inLayout ? [.../* @__PURE__ */ new Set([...actualUsedIn, "app/layout.tsx"])] : actualUsedIn;
9042
+ const fullActual = [.../* @__PURE__ */ new Set([...actualUsedIn, ...layoutPaths])];
8917
9043
  const isStale = manifestUsedIn.length !== fullActual.length || !manifestUsedIn.every((p) => fullActual.includes(p));
8918
9044
  if (isStale) _staleUsedIn++;
8919
9045
  if (totalUsage === 0) {
@@ -8924,7 +9050,7 @@ async function checkCommand(opts = {}) {
8924
9050
  }
8925
9051
  } else {
8926
9052
  consistent++;
8927
- 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)`;
8928
9054
  if (!opts.json) {
8929
9055
  const staleNote = isStale ? chalk16.yellow(" [usedIn stale]") : "";
8930
9056
  console.log(chalk16.green(` \u2714 ${entry.id} (${entry.name})`) + chalk16.dim(` \u2014 ${usageDesc}`) + staleNote);
@@ -8962,7 +9088,7 @@ async function checkCommand(opts = {}) {
8962
9088
  id: e.id,
8963
9089
  name: e.name,
8964
9090
  type: e.type,
8965
- status: existsSync17(resolve11(projectRoot, e.file)) ? "ok" : "unused",
9091
+ status: existsSync18(resolve11(projectRoot, e.file)) ? "ok" : "unused",
8966
9092
  message: "",
8967
9093
  suggestions: void 0
8968
9094
  }))
@@ -8976,11 +9102,11 @@ async function checkCommand(opts = {}) {
8976
9102
  const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-EIP2XM7T.js");
8977
9103
  const manifest = await loadManifest10(projectRoot);
8978
9104
  const appDir = resolve11(projectRoot, "app");
8979
- const pageFiles = existsSync17(appDir) ? findTsxFiles(appDir) : [];
9105
+ const pageFiles = existsSync18(appDir) ? findTsxFiles(appDir) : [];
8980
9106
  if (manifest.shared.length > 0 && pageFiles.length > 0) {
8981
9107
  const reuseWarnings = [];
8982
9108
  for (const file of pageFiles) {
8983
- const code = readFileSync13(file, "utf-8");
9109
+ const code = readFileSync14(file, "utf-8");
8984
9110
  const relativePath = file.replace(projectRoot + "/", "");
8985
9111
  const route = "/" + relativePath.replace(/^app\//, "").replace(/\/page\.tsx$/, "").replace(/^\(.*?\)\//, "");
8986
9112
  const pageType = inferPageTypeFromRoute2(route);
@@ -9091,12 +9217,12 @@ import {
9091
9217
  generateSharedComponent as generateSharedComponent4,
9092
9218
  integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2
9093
9219
  } from "@getcoherent/core";
9094
- import { existsSync as existsSync18 } from "fs";
9220
+ import { existsSync as existsSync19 } from "fs";
9095
9221
  import { resolve as resolve12 } from "path";
9096
9222
 
9097
9223
  // src/utils/ds-files.ts
9098
9224
  import { mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
9099
- import { join as join12, dirname as dirname5 } from "path";
9225
+ import { join as join13, dirname as dirname5 } from "path";
9100
9226
  import { DesignSystemGenerator } from "@getcoherent/core";
9101
9227
  var SHARED_DS_KEYS = [
9102
9228
  "app/design-system/shared/page.tsx",
@@ -9110,7 +9236,7 @@ async function writeDesignSystemFiles(projectRoot, config2, options) {
9110
9236
  const toWrite = options?.sharedOnly ? new Map([...files].filter(([path3]) => SHARED_DS_KEYS.includes(path3))) : files;
9111
9237
  const written = [];
9112
9238
  for (const [relativePath, content] of toWrite) {
9113
- const fullPath = join12(projectRoot, relativePath);
9239
+ const fullPath = join13(projectRoot, relativePath);
9114
9240
  await mkdir3(dirname5(fullPath), { recursive: true });
9115
9241
  await writeFile4(fullPath, content, "utf-8");
9116
9242
  written.push(relativePath);
@@ -9246,7 +9372,7 @@ function createComponentsCommand() {
9246
9372
  if (updated) console.log(chalk22.cyan(" Updated app/layout.tsx to use shared layout components.\n"));
9247
9373
  }
9248
9374
  const sharedPagePath = resolve12(project.root, "app/design-system/shared/page.tsx");
9249
- if (!existsSync18(sharedPagePath)) {
9375
+ if (!existsSync19(sharedPagePath)) {
9250
9376
  try {
9251
9377
  const dsm = new DesignSystemManager10(project.configPath);
9252
9378
  await dsm.load();
@@ -9272,8 +9398,8 @@ function createComponentsCommand() {
9272
9398
  import chalk23 from "chalk";
9273
9399
  import ora6 from "ora";
9274
9400
  import { writeFile as writeFile5, mkdir as mkdir4 } from "fs/promises";
9275
- import { resolve as resolve13, join as join13, dirname as dirname6 } from "path";
9276
- 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";
9277
9403
  import {
9278
9404
  FigmaClient,
9279
9405
  parseFigmaFileResponse,
@@ -9420,7 +9546,7 @@ async function importFigmaAction(urlOrKey, opts) {
9420
9546
  stats.filesWritten.push(filePath);
9421
9547
  return;
9422
9548
  }
9423
- const fullPath = join13(projectRoot, filePath);
9549
+ const fullPath = join14(projectRoot, filePath);
9424
9550
  await mkdir4(dirname6(fullPath), { recursive: true });
9425
9551
  await writeFile5(fullPath, content, "utf-8");
9426
9552
  stats.filesWritten.push(filePath);
@@ -9522,7 +9648,7 @@ async function importFigmaAction(urlOrKey, opts) {
9522
9648
  spinner.start("Updating design-system.config.ts...");
9523
9649
  const configPath = resolve13(projectRoot, DESIGN_SYSTEM_CONFIG_PATH);
9524
9650
  const dsm = new DesignSystemManager11(configPath);
9525
- if (existsSync19(configPath)) {
9651
+ if (existsSync20(configPath)) {
9526
9652
  await dsm.load();
9527
9653
  const existing = dsm.getConfig();
9528
9654
  dsm.updateConfig({
@@ -9551,8 +9677,8 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
9551
9677
  stats.configUpdated = true;
9552
9678
  spinner.succeed("design-system.config.ts updated");
9553
9679
  spinner.start("Ensuring root layout...");
9554
- const layoutPath = join13(projectRoot, "app/layout.tsx");
9555
- if (!existsSync19(layoutPath)) {
9680
+ const layoutPath = join14(projectRoot, "app/layout.tsx");
9681
+ if (!existsSync20(layoutPath)) {
9556
9682
  await mkdir4(dirname6(layoutPath), { recursive: true });
9557
9683
  await writeFile5(layoutPath, MINIMAL_ROOT_LAYOUT, "utf-8");
9558
9684
  stats.filesWritten.push("app/layout.tsx");
@@ -9642,8 +9768,8 @@ async function dsRegenerateCommand() {
9642
9768
  // src/commands/update.ts
9643
9769
  import chalk25 from "chalk";
9644
9770
  import ora8 from "ora";
9645
- import { readFileSync as readFileSync14, existsSync as existsSync20 } from "fs";
9646
- import { join as join14 } from "path";
9771
+ import { readFileSync as readFileSync15, existsSync as existsSync21 } from "fs";
9772
+ import { join as join15 } from "path";
9647
9773
  import { DesignSystemManager as DesignSystemManager13, CLI_VERSION as CLI_VERSION4 } from "@getcoherent/core";
9648
9774
 
9649
9775
  // src/utils/migrations.ts
@@ -9812,20 +9938,20 @@ var EXPECTED_CSS_VARS = [
9812
9938
  "--sidebar-ring"
9813
9939
  ];
9814
9940
  function checkMissingCssVars(projectRoot) {
9815
- const globalsPath = join14(projectRoot, "app", "globals.css");
9816
- if (!existsSync20(globalsPath)) return [];
9941
+ const globalsPath = join15(projectRoot, "app", "globals.css");
9942
+ if (!existsSync21(globalsPath)) return [];
9817
9943
  try {
9818
- const content = readFileSync14(globalsPath, "utf-8");
9944
+ const content = readFileSync15(globalsPath, "utf-8");
9819
9945
  return EXPECTED_CSS_VARS.filter((v) => !content.includes(v));
9820
9946
  } catch {
9821
9947
  return [];
9822
9948
  }
9823
9949
  }
9824
9950
  function patchGlobalsCss(projectRoot, missingVars) {
9825
- const globalsPath = join14(projectRoot, "app", "globals.css");
9826
- if (!existsSync20(globalsPath) || missingVars.length === 0) return;
9827
- const { writeFileSync: writeFileSync13 } = __require("fs");
9828
- 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");
9829
9955
  const defaultValues = {
9830
9956
  "--chart-1": "220 70% 50%",
9831
9957
  "--chart-2": "160 60% 45%",
@@ -9853,7 +9979,7 @@ function patchGlobalsCss(projectRoot, missingVars) {
9853
9979
  const lightSectionEnd = content.indexOf("}");
9854
9980
  if (lightSectionEnd > 0) {
9855
9981
  content = content.slice(0, lightSectionEnd) + "\n" + injection + "\n" + content.slice(lightSectionEnd);
9856
- writeFileSync13(globalsPath, content, "utf-8");
9982
+ writeFileSync14(globalsPath, content, "utf-8");
9857
9983
  }
9858
9984
  }
9859
9985
 
@@ -9903,26 +10029,26 @@ async function undoCommand(options) {
9903
10029
  // src/commands/sync.ts
9904
10030
  import chalk27 from "chalk";
9905
10031
  import ora9 from "ora";
9906
- import { existsSync as existsSync21, readFileSync as readFileSync15 } from "fs";
9907
- 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";
9908
10034
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
9909
10035
  import { DesignSystemManager as DesignSystemManager14 } from "@getcoherent/core";
9910
10036
  import { loadManifest as loadManifest12, saveManifest as saveManifest6, findSharedComponent } from "@getcoherent/core";
9911
10037
  function extractTokensFromProject(projectRoot) {
9912
10038
  const lightColors = {};
9913
10039
  const darkColors = {};
9914
- const globalsPath = join15(projectRoot, "app", "globals.css");
9915
- if (existsSync21(globalsPath)) {
9916
- 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");
9917
10043
  const rootMatch = css.match(/:root\s*\{([^}]+)\}/s);
9918
10044
  if (rootMatch) parseVarsInto(rootMatch[1], lightColors);
9919
10045
  const darkMatch = css.match(/\.dark\s*\{([^}]+)\}/s);
9920
10046
  if (darkMatch) parseVarsInto(darkMatch[1], darkColors);
9921
10047
  }
9922
- const layoutPath = join15(projectRoot, "app", "layout.tsx");
10048
+ const layoutPath = join16(projectRoot, "app", "layout.tsx");
9923
10049
  let layoutCode = "";
9924
- if (existsSync21(layoutPath)) {
9925
- layoutCode = readFileSync15(layoutPath, "utf-8");
10050
+ if (existsSync22(layoutPath)) {
10051
+ layoutCode = readFileSync16(layoutPath, "utf-8");
9926
10052
  const rootInline = layoutCode.match(/:root\s*\{([^}]+)\}/s);
9927
10053
  if (rootInline && Object.keys(lightColors).length === 0) {
9928
10054
  parseVarsInto(rootInline[1], lightColors);
@@ -9940,7 +10066,7 @@ function extractTokensFromProject(projectRoot) {
9940
10066
  defaultMode = "dark";
9941
10067
  }
9942
10068
  let radius;
9943
- const allCss = [existsSync21(globalsPath) ? readFileSync15(globalsPath, "utf-8") : "", layoutCode].join("\n");
10069
+ const allCss = [existsSync22(globalsPath) ? readFileSync16(globalsPath, "utf-8") : "", layoutCode].join("\n");
9944
10070
  const radiusMatch = allCss.match(/--radius:\s*([^;]+);/);
9945
10071
  if (radiusMatch) radius = radiusMatch[1].trim();
9946
10072
  return {
@@ -9963,14 +10089,14 @@ function parseVarsInto(block, target) {
9963
10089
  }
9964
10090
  async function detectCustomComponents(projectRoot, allPageCode) {
9965
10091
  const results = [];
9966
- const componentsDir = join15(projectRoot, "components");
9967
- if (!existsSync21(componentsDir)) return results;
10092
+ const componentsDir = join16(projectRoot, "components");
10093
+ if (!existsSync22(componentsDir)) return results;
9968
10094
  const files = [];
9969
10095
  await walkForTsx(componentsDir, files, ["ui"]);
9970
10096
  const fileResults = await Promise.all(
9971
10097
  files.map(async (filePath) => {
9972
10098
  const code = await readFile4(filePath, "utf-8");
9973
- const relFile = relative5(projectRoot, filePath);
10099
+ const relFile = relative6(projectRoot, filePath);
9974
10100
  const exportedNames = extractExportedComponentNames2(code);
9975
10101
  return exportedNames.map((name) => ({
9976
10102
  name,
@@ -9991,7 +10117,7 @@ async function walkForTsx(dir, files, skipDirs) {
9991
10117
  return;
9992
10118
  }
9993
10119
  for (const e of entries) {
9994
- const full = join15(dir, e.name);
10120
+ const full = join16(dir, e.name);
9995
10121
  if (e.isDirectory()) {
9996
10122
  if (skipDirs.includes(e.name) || e.name.startsWith(".")) continue;
9997
10123
  await walkForTsx(full, files, skipDirs);
@@ -10065,14 +10191,14 @@ async function discoverPages(appDir) {
10065
10191
  return;
10066
10192
  }
10067
10193
  for (const entry of entries) {
10068
- const full = join15(dir, entry.name);
10194
+ const full = join16(dir, entry.name);
10069
10195
  if (entry.isDirectory()) {
10070
10196
  if (["design-system", "api", "_not-found"].includes(entry.name)) continue;
10071
10197
  if (entry.name.startsWith(".")) continue;
10072
10198
  await walk(full);
10073
10199
  } else if (entry.name === "page.tsx" || entry.name === "page.jsx") {
10074
10200
  const code = await readFile4(full, "utf-8");
10075
- const routeDir = dirname7(relative5(appDir, full));
10201
+ const routeDir = dirname7(relative6(appDir, full));
10076
10202
  let route = routeDir === "." ? "/" : "/" + routeDir;
10077
10203
  route = route.replace(/\/\([^)]+\)/g, "");
10078
10204
  if (!route.startsWith("/")) route = "/" + route;
@@ -10154,8 +10280,8 @@ async function syncCommand(options = {}) {
10154
10280
  if (dryRun) console.log(chalk27.yellow(" [dry-run] No files will be written\n"));
10155
10281
  const spinner = ora9("Scanning project files...").start();
10156
10282
  try {
10157
- const appDir = join15(project.root, "app");
10158
- if (!existsSync21(appDir)) {
10283
+ const appDir = join16(project.root, "app");
10284
+ if (!existsSync22(appDir)) {
10159
10285
  spinner.fail("No app/ directory found");
10160
10286
  process.exit(1);
10161
10287
  }
@@ -10385,53 +10511,53 @@ async function syncCommand(options = {}) {
10385
10511
  // src/commands/migrate.ts
10386
10512
  import chalk28 from "chalk";
10387
10513
  import ora10 from "ora";
10388
- import { existsSync as existsSync22, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync11, readFileSync as readFileSync16, readdirSync as readdirSync9 } from "fs";
10389
- 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";
10390
10516
  function backupDir(projectRoot) {
10391
10517
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
10392
- return join16(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10518
+ return join17(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10393
10519
  }
10394
10520
  function guardPath(projectRoot) {
10395
- return join16(projectRoot, ".coherent", "migration-in-progress");
10521
+ return join17(projectRoot, ".coherent", "migration-in-progress");
10396
10522
  }
10397
10523
  function createBackup2(projectRoot) {
10398
- const uiDir = join16(projectRoot, "components", "ui");
10524
+ const uiDir = join17(projectRoot, "components", "ui");
10399
10525
  const dest = backupDir(projectRoot);
10400
10526
  mkdirSync8(dest, { recursive: true });
10401
- if (existsSync22(uiDir)) {
10402
- cpSync(uiDir, join16(dest, "components-ui"), { recursive: true });
10527
+ if (existsSync23(uiDir)) {
10528
+ cpSync(uiDir, join17(dest, "components-ui"), { recursive: true });
10403
10529
  }
10404
- const configPath = join16(projectRoot, "design-system.config.ts");
10405
- if (existsSync22(configPath)) {
10406
- 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"));
10407
10533
  }
10408
10534
  return dest;
10409
10535
  }
10410
10536
  function setGuard(projectRoot, backupPath) {
10411
10537
  const guard = guardPath(projectRoot);
10412
- mkdirSync8(join16(projectRoot, ".coherent"), { recursive: true });
10413
- 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() }));
10414
10540
  }
10415
10541
  function clearGuard(projectRoot) {
10416
10542
  const guard = guardPath(projectRoot);
10417
- if (existsSync22(guard)) rmSync6(guard);
10543
+ if (existsSync23(guard)) rmSync6(guard);
10418
10544
  }
10419
10545
  function rollback(projectRoot) {
10420
10546
  const guard = guardPath(projectRoot);
10421
- if (!existsSync22(guard)) return false;
10547
+ if (!existsSync23(guard)) return false;
10422
10548
  try {
10423
- const data = JSON.parse(readFileSync16(guard, "utf-8"));
10549
+ const data = JSON.parse(readFileSync17(guard, "utf-8"));
10424
10550
  const backup = data.backup;
10425
- if (!existsSync22(backup)) return false;
10426
- const uiBackup = join16(backup, "components-ui");
10427
- const uiDir = join16(projectRoot, "components", "ui");
10428
- if (existsSync22(uiBackup)) {
10429
- 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 });
10430
10556
  cpSync(uiBackup, uiDir, { recursive: true });
10431
10557
  }
10432
- const configBackup = join16(backup, "design-system.config.ts");
10433
- const configDest = join16(projectRoot, "design-system.config.ts");
10434
- 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)) {
10435
10561
  cpSync(configBackup, configDest);
10436
10562
  }
10437
10563
  clearGuard(projectRoot);
@@ -10459,13 +10585,13 @@ async function migrateAction(options) {
10459
10585
  return;
10460
10586
  }
10461
10587
  const guard = guardPath(projectRoot);
10462
- if (existsSync22(guard)) {
10588
+ if (existsSync23(guard)) {
10463
10589
  console.log(chalk28.yellow("A migration is already in progress."));
10464
10590
  console.log(chalk28.dim("Run `coherent migrate --rollback` to undo, or delete .coherent/migration-in-progress"));
10465
10591
  return;
10466
10592
  }
10467
- const uiDir = join16(projectRoot, "components", "ui");
10468
- if (!existsSync22(uiDir)) {
10593
+ const uiDir = join17(projectRoot, "components", "ui");
10594
+ if (!existsSync23(uiDir)) {
10469
10595
  console.log(chalk28.yellow("No components/ui directory found. Nothing to migrate."));
10470
10596
  return;
10471
10597
  }
@@ -10491,8 +10617,8 @@ Found ${migratable.length} component(s) to migrate:`));
10491
10617
  setGuard(projectRoot, backup);
10492
10618
  try {
10493
10619
  for (const id of migratable) {
10494
- const filePath = join16(uiDir, `${id}.tsx`);
10495
- if (existsSync22(filePath)) rmSync6(filePath);
10620
+ const filePath = join17(uiDir, `${id}.tsx`);
10621
+ if (existsSync23(filePath)) rmSync6(filePath);
10496
10622
  }
10497
10623
  const results = await provider.installBatch(migratable, projectRoot, { force: true });
10498
10624
  let migrated = 0;
@@ -10514,20 +10640,20 @@ Found ${migratable.length} component(s) to migrate:`));
10514
10640
  }
10515
10641
 
10516
10642
  // src/utils/update-notifier.ts
10517
- import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync17, writeFileSync as writeFileSync12 } from "fs";
10518
- 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";
10519
10645
  import { homedir } from "os";
10520
10646
  import chalk29 from "chalk";
10521
10647
  import { CLI_VERSION as CLI_VERSION5 } from "@getcoherent/core";
10522
10648
  var DEBUG5 = process.env.COHERENT_DEBUG === "1";
10523
10649
  var PACKAGE_NAME = "@getcoherent/cli";
10524
- var CACHE_DIR = join17(homedir(), ".coherent");
10525
- 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");
10526
10652
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10527
10653
  function readCache() {
10528
10654
  try {
10529
- if (!existsSync23(CACHE_FILE)) return null;
10530
- const raw = readFileSync17(CACHE_FILE, "utf-8");
10655
+ if (!existsSync24(CACHE_FILE)) return null;
10656
+ const raw = readFileSync18(CACHE_FILE, "utf-8");
10531
10657
  return JSON.parse(raw);
10532
10658
  } catch (e) {
10533
10659
  if (DEBUG5) console.error("Failed to read update cache:", e);
@@ -10536,8 +10662,8 @@ function readCache() {
10536
10662
  }
10537
10663
  function writeCache(data) {
10538
10664
  try {
10539
- if (!existsSync23(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10540
- 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");
10541
10667
  } catch (e) {
10542
10668
  if (DEBUG5) console.error("Failed to write update cache:", e);
10543
10669
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.6.38",
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.38"
46
+ "@getcoherent/core": "0.6.39"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^20.11.0",