@getcoherent/cli 0.6.38 → 0.6.40

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 -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,74 @@ 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(
8649
+ sidebarComponentPath2,
8650
+ gen.generateSharedSidebarCode(),
8651
+ projectRoot,
8652
+ backups
8653
+ );
8654
+ if (sidebarResult2.ok) {
8655
+ fixes.push("Regenerated sidebar component");
8656
+ console.log(chalk15.green(" \u2714 Regenerated sidebar component"));
8657
+ } else {
8658
+ console.log(chalk15.yellow(" \u26A0 Sidebar regeneration failed validation \u2014 restored original"));
8659
+ }
8559
8660
  }
8560
8661
  }
8561
8662
  const rootPagePath = resolve10(projectRoot, "app", "page.tsx");
8562
8663
  const publicPagePath = resolve10(projectRoot, "app", "(public)", "page.tsx");
8563
- if (existsSync16(rootPagePath) && !existsSync16(publicPagePath)) {
8664
+ if (existsSync17(rootPagePath) && !existsSync17(publicPagePath)) {
8564
8665
  const { renameSync } = await import("fs");
8565
8666
  mkdirSync7(resolve10(projectRoot, "app", "(public)"), { recursive: true });
8566
8667
  renameSync(rootPagePath, publicPagePath);
@@ -8568,27 +8669,42 @@ async function fixCommand(opts = {}) {
8568
8669
  console.log(chalk15.green(" \u2714 Moved app/page.tsx \u2192 app/(public)/page.tsx (gets Header/Footer)"));
8569
8670
  }
8570
8671
  const themeTogglePath = resolve10(projectRoot, "components", "shared", "theme-toggle.tsx");
8571
- if (!existsSync16(themeTogglePath)) {
8672
+ if (!existsSync17(themeTogglePath)) {
8572
8673
  const { generateThemeToggleCode } = await import("./code-generator-D3ZHOO4M.js");
8573
8674
  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"));
8675
+ const themeResult = safeWrite(themeTogglePath, generateThemeToggleCode(), projectRoot, backups);
8676
+ if (themeResult.ok) {
8677
+ fixes.push("Generated ThemeToggle component (components/shared/theme-toggle.tsx)");
8678
+ console.log(chalk15.green(" \u2714 Generated ThemeToggle component"));
8679
+ } else {
8680
+ console.log(chalk15.yellow(" \u26A0 ThemeToggle generation failed validation"));
8681
+ }
8577
8682
  }
8578
8683
  }
8579
8684
  }
8580
- } catch {
8685
+ } catch (err) {
8686
+ console.log(chalk15.yellow(` \u26A0 Layout repair skipped: ${err instanceof Error ? err.message : "unknown error"}`));
8581
8687
  }
