@fragments-sdk/cli 0.9.0 → 0.10.0

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 (166) hide show
  1. package/dist/bin.d.ts +1 -0
  2. package/dist/bin.js +502 -84
  3. package/dist/bin.js.map +1 -1
  4. package/dist/{chunk-CJEGT3WD.js → chunk-566BNPQZ.js} +21 -6
  5. package/dist/chunk-566BNPQZ.js.map +1 -0
  6. package/dist/{chunk-WI6SLMSO.js → chunk-CAMXG5HJ.js} +5 -5
  7. package/dist/chunk-D2CDBRNU.js +2 -0
  8. package/dist/{chunk-YMPGYEWK.js → chunk-D5PYOXEI.js} +2 -2
  9. package/dist/{chunk-NGIMCIK2.js → chunk-OQO55NKV.js} +405 -34
  10. package/dist/chunk-OQO55NKV.js.map +1 -0
  11. package/dist/{chunk-TOIE7VXF.js → chunk-PW7QTQA6.js} +2 -2
  12. package/dist/{chunk-AWYCDRPG.js → chunk-WXSR2II7.js} +2 -2
  13. package/dist/chunk-WXSR2II7.js.map +1 -0
  14. package/dist/{chunk-2JIKCJX3.js → chunk-ZDA3PLQ6.js} +17 -14
  15. package/dist/chunk-ZDA3PLQ6.js.map +1 -0
  16. package/dist/core/index.d.ts +1 -2092
  17. package/dist/core/index.js +26 -21
  18. package/dist/{discovery-Z4RDDFVR.js → discovery-NEOY4MPN.js} +3 -3
  19. package/dist/generate-BGKTKO6E.js +459 -0
  20. package/dist/generate-BGKTKO6E.js.map +1 -0
  21. package/dist/index.d.ts +3 -5
  22. package/dist/index.js +7 -8
  23. package/dist/index.js.map +1 -1
  24. package/dist/{init-KSAAS7X3.js → init-Q53R5Q2T.js} +66 -76
  25. package/dist/init-Q53R5Q2T.js.map +1 -0
  26. package/dist/mcp-bin.js +5 -7
  27. package/dist/mcp-bin.js.map +1 -1
  28. package/dist/scan-OQU7M4GH.js +14 -0
  29. package/dist/scan-generate-T5QNUG7N.js +691 -0
  30. package/dist/scan-generate-T5QNUG7N.js.map +1 -0
  31. package/dist/{service-A5GIGGGK.js → service-TQYWY65E.js} +4 -5
  32. package/dist/{static-viewer-NSODM5VX.js → static-viewer-NUBFPKWH.js} +4 -5
  33. package/dist/static-viewer-NUBFPKWH.js.map +1 -0
  34. package/dist/{test-RPWZAYSJ.js → test-2CSOSS3B.js} +4 -5
  35. package/dist/{test-RPWZAYSJ.js.map → test-2CSOSS3B.js.map} +1 -1
  36. package/dist/{tokens-NIXSZRX7.js → tokens-DXEGYTOJ.js} +6 -7
  37. package/dist/{tokens-NIXSZRX7.js.map → tokens-DXEGYTOJ.js.map} +1 -1
  38. package/dist/{viewer-SBTJDMP7.js → viewer-DBEPYM3G.js} +245 -23
  39. package/dist/viewer-DBEPYM3G.js.map +1 -0
  40. package/package.json +2 -1
  41. package/src/bin.ts +33 -1
  42. package/src/build.ts +13 -3
  43. package/src/commands/__tests__/scan-generate.test.ts +308 -0
  44. package/src/commands/build.ts +16 -2
  45. package/src/commands/generate.ts +383 -68
  46. package/src/commands/init.ts +81 -56
  47. package/src/commands/perf.ts +1 -1
  48. package/src/commands/scan-generate.ts +1013 -0
  49. package/src/commands/setup.ts +499 -0
  50. package/src/core/auto-props.ts +1 -1
  51. package/src/core/bundle-measurer.ts +2 -2
  52. package/src/core/config.ts +16 -4
  53. package/src/core/discovery.ts +2 -2
  54. package/src/core/generators/context.ts +1 -1
  55. package/src/core/generators/registry.ts +3 -3
  56. package/src/core/generators/typescript-extractor.ts +11 -1
  57. package/src/core/graph-extractor.ts +1 -1
  58. package/src/core/index.ts +3 -190
  59. package/src/core/loader.ts +2 -2
  60. package/src/core/parser.ts +1 -1
  61. package/src/core/previewLoader.ts +1 -1
  62. package/src/index.ts +2 -2
  63. package/src/migrate/converter.ts +9 -1
  64. package/src/migrate/parser.ts +2 -0
  65. package/src/migrate/types.ts +2 -0
  66. package/src/service/snippet-validation.test.ts +1 -1
  67. package/src/service/snippet-validation.ts +2 -2
  68. package/src/setup.ts +69 -24
  69. package/src/viewer/__tests__/viewer-integration.test.ts +4 -10
  70. package/src/viewer/components/AccessibilityPanel.tsx +305 -312
  71. package/src/viewer/components/ActionsPanel.tsx +31 -29
  72. package/src/viewer/components/AllVariantsPreview.tsx +78 -0
  73. package/src/viewer/components/App.tsx +187 -740
  74. package/src/viewer/components/BottomPanel.tsx +228 -132
  75. package/src/viewer/components/CodePanel.tsx +1 -1
  76. package/src/viewer/components/CommandPalette.tsx +7 -10
  77. package/src/viewer/components/ComponentDocView.tsx +164 -0
  78. package/src/viewer/components/ComponentGraph.tsx +111 -142
  79. package/src/viewer/components/ContractPanel.tsx +6 -6
  80. package/src/viewer/components/EmptyVariantMessage.tsx +54 -0
  81. package/src/viewer/components/FigmaEmbed.tsx +20 -18
  82. package/src/viewer/components/FragmentEditor.tsx +92 -115
  83. package/src/viewer/components/HeaderSearch.tsx +24 -0
  84. package/src/viewer/components/HealthDashboard.tsx +16 -2
  85. package/src/viewer/components/Icons.tsx +9 -0
  86. package/src/viewer/components/InteractionsPanel.tsx +101 -117
  87. package/src/viewer/components/IsolatedPreviewFrame.tsx +1 -0
  88. package/src/viewer/components/LandingPage.tsx +3 -3
  89. package/src/viewer/components/LeftSidebar.tsx +141 -63
  90. package/src/viewer/components/LoadErrorMessage.tsx +102 -0
  91. package/src/viewer/components/MultiViewportPreview.tsx +61 -142
  92. package/src/viewer/components/NoVariantsMessage.tsx +59 -0
  93. package/src/viewer/components/PanelShell.tsx +161 -0
  94. package/src/viewer/components/PerformancePanel.tsx +31 -28
  95. package/src/viewer/components/PreviewArea.tsx +1 -1
  96. package/src/viewer/components/PreviewAside.tsx +168 -0
  97. package/src/viewer/components/PreviewFrameHost.tsx +3 -3
  98. package/src/viewer/components/PropsEditor.tsx +70 -156
  99. package/src/viewer/components/ResizablePanel.tsx +103 -263
  100. package/src/viewer/components/RightSidebar.tsx +3 -9
  101. package/src/viewer/components/SkeletonLoader.tsx +13 -13
  102. package/src/viewer/components/TokenStylePanel.tsx +182 -209
  103. package/src/viewer/components/TopToolbar.tsx +159 -0
  104. package/src/viewer/components/VariantMatrix.tsx +42 -86
  105. package/src/viewer/components/VariantTabs.tsx +3 -3
  106. package/src/viewer/components/ViewerHeader.tsx +69 -0
  107. package/src/viewer/components/WebMCPDevTools.tsx +17 -23
  108. package/src/viewer/components/viewer-utils.ts +16 -0
  109. package/src/viewer/entry.tsx +5 -0
  110. package/src/viewer/hooks/useAppState.ts +27 -4
  111. package/src/viewer/hooks/usePreviewBridge.ts +2 -2
  112. package/src/viewer/preview-frame.html +6 -12
  113. package/src/viewer/server.ts +169 -2
  114. package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss +10 -0
  115. package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss.d.ts +2 -0
  116. package/src/viewer/vendor/shared/src/ComponentDocContent.tsx +274 -0
  117. package/src/viewer/vendor/shared/src/DocsHeaderBar.tsx +6 -18
  118. package/src/viewer/vendor/shared/src/DocsPageShell.tsx +5 -0
  119. package/src/viewer/vendor/shared/src/DocsSidebarNav.tsx +5 -16
  120. package/src/viewer/vendor/shared/src/PropsTable.module.scss +68 -0
  121. package/src/viewer/vendor/shared/src/PropsTable.module.scss.d.ts +2 -0
  122. package/src/viewer/vendor/shared/src/PropsTable.tsx +76 -0
  123. package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss +114 -0
  124. package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss.d.ts +2 -0
  125. package/src/viewer/vendor/shared/src/VariantPreviewCard.tsx +134 -0
  126. package/src/viewer/vendor/shared/src/index.ts +8 -0
  127. package/src/viewer/vendor/shared/src/types.ts +12 -0
  128. package/src/viewer/vite-plugin.ts +109 -4
  129. package/dist/chunk-2JIKCJX3.js.map +0 -1
  130. package/dist/chunk-AWYCDRPG.js.map +0 -1
  131. package/dist/chunk-CJEGT3WD.js.map +0 -1
  132. package/dist/chunk-EKLMXTWU.js +0 -80
  133. package/dist/chunk-EKLMXTWU.js.map +0 -1
  134. package/dist/chunk-GOVI6COW.js +0 -195
  135. package/dist/chunk-GOVI6COW.js.map +0 -1
  136. package/dist/chunk-NGIMCIK2.js.map +0 -1
  137. package/dist/defineFragment-D0UTve-I.d.ts +0 -665
  138. package/dist/generate-35OIMW4Y.js +0 -252
  139. package/dist/generate-35OIMW4Y.js.map +0 -1
  140. package/dist/init-KSAAS7X3.js.map +0 -1
  141. package/dist/scan-65RH3QMM.js +0 -15
  142. package/dist/viewer-SBTJDMP7.js.map +0 -1
  143. package/src/core/__tests__/preview-runtime.test.tsx +0 -111
  144. package/src/core/composition.test.ts +0 -262
  145. package/src/core/composition.ts +0 -318
  146. package/src/core/constants.ts +0 -114
  147. package/src/core/context.ts +0 -2
  148. package/src/core/defineFragment.ts +0 -141
  149. package/src/core/figma.ts +0 -263
  150. package/src/core/fragment-types.ts +0 -214
  151. package/src/core/performance-presets.ts +0 -142
  152. package/src/core/preview-runtime.tsx +0 -144
  153. package/src/core/schema.ts +0 -221
  154. package/src/core/storyAdapter.test.ts +0 -571
  155. package/src/core/storyAdapter.ts +0 -761
  156. package/src/core/storybook-csf.ts +0 -11
  157. package/src/core/token-parser.ts +0 -321
  158. package/src/core/token-types.ts +0 -287
  159. package/src/core/types.ts +0 -762
  160. /package/dist/{chunk-WI6SLMSO.js.map → chunk-CAMXG5HJ.js.map} +0 -0
  161. /package/dist/{discovery-Z4RDDFVR.js.map → chunk-D2CDBRNU.js.map} +0 -0
  162. /package/dist/{chunk-YMPGYEWK.js.map → chunk-D5PYOXEI.js.map} +0 -0
  163. /package/dist/{chunk-TOIE7VXF.js.map → chunk-PW7QTQA6.js.map} +0 -0
  164. /package/dist/{scan-65RH3QMM.js.map → discovery-NEOY4MPN.js.map} +0 -0
  165. /package/dist/{service-A5GIGGGK.js.map → scan-OQU7M4GH.js.map} +0 -0
  166. /package/dist/{static-viewer-NSODM5VX.js.map → service-TQYWY65E.js.map} +0 -0
