@getcoherent/cli 0.4.0 → 0.5.1

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 (3) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.js +141 -118
  3. package/package.json +10 -10
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sergei Kovtun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.js CHANGED
@@ -698,10 +698,7 @@ function generateWelcomeComponent(_markdown) {
698
698
  import { useState } from 'react'
699
699
  import {
700
700
  ArrowRight,
701
- Blocks,
702
701
  ClipboardCopy,
703
- Eye,
704
- Globe,
705
702
  LayoutDashboard,
706
703
  LogIn,
707
704
  Monitor,
@@ -709,7 +706,6 @@ import {
709
706
  Rocket,
710
707
  Settings,
711
708
  ShoppingBag,
712
- Sparkles,
713
709
  } from 'lucide-react'
714
710
 
715
711
  export default function HomePage() {
@@ -1020,47 +1016,7 @@ export default function HomePage() {
1020
1016
  </div>
1021
1017
  </section>
1022
1018
 
1023
- {/* Footer links (shared Footer component provides the main footer) */}
1024
- <div className="border-t pt-8 pb-8 mt-auto">
1025
- <div className="flex flex-col items-center gap-5 px-4">
1026
- <div className="flex items-center gap-3">
1027
- <div className="flex size-8 items-center justify-center rounded-lg bg-primary text-primary-foreground shrink-0">
1028
- <Blocks className="size-4" />
1029
- </div>
1030
- <span className="text-sm font-semibold">Coherent Design Method</span>
1031
- </div>
1032
- <div className="flex flex-wrap items-center justify-center gap-x-6 gap-y-2">
1033
- <a
1034
- href="https://getcoherent.design"
1035
- target="_blank"
1036
- rel="noopener noreferrer"
1037
- className="text-xs text-muted-foreground hover:text-foreground transition-colors"
1038
- >
1039
- getcoherent.design
1040
- </a>
1041
- <a href="https://github.com/skovtun/coherent-design-method" target="_blank" rel="noopener noreferrer" className="text-xs text-muted-foreground hover:text-foreground transition-colors">
1042
- GitHub
1043
- </a>
1044
- <a href="#" className="text-xs text-muted-foreground hover:text-foreground transition-colors">
1045
- Terms of Use
1046
- </a>
1047
- <a href="#" className="text-xs text-muted-foreground hover:text-foreground transition-colors">
1048
- Privacy Policy
1049
- </a>
1050
- </div>
1051
- <p className="text-xs text-muted-foreground">
1052
- \xA9 {new Date().getFullYear()}{' '}
1053
- <a
1054
- href="https://www.linkedin.com/in/sergeikovtun/"
1055
- target="_blank"
1056
- rel="noopener noreferrer"
1057
- className="underline underline-offset-2 hover:text-foreground transition-colors"
1058
- >
1059
- Sergei Kovtun
1060
- </a>
1061
- </p>
1062
- </div>
1063
- </div>
1019
+
1064
1020
  </div>
1065
1021
  )
1066
1022
  }
@@ -2459,7 +2415,7 @@ async function createAppRouteGroupLayout(projectPath) {
2459
2415
  children: React.ReactNode
2460
2416
  }) {
2461
2417
  return (
2462
- <main className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
2418
+ <main className="mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
2463
2419
  {children}
2464
2420
  </main>
2465
2421
  )
@@ -2479,7 +2435,7 @@ import {
2479
2435
  PageManager as PageManager3,
2480
2436
  CLI_VERSION as CLI_VERSION2,
2481
2437
  getTemplateForPageType as getTemplateForPageType2,
2482
- loadManifest as loadManifest8,
2438
+ loadManifest as loadManifest7,
2483
2439
  saveManifest as saveManifest2
2484
2440
  } from "@getcoherent/core";
2485
2441
 
@@ -4534,15 +4490,19 @@ LAYOUT CONTRACT (CRITICAL \u2014 prevents duplicate navigation and footer):
4534
4490
  - Do NOT add any navigation bars, logo headers, site-wide menus, or site footers to pages. The layout provides all of these.
4535
4491
 
4536
4492
  PAGE WRAPPER (CRITICAL \u2014 the layout provides width/padding automatically):
4537
- - App pages (dashboard, projects, team, settings, etc.) are rendered inside a route group layout that already provides <main className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-6">.
4538
- - Do NOT include any <main> wrapper, max-w-*, mx-auto, or px-* padding classes on the outermost element. The layout handles this.
4539
- - Start page content directly with a <div className="space-y-6"> or similar spacing wrapper. The first visible element should be the page title.
4540
- - Do NOT add inner centering wrappers like <div className="max-w-4xl mx-auto">. All content flows within the layout's max-w-7xl container.
4493
+ - App pages are rendered inside a route group layout that ALREADY provides: <main className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
4494
+ - Your outermost element MUST be exactly: <div className="space-y-6">
4495
+ - FORBIDDEN on the outermost element: <main>, max-w-*, mx-auto, px-*, py-*, p-*, flex-1, min-h-*
4496
+ - FORBIDDEN anywhere: <div className="max-w-4xl mx-auto">, <div className="max-w-2xl mx-auto">, or any inner centering wrapper
4497
+ - The first child inside <div className="space-y-6"> should be the page header (h1 + description)
4498
+ - ALL app pages must follow this exact same structure so content aligns consistently across pages
4541
4499
  - Landing/marketing pages are an exception: they render outside the app layout and should use full-width <section> elements with inner "mx-auto max-w-6xl" for content.
4542
4500
 
4543
4501
  PAGE CONTENT (CRITICAL \u2014 prevents empty or duplicate pages):
4544
4502
  - Every page MUST have substantial content. NEVER generate a page with only metadata and an empty <main> element.
4545
4503
  - NEVER create an inline preview/demo of another page (e.g., embedding a "dashboard view" inside the landing page with a toggle). Each page should be its own route.
4504
+ - NEVER create a single-page app (SPA) that renders multiple views via useState. Each view must be a separate Next.js page with its own route.
4505
+ - The home page (route "/") should be a simple redirect using next/navigation redirect('/dashboard') \u2014 OR a standalone landing page. NEVER a multi-view SPA.
4546
4506
  - Landing pages should link to app pages via <Link href="/dashboard">, NOT via useState toggles that render inline content.
4547
4507
 
4548
4508
  pageCode rules (shadcn/ui blocks quality):
@@ -5930,7 +5890,7 @@ import { dirname as dirname6 } from "path";
5930
5890
  import chalk11 from "chalk";
5931
5891
  import {
5932
5892
  getTemplateForPageType,
5933
- loadManifest as loadManifest6,
5893
+ loadManifest as loadManifest5,
5934
5894
  saveManifest,
5935
5895
  updateUsedIn,
5936
5896
  findSharedComponentByIdOrName,
@@ -6724,7 +6684,7 @@ import {
6724
6684
  PageGenerator,
6725
6685
  TailwindConfigGenerator
6726
6686
  } from "@getcoherent/core";
6727
- import { integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2, loadManifest as loadManifest5, generateSharedComponent as generateSharedComponent2 } from "@getcoherent/core";
6687
+ import { integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2, generateSharedComponent as generateSharedComponent2 } from "@getcoherent/core";
6728
6688
  import chalk9 from "chalk";
6729
6689
  async function validateAndFixGeneratedCode(projectRoot, code, options = {}) {
6730
6690
  const fixes = [];
@@ -6795,34 +6755,39 @@ async function regenerateLayout(config2, projectRoot) {
6795
6755
  const layout = config2.pages[0]?.layout || "centered";
6796
6756
  const appType = config2.settings.appType || "multi-page";
6797
6757
  const generator = new PageGenerator(config2);
6798
- let manifest = null;
6799
- try {
6800
- manifest = await loadManifest5(projectRoot);
6801
- } catch {
6802
- }
6803
- const hasSharedHeader = manifest?.shared.some((c) => c.type === "layout" && /header|nav/i.test(c.name)) ?? false;
6804
- const hasSharedFooter = manifest?.shared.some((c) => c.type === "layout" && /footer/i.test(c.name)) ?? false;
6805
6758
  const code = await generator.generateLayout(layout, appType, { skipNav: true });
6806
6759
  const layoutPath = resolve6(projectRoot, "app", "layout.tsx");
6807
6760
  await writeFile(layoutPath, code);
6808
6761
  if (config2.navigation?.enabled && appType === "multi-page") {
6809
- const headerCode = generator.generateSharedHeaderCode();
6762
+ const navType = config2.navigation.type || "header";
6763
+ if (navType === "header" || navType === "both") {
6764
+ const headerCode = generator.generateSharedHeaderCode();
6765
+ await generateSharedComponent2(projectRoot, {
6766
+ name: "Header",
6767
+ type: "layout",
6768
+ code: headerCode,
6769
+ description: "Main site header with navigation and theme toggle",
6770
+ usedIn: ["app/layout.tsx"],
6771
+ overwrite: true
6772
+ });
6773
+ }
6774
+ const footerCode = generator.generateSharedFooterCode();
6810
6775
  await generateSharedComponent2(projectRoot, {
6811
- name: "Header",
6776
+ name: "Footer",
6812
6777
  type: "layout",
6813
- code: headerCode,
6814
- description: "Main site header with navigation and theme toggle",
6778
+ code: footerCode,
6779
+ description: "Site footer",
6815
6780
  usedIn: ["app/layout.tsx"],
6816
6781
  overwrite: true
6817
6782
  });
6818
- if (!hasSharedFooter) {
6819
- const footerCode = generator.generateSharedFooterCode();
6783
+ if (navType === "sidebar" || navType === "both") {
6784
+ const sidebarCode = generator.generateSharedSidebarCode();
6820
6785
  await generateSharedComponent2(projectRoot, {
6821
- name: "Footer",
6786
+ name: "Sidebar",
6822
6787
  type: "layout",
6823
- code: footerCode,
6824
- description: "Site footer",
6825
- usedIn: ["app/layout.tsx"],
6788
+ code: sidebarCode,
6789
+ description: "Vertical sidebar navigation with collapsible sections",
6790
+ usedIn: ["app/(app)/layout.tsx"],
6826
6791
  overwrite: true
6827
6792
  });
6828
6793
  }
@@ -6830,31 +6795,54 @@ async function regenerateLayout(config2, projectRoot) {
6830
6795
  try {
6831
6796
  await integrateSharedLayoutIntoRootLayout2(projectRoot);
6832
6797
  await ensureAuthRouteGroup(projectRoot);
6833
- await ensureAppRouteGroupLayout(projectRoot);
6798
+ await ensureAppRouteGroupLayout(projectRoot, config2.navigation?.type);
6834
6799
  } catch (err) {
6835
6800
  if (process.env.COHERENT_DEBUG === "1") {
6836
6801
  console.log(chalk9.dim("Layout integration warning:", err));
6837
6802
  }
6838
6803
  }
6839
6804
  }
6840
- async function ensureAppRouteGroupLayout(projectRoot) {
6805
+ async function ensureAppRouteGroupLayout(projectRoot, navType) {
6841
6806
  const layoutPath = resolve6(projectRoot, "app", "(app)", "layout.tsx");
6842
6807
  if (existsSync14(layoutPath)) return;
6843
6808
  const { mkdir: mkdirAsync } = await import("fs/promises");
6844
6809
  await mkdirAsync(resolve6(projectRoot, "app", "(app)"), { recursive: true });
6845
- const code = `export default function AppLayout({
6810
+ const code = buildAppLayoutCode(navType);
6811
+ await writeFile(layoutPath, code);
6812
+ }
6813
+ function buildAppLayoutCode(navType) {
6814
+ const hasSidebar = navType === "sidebar" || navType === "both";
6815
+ if (hasSidebar) {
6816
+ return `import { Sidebar } from '@/components/shared/sidebar'
6817
+
6818
+ export default function AppLayout({
6819
+ children,
6820
+ }: {
6821
+ children: React.ReactNode
6822
+ }) {
6823
+ return (
6824
+ <div className="flex min-h-[calc(100vh-3.5rem)]">
6825
+ <Sidebar />
6826
+ <main className="flex-1 px-4 sm:px-6 lg:px-8 py-6">
6827
+ {children}
6828
+ </main>
6829
+ </div>
6830
+ )
6831
+ }
6832
+ `;
6833
+ }
6834
+ return `export default function AppLayout({
6846
6835
  children,
6847
6836
  }: {
6848
6837
  children: React.ReactNode
6849
6838
  }) {
6850
6839
  return (
6851
- <main className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
6840
+ <main className="mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
6852
6841
  {children}
6853
6842
  </main>
6854
6843
  )
6855
6844
  }
6856
6845
  `;
6857
- await writeFile(layoutPath, code);
6858
6846
  }
6859
6847
  async function regenerateFiles(modified, config2, projectRoot) {
6860
6848
  const componentIds = /* @__PURE__ */ new Set();
@@ -7189,26 +7177,41 @@ function stripInlineLayoutElements(code) {
7189
7177
  }
7190
7178
  return { code: result, stripped };
7191
7179
  }
7192
- function stripOuterMainWrapper(code) {
7193
- const mainWrapperRe = /(return\s*\(\s*\n?\s*)<main\s+className="[^"]*">\s*\n([\s\S]*?)\n\s*<\/main>(\s*\n?\s*\))/;
7194
- const match = code.match(mainWrapperRe);
7195
- if (match) {
7196
- const [, before, children, after] = match;
7197
- const dedented = children.replace(/^ /gm, " ");
7198
- return {
7199
- code: code.replace(match[0], `${before}<>${dedented}
7200
- </${">"}${after}`),
7201
- stripped: true
7202
- };
7180
+ var STANDARD_PAGE_WRAPPER = "space-y-6";
7181
+ var HOME_REDIRECT_CODE = `import { redirect } from 'next/navigation'
7182
+
7183
+ export default function Home() {
7184
+ redirect('/dashboard')
7185
+ }
7186
+ `;
7187
+ function detectAndFixSpaHomePage(code, route) {
7188
+ if (route !== "/" && route !== "") return { code, fixed: false };
7189
+ const hasMultipleRenders = (code.match(/const render\w+\s*=\s*\(\)/g) || []).length >= 2;
7190
+ const hasPageToggle = /useState\s*\(\s*['"](?:dashboard|home|page)/i.test(code);
7191
+ const isMassive = code.split("\n").length > 200;
7192
+ if (hasMultipleRenders && hasPageToggle || isMassive && hasPageToggle) {
7193
+ return { code: HOME_REDIRECT_CODE, fixed: true };
7203
7194
  }
7195
+ return { code, fixed: false };
7196
+ }
7197
+ function normalizePageWrapper(code) {
7204
7198
  let result = code;
7205
- let stripped = false;
7199
+ let fixed = false;
7206
7200
  if (/<main\s+className="[^"]*">/.test(result)) {
7207
- result = result.replace(/<main\s+className="[^"]*">\s*/g, '<div className="space-y-6">');
7201
+ result = result.replace(/<main\s+className="[^"]*">/g, `<div className="${STANDARD_PAGE_WRAPPER}">`);
7208
7202
  result = result.replace(/<\/main>/g, "</div>");
7209
- stripped = true;
7203
+ fixed = true;
7210
7204
  }
7211
- return { code: result, stripped };
7205
+ const outerDivRe = /(return\s*\(\s*\n?\s*)<div\s+className="([^"]*)">/;
7206
+ const match = result.match(outerDivRe);
7207
+ if (match) {
7208
+ const cls = match[2];
7209
+ if (cls !== STANDARD_PAGE_WRAPPER) {
7210
+ result = result.replace(match[0], `${match[1]}<div className="${STANDARD_PAGE_WRAPPER}">`);
7211
+ fixed = true;
7212
+ }
7213
+ }
7214
+ return { code: result, fixed };
7212
7215
  }
7213
7216
  async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider, originalMessage) {
7214
7217
  switch (request.type) {
@@ -7326,7 +7329,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
7326
7329
  fixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
7327
7330
  }
7328
7331
  await writeFile(pageFilePath, fixedCode);
7329
- const manifest = await loadManifest6(projectRoot);
7332
+ const manifest = await loadManifest5(projectRoot);
7330
7333
  const usedIn = manifest.shared.find((e) => e.id === resolved.id)?.usedIn ?? [];
7331
7334
  const routePath = route.replace(/^\//, "");
7332
7335
  const filePathRel = routePath ? `app/${routePath}/page.tsx` : "app/page.tsx";
@@ -7431,7 +7434,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
7431
7434
  await writeFile(fullPath, fixedCode);
7432
7435
  usedInFiles.push(relPath);
7433
7436
  }
7434
- const manifest = await loadManifest6(projectRoot);
7437
+ const manifest = await loadManifest5(projectRoot);
7435
7438
  const nextManifest = updateUsedIn(manifest, created.id, usedInFiles);
7436
7439
  await saveManifest(projectRoot, nextManifest);
7437
7440
  printPromoteAndLinkReport({
@@ -7541,7 +7544,11 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
7541
7544
  console.log(chalk11.yellow(`
7542
7545
  \u26A0\uFE0F Page "${page.name || page.id}" has no generated code \u2014 it will appear empty.`));
7543
7546
  console.log(chalk11.dim(" This usually means the AI did not produce pageCode for this page."));
7544
- console.log(chalk11.dim(' Try running: coherent chat "regenerate the ' + (page.name || page.id) + ' page with full content"'));
7547
+ console.log(
7548
+ chalk11.dim(
7549
+ ' Try running: coherent chat "regenerate the ' + (page.name || page.id) + ' page with full content"'
7550
+ )
7551
+ );
7545
7552
  }
7546
7553
  const pageForConfig = {
7547
7554
  ...page,
@@ -7582,11 +7589,19 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
7582
7589
  let codeToWrite = fixedCode;
7583
7590
  const { code: autoFixed, fixes: autoFixes } = await autoFixCode(codeToWrite);
7584
7591
  codeToWrite = autoFixed;
7592
+ const { code: spaFixed, fixed: spaWasFixed } = detectAndFixSpaHomePage(codeToWrite, route);
7593
+ if (spaWasFixed) {
7594
+ codeToWrite = spaFixed;
7595
+ autoFixes.push("replaced SPA-style home page with redirect to /dashboard");
7596
+ }
7585
7597
  const { code: layoutStripped, stripped } = stripInlineLayoutElements(codeToWrite);
7586
7598
  codeToWrite = layoutStripped;
7587
7599
  if (!isMarketingRoute(route)) {
7588
- const { code: noMain, stripped: mainStripped } = stripOuterMainWrapper(codeToWrite);
7589
- if (mainStripped) codeToWrite = noMain;
7600
+ const { code: normalized, fixed: wrapperFixed } = normalizePageWrapper(codeToWrite);
7601
+ if (wrapperFixed) {
7602
+ codeToWrite = normalized;
7603
+ autoFixes.push("normalized page wrapper to standard spacing");
7604
+ }
7590
7605
  }
7591
7606
  const allFixes = [...postFixes, ...autoFixes];
7592
7607
  if (stripped.length > 0) allFixes.push(`stripped inline ${stripped.join(", ")} (layout owns these)`);
@@ -7603,7 +7618,7 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
7603
7618
  cm.updateConfig(cfg);
7604
7619
  pm.updateConfig(cfg);
7605
7620
  }
7606
- const manifestForAudit = await loadManifest6(projectRoot);
7621
+ const manifestForAudit = await loadManifest5(projectRoot);
7607
7622
  await warnInlineDuplicates(projectRoot, page.name || page.id || route.slice(1), codeToWrite, manifestForAudit);
7608
7623
  const relFilePath = routeToRelPath(route, isAuth);
7609
7624
  printPostGenerationReport({
@@ -7753,11 +7768,19 @@ ${pagesCtx}`
7753
7768
  let codeToWrite = fixedCode;
7754
7769
  const { code: autoFixed, fixes: autoFixes } = await autoFixCode(codeToWrite);
7755
7770
  codeToWrite = autoFixed;
7771
+ const { code: spaFixed, fixed: spaWasFixed } = detectAndFixSpaHomePage(codeToWrite, route);
7772
+ if (spaWasFixed) {
7773
+ codeToWrite = spaFixed;
7774
+ autoFixes.push("replaced SPA-style home page with redirect to /dashboard");
7775
+ }
7756
7776
  const { code: layoutStripped, stripped } = stripInlineLayoutElements(codeToWrite);
7757
7777
  codeToWrite = layoutStripped;
7758
7778
  if (!isMarketingRoute(route)) {
7759
- const { code: noMain, stripped: mainStripped } = stripOuterMainWrapper(codeToWrite);
7760
- if (mainStripped) codeToWrite = noMain;
7779
+ const { code: normalized, fixed: wrapperFixed } = normalizePageWrapper(codeToWrite);
7780
+ if (wrapperFixed) {
7781
+ codeToWrite = normalized;
7782
+ autoFixes.push("normalized page wrapper to standard spacing");
7783
+ }
7761
7784
  }
7762
7785
  const allFixes = [...postFixes, ...autoFixes];
7763
7786
  if (stripped.length > 0) allFixes.push(`stripped inline ${stripped.join(", ")} (layout owns these)`);
@@ -7774,7 +7797,7 @@ ${pagesCtx}`
7774
7797
  cm.updateConfig(cfg);
7775
7798
  pm.updateConfig(cfg);
7776
7799
  }
7777
- const manifestForAudit = await loadManifest6(projectRoot);
7800
+ const manifestForAudit = await loadManifest5(projectRoot);
7778
7801
  await warnInlineDuplicates(
7779
7802
  projectRoot,
7780
7803
  pageDef.name || pageDef.id || route.slice(1),
@@ -7811,7 +7834,7 @@ ${pagesCtx}`
7811
7834
  fixes.forEach((f) => console.log(chalk11.dim(` ${f}`)));
7812
7835
  }
7813
7836
  const relFilePath = routeToRelPath(route, isAuth);
7814
- const manifest = await loadManifest6(projectRoot);
7837
+ const manifest = await loadManifest5(projectRoot);
7815
7838
  printPostGenerationReport({
7816
7839
  action: "updated",
7817
7840
  pageTitle: pageDef.name || pageDef.id || "Page",
@@ -7860,7 +7883,7 @@ ${pagesCtx}`
7860
7883
  import chalk12 from "chalk";
7861
7884
  import { resolve as resolve8 } from "path";
7862
7885
  import { existsSync as existsSync15, readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
7863
- import { DesignSystemManager as DesignSystemManager6, ComponentManager as ComponentManager3, loadManifest as loadManifest7 } from "@getcoherent/core";
7886
+ import { DesignSystemManager as DesignSystemManager6, ComponentManager as ComponentManager3, loadManifest as loadManifest6 } from "@getcoherent/core";
7864
7887
  var DEBUG3 = process.env.COHERENT_DEBUG === "1";
7865
7888
  async function interactiveChat(options, chatCommandFn) {
7866
7889
  const { createInterface } = await import("readline");
@@ -7930,7 +7953,7 @@ async function interactiveChat(options, chatCommandFn) {
7930
7953
  return;
7931
7954
  }
7932
7955
  if (lower === "components" || lower === "list components" || lower.includes("what components")) {
7933
- const manifest = await loadManifest7(projectRoot);
7956
+ const manifest = await loadManifest6(projectRoot);
7934
7957
  if (manifest.shared.length === 0) {
7935
7958
  console.log(chalk12.gray("\n No shared components yet.\n"));
7936
7959
  } else {
@@ -7964,7 +7987,7 @@ async function interactiveChat(options, chatCommandFn) {
7964
7987
  }
7965
7988
  if (lower === "status") {
7966
7989
  const currentConfig = dsm.getConfig();
7967
- const manifest = await loadManifest7(projectRoot);
7990
+ const manifest = await loadManifest6(projectRoot);
7968
7991
  console.log(chalk12.bold(`
7969
7992
  ${currentConfig.name || "Coherent Project"}`));
7970
7993
  console.log(
@@ -8146,7 +8169,7 @@ async function chatCommand(message, options) {
8146
8169
  }
8147
8170
  }
8148
8171
  spinner.start("Parsing your request...");
8149
- let manifest = await loadManifest8(project.root);
8172
+ let manifest = await loadManifest7(project.root);
8150
8173
  const validShared = manifest.shared.filter((s) => {
8151
8174
  const fp = resolve9(project.root, s.file);
8152
8175
  return existsSync16(fp);
@@ -8717,7 +8740,7 @@ import { DesignSystemManager as DesignSystemManager8, ComponentGenerator as Comp
8717
8740
  // src/utils/file-watcher.ts
8718
8741
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, existsSync as existsSync18 } from "fs";
8719
8742
  import { relative as relative3, join as join10 } from "path";
8720
- import { loadManifest as loadManifest9, saveManifest as saveManifest3 } from "@getcoherent/core";
8743
+ import { loadManifest as loadManifest8, saveManifest as saveManifest3 } from "@getcoherent/core";
8721
8744
 
8722
8745
  // src/utils/component-integrity.ts
8723
8746
  import { existsSync as existsSync17, readFileSync as readFileSync11, readdirSync as readdirSync2 } from "fs";
@@ -9071,7 +9094,7 @@ async function handleFileChange(projectRoot, filePath) {
9071
9094
  if (config2.warnSharedReuse) {
9072
9095
  let manifest;
9073
9096
  try {
9074
- manifest = await loadManifest9(projectRoot);
9097
+ manifest = await loadManifest8(projectRoot);
9075
9098
  } catch {
9076
9099
  manifest = { shared: [], nextId: 1 };
9077
9100
  }
@@ -9090,7 +9113,7 @@ async function handleFileDelete(projectRoot, filePath) {
9090
9113
  if (!relativePath.startsWith("components/") || relativePath.startsWith("components/ui/")) return;
9091
9114
  try {
9092
9115
  const chalk32 = (await import("chalk")).default;
9093
- const manifest = await loadManifest9(projectRoot);
9116
+ const manifest = await loadManifest8(projectRoot);
9094
9117
  const orphaned = manifest.shared.find((s) => s.file === relativePath);
9095
9118
  if (orphaned) {
9096
9119
  const cleaned = {
@@ -9111,7 +9134,7 @@ async function detectNewComponent(projectRoot, filePath) {
9111
9134
  if (!relativePath.endsWith(".tsx") && !relativePath.endsWith(".jsx")) return;
9112
9135
  try {
9113
9136
  const chalk32 = (await import("chalk")).default;
9114
- const manifest = await loadManifest9(projectRoot);
9137
+ const manifest = await loadManifest8(projectRoot);
9115
9138
  const alreadyRegistered = manifest.shared.some((s) => s.file === relativePath);
9116
9139
  if (alreadyRegistered) return;
9117
9140
  const code = readFileSync12(filePath, "utf-8");
@@ -10028,7 +10051,7 @@ import {
10028
10051
  ComponentManager as ComponentManager5,
10029
10052
  PageManager as PageManager4,
10030
10053
  ComponentGenerator as ComponentGenerator4,
10031
- loadManifest as loadManifest10,
10054
+ loadManifest as loadManifest9,
10032
10055
  saveManifest as saveManifest4
10033
10056
  } from "@getcoherent/core";
10034
10057
  function extractComponentIdsFromCode2(code) {
@@ -10235,7 +10258,7 @@ async function fixCommand(opts = {}) {
10235
10258
  fileIssues.push({ path: relativePath, report });
10236
10259
  }
10237
10260
  try {
10238
- let manifest = await loadManifest10(project.root);
10261
+ let manifest = await loadManifest9(project.root);
10239
10262
  let manifestModified = false;
10240
10263
  const { manifest: cleaned, removed: orphaned } = removeOrphanedEntries(project.root, manifest);
10241
10264
  if (orphaned.length > 0) {
@@ -10335,7 +10358,7 @@ async function fixCommand(opts = {}) {
10335
10358
  import chalk19 from "chalk";
10336
10359
  import { resolve as resolve13 } from "path";
10337
10360
  import { readdirSync as readdirSync5, readFileSync as readFileSync15, statSync as statSync2, existsSync as existsSync22 } from "fs";
10338
- import { loadManifest as loadManifest11 } from "@getcoherent/core";
10361
+ import { loadManifest as loadManifest10 } from "@getcoherent/core";
10339
10362
  var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["node_modules", "design-system"]);
10340
10363
  function findTsxFiles(dir) {
10341
10364
  const results = [];
@@ -10462,7 +10485,7 @@ async function checkCommand(opts = {}) {
10462
10485
  \u{1F517} Internal Links`) + chalk19.dim(` \u2014 all ${result.links.total} links resolve \u2713`));
10463
10486
  }
10464
10487
  try {
10465
- const manifest = await loadManifest11(project.root);
10488
+ const manifest = await loadManifest10(project.root);
10466
10489
  if (manifest.shared.length > 0) {
10467
10490
  for (const entry of manifest.shared) {
10468
10491
  const fullPath = resolve13(project.root, entry.file);
@@ -10478,7 +10501,7 @@ async function checkCommand(opts = {}) {
10478
10501
  }
10479
10502
  if (!skipShared) {
10480
10503
  try {
10481
- const manifest = await loadManifest11(projectRoot);
10504
+ const manifest = await loadManifest10(projectRoot);
10482
10505
  if (!opts.json && manifest.shared.length > 0) {
10483
10506
  console.log(chalk19.cyan(`
10484
10507
  \u{1F9E9} Shared Components`) + chalk19.dim(` (${manifest.shared.length} registered)
@@ -10660,7 +10683,7 @@ import chalk25 from "chalk";
10660
10683
  import {
10661
10684
  DesignSystemManager as DesignSystemManager12,
10662
10685
  ComponentManager as ComponentManager6,
10663
- loadManifest as loadManifest12,
10686
+ loadManifest as loadManifest11,
10664
10687
  generateSharedComponent as generateSharedComponent4,
10665
10688
  integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout3
10666
10689
  } from "@getcoherent/core";
@@ -10701,7 +10724,7 @@ function createComponentsCommand() {
10701
10724
  await dsm.load();
10702
10725
  const config2 = dsm.getConfig();
10703
10726
  const cm = new ComponentManager6(config2);
10704
- const manifest = await loadManifest12(project.root);
10727
+ const manifest = await loadManifest11(project.root);
10705
10728
  if (opts.json) {
10706
10729
  const installed2 = cm.getAllComponents();
10707
10730
  console.log(JSON.stringify({ shared: manifest.shared, ui: installed2 }, null, 2));
@@ -10753,7 +10776,7 @@ function createComponentsCommand() {
10753
10776
  sharedCmd.option("--json", "Machine-readable JSON output").option("--verbose", "Show file paths and usage details").action(async (opts) => {
10754
10777
  const project = findConfig();
10755
10778
  if (!project) exitNotCoherent();
10756
- const manifest = await loadManifest12(project.root);
10779
+ const manifest = await loadManifest11(project.root);
10757
10780
  if (opts.json) {
10758
10781
  console.log(JSON.stringify(manifest, null, 2));
10759
10782
  return;
@@ -11457,7 +11480,7 @@ import { existsSync as existsSync26, readFileSync as readFileSync17 } from "fs";
11457
11480
  import { join as join17, relative as relative4, dirname as dirname10 } from "path";
11458
11481
  import { readdir as readdir4, readFile as readFile6 } from "fs/promises";
11459
11482
  import { DesignSystemManager as DesignSystemManager16 } from "@getcoherent/core";
11460
- import { loadManifest as loadManifest13, saveManifest as saveManifest5, findSharedComponent } from "@getcoherent/core";
11483
+ import { loadManifest as loadManifest12, saveManifest as saveManifest5, findSharedComponent } from "@getcoherent/core";
11461
11484
  function extractTokensFromProject(projectRoot) {
11462
11485
  const lightColors = {};
11463
11486
  const darkColors = {};
@@ -11737,7 +11760,7 @@ async function syncCommand(options = {}) {
11737
11760
  let reconcileResult = null;
11738
11761
  if (doComponents) {
11739
11762
  spinner.start("Reconciling shared components...");
11740
- const manifest = await loadManifest13(project.root);
11763
+ const manifest = await loadManifest12(project.root);
11741
11764
  const { manifest: reconciledManifest, result: rr } = reconcileComponents(project.root, manifest);
11742
11765
  reconcileResult = rr;
11743
11766
  if (!dryRun) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.4.0",
6
+ "version": "0.5.1",
7
7
  "description": "CLI interface for Coherent Design Method",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",
@@ -33,15 +33,8 @@
33
33
  ],
34
34
  "author": "Coherent Design Method",
35
35
  "license": "MIT",
36
- "scripts": {
37
- "dev": "tsup --watch",
38
- "build": "tsup",
39
- "typecheck": "tsc --noEmit",
40
- "test": "vitest"
41
- },
42
36
  "dependencies": {
43
37
  "@anthropic-ai/sdk": "^0.32.0",
44
- "@getcoherent/core": "workspace:*",
45
38
  "chalk": "^5.3.0",
46
39
  "chokidar": "^4.0.1",
47
40
  "commander": "^11.1.0",
@@ -49,12 +42,19 @@
49
42
  "open": "^10.1.0",
50
43
  "ora": "^7.0.1",
51
44
  "prompts": "^2.4.2",
52
- "zod": "^3.22.4"
45
+ "zod": "^3.22.4",
46
+ "@getcoherent/core": "0.5.1"
53
47
  },
54
48
  "devDependencies": {
55
49
  "@types/node": "^20.11.0",
56
50
  "@types/prompts": "^2.4.9",
57
51
  "tsup": "^8.0.1",
58
52
  "typescript": "^5.3.3"
53
+ },
54
+ "scripts": {
55
+ "dev": "tsup --watch",
56
+ "build": "tsup",
57
+ "typecheck": "tsc --noEmit",
58
+ "test": "vitest"
59
59
  }
60
- }
60
+ }