8582
8688
  if (!skipQuality) {
8583
8689
  let qualityFixCount = 0;
8584
8690
  const qualityFixDetails = [];
8585
8691
  for (const file of userTsxFiles) {
8586
- const content = readFileSync12(file, "utf-8");
8692
+ const content = readFileSync13(file, "utf-8");
8587
8693
  const { code: autoFixed, fixes: fileFixes } = await autoFixCode(content);
8588
8694
  if (autoFixed !== content) {
8589
- if (!dryRun) writeFileSync10(file, autoFixed, "utf-8");
8590
- qualityFixCount++;
8591
- qualityFixDetails.push(...fileFixes);
8695
+ if (!dryRun) {
8696
+ const qResult = safeWrite(file, autoFixed, projectRoot, backups);
8697
+ if (qResult.ok) {
8698
+ modifiedFiles.push(file);
8699
+ qualityFixCount++;
8700
+ qualityFixDetails.push(...fileFixes);
8701
+ } else {
8702
+ console.log(chalk15.yellow(` \u26A0 Quality fix rolled back for ${relative5(projectRoot, file)} (parse error)`));
8703
+ }
8704
+ } else {
8705
+ qualityFixCount++;
8706
+ qualityFixDetails.push(...fileFixes);
8707
+ }
8592
8708
  }
8593
8709
  }
8594
8710
  if (qualityFixCount > 0) {
@@ -8598,11 +8714,22 @@ async function fixCommand(opts = {}) {
8598
8714
  console.log(chalk15.green(` \u2714 ${verb} ${uniqueFixes.length} quality issue type(s): ${uniqueFixes.join(", ")}`));
8599
8715
  }
8600
8716
  }
8717
+ for (const file of modifiedFiles) {
8718
+ if (!backups.has(file)) continue;
8719
+ const before = backups.get(file);
8720
+ const after = readFileSync13(file, "utf-8");
8721
+ const issues = verifyIncrementalEdit(before, after);
8722
+ if (issues.length > 0) {
8723
+ for (const issue of issues) {
8724
+ remaining.push(`${relative5(projectRoot, file)}: ${issue.message}`);
8725
+ }
8726
+ }
8727
+ }
8601
8728
  let totalErrors = 0;
8602
8729
  let totalWarnings = 0;
8603
8730
  const fileIssues = [];
8604
8731
  for (const file of allTsxFiles) {
8605
- const code = dryRun ? readFileSync12(file, "utf-8") : readFileSync12(file, "utf-8");
8732
+ const code = dryRun ? readFileSync13(file, "utf-8") : readFileSync13(file, "utf-8");
8606
8733
  const relativePath = file.replace(projectRoot + "/", "");
8607
8734
  const baseName = file.split("/").pop() || "";
8608
8735
  const isAuthPage = relativePath.includes("(auth)");
@@ -8653,8 +8780,8 @@ async function fixCommand(opts = {}) {
8653
8780
  }
8654
8781
  for (const entry of manifest.shared) {
8655
8782
  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;
8783
+ const layoutPaths = isUsedInLayout(project.root, entry.name);
8784
+ const fullActual = [.../* @__PURE__ */ new Set([...actualUsedIn, ...layoutPaths])];
8658
8785
  if (!arraysEqual(fullActual, entry.usedIn || [])) {
8659
8786
  entry.usedIn = fullActual;
8660
8787
  manifestModified = true;
@@ -8691,12 +8818,18 @@ async function fixCommand(opts = {}) {
8691
8818
  }
8692
8819
  for (const entry of manifest.shared) {
8693
8820
  const actualUsedIn = findPagesImporting(project.root, entry.name, entry.file);
8694
- const inLayout = isUsedInLayout(project.root, entry.name);
8695
- if (actualUsedIn.length === 0 && !inLayout) {
8821
+ const layoutPaths2 = isUsedInLayout(project.root, entry.name);
8822
+ if (actualUsedIn.length === 0 && layoutPaths2.length === 0) {
8696
8823
  remaining.push(`${entry.id} (${entry.name}) \u2014 unused. Remove: coherent components shared remove ${entry.id}`);
8697
8824
  }
8698
8825
  }
8699
- } catch {
8826
+ } catch (err) {
8827
+ const isNotFound = err instanceof Error && "code" in err && err.code === "ENOENT";
8828
+ if (!isNotFound) {
8829
+ console.log(
8830
+ chalk15.yellow(` \u26A0 Component manifest check skipped: ${err instanceof Error ? err.message : "unknown error"}`)
8831
+ );
8832
+ }
8700
8833
  }
8701
8834
  if (fixes.length === 0 && totalErrors === 0 && totalWarnings === 0 && remaining.length === 0) {
8702
8835
  console.log(chalk15.green("\n \u2705 Everything looks good \u2014 no issues found\n"));
@@ -8727,7 +8860,7 @@ async function fixCommand(opts = {}) {
8727
8860
  // src/commands/check.ts
8728
8861
  import chalk16 from "chalk";
8729
8862
  import { resolve as resolve11 } from "path";
8730
- import { readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync3, existsSync as existsSync17 } from "fs";
8863
+ import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync3, existsSync as existsSync18 } from "fs";
8731
8864
  import { loadManifest as loadManifest10 } from "@getcoherent/core";
8732
8865
  var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["node_modules", "design-system"]);
8733
8866
  function findTsxFiles(dir) {
@@ -8784,7 +8917,7 @@ async function checkCommand(opts = {}) {
8784
8917
  "NATIVE_TABLE"
8785
8918
  ]);
8786
8919
  for (const file of files) {
8787
- const code = readFileSync13(file, "utf-8");
8920
+ const code = readFileSync14(file, "utf-8");
8788
8921
  const relativePath = file.replace(projectRoot + "/", "");
8789
8922
  const baseName = file.split("/").pop() || "";
8790
8923
  const isAuthPage = relativePath.includes("(auth)");
@@ -8826,7 +8959,7 @@ async function checkCommand(opts = {}) {
8826
8959
  routeSet.add("/");
8827
8960
  routeSet.add("#");
8828
8961
  for (const file of files) {
8829
- const code = readFileSync13(file, "utf-8");
8962
+ const code = readFileSync14(file, "utf-8");
8830
8963
  const relativePath = file.replace(projectRoot + "/", "");
8831
8964
  const lines = code.split("\n");
8832
8965
  const linkHrefRe = /href\s*=\s*["'](\/[a-z0-9/-]*)["']/gi;
@@ -8859,7 +8992,7 @@ async function checkCommand(opts = {}) {
8859
8992
  if (manifest.shared.length > 0) {
8860
8993
  for (const entry of manifest.shared) {
8861
8994
  const fullPath = resolve11(project.root, entry.file);
8862
- if (!existsSync17(fullPath)) {
8995
+ if (!existsSync18(fullPath)) {
8863
8996
  result.pages.withErrors++;
8864
8997
  if (!opts.json) console.log(chalk16.red(`
8865
8998
  \u2717 Missing shared component file: ${entry.id} (${entry.file})`));
@@ -8884,7 +9017,7 @@ async function checkCommand(opts = {}) {
8884
9017
  let _nameMismatch = 0;
8885
9018
  for (const entry of manifest.shared) {
8886
9019
  const filePath = resolve11(projectRoot, entry.file);
8887
- const fileExists = existsSync17(filePath);
9020
+ const fileExists = existsSync18(filePath);
8888
9021
  if (!fileExists) {
8889
9022
  _orphaned++;
8890
9023
  if (!opts.json) {
@@ -8894,7 +9027,7 @@ async function checkCommand(opts = {}) {
8894
9027
  continue;
8895
9028
  }
8896
9029
  try {
8897
- const code = readFileSync13(filePath, "utf-8");
9030
+ const code = readFileSync14(filePath, "utf-8");
8898
9031
  const actualExports = extractExportedComponentNames(code);
8899
9032
  if (actualExports.length > 0 && !actualExports.includes(entry.name)) {
8900
9033
  _nameMismatch++;
@@ -8910,10 +9043,10 @@ async function checkCommand(opts = {}) {
8910
9043
  } catch {
8911
9044
  }
8912
9045
  const actualUsedIn = findPagesImporting(projectRoot, entry.name, entry.file);
8913
- const inLayout = isUsedInLayout(projectRoot, entry.name);
8914
- const totalUsage = actualUsedIn.length + (inLayout ? 1 : 0);
9046
+ const layoutPaths = isUsedInLayout(projectRoot, entry.name);
9047
+ const totalUsage = actualUsedIn.length + layoutPaths.length;
8915
9048
  const manifestUsedIn = entry.usedIn || [];
8916
- const fullActual = inLayout ? [.../* @__PURE__ */ new Set([...actualUsedIn, "app/layout.tsx"])] : actualUsedIn;
9049
+ const fullActual = [.../* @__PURE__ */ new Set([...actualUsedIn, ...layoutPaths])];
8917
9050
  const isStale = manifestUsedIn.length !== fullActual.length || !manifestUsedIn.every((p) => fullActual.includes(p));
8918
9051
  if (isStale) _staleUsedIn++;
8919
9052
  if (totalUsage === 0) {
@@ -8924,7 +9057,7 @@ async function checkCommand(opts = {}) {
8924
9057
  }
8925
9058
  } else {
8926
9059
  consistent++;
8927
- const usageDesc = inLayout ? `layout + ${actualUsedIn.length} page(s)` : `${actualUsedIn.length} page(s)`;
9060
+ const usageDesc = layoutPaths.length > 0 ? `layout(${layoutPaths.length}) + ${actualUsedIn.length} page(s)` : `${actualUsedIn.length} page(s)`;
8928
9061
  if (!opts.json) {
8929
9062
  const staleNote = isStale ? chalk16.yellow(" [usedIn stale]") : "";
8930
9063
  console.log(chalk16.green(` \u2714 ${entry.id} (${entry.name})`) + chalk16.dim(` \u2014 ${usageDesc}`) + staleNote);
@@ -8962,7 +9095,7 @@ async function checkCommand(opts = {}) {
8962
9095
  id: e.id,
8963
9096
  name: e.name,
8964
9097
  type: e.type,
8965
- status: existsSync17(resolve11(projectRoot, e.file)) ? "ok" : "unused",
9098
+ status: existsSync18(resolve11(projectRoot, e.file)) ? "ok" : "unused",
8966
9099
  message: "",
8967
9100
  suggestions: void 0
8968
9101
  }))
@@ -8976,11 +9109,11 @@ async function checkCommand(opts = {}) {
8976
9109
  const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-EIP2XM7T.js");
8977
9110
  const manifest = await loadManifest10(projectRoot);
8978
9111
  const appDir = resolve11(projectRoot, "app");
8979
- const pageFiles = existsSync17(appDir) ? findTsxFiles(appDir) : [];
9112
+ const pageFiles = existsSync18(appDir) ? findTsxFiles(appDir) : [];
8980
9113
  if (manifest.shared.length > 0 && pageFiles.length > 0) {
8981
9114
  const reuseWarnings = [];
8982
9115
  for (const file of pageFiles) {
8983
- const code = readFileSync13(file, "utf-8");
9116
+ const code = readFileSync14(file, "utf-8");
8984
9117
  const relativePath = file.replace(projectRoot + "/", "");
8985
9118
  const route = "/" + relativePath.replace(/^app\//, "").replace(/\/page\.tsx$/, "").replace(/^\(.*?\)\//, "");
8986
9119
  const pageType = inferPageTypeFromRoute2(route);
@@ -9091,12 +9224,12 @@ import {
9091
9224
  generateSharedComponent as generateSharedComponent4,
9092
9225
  integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2
9093
9226
  } from "@getcoherent/core";
9094
- import { existsSync as existsSync18 } from "fs";
9227
+ import { existsSync as existsSync19 } from "fs";
9095
9228
  import { resolve as resolve12 } from "path";
9096
9229
 
9097
9230
  // src/utils/ds-files.ts
9098
9231
  import { mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
9099
- import { join as join12, dirname as dirname5 } from "path";
9232
+ import { join as join13, dirname as dirname5 } from "path";
9100
9233
  import { DesignSystemGenerator } from "@getcoherent/core";
9101
9234
  var SHARED_DS_KEYS = [
9102
9235
  "app/design-system/shared/page.tsx",
@@ -9110,7 +9243,7 @@ async function writeDesignSystemFiles(projectRoot, config2, options) {
9110
9243
  const toWrite = options?.sharedOnly ? new Map([...files].filter(([path3]) => SHARED_DS_KEYS.includes(path3))) : files;
9111
9244
  const written = [];
9112
9245
  for (const [relativePath, content] of toWrite) {
9113
- const fullPath = join12(projectRoot, relativePath);
9246
+ const fullPath = join13(projectRoot, relativePath);
9114
9247
  await mkdir3(dirname5(fullPath), { recursive: true });
9115
9248
  await writeFile4(fullPath, content, "utf-8");
9116
9249
  written.push(relativePath);
@@ -9246,7 +9379,7 @@ function createComponentsCommand() {
9246
9379
  if (updated) console.log(chalk22.cyan(" Updated app/layout.tsx to use shared layout components.\n"));
9247
9380
  }
9248
9381
  const sharedPagePath = resolve12(project.root, "app/design-system/shared/page.tsx");
9249
- if (!existsSync18(sharedPagePath)) {
9382
+ if (!existsSync19(sharedPagePath)) {
9250
9383
  try {
9251
9384
  const dsm = new DesignSystemManager10(project.configPath);
9252
9385
  await dsm.load();
@@ -9272,8 +9405,8 @@ function createComponentsCommand() {
9272
9405
  import chalk23 from "chalk";
9273
9406
  import ora6 from "ora";
9274
9407
  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";
9408
+ import { resolve as resolve13, join as join14, dirname as dirname6 } from "path";
9409
+ import { existsSync as existsSync20 } from "fs";
9277
9410
  import {
9278
9411
  FigmaClient,
9279
9412
  parseFigmaFileResponse,
@@ -9420,7 +9553,7 @@ async function importFigmaAction(urlOrKey, opts) {
9420
9553
  stats.filesWritten.push(filePath);
9421
9554
  return;
9422
9555
  }
9423
- const fullPath = join13(projectRoot, filePath);
9556
+ const fullPath = join14(projectRoot, filePath);
9424
9557
  await mkdir4(dirname6(fullPath), { recursive: true });
9425
9558
  await writeFile5(fullPath, content, "utf-8");
9426
9559
  stats.filesWritten.push(filePath);
@@ -9522,7 +9655,7 @@ async function importFigmaAction(urlOrKey, opts) {
9522
9655
  spinner.start("Updating design-system.config.ts...");
9523
9656
  const configPath = resolve13(projectRoot, DESIGN_SYSTEM_CONFIG_PATH);
9524
9657
  const dsm = new DesignSystemManager11(configPath);
9525
- if (existsSync19(configPath)) {
9658
+ if (existsSync20(configPath)) {
9526
9659
  await dsm.load();
9527
9660
  const existing = dsm.getConfig();
9528
9661
  dsm.updateConfig({
@@ -9551,8 +9684,8 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
9551
9684
  stats.configUpdated = true;
9552
9685
  spinner.succeed("design-system.config.ts updated");
9553
9686
  spinner.start("Ensuring root layout...");
9554
- const layoutPath = join13(projectRoot, "app/layout.tsx");
9555
- if (!existsSync19(layoutPath)) {
9687
+ const layoutPath = join14(projectRoot, "app/layout.tsx");
9688
+ if (!existsSync20(layoutPath)) {
9556
9689
  await mkdir4(dirname6(layoutPath), { recursive: true });
9557
9690
  await writeFile5(layoutPath, MINIMAL_ROOT_LAYOUT, "utf-8");
9558
9691
  stats.filesWritten.push("app/layout.tsx");
@@ -9642,8 +9775,8 @@ async function dsRegenerateCommand() {
9642
9775
  // src/commands/update.ts
9643
9776
  import chalk25 from "chalk";
9644
9777
  import ora8 from "ora";
9645
- import { readFileSync as readFileSync14, existsSync as existsSync20 } from "fs";
9646
- import { join as join14 } from "path";
9778
+ import { readFileSync as readFileSync15, existsSync as existsSync21 } from "fs";
9779
+ import { join as join15 } from "path";
9647
9780
  import { DesignSystemManager as DesignSystemManager13, CLI_VERSION as CLI_VERSION4 } from "@getcoherent/core";
9648
9781
 
9649
9782
  // src/utils/migrations.ts
@@ -9812,20 +9945,20 @@ var EXPECTED_CSS_VARS = [
9812
9945
  "--sidebar-ring"
9813
9946
  ];
9814
9947
  function checkMissingCssVars(projectRoot) {
9815
- const globalsPath = join14(projectRoot, "app", "globals.css");
9816
- if (!existsSync20(globalsPath)) return [];
9948
+ const globalsPath = join15(projectRoot, "app", "globals.css");
9949
+ if (!existsSync21(globalsPath)) return [];
9817
9950
  try {
9818
- const content = readFileSync14(globalsPath, "utf-8");
9951
+ const content = readFileSync15(globalsPath, "utf-8");
9819
9952
  return EXPECTED_CSS_VARS.filter((v) => !content.includes(v));
9820
9953
  } catch {
9821
9954
  return [];
9822
9955
  }
9823
9956
  }
9824
9957
  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");
9958
+ const globalsPath = join15(projectRoot, "app", "globals.css");
9959
+ if (!existsSync21(globalsPath) || missingVars.length === 0) return;
9960
+ const { writeFileSync: writeFileSync14 } = __require("fs");
9961
+ let content = readFileSync15(globalsPath, "utf-8");
9829
9962
  const defaultValues = {
9830
9963
  "--chart-1": "220 70% 50%",
9831
9964
  "--chart-2": "160 60% 45%",
@@ -9853,7 +9986,7 @@ function patchGlobalsCss(projectRoot, missingVars) {
9853
9986
  const lightSectionEnd = content.indexOf("}");
9854
9987
  if (lightSectionEnd > 0) {
9855
9988
  content = content.slice(0, lightSectionEnd) + "\n" + injection + "\n" + content.slice(lightSectionEnd);
9856
- writeFileSync13(globalsPath, content, "utf-8");
9989
+ writeFileSync14(globalsPath, content, "utf-8");
9857
9990
  }
9858
9991
  }
9859
9992
 
@@ -9903,26 +10036,26 @@ async function undoCommand(options) {
9903
10036
  // src/commands/sync.ts
9904
10037
  import chalk27 from "chalk";
9905
10038
  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";
10039
+ import { existsSync as existsSync22, readFileSync as readFileSync16 } from "fs";
10040
+ import { join as join16, relative as relative6, dirname as dirname7 } from "path";
9908
10041
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
9909
10042
  import { DesignSystemManager as DesignSystemManager14 } from "@getcoherent/core";
9910
10043
  import { loadManifest as loadManifest12, saveManifest as saveManifest6, findSharedComponent } from "@getcoherent/core";
9911
10044
  function extractTokensFromProject(projectRoot) {
9912
10045
  const lightColors = {};
9913
10046
  const darkColors = {};
9914
- const globalsPath = join15(projectRoot, "app", "globals.css");
9915
- if (existsSync21(globalsPath)) {
9916
- const css = readFileSync15(globalsPath, "utf-8");
10047
+ const globalsPath = join16(projectRoot, "app", "globals.css");
10048
+ if (existsSync22(globalsPath)) {
10049
+ const css = readFileSync16(globalsPath, "utf-8");
9917
10050
  const rootMatch = css.match(/:root\s*\{([^}]+)\}/s);
9918
10051
  if (rootMatch) parseVarsInto(rootMatch[1], lightColors);
9919
10052
  const darkMatch = css.match(/\.dark\s*\{([^}]+)\}/s);
9920
10053
  if (darkMatch) parseVarsInto(darkMatch[1], darkColors);
9921
10054
  }
9922
- const layoutPath = join15(projectRoot, "app", "layout.tsx");
10055
+ const layoutPath = join16(projectRoot, "app", "layout.tsx");
9923
10056
  let layoutCode = "";
9924
- if (existsSync21(layoutPath)) {
9925
- layoutCode = readFileSync15(layoutPath, "utf-8");
10057
+ if (existsSync22(layoutPath)) {
10058
+ layoutCode = readFileSync16(layoutPath, "utf-8");
9926
10059
  const rootInline = layoutCode.match(/:root\s*\{([^}]+)\}/s);
9927
10060
  if (rootInline && Object.keys(lightColors).length === 0) {
9928
10061
  parseVarsInto(rootInline[1], lightColors);
@@ -9940,7 +10073,7 @@ function extractTokensFromProject(projectRoot) {
9940
10073
  defaultMode = "dark";
9941
10074
  }
9942
10075
  let radius;
9943
- const allCss = [existsSync21(globalsPath) ? readFileSync15(globalsPath, "utf-8") : "", layoutCode].join("\n");
10076
+ const allCss = [existsSync22(globalsPath) ? readFileSync16(globalsPath, "utf-8") : "", layoutCode].join("\n");
9944
10077
  const radiusMatch = allCss.match(/--radius:\s*([^;]+);/);
9945
10078
  if (radiusMatch) radius = radiusMatch[1].trim();
9946
10079
  return {
@@ -9963,14 +10096,14 @@ function parseVarsInto(block, target) {
9963
10096
  }
9964
10097
  async function detectCustomComponents(projectRoot, allPageCode) {
9965
10098
  const results = [];
9966
- const componentsDir = join15(projectRoot, "components");
9967
- if (!existsSync21(componentsDir)) return results;
10099
+ const componentsDir = join16(projectRoot, "components");
10100
+ if (!existsSync22(componentsDir)) return results;
9968
10101
  const files = [];
9969
10102
  await walkForTsx(componentsDir, files, ["ui"]);
9970
10103
  const fileResults = await Promise.all(
9971
10104
  files.map(async (filePath) => {
9972
10105
  const code = await readFile4(filePath, "utf-8");
9973
- const relFile = relative5(projectRoot, filePath);
10106
+ const relFile = relative6(projectRoot, filePath);
9974
10107
  const exportedNames = extractExportedComponentNames2(code);
9975
10108
  return exportedNames.map((name) => ({
9976
10109
  name,
@@ -9991,7 +10124,7 @@ async function walkForTsx(dir, files, skipDirs) {
9991
10124
  return;
9992
10125
  }
9993
10126
  for (const e of entries) {
9994
- const full = join15(dir, e.name);
10127
+ const full = join16(dir, e.name);
9995
10128
  if (e.isDirectory()) {
9996
10129
  if (skipDirs.includes(e.name) || e.name.startsWith(".")) continue;
9997
10130
  await walkForTsx(full, files, skipDirs);
@@ -10065,14 +10198,14 @@ async function discoverPages(appDir) {
10065
10198
  return;
10066
10199
  }
10067
10200
  for (const entry of entries) {
10068
- const full = join15(dir, entry.name);
10201
+ const full = join16(dir, entry.name);
10069
10202
  if (entry.isDirectory()) {
10070
10203
  if (["design-system", "api", "_not-found"].includes(entry.name)) continue;
10071
10204
  if (entry.name.startsWith(".")) continue;
10072
10205
  await walk(full);
10073
10206
  } else if (entry.name === "page.tsx" || entry.name === "page.jsx") {
10074
10207
  const code = await readFile4(full, "utf-8");
10075
- const routeDir = dirname7(relative5(appDir, full));
10208
+ const routeDir = dirname7(relative6(appDir, full));
10076
10209
  let route = routeDir === "." ? "/" : "/" + routeDir;
10077
10210
  route = route.replace(/\/\([^)]+\)/g, "");
10078
10211
  if (!route.startsWith("/")) route = "/" + route;
@@ -10154,8 +10287,8 @@ async function syncCommand(options = {}) {
10154
10287
  if (dryRun) console.log(chalk27.yellow(" [dry-run] No files will be written\n"));
10155
10288
  const spinner = ora9("Scanning project files...").start();
10156
10289
  try {
10157
- const appDir = join15(project.root, "app");
10158
- if (!existsSync21(appDir)) {
10290
+ const appDir = join16(project.root, "app");
10291
+ if (!existsSync22(appDir)) {
10159
10292
  spinner.fail("No app/ directory found");
10160
10293
  process.exit(1);
10161
10294
  }
@@ -10385,53 +10518,53 @@ async function syncCommand(options = {}) {
10385
10518
  // src/commands/migrate.ts
10386
10519
  import chalk28 from "chalk";
10387
10520
  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";
10521
+ import { existsSync as existsSync23, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync12, readFileSync as readFileSync17, readdirSync as readdirSync9 } from "fs";
10522
+ import { join as join17 } from "path";
10390
10523
  function backupDir(projectRoot) {
10391
10524
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
10392
- return join16(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10525
+ return join17(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10393
10526
  }
10394
10527
  function guardPath(projectRoot) {
10395
- return join16(projectRoot, ".coherent", "migration-in-progress");
10528
+ return join17(projectRoot, ".coherent", "migration-in-progress");
10396
10529
  }
10397
10530
  function createBackup2(projectRoot) {
10398
- const uiDir = join16(projectRoot, "components", "ui");
10531
+ const uiDir = join17(projectRoot, "components", "ui");
10399
10532
  const dest = backupDir(projectRoot);
10400
10533
  mkdirSync8(dest, { recursive: true });
10401
- if (existsSync22(uiDir)) {
10402
- cpSync(uiDir, join16(dest, "components-ui"), { recursive: true });
10534
+ if (existsSync23(uiDir)) {
10535
+ cpSync(uiDir, join17(dest, "components-ui"), { recursive: true });
10403
10536
  }
10404
- const configPath = join16(projectRoot, "design-system.config.ts");
10405
- if (existsSync22(configPath)) {
10406
- cpSync(configPath, join16(dest, "design-system.config.ts"));
10537
+ const configPath = join17(projectRoot, "design-system.config.ts");
10538
+ if (existsSync23(configPath)) {
10539
+ cpSync(configPath, join17(dest, "design-system.config.ts"));
10407
10540
  }
10408
10541
  return dest;
10409
10542
  }
10410
10543
  function setGuard(projectRoot, backupPath) {
10411
10544
  const guard = guardPath(projectRoot);
10412
- mkdirSync8(join16(projectRoot, ".coherent"), { recursive: true });
10413
- writeFileSync11(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10545
+ mkdirSync8(join17(projectRoot, ".coherent"), { recursive: true });
10546
+ writeFileSync12(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10414
10547
  }
10415
10548
  function clearGuard(projectRoot) {
10416
10549
  const guard = guardPath(projectRoot);
10417
- if (existsSync22(guard)) rmSync6(guard);
10550
+ if (existsSync23(guard)) rmSync6(guard);
10418
10551
  }
10419
10552
  function rollback(projectRoot) {
10420
10553
  const guard = guardPath(projectRoot);
10421
- if (!existsSync22(guard)) return false;
10554
+ if (!existsSync23(guard)) return false;
10422
10555
  try {
10423
- const data = JSON.parse(readFileSync16(guard, "utf-8"));
10556
+ const data = JSON.parse(readFileSync17(guard, "utf-8"));
10424
10557
  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 });
10558
+ if (!existsSync23(backup)) return false;
10559
+ const uiBackup = join17(backup, "components-ui");
10560
+ const uiDir = join17(projectRoot, "components", "ui");
10561
+ if (existsSync23(uiBackup)) {
10562
+ if (existsSync23(uiDir)) rmSync6(uiDir, { recursive: true });
10430
10563
  cpSync(uiBackup, uiDir, { recursive: true });
10431
10564
  }
10432
- const configBackup = join16(backup, "design-system.config.ts");
10433
- const configDest = join16(projectRoot, "design-system.config.ts");
10434
- if (existsSync22(configBackup)) {
10565
+ const configBackup = join17(backup, "design-system.config.ts");
10566
+ const configDest = join17(projectRoot, "design-system.config.ts");
10567
+ if (existsSync23(configBackup)) {
10435
10568
  cpSync(configBackup, configDest);
10436
10569
  }
10437
10570
  clearGuard(projectRoot);
@@ -10459,13 +10592,13 @@ async function migrateAction(options) {
10459
10592
  return;
10460
10593
  }
10461
10594
  const guard = guardPath(projectRoot);
10462
- if (existsSync22(guard)) {
10595
+ if (existsSync23(guard)) {
10463
10596
  console.log(chalk28.yellow("A migration is already in progress."));
10464
10597
  console.log(chalk28.dim("Run `coherent migrate --rollback` to undo, or delete .coherent/migration-in-progress"));
10465
10598
  return;
10466
10599
  }
10467
- const uiDir = join16(projectRoot, "components", "ui");
10468
- if (!existsSync22(uiDir)) {
10600
+ const uiDir = join17(projectRoot, "components", "ui");
10601
+ if (!existsSync23(uiDir)) {
10469
10602
  console.log(chalk28.yellow("No components/ui directory found. Nothing to migrate."));
10470
10603
  return;
10471
10604
  }
@@ -10491,8 +10624,8 @@ Found ${migratable.length} component(s) to migrate:`));
10491
10624
  setGuard(projectRoot, backup);
10492
10625
  try {
10493
10626
  for (const id of migratable) {
10494
- const filePath = join16(uiDir, `${id}.tsx`);
10495
- if (existsSync22(filePath)) rmSync6(filePath);
10627
+ const filePath = join17(uiDir, `${id}.tsx`);
10628
+ if (existsSync23(filePath)) rmSync6(filePath);
10496
10629
  }
10497
10630
  const results = await provider.installBatch(migratable, projectRoot, { force: true });
10498
10631
  let migrated = 0;
@@ -10514,20 +10647,20 @@ Found ${migratable.length} component(s) to migrate:`));
10514
10647
  }
10515
10648
 
10516
10649
  // 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";
10650
+ import { existsSync as existsSync24, mkdirSync as mkdirSync9, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "fs";
10651
+ import { join as join18 } from "path";
10519
10652
  import { homedir } from "os";
10520
10653
  import chalk29 from "chalk";
10521
10654
  import { CLI_VERSION as CLI_VERSION5 } from "@getcoherent/core";
10522
10655
  var DEBUG5 = process.env.COHERENT_DEBUG === "1";
10523
10656
  var PACKAGE_NAME = "@getcoherent/cli";
10524
- var CACHE_DIR = join17(homedir(), ".coherent");
10525
- var CACHE_FILE = join17(CACHE_DIR, "update-check.json");
10657
+ var CACHE_DIR = join18(homedir(), ".coherent");
10658
+ var CACHE_FILE = join18(CACHE_DIR, "update-check.json");
10526
10659
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10527
10660
  function readCache() {
10528
10661
  try {
10529
- if (!existsSync23(CACHE_FILE)) return null;
10530
- const raw = readFileSync17(CACHE_FILE, "utf-8");
10662
+ if (!existsSync24(CACHE_FILE)) return null;
10663
+ const raw = readFileSync18(CACHE_FILE, "utf-8");
10531
10664
  return JSON.parse(raw);
10532
10665
  } catch (e) {
10533
10666
  if (DEBUG5) console.error("Failed to read update cache:", e);
@@ -10536,8 +10669,8 @@ function readCache() {
10536
10669
  }
10537
10670
  function writeCache(data) {
10538
10671
  try {
10539
- if (!existsSync23(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10540
- writeFileSync12(CACHE_FILE, JSON.stringify(data), "utf-8");
10672
+ if (!existsSync24(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10673
+ writeFileSync13(CACHE_FILE, JSON.stringify(data), "utf-8");
10541
10674
  } catch (e) {
10542
10675
  if (DEBUG5) console.error("Failed to write update cache:", e);
10543
10676
  }
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.40",
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.40"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^20.11.0",