package/dist/bin.js CHANGED
@@ -12,17 +12,17 @@ import {
12
12
  validateCoverage,
13
13
  validateSchema,
14
14
  validateSnippets
15
- } from "./chunk-2JIKCJX3.js";
15
+ } from "./chunk-ZDA3PLQ6.js";
16
16
  import {
17
17
  scan
18
- } from "./chunk-WI6SLMSO.js";
18
+ } from "./chunk-CAMXG5HJ.js";
19
19
  import {
20
20
  loadConfig,
21
21
  loadFragmentFile
22
- } from "./chunk-CJEGT3WD.js";
22
+ } from "./chunk-566BNPQZ.js";
23
23
  import {
24
24
  discoverFragmentFiles
25
- } from "./chunk-AWYCDRPG.js";
25
+ } from "./chunk-WXSR2II7.js";
26
26
  import {
27
27
  FigmaClient,
28
28
  StorageManager,
@@ -38,25 +38,23 @@ import {
38
38
  renderAllComponentVariants,
39
39
  scanCodebase,
40
40
  shutdownSharedPool
41
- } from "./chunk-YMPGYEWK.js";
41
+ } from "./chunk-D5PYOXEI.js";
42
+ import "./chunk-D2CDBRNU.js";
42
43
  import {
44
+ BRAND,
43
45
  budgetBar,
44
46
  formatBytes,
45
47
  generateContext,
46
48
  resolvePerformanceConfig
47
- } from "./chunk-NGIMCIK2.js";
48
- import "./chunk-GOVI6COW.js";
49
- import {
50
- BRAND
51
- } from "./chunk-EKLMXTWU.js";
49
+ } from "./chunk-OQO55NKV.js";
52
50
  import "./chunk-Z7EY4VHE.js";
53
51
 
54
52
  // src/bin.ts
55
53
  import { Command } from "commander";
56
- import pc23 from "picocolors";
54
+ import pc24 from "picocolors";
57
55
  import { readFileSync } from "fs";
58
56
  import { fileURLToPath } from "url";
59
- import { dirname as dirname4, join as join11 } from "path";
57
+ import { dirname as dirname5, join as join12 } from "path";
60
58
 
61
59
  // src/commands/validate.ts
62
60
  import pc from "picocolors";
@@ -176,9 +174,20 @@ ${BRAND.name} Build
176
174
  }
177
175
  fragmentCount = result.fragmentCount;
178
176
  outputPath = result.outputPath;
179
- console.log(pc2.green(`\u2713 Built ${result.fragmentCount} fragment(s)`));
180
- console.log(pc2.dim(` Output: ${result.outputPath}
177
+ if (result.fragmentCount === 0 && result.errors.length === 0) {
178
+ console.log(pc2.dim("No compilable fragment files found. Falling back to source scan...\n"));
179
+ const scanResult = await scan({
180
+ config: options.config,
181
+ output: options.output,
182
+ verbose: options.verbose
183
+ });
184
+ fragmentCount = scanResult.componentCount;
185
+ outputPath = scanResult.outputPath;
186
+ } else {
187
+ console.log(pc2.green(`\u2713 Built ${result.fragmentCount} fragment(s)`));
188
+ console.log(pc2.dim(` Output: ${result.outputPath}
181
189
  `));
190
+ }
182
191
  }
183
192
  if (options.registry || options.registryOnly) {
184
193
  console.log(pc2.dim("Generating registry and context...\n"));
@@ -602,6 +611,7 @@ function parseMeta(content, filePath, warnings) {
602
611
  );
603
612
  if (importMatch) {
604
613
  result.componentImport = importMatch[1];
614
+ result.isDefaultImport = false;
605
615
  } else {
606
616
  const defaultImportMatch = content.match(
607
617
  new RegExp(
@@ -610,6 +620,7 @@ function parseMeta(content, filePath, warnings) {
610
620
  );
611
621
  if (defaultImportMatch) {
612
622
  result.componentImport = defaultImportMatch[1];
623
+ result.isDefaultImport = true;
613
624
  }
614
625
  }
615
626
  }
@@ -1199,6 +1210,7 @@ function convertToFragment(parsed) {
1199
1210
  const code = generateFragmentCode({
1200
1211
  componentName,
1201
1212
  componentImport: parsed.meta.componentImport,
1213
+ isDefaultImport: parsed.meta.isDefaultImport,
1202
1214
  description: parsed.meta.description,
1203
1215
  category,
1204
1216
  tags: parsed.meta.tags,
@@ -1434,6 +1446,7 @@ function generateFragmentCode(options) {
1434
1446
  const {
1435
1447
  componentName,
1436
1448
  componentImport,
1449
+ isDefaultImport,
1437
1450
  description,
1438
1451
  category,
1439
1452
  tags,
@@ -1461,8 +1474,9 @@ ${generated.skippedVariants.map((sv) => ` { name: "${escapeString(sv.name)}
1461
1474
  },
1462
1475
  `;
1463
1476
  }
1477
+ const componentImportStatement = isDefaultImport ? `import ${componentName} from "${componentImport}";` : `import { ${componentName} } from "${componentImport}";`;
1464
1478
  return `import { defineFragment } from "@fragments-sdk/cli/core";
1465
- import { ${componentName} } from "${componentImport}";
1479
+ ${componentImportStatement}
1466
1480
 
1467
1481
  export default defineFragment({
1468
1482
  component: ${componentName},
@@ -1717,27 +1731,48 @@ async function runSetup(options = {}) {
1717
1731
  const sbConfig = await detectStorybookConfig(configDir);
1718
1732
  if (sbConfig) {
1719
1733
  log(pc6.dim(` Found Storybook at ${sbConfig.configPath}`));
1720
- log(pc6.dim(" Converting stories to fragments...\n"));
1721
- const storyFiles = await discoverStoryFiles(configDir, sbConfig.storyPatterns);
1722
- if (storyFiles.length > 0) {
1723
- let converted = 0;
1724
- for (const storyFile of storyFiles) {
1725
- try {
1726
- const parsed = await parseStoryFile(storyFile);
1727
- const fragmentResult = convertToFragment(parsed);
1728
- await fs2.mkdir(path.dirname(fragmentResult.outputFile), { recursive: true });
1729
- await fs2.writeFile(fragmentResult.outputFile, fragmentResult.code);
1730
- converted++;
1731
- } catch {
1734
+ const hasStoryPatterns = config.include.some((p) => p.includes(".stories."));
1735
+ if (hasStoryPatterns) {
1736
+ log(pc6.dim(" Stories included in config \u2014 viewer will load them directly\n"));
1737
+ fragmentFiles = await discoverFragmentFiles(config, configDir);
1738
+ if (fragmentFiles.length > 0) {
1739
+ log(pc6.green(` Found ${fragmentFiles.length} story/fragment file(s)`));
1740
+ }
1741
+ } else {
1742
+ log(pc6.dim(" Converting stories to fragments...\n"));
1743
+ const storyFiles = await discoverStoryFiles(configDir, sbConfig.storyPatterns);
1744
+ if (storyFiles.length > 0) {
1745
+ let converted = 0;
1746
+ for (const storyFile of storyFiles) {
1747
+ try {
1748
+ const parsed = await parseStoryFile(storyFile);
1749
+ const fragmentResult = convertToFragment(parsed);
1750
+ await fs2.mkdir(path.dirname(fragmentResult.outputFile), { recursive: true });
1751
+ await fs2.writeFile(fragmentResult.outputFile, fragmentResult.code);
1752
+ converted++;
1753
+ } catch {
1754
+ }
1732
1755
  }
1756
+ result.fragmentFilesCreated = converted;
1757
+ log(pc6.green(` Generated ${converted} fragment file(s)`));
1758
+ fragmentFiles = await discoverFragmentFiles(config, configDir);
1733
1759
  }
1734
- result.fragmentFilesCreated = converted;
1735
- log(pc6.green(` Generated ${converted} fragment file(s)`));
1736
- fragmentFiles = await discoverFragmentFiles(config, configDir);
1737
1760
  }
1738
1761
  } else {
1739
1762
  log(pc6.dim(" No Storybook config found"));
1740
- log(pc6.dim(` Run ${pc6.cyan(`${BRAND.cliCommand} add <ComponentName>`)} to create your first fragment`));
1763
+ log(pc6.dim(" Auto-scanning source code...\n"));
1764
+ try {
1765
+ const scanResult = await scan({
1766
+ config: options.configPath,
1767
+ verbose: false
1768
+ });
1769
+ if (scanResult.componentCount > 0) {
1770
+ result.fragmentsBuilt = scanResult.componentCount;
1771
+ log(pc6.green(` Scanned ${scanResult.componentCount} component(s) from source`));
1772
+ }
1773
+ } catch {
1774
+ log(pc6.dim(` Run ${pc6.cyan(`${BRAND.cliCommand} scan`)} to generate documentation from source`));
1775
+ }
1741
1776
  }
1742
1777
  } else if (fragmentFiles.length > 0) {
1743
1778
  log(pc6.green(` Found ${fragmentFiles.length} fragment file(s)`));
@@ -1757,7 +1792,19 @@ ${reason} ${BRAND.outFile}...`));
1757
1792
  result.errors.push(`${err.file}: ${err.error}`);
1758
1793
  }
1759
1794
  }
1760
- log(pc6.green(` Built ${buildResult.fragmentCount} fragment(s)`));
1795
+ if (buildResult.fragmentCount > 0) {
1796
+ log(pc6.green(` Built ${buildResult.fragmentCount} fragment(s)`));
1797
+ } else {
1798
+ log(pc6.dim(" No compilable fragments found, falling back to source scan..."));
1799
+ try {
1800
+ const scanResult = await scan({ verbose: false });
1801
+ if (scanResult.componentCount > 0) {
1802
+ result.fragmentsBuilt = scanResult.componentCount;
1803
+ log(pc6.green(` Scanned ${scanResult.componentCount} component(s) from source`));
1804
+ }
1805
+ } catch {
1806
+ }
1807
+ }
1761
1808
  } catch (error) {
1762
1809
  result.errors.push(`Build failed: ${error instanceof Error ? error.message : "Unknown error"}`);
1763
1810
  }
@@ -1811,7 +1858,7 @@ ${BRAND.name} Dev Server
1811
1858
  }
1812
1859
  }
1813
1860
  }
1814
- const { createDevServer } = await import("./viewer-SBTJDMP7.js");
1861
+ const { createDevServer } = await import("./viewer-DBEPYM3G.js");
1815
1862
  console.log(pc7.dim("\nStarting dev server..."));
1816
1863
  const parsedPort = typeof port === "string" ? parseInt(port, 10) : port;
1817
1864
  try {
@@ -5738,9 +5785,362 @@ ${BRAND.name} Doctor
5738
5785
  return result;
5739
5786
  }
5740
5787
 
5788
+ // src/commands/setup.ts
5789
+ import { readFile as readFile9, writeFile as writeFile9, access as access4, mkdir as mkdir7 } from "fs/promises";
5790
+ import { join as join11, resolve as resolve9, dirname as dirname4 } from "path";
5791
+ import pc23 from "picocolors";
5792
+ async function fileExists(path) {
5793
+ try {
5794
+ await access4(path);
5795
+ return true;
5796
+ } catch {
5797
+ return false;
5798
+ }
5799
+ }
5800
+ async function detectFramework(root) {
5801
+ if (await fileExists(join11(root, "app/layout.tsx")) || await fileExists(join11(root, "src/app/layout.tsx"))) {
5802
+ return "nextjs-app";
5803
+ }
5804
+ if (await fileExists(join11(root, "pages/_app.tsx")) || await fileExists(join11(root, "pages/_app.ts"))) {
5805
+ return "nextjs-pages";
5806
+ }
5807
+ if (await fileExists(join11(root, "next.config.ts")) || await fileExists(join11(root, "next.config.js")) || await fileExists(join11(root, "next.config.mjs"))) {
5808
+ return "nextjs-app";
5809
+ }
5810
+ if (await fileExists(join11(root, "vite.config.ts")) || await fileExists(join11(root, "vite.config.js"))) {
5811
+ return "vite";
5812
+ }
5813
+ return "unknown";
5814
+ }
5815
+ async function findEntryFile(root, framework) {
5816
+ const candidates = [];
5817
+ switch (framework) {
5818
+ case "nextjs-app":
5819
+ candidates.push(
5820
+ "src/app/layout.tsx",
5821
+ "app/layout.tsx",
5822
+ "src/app/layout.ts",
5823
+ "app/layout.ts"
5824
+ );
5825
+ break;
5826
+ case "nextjs-pages":
5827
+ candidates.push("pages/_app.tsx", "pages/_app.ts");
5828
+ break;
5829
+ case "vite":
5830
+ candidates.push(
5831
+ "src/main.tsx",
5832
+ "src/main.ts",
5833
+ "src/index.tsx",
5834
+ "src/index.ts"
5835
+ );
5836
+ break;
5837
+ default:
5838
+ candidates.push(
5839
+ "src/main.tsx",
5840
+ "src/main.ts",
5841
+ "src/index.tsx",
5842
+ "src/index.ts",
5843
+ "src/App.tsx",
5844
+ "src/App.ts"
5845
+ );
5846
+ }
5847
+ for (const candidate of candidates) {
5848
+ if (await fileExists(join11(root, candidate))) {
5849
+ return candidate;
5850
+ }
5851
+ }
5852
+ return null;
5853
+ }
5854
+ async function findNextConfig(root) {
5855
+ const candidates = ["next.config.ts", "next.config.mjs", "next.config.js"];
5856
+ for (const candidate of candidates) {
5857
+ if (await fileExists(join11(root, candidate))) {
5858
+ return candidate;
5859
+ }
5860
+ }
5861
+ return null;
5862
+ }
5863
+ async function addStylesImport(root, entryFile) {
5864
+ const fullPath = join11(root, entryFile);
5865
+ const content = await readFile9(fullPath, "utf-8");
5866
+ if (content.includes("@fragments-sdk/ui/styles")) {
5867
+ return { modified: false, message: `Styles already imported in ${entryFile}` };
5868
+ }
5869
+ const stylesImport = "import '@fragments-sdk/ui/styles';";
5870
+ let newContent;
5871
+ if (content.startsWith("'use client'") || content.startsWith('"use client"')) {
5872
+ const directiveEnd = content.indexOf("\n") + 1;
5873
+ newContent = content.slice(0, directiveEnd) + stylesImport + "\n" + content.slice(directiveEnd);
5874
+ } else {
5875
+ newContent = stylesImport + "\n" + content;
5876
+ }
5877
+ await writeFile9(fullPath, newContent, "utf-8");
5878
+ return { modified: true, message: `Added styles import to ${entryFile}` };
5879
+ }
5880
+ async function addThemeProvider(root, entryFile, framework) {
5881
+ const fullPath = join11(root, entryFile);
5882
+ const content = await readFile9(fullPath, "utf-8");
5883
+ if (content.includes("ThemeProvider")) {
5884
+ return { modified: false, message: `ThemeProvider already present in ${entryFile}` };
5885
+ }
5886
+ if (framework === "nextjs-app") {
5887
+ const providerImport = "import { ThemeProvider, TooltipProvider, ToastProvider } from '@fragments-sdk/ui';";
5888
+ let newContent = content;
5889
+ const importLines = content.split("\n");
5890
+ let lastImportIdx = -1;
5891
+ for (let i = 0; i < importLines.length; i++) {
5892
+ if (importLines[i].startsWith("import ") || importLines[i].startsWith("import '") || importLines[i].startsWith('import "')) {
5893
+ lastImportIdx = i;
5894
+ }
5895
+ }
5896
+ if (lastImportIdx >= 0) {
5897
+ importLines.splice(lastImportIdx + 1, 0, providerImport);
5898
+ newContent = importLines.join("\n");
5899
+ } else {
5900
+ newContent = providerImport + "\n" + content;
5901
+ }
5902
+ if (!content.includes("suppressHydrationWarning")) {
5903
+ await writeFile9(fullPath, newContent, "utf-8");
5904
+ return {
5905
+ modified: true,
5906
+ message: `Added provider imports to ${entryFile}. Wrap your {children} with:
5907
+ <ThemeProvider defaultMode="system"><TooltipProvider><ToastProvider>{children}</ToastProvider></TooltipProvider></ThemeProvider>
5908
+ Add suppressHydrationWarning to your <html> tag`
5909
+ };
5910
+ }
5911
+ await writeFile9(fullPath, newContent, "utf-8");
5912
+ return { modified: true, message: `Added provider imports to ${entryFile}. Wrap {children} with ThemeProvider.` };
5913
+ }
5914
+ return { modified: false, message: "Manual ThemeProvider setup needed \u2014 see https://usefragments.com/getting-started#provider-setup" };
5915
+ }
5916
+ async function addTranspilePackages(root) {
5917
+ const configFile = await findNextConfig(root);
5918
+ if (!configFile) {
5919
+ return { modified: false, message: "No next.config found" };
5920
+ }
5921
+ const fullPath = join11(root, configFile);
5922
+ const content = await readFile9(fullPath, "utf-8");
5923
+ if (content.includes("transpilePackages") && content.includes("@fragments-sdk/ui")) {
5924
+ return { modified: false, message: `transpilePackages already configured in ${configFile}` };
5925
+ }
5926
+ if (content.includes("transpilePackages")) {
5927
+ return {
5928
+ modified: false,
5929
+ message: `transpilePackages found in ${configFile} but missing '@fragments-sdk/ui'. Please add it manually.`
5930
+ };
5931
+ }
5932
+ const patterns = [
5933
+ // const nextConfig = { ... }
5934
+ { search: /const\s+\w+\s*=\s*\{/, replacement: (match) => `${match}
5935
+ transpilePackages: ['@fragments-sdk/ui'],` },
5936
+ // module.exports = { ... }
5937
+ { search: /module\.exports\s*=\s*\{/, replacement: (match) => `${match}
5938
+ transpilePackages: ['@fragments-sdk/ui'],` },
5939
+ // export default { ... }
5940
+ { search: /export\s+default\s*\{/, replacement: (match) => `${match}
5941
+ transpilePackages: ['@fragments-sdk/ui'],` }
5942
+ ];
5943
+ for (const pattern of patterns) {
5944
+ if (pattern.search.test(content)) {
5945
+ const newContent = content.replace(pattern.search, pattern.replacement);
5946
+ await writeFile9(fullPath, newContent, "utf-8");
5947
+ return { modified: true, message: `Added transpilePackages to ${configFile}` };
5948
+ }
5949
+ }
5950
+ return {
5951
+ modified: false,
5952
+ message: `Could not auto-modify ${configFile}. Add transpilePackages: ['@fragments-sdk/ui'] manually.`
5953
+ };
5954
+ }
5955
+ async function createScssSeeds(root, brand) {
5956
+ const scssLocations = [
5957
+ "src/app/globals.scss",
5958
+ "app/globals.scss",
5959
+ "src/styles/globals.scss",
5960
+ "src/globals.scss",
5961
+ "styles/globals.scss"
5962
+ ];
5963
+ for (const loc of scssLocations) {
5964
+ const fullPath2 = join11(root, loc);
5965
+ if (await fileExists(fullPath2)) {
5966
+ const content = await readFile9(fullPath2, "utf-8");
5967
+ if (content.includes("@fragments-sdk/ui/styles")) {
5968
+ return { modified: false, message: `SCSS seeds already configured in ${loc}` };
5969
+ }
5970
+ const seedContent = generateScssSeedImport(brand);
5971
+ const newContent = seedContent + "\n" + content;
5972
+ await writeFile9(fullPath2, newContent, "utf-8");
5973
+ return { modified: true, message: `Added SCSS seed import to ${loc}` };
5974
+ }
5975
+ }
5976
+ const targetDir = await fileExists(join11(root, "src/app")) ? "src/app" : await fileExists(join11(root, "src")) ? "src/styles" : "styles";
5977
+ const targetPath = join11(targetDir, "globals.scss");
5978
+ const fullPath = join11(root, targetPath);
5979
+ await mkdir7(dirname4(fullPath), { recursive: true });
5980
+ await writeFile9(fullPath, generateScssSeedImport(brand), "utf-8");
5981
+ return { modified: true, message: `Created ${targetPath} with SCSS seed configuration` };
5982
+ }
5983
+ async function setupMcpConfig(root) {
5984
+ const mcpConfigPaths = [
5985
+ ".cursor/mcp.json",
5986
+ ".vscode/mcp.json"
5987
+ ];
5988
+ for (const configPath of mcpConfigPaths) {
5989
+ const fullPath = join11(root, configPath);
5990
+ if (await fileExists(fullPath)) {
5991
+ try {
5992
+ const content = await readFile9(fullPath, "utf-8");
5993
+ const config = JSON.parse(content);
5994
+ const servers = config.mcpServers || {};
5995
+ const hasFragments = Object.values(servers).some((server) => {
5996
+ const s = server;
5997
+ return s.args?.some((arg) => arg.includes("@fragments-sdk/mcp"));
5998
+ });
5999
+ if (hasFragments) {
6000
+ return { modified: false, message: `MCP server already configured in ${configPath}` };
6001
+ }
6002
+ servers.fragments = {
6003
+ command: "npx",
6004
+ args: ["@fragments-sdk/mcp"]
6005
+ };
6006
+ config.mcpServers = servers;
6007
+ await writeFile9(fullPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
6008
+ return { modified: true, message: `Added Fragments MCP server to ${configPath}` };
6009
+ } catch {
6010
+ return { modified: false, message: `Could not parse ${configPath}` };
6011
+ }
6012
+ }
6013
+ }
6014
+ const cursorDir = join11(root, ".cursor");
6015
+ const cursorMcpPath = join11(cursorDir, "mcp.json");
6016
+ await mkdir7(cursorDir, { recursive: true });
6017
+ const mcpConfig = {
6018
+ mcpServers: {
6019
+ fragments: {
6020
+ command: "npx",
6021
+ args: ["@fragments-sdk/mcp"]
6022
+ }
6023
+ }
6024
+ };
6025
+ await writeFile9(cursorMcpPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
6026
+ return { modified: true, message: "Created .cursor/mcp.json with Fragments MCP server" };
6027
+ }
6028
+ function generateScssSeedImport(brand) {
6029
+ const brandColor = brand || "#0066ff";
6030
+ return `@use '@fragments-sdk/ui/styles' with (
6031
+ $fui-brand: ${brandColor},
6032
+ $fui-neutral: "stone",
6033
+ $fui-density: "default",
6034
+ $fui-radius-style: "rounded"
6035
+ );
6036
+ `;
6037
+ }
6038
+ async function setup(options = {}) {
6039
+ const root = resolve9(options.root ?? process.cwd());
6040
+ const actions = [];
6041
+ const errors = [];
6042
+ console.log(pc23.cyan(`
6043
+ ${BRAND.name} Setup
6044
+ `));
6045
+ const framework = await detectFramework(root);
6046
+ const frameworkLabel = framework === "nextjs-app" ? "Next.js (App Router)" : framework === "nextjs-pages" ? "Next.js (Pages Router)" : framework === "vite" ? "Vite" : "Unknown";
6047
+ console.log(` ${pc23.dim("Framework:")} ${frameworkLabel}`);
6048
+ const entryFile = await findEntryFile(root, framework);
6049
+ if (entryFile) {
6050
+ console.log(` ${pc23.dim("Entry:")} ${entryFile}`);
6051
+ } else {
6052
+ console.log(` ${pc23.yellow("!")} Could not detect entry file`);
6053
+ }
6054
+ console.log();
6055
+ if (entryFile) {
6056
+ try {
6057
+ const result = await addStylesImport(root, entryFile);
6058
+ const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
6059
+ console.log(` ${icon} ${result.message}`);
6060
+ if (result.modified) actions.push(result.message);
6061
+ } catch (error) {
6062
+ const msg = `Failed to add styles import: ${error instanceof Error ? error.message : error}`;
6063
+ console.log(` ${pc23.red("\u2717")} ${msg}`);
6064
+ errors.push(msg);
6065
+ }
6066
+ }
6067
+ if (entryFile) {
6068
+ try {
6069
+ const result = await addThemeProvider(root, entryFile, framework);
6070
+ const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
6071
+ console.log(` ${icon} ${result.message}`);
6072
+ if (result.modified) actions.push(result.message);
6073
+ } catch (error) {
6074
+ const msg = `Failed to add ThemeProvider: ${error instanceof Error ? error.message : error}`;
6075
+ console.log(` ${pc23.red("\u2717")} ${msg}`);
6076
+ errors.push(msg);
6077
+ }
6078
+ }
6079
+ if (framework === "nextjs-app" || framework === "nextjs-pages") {
6080
+ try {
6081
+ const result = await addTranspilePackages(root);
6082
+ const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
6083
+ console.log(` ${icon} ${result.message}`);
6084
+ if (result.modified) actions.push(result.message);
6085
+ } catch (error) {
6086
+ const msg = `Failed to update next.config: ${error instanceof Error ? error.message : error}`;
6087
+ console.log(` ${pc23.red("\u2717")} ${msg}`);
6088
+ errors.push(msg);
6089
+ }
6090
+ }
6091
+ if (options.scss || options.brand) {
6092
+ try {
6093
+ const result = await createScssSeeds(root, options.brand);
6094
+ const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
6095
+ console.log(` ${icon} ${result.message}`);
6096
+ if (result.modified) actions.push(result.message);
6097
+ } catch (error) {
6098
+ const msg = `Failed to create SCSS seeds: ${error instanceof Error ? error.message : error}`;
6099
+ console.log(` ${pc23.red("\u2717")} ${msg}`);
6100
+ errors.push(msg);
6101
+ }
6102
+ }
6103
+ if (options.mcp) {
6104
+ try {
6105
+ const result = await setupMcpConfig(root);
6106
+ const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
6107
+ console.log(` ${icon} ${result.message}`);
6108
+ if (result.modified) actions.push(result.message);
6109
+ } catch (error) {
6110
+ const msg = `Failed to configure MCP: ${error instanceof Error ? error.message : error}`;
6111
+ console.log(` ${pc23.red("\u2717")} ${msg}`);
6112
+ errors.push(msg);
6113
+ }
6114
+ }
6115
+ console.log();
6116
+ if (errors.length > 0) {
6117
+ console.log(pc23.red(` ${errors.length} error(s) occurred during setup`));
6118
+ } else if (actions.length > 0) {
6119
+ console.log(pc23.green(` \u2713 Setup complete \u2014 ${actions.length} file(s) modified`));
6120
+ } else {
6121
+ console.log(pc23.green(" \u2713 Already configured \u2014 no changes needed"));
6122
+ }
6123
+ console.log();
6124
+ console.log(pc23.dim(" Next steps:"));
6125
+ if (!options.scss && !options.brand) {
6126
+ console.log(pc23.dim(" \u2022 Run with --scss to add build-time theme seeds"));
6127
+ }
6128
+ if (!options.mcp) {
6129
+ console.log(pc23.dim(" \u2022 Run with --mcp to configure AI tooling (MCP server)"));
6130
+ }
6131
+ console.log(pc23.dim(" \u2022 Run `fragments doctor` to verify your setup"));
6132
+ console.log(pc23.dim(" \u2022 Visit https://usefragments.com/getting-started"));
6133
+ console.log();
6134
+ return {
6135
+ success: errors.length === 0,
6136
+ actions,
6137
+ errors
6138
+ };
6139
+ }
6140
+
5741
6141
  // src/bin.ts
5742
- var __dirname = dirname4(fileURLToPath(import.meta.url));
5743
- var pkg = JSON.parse(readFileSync(join11(__dirname, "../package.json"), "utf-8"));
6142
+ var __dirname = dirname5(fileURLToPath(import.meta.url));
6143
+ var pkg = JSON.parse(readFileSync(join12(__dirname, "../package.json"), "utf-8"));
5744
6144
  var program = new Command();
5745
6145
  program.name(BRAND.cliCommand).description(`${BRAND.name} - Design system documentation and compliance tool`).version(pkg.version);
5746
6146
  program.command("validate").description("Validate fragment files").option("-c, --config <path>", "Path to config file").option("--schema", "Validate fragment schema only").option("--coverage", "Validate coverage only").option("--snippets", "Validate snippet/render policy only").option("--snippet-mode <mode>", "Override snippet policy mode (warn|error)").option("--component-start <name>", "Start component name for alphabetical snippet batch validation").option("--component-limit <n>", "Component count for alphabetical snippet batch validation", (value) => Number.parseInt(value, 10)).action(async (options) => {
@@ -5750,7 +6150,7 @@ program.command("validate").description("Validate fragment files").option("-c, -
5750
6150
  process.exit(1);
5751
6151
  }
5752
6152
  } catch (error) {
5753
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6153
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5754
6154
  process.exit(1);
5755
6155
  }
5756
6156
  });
@@ -5770,7 +6170,7 @@ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAN
5770
6170
  process.exit(1);
5771
6171
  }
5772
6172
  } catch (error) {
5773
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6173
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5774
6174
  process.exit(1);
5775
6175
  }
5776
6176
  });
@@ -5789,7 +6189,7 @@ program.command("context").description("Generate AI-ready context for your desig
5789
6189
  process.exit(1);
5790
6190
  }
5791
6191
  } catch (error) {
5792
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6192
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5793
6193
  process.exit(1);
5794
6194
  }
5795
6195
  });
@@ -5816,7 +6216,7 @@ program.command("ai").description("Generate context optimized for AI assistants
5816
6216
  }
5817
6217
  }
5818
6218
  } catch (error) {
5819
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6219
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5820
6220
  process.exit(1);
5821
6221
  }
5822
6222
  });
@@ -5824,7 +6224,7 @@ program.command("list").description("List all discovered fragment files").option
5824
6224
  try {
5825
6225
  await list(options);
5826
6226
  } catch (error) {
5827
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6227
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5828
6228
  process.exit(1);
5829
6229
  }
5830
6230
  });
@@ -5832,7 +6232,7 @@ program.command("reset").description("Reset to initial state (delete all generat
5832
6232
  try {
5833
6233
  await reset(options);
5834
6234
  } catch (error) {
5835
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6235
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5836
6236
  process.exit(1);
5837
6237
  }
5838
6238
  });
@@ -5846,7 +6246,7 @@ linkCommand.command("figma").argument("[figma-url]", "Figma file URL to link com
5846
6246
  variants: options.variants
5847
6247
  });
5848
6248
  } catch (error) {
5849
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6249
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5850
6250
  process.exit(1);
5851
6251
  }
5852
6252
  });
@@ -5861,7 +6261,7 @@ linkCommand.command("storybook").description("Bootstrap fragments from existing
5861
6261
  exclude: options.exclude
5862
6262
  });
5863
6263
  } catch (error) {
5864
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6264
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5865
6265
  process.exit(1);
5866
6266
  }
5867
6267
  });
@@ -5876,9 +6276,9 @@ program.command("dev").description("Start the development server with live compo
5876
6276
  skipBuild: options.skipBuild
5877
6277
  });
5878
6278
  } catch (error) {
5879
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6279
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5880
6280
  if (error instanceof Error && error.stack) {
5881
- console.error(pc23.dim(error.stack));
6281
+ console.error(pc24.dim(error.stack));
5882
6282
  }
5883
6283
  process.exit(1);
5884
6284
  }
@@ -5899,7 +6299,7 @@ program.command("screenshot").description("Capture screenshots of component vari
5899
6299
  process.exit(1);
5900
6300
  }
5901
6301
  } catch (error) {
5902
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6302
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5903
6303
  process.exit(1);
5904
6304
  }
5905
6305
  });
@@ -5918,7 +6318,7 @@ program.command("diff").argument("[component]", "Component name to diff (optiona
5918
6318
  process.exit(1);
5919
6319
  }
5920
6320
  } catch (error) {
5921
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6321
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5922
6322
  process.exit(1);
5923
6323
  }
5924
6324
  });
@@ -5937,8 +6337,8 @@ program.command("compare").argument("[component]", "Component name to compare").
5937
6337
  process.exit(1);
5938
6338
  }
5939
6339
  } catch (error) {
5940
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
5941
- console.log(pc23.dim(`
6340
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6341
+ console.log(pc24.dim(`
5942
6342
  Make sure the dev server is running: ${BRAND.cliCommand} dev`));
5943
6343
  process.exit(1);
5944
6344
  }
@@ -5957,7 +6357,7 @@ program.command("analyze").description("Analyze design system and generate repor
5957
6357
  process.exit(1);
5958
6358
  }
5959
6359
  } catch (error) {
5960
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6360
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5961
6361
  process.exit(1);
5962
6362
  }
5963
6363
  });
@@ -5976,7 +6376,7 @@ program.command("verify").argument("[component]", "Component name to verify (opt
5976
6376
  if (options.ci) {
5977
6377
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Verification failed" }));
5978
6378
  } else {
5979
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6379
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5980
6380
  }
5981
6381
  process.exit(1);
5982
6382
  }
@@ -5993,7 +6393,7 @@ program.command("audit").description("Scan all fragments and show compliance met
5993
6393
  if (options.json) {
5994
6394
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Audit failed" }));
5995
6395
  } else {
5996
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6396
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
5997
6397
  }
5998
6398
  process.exit(1);
5999
6399
  }
@@ -6015,7 +6415,7 @@ program.command("a11y").description("Run accessibility checks on all component v
6015
6415
  if (options.json) {
6016
6416
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "A11y check failed" }));
6017
6417
  } else {
6018
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6418
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6019
6419
  }
6020
6420
  process.exit(1);
6021
6421
  }
@@ -6038,7 +6438,7 @@ program.command("enhance").description("AI-powered documentation generation from
6038
6438
  if (options.format === "json") {
6039
6439
  console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Enhance failed" }));
6040
6440
  } else {
6041
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6441
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6042
6442
  }
6043
6443
  process.exit(1);
6044
6444
  }
@@ -6059,7 +6459,7 @@ program.command("scan").description(`Zero-config ${BRAND.outFile} generation fro
6059
6459
  process.exit(1);
6060
6460
  }
6061
6461
  } catch (error) {
6062
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6462
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6063
6463
  process.exit(1);
6064
6464
  }
6065
6465
  });
@@ -6072,7 +6472,7 @@ program.command("storygen").description("Generate Storybook stories from fragmen
6072
6472
  format: options.format
6073
6473
  });
6074
6474
  } catch (error) {
6075
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6475
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6076
6476
  process.exit(1);
6077
6477
  }
6078
6478
  });
@@ -6084,7 +6484,7 @@ program.command("metrics").argument("[component]", "Component name (optional, sh
6084
6484
  json: options.json
6085
6485
  });
6086
6486
  } catch (error) {
6087
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6487
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6088
6488
  process.exit(1);
6089
6489
  }
6090
6490
  });
@@ -6098,9 +6498,9 @@ program.command("baseline").description("Manage visual regression baselines").ar
6098
6498
  port: options.port
6099
6499
  });
6100
6500
  } catch (error) {
6101
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6501
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6102
6502
  if (action === "update") {
6103
- console.log(pc23.dim(`
6503
+ console.log(pc24.dim(`
6104
6504
  Make sure the dev server is running: ${BRAND.cliCommand} dev`));
6105
6505
  }
6106
6506
  process.exit(1);
@@ -6108,27 +6508,27 @@ Make sure the dev server is running: ${BRAND.cliCommand} dev`));
6108
6508
  });
6109
6509
  program.command("view").description(`Generate a static HTML viewer for ${BRAND.outFile}`).option("-i, --input <path>", `Path to ${BRAND.outFile}`, BRAND.outFile).option("-o, --output <path>", "Output HTML file path", BRAND.viewerHtmlFile).option("--open", "Open in browser after generation").action(async (options) => {
6110
6510
  try {
6111
- const { generateViewerFromJson } = await import("./static-viewer-NSODM5VX.js");
6511
+ const { generateViewerFromJson } = await import("./static-viewer-NUBFPKWH.js");
6112
6512
  const fs2 = await import("fs/promises");
6113
6513
  const path = await import("path");
6114
6514
  const inputPath = path.resolve(process.cwd(), options.input);
6115
6515
  const outputPath = path.resolve(process.cwd(), options.output);
6116
- console.log(pc23.cyan(`
6516
+ console.log(pc24.cyan(`
6117
6517
  ${BRAND.name} Viewer Generator
6118
6518
  `));
6119
6519
  try {
6120
6520
  await fs2.access(inputPath);
6121
6521
  } catch {
6122
- console.log(pc23.red(`Error: ${options.input} not found.`));
6123
- console.log(pc23.dim(`
6124
- Run ${pc23.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
6522
+ console.log(pc24.red(`Error: ${options.input} not found.`));
6523
+ console.log(pc24.dim(`
6524
+ Run ${pc24.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
6125
6525
  `));
6126
6526
  process.exit(1);
6127
6527
  }
6128
- console.log(pc23.dim(`Reading: ${options.input}`));
6528
+ console.log(pc24.dim(`Reading: ${options.input}`));
6129
6529
  const html = await generateViewerFromJson(inputPath);
6130
6530
  await fs2.writeFile(outputPath, html);
6131
- console.log(pc23.green(`
6531
+ console.log(pc24.green(`
6132
6532
  \u2713 Generated: ${options.output}
6133
6533
  `));
6134
6534
  if (options.open) {
@@ -6137,7 +6537,7 @@ Run ${pc23.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
6137
6537
  exec(`${openCmd} "${outputPath}"`);
6138
6538
  }
6139
6539
  } catch (error) {
6140
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6540
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6141
6541
  process.exit(1);
6142
6542
  }
6143
6543
  });
@@ -6150,33 +6550,51 @@ program.command("add").argument("[name]", 'Component name (e.g., "Button", "Text
6150
6550
  component: options.component
6151
6551
  });
6152
6552
  } catch (error) {
6153
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6553
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6554
+ process.exit(1);
6555
+ }
6556
+ });
6557
+ program.command("setup").description("Configure @fragments-sdk/ui in a consumer project (styles, providers, Next.js config)").option("--root <dir>", "Project root directory", process.cwd()).option("-y, --yes", "Skip interactive prompts").option("--brand <color>", "Brand color hex (e.g., #6366f1)").option("--scss", "Create SCSS seed file for build-time theming").option("--mcp", "Configure MCP server for AI tooling").action(async (options) => {
6558
+ try {
6559
+ const result = await setup({
6560
+ root: options.root,
6561
+ yes: options.yes,
6562
+ brand: options.brand,
6563
+ scss: options.scss,
6564
+ mcp: options.mcp
6565
+ });
6566
+ if (!result.success) {
6567
+ process.exit(1);
6568
+ }
6569
+ } catch (error) {
6570
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6154
6571
  process.exit(1);
6155
6572
  }
6156
6573
  });
6157
- program.command("init").description("Initialize fragments in a project (interactive by default)").option("--force", "Overwrite existing config").option("-y, --yes", "Non-interactive mode - auto-detect and use defaults").action(async (options) => {
6574
+ program.command("init").description("Initialize fragments in a project (interactive by default)").option("--force", "Overwrite existing config").option("-y, --yes", "Non-interactive mode - auto-detect and use defaults").option("--scan <path>", "Scan a TypeScript component directory and generate fragment files").action(async (options) => {
6158
6575
  try {
6159
- const { init } = await import("./init-KSAAS7X3.js");
6576
+ const { init } = await import("./init-Q53R5Q2T.js");
6160
6577
  const result = await init({
6161
6578
  projectRoot: process.cwd(),
6162
6579
  force: options.force,
6163
- yes: options.yes
6580
+ yes: options.scan ? true : options.yes,
6581
+ scan: options.scan
6164
6582
  });
6165
6583
  if (!result.success) {
6166
- console.error(pc23.red("\nInit failed with errors:"));
6584
+ console.error(pc24.red("\nInit failed with errors:"));
6167
6585
  for (const error of result.errors) {
6168
- console.error(pc23.red(` - ${error}`));
6586
+ console.error(pc24.red(` - ${error}`));
6169
6587
  }
6170
6588
  process.exit(1);
6171
6589
  }
6172
6590
  } catch (error) {
6173
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6591
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6174
6592
  process.exit(1);
6175
6593
  }
6176
6594
  });
6177
6595
  program.command("tokens").description("Discover and list design tokens from CSS/SCSS files").option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--categories", "Group tokens by category").option("--theme <theme>", "Filter by theme name").option("--category <category>", "Filter by category (color, spacing, typography, etc.)").option("--verbose", "Show all tokens (no truncation)").action(async (options) => {
6178
6596
  try {
6179
- const { tokens } = await import("./tokens-NIXSZRX7.js");
6597
+ const { tokens } = await import("./tokens-DXEGYTOJ.js");
6180
6598
  const result = await tokens({
6181
6599
  config: options.config,
6182
6600
  json: options.json,
@@ -6189,13 +6607,13 @@ program.command("tokens").description("Discover and list design tokens from CSS/
6189
6607
  process.exit(1);
6190
6608
  }
6191
6609
  } catch (error) {
6192
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6610
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6193
6611
  process.exit(1);
6194
6612
  }
6195
6613
  });
6196
6614
  program.command("generate").description("Generate fragment files from component source code").argument("[component]", "Specific component name to generate (optional)").option("--force", "Overwrite existing fragment files").option("--pattern <glob>", "Pattern for component files", "src/components/**/*.tsx").action(async (component, options) => {
6197
6615
  try {
6198
- const { generate } = await import("./generate-35OIMW4Y.js");
6616
+ const { generate } = await import("./generate-BGKTKO6E.js");
6199
6617
  const result = await generate({
6200
6618
  projectRoot: process.cwd(),
6201
6619
  component,
@@ -6203,11 +6621,11 @@ program.command("generate").description("Generate fragment files from component
6203
6621
  componentPattern: options.pattern
6204
6622
  });
6205
6623
  if (!result.success) {
6206
- console.error(pc23.red("\nGenerate completed with errors"));
6624
+ console.error(pc24.red("\nGenerate completed with errors"));
6207
6625
  process.exit(1);
6208
6626
  }
6209
6627
  } catch (error) {
6210
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6628
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6211
6629
  process.exit(1);
6212
6630
  }
6213
6631
  });
@@ -6215,7 +6633,7 @@ program.command("graph").description("Query the component relationship graph").a
6215
6633
  try {
6216
6634
  await graph(component, options);
6217
6635
  } catch (error) {
6218
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6636
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6219
6637
  process.exit(1);
6220
6638
  }
6221
6639
  });
@@ -6233,14 +6651,14 @@ program.command("perf").description("Profile component bundle sizes and performa
6233
6651
  process.exit(1);
6234
6652
  }
6235
6653
  } catch (error) {
6236
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6654
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6237
6655
  process.exit(1);
6238
6656
  }
6239
6657
  });
6240
6658
  program.command("test").description("Run interaction tests for fragments with play functions").option("-c, --config <path>", "Path to config file").option("--component <name>", "Filter by component name").option("--tags <tags>", "Filter by tags (comma-separated)").option("--grep <pattern>", "Filter by variant name pattern").option("--exclude <pattern>", "Exclude tests matching pattern").option("--parallel <count>", "Number of parallel browser contexts", parseInt, 4).option("--timeout <ms>", "Timeout per test in milliseconds", parseInt, 3e4).option("--retries <count>", "Number of retries for failed tests", parseInt, 0).option("--bail", "Stop on first failure").option("--browser <name>", "Browser to use (chromium, firefox, webkit)", "chromium").option("--headed", "Run in headed mode (show browser)").option("--a11y", "Run accessibility checks with axe-core").option("--visual", "Capture screenshots for visual regression").option("--update-snapshots", "Update visual snapshots").option("--watch", "Watch mode - re-run on file changes").option("--reporters <names>", "Reporters to use (console, junit, json)", "console").option("-o, --output <dir>", "Output directory for results", "./test-results").option("--server-url <url>", "URL of running dev server (skips starting server)").option("-p, --port <port>", "Port for dev server", parseInt, 6006).option("--ci", "CI mode - non-interactive, exit with code 1 on failure").option("--list", "List available tests without running them").action(async (options) => {
6241
6659
  try {
6242
6660
  const { config, configDir } = await loadConfig(options.config);
6243
- const { runTestCommand, listTests } = await import("./test-RPWZAYSJ.js");
6661
+ const { runTestCommand, listTests } = await import("./test-2CSOSS3B.js");
6244
6662
  if (options.list) {
6245
6663
  await listTests(config, configDir, {
6246
6664
  component: options.component,
@@ -6273,7 +6691,7 @@ program.command("test").description("Run interaction tests for fragments with pl
6273
6691
  });
6274
6692
  process.exit(exitCode);
6275
6693
  } catch (error) {
6276
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6694
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6277
6695
  process.exit(1);
6278
6696
  }
6279
6697
  });
@@ -6288,7 +6706,7 @@ program.command("doctor").description("Diagnose design system configuration issu
6288
6706
  process.exit(1);
6289
6707
  }
6290
6708
  } catch (error) {
6291
- console.error(pc23.red("Error:"), error instanceof Error ? error.message : error);
6709
+ console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
6292
6710
  process.exit(1);
6293
6711
  }
6294
6712
  });