@fragments-sdk/cli 0.7.0 → 0.7.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 (171) hide show
  1. package/dist/bin.js +245 -245
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-XHUDJNN3.js → chunk-32VIEOQY.js} +18 -18
  4. package/dist/chunk-32VIEOQY.js.map +1 -0
  5. package/dist/{chunk-CVXKXVOY.js → chunk-5ITIP3ES.js} +27 -27
  6. package/dist/chunk-5ITIP3ES.js.map +1 -0
  7. package/dist/{chunk-RVRTRESS.js → chunk-DQHWLAUV.js} +29 -29
  8. package/dist/chunk-DQHWLAUV.js.map +1 -0
  9. package/dist/{chunk-TJ34N7C7.js → chunk-GCZMFLDI.js} +30 -32
  10. package/dist/chunk-GCZMFLDI.js.map +1 -0
  11. package/dist/{chunk-6JBGU74P.js → chunk-GHYYFAQN.js} +23 -23
  12. package/dist/chunk-GHYYFAQN.js.map +1 -0
  13. package/dist/{chunk-NWQ4CJOQ.js → chunk-GKX2HPZ6.js} +40 -40
  14. package/dist/chunk-GKX2HPZ6.js.map +1 -0
  15. package/dist/{chunk-7OPWMLOE.js → chunk-U6VTHBNI.js} +110 -110
  16. package/dist/chunk-U6VTHBNI.js.map +1 -0
  17. package/dist/{core-W2HYIQW6.js → core-SFHPYR5H.js} +24 -26
  18. package/dist/{generate-LMTISDIJ.js → generate-54GJAWUY.js} +5 -5
  19. package/dist/generate-54GJAWUY.js.map +1 -0
  20. package/dist/index.d.ts +23 -27
  21. package/dist/index.js +10 -10
  22. package/dist/{init-7CHRKQ7P.js → init-EIM5WNMP.js} +5 -5
  23. package/dist/{init-7CHRKQ7P.js.map → init-EIM5WNMP.js.map} +1 -1
  24. package/dist/mcp-bin.js +73 -73
  25. package/dist/mcp-bin.js.map +1 -1
  26. package/dist/scan-KQBKUS64.js +12 -0
  27. package/dist/{service-T2L7VLTE.js → service-ED2LNCTU.js} +6 -6
  28. package/dist/{static-viewer-GBR7YNF3.js → static-viewer-Q4F4QP5M.js} +4 -4
  29. package/dist/{test-OJRXNDO2.js → test-6VN2DA3S.js} +19 -19
  30. package/dist/test-6VN2DA3S.js.map +1 -0
  31. package/dist/{tokens-3BWDESVM.js → tokens-P2B7ZAM3.js} +5 -5
  32. package/dist/{viewer-SUFOISZM.js → viewer-GM7IQPPB.js} +199 -199
  33. package/dist/viewer-GM7IQPPB.js.map +1 -0
  34. package/package.json +2 -2
  35. package/src/ai.ts +5 -5
  36. package/src/analyze.ts +11 -11
  37. package/src/bin.ts +1 -1
  38. package/src/build.ts +33 -33
  39. package/src/commands/a11y.ts +6 -6
  40. package/src/commands/add.ts +11 -11
  41. package/src/commands/audit.ts +4 -4
  42. package/src/commands/baseline.ts +3 -3
  43. package/src/commands/build.ts +8 -8
  44. package/src/commands/compare.ts +20 -20
  45. package/src/commands/context.ts +16 -16
  46. package/src/commands/enhance.ts +36 -36
  47. package/src/commands/generate.ts +1 -1
  48. package/src/commands/graph.ts +3 -3
  49. package/src/commands/init.ts +1 -1
  50. package/src/commands/link/figma.ts +82 -82
  51. package/src/commands/link/index.ts +3 -3
  52. package/src/commands/link/storybook.ts +9 -9
  53. package/src/commands/list.ts +2 -2
  54. package/src/commands/reset.ts +15 -15
  55. package/src/commands/scan.ts +27 -27
  56. package/src/commands/storygen.ts +24 -24
  57. package/src/commands/validate.ts +2 -2
  58. package/src/commands/verify.ts +8 -8
  59. package/src/core/auto-props.ts +4 -4
  60. package/src/core/composition.test.ts +36 -36
  61. package/src/core/composition.ts +19 -19
  62. package/src/core/config.ts +6 -6
  63. package/src/core/{defineSegment.ts → defineFragment.ts} +16 -22
  64. package/src/core/discovery.ts +6 -6
  65. package/src/core/figma.ts +2 -2
  66. package/src/core/graph-extractor.test.ts +77 -77
  67. package/src/core/graph-extractor.ts +32 -32
  68. package/src/core/importAnalyzer.ts +1 -1
  69. package/src/core/index.ts +22 -23
  70. package/src/core/loader.ts +22 -22
  71. package/src/core/node.ts +5 -5
  72. package/src/core/parser.ts +31 -31
  73. package/src/core/previewLoader.ts +1 -1
  74. package/src/core/schema.ts +16 -16
  75. package/src/core/storyAdapter.test.ts +87 -87
  76. package/src/core/storyAdapter.ts +16 -16
  77. package/src/core/types.ts +21 -26
  78. package/src/diff.ts +22 -22
  79. package/src/index.ts +2 -2
  80. package/src/mcp/server.ts +80 -80
  81. package/src/migrate/__tests__/utils/utils.test.ts +3 -3
  82. package/src/migrate/bin.ts +4 -4
  83. package/src/migrate/converter.ts +16 -16
  84. package/src/migrate/index.ts +3 -3
  85. package/src/migrate/migrate.ts +3 -3
  86. package/src/migrate/parser.ts +8 -8
  87. package/src/migrate/report.ts +2 -2
  88. package/src/migrate/types.ts +4 -4
  89. package/src/screenshot.ts +22 -22
  90. package/src/service/__tests__/props-extractor.test.ts +15 -15
  91. package/src/service/analytics.ts +39 -39
  92. package/src/service/enhance/codebase-scanner.ts +1 -1
  93. package/src/service/enhance/index.ts +1 -1
  94. package/src/service/enhance/props-extractor.ts +2 -2
  95. package/src/service/enhance/types.ts +2 -2
  96. package/src/service/index.ts +2 -2
  97. package/src/service/metrics-store.ts +1 -1
  98. package/src/service/patch-generator.ts +1 -1
  99. package/src/setup.ts +52 -52
  100. package/src/shared/dev-server-client.ts +7 -7
  101. package/src/shared/fragment-loader.ts +59 -0
  102. package/src/shared/index.ts +1 -1
  103. package/src/shared/types.ts +4 -4
  104. package/src/static-viewer.ts +35 -35
  105. package/src/test/discovery.ts +6 -6
  106. package/src/test/index.ts +5 -5
  107. package/src/test/reporters/console.ts +1 -1
  108. package/src/test/reporters/junit.ts +1 -1
  109. package/src/test/runner.ts +7 -7
  110. package/src/test/types.ts +3 -3
  111. package/src/test/watch.ts +9 -9
  112. package/src/validators.ts +26 -26
  113. package/src/viewer/__tests__/render-utils.test.ts +28 -28
  114. package/src/viewer/__tests__/viewer-integration.test.ts +4 -4
  115. package/src/viewer/cli/health.ts +26 -26
  116. package/src/viewer/components/App.tsx +79 -79
  117. package/src/viewer/components/BottomPanel.tsx +17 -17
  118. package/src/viewer/components/CodePanel.tsx +3 -3
  119. package/src/viewer/components/CommandPalette.tsx +11 -11
  120. package/src/viewer/components/ComponentGraph.tsx +28 -28
  121. package/src/viewer/components/ComponentHeader.tsx +2 -2
  122. package/src/viewer/components/ContractPanel.tsx +6 -6
  123. package/src/viewer/components/FigmaEmbed.tsx +9 -9
  124. package/src/viewer/components/HealthDashboard.tsx +17 -17
  125. package/src/viewer/components/InteractionsPanel.tsx +2 -2
  126. package/src/viewer/components/IsolatedPreviewFrame.tsx +6 -6
  127. package/src/viewer/components/IsolatedRender.tsx +10 -10
  128. package/src/viewer/components/LeftSidebar.tsx +28 -28
  129. package/src/viewer/components/MultiViewportPreview.tsx +14 -14
  130. package/src/viewer/components/PreviewArea.tsx +11 -11
  131. package/src/viewer/components/PreviewFrameHost.tsx +51 -51
  132. package/src/viewer/components/RightSidebar.tsx +9 -9
  133. package/src/viewer/components/Sidebar.tsx +17 -17
  134. package/src/viewer/components/StoryRenderer.tsx +2 -2
  135. package/src/viewer/components/TokenStylePanel.tsx +1 -1
  136. package/src/viewer/components/UsageSection.tsx +2 -2
  137. package/src/viewer/components/VariantMatrix.tsx +11 -11
  138. package/src/viewer/components/VariantRenderer.tsx +3 -3
  139. package/src/viewer/components/VariantTabs.tsx +2 -2
  140. package/src/viewer/components/_future/CreatePage.tsx +6 -6
  141. package/src/viewer/composition-renderer.ts +11 -11
  142. package/src/viewer/entry.tsx +40 -40
  143. package/src/viewer/hooks/useFigmaIntegration.ts +1 -1
  144. package/src/viewer/hooks/usePreviewBridge.ts +5 -5
  145. package/src/viewer/hooks/useUrlState.ts +6 -6
  146. package/src/viewer/index.ts +2 -2
  147. package/src/viewer/intelligence/healthReport.ts +17 -17
  148. package/src/viewer/intelligence/styleDrift.ts +1 -1
  149. package/src/viewer/intelligence/usageScanner.ts +1 -1
  150. package/src/viewer/render-template.html +1 -1
  151. package/src/viewer/render-utils.ts +21 -21
  152. package/src/viewer/server.ts +18 -18
  153. package/src/viewer/utils/detectRelationships.ts +22 -22
  154. package/src/viewer/vite-plugin.ts +213 -213
  155. package/dist/chunk-6JBGU74P.js.map +0 -1
  156. package/dist/chunk-7OPWMLOE.js.map +0 -1
  157. package/dist/chunk-CVXKXVOY.js.map +0 -1
  158. package/dist/chunk-NWQ4CJOQ.js.map +0 -1
  159. package/dist/chunk-RVRTRESS.js.map +0 -1
  160. package/dist/chunk-TJ34N7C7.js.map +0 -1
  161. package/dist/chunk-XHUDJNN3.js.map +0 -1
  162. package/dist/generate-LMTISDIJ.js.map +0 -1
  163. package/dist/scan-WY23TJCP.js +0 -12
  164. package/dist/test-OJRXNDO2.js.map +0 -1
  165. package/dist/viewer-SUFOISZM.js.map +0 -1
  166. package/src/shared/segment-loader.ts +0 -59
  167. /package/dist/{core-W2HYIQW6.js.map → core-SFHPYR5H.js.map} +0 -0
  168. /package/dist/{scan-WY23TJCP.js.map → scan-KQBKUS64.js.map} +0 -0
  169. /package/dist/{service-T2L7VLTE.js.map → service-ED2LNCTU.js.map} +0 -0
  170. /package/dist/{static-viewer-GBR7YNF3.js.map → static-viewer-Q4F4QP5M.js.map} +0 -0
  171. /package/dist/{tokens-3BWDESVM.js.map → tokens-P2B7ZAM3.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,27 +1,27 @@
1
1
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
2
2
  import {
3
- buildSegments,
3
+ buildFragments,
4
4
  runAnalyzeCommand,
5
5
  runDiffCommand,
6
6
  runScreenshotCommand,
7
7
  validateAll,
8
8
  validateCoverage,
9
9
  validateSchema
10
- } from "./chunk-7OPWMLOE.js";
11
- import "./chunk-NWQ4CJOQ.js";
10
+ } from "./chunk-U6VTHBNI.js";
11
+ import "./chunk-GKX2HPZ6.js";
12
12
  import {
13
13
  discoverComponentFiles,
14
- discoverSegmentFiles,
14
+ discoverFragmentFiles,
15
15
  extractComponentName,
16
16
  findConfigFile,
17
17
  loadConfig
18
- } from "./chunk-CVXKXVOY.js";
18
+ } from "./chunk-5ITIP3ES.js";
19
19
  import {
20
20
  generateStaticViewer,
21
21
  generateViewerFromJson
22
- } from "./chunk-RVRTRESS.js";
23
- import "./chunk-TJ34N7C7.js";
24
- import "./chunk-6JBGU74P.js";
22
+ } from "./chunk-DQHWLAUV.js";
23
+ import "./chunk-GCZMFLDI.js";
24
+ import "./chunk-GHYYFAQN.js";
25
25
 
26
26
  // src/cli-commands.ts
27
27
  import {
@@ -31,9 +31,9 @@ import {
31
31
  export {
32
32
  CLI_COMMANDS,
33
33
  CLI_COMMAND_CATEGORIES,
34
- buildSegments,
34
+ buildFragments,
35
35
  discoverComponentFiles,
36
- discoverSegmentFiles,
36
+ discoverFragmentFiles,
37
37
  extractComponentName,
38
38
  findConfigFile,
39
39
  generateStaticViewer,
@@ -1,8 +1,8 @@
1
1
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
2
- import "./chunk-TJ34N7C7.js";
2
+ import "./chunk-GCZMFLDI.js";
3
3
  import {
4
4
  BRAND
5
- } from "./chunk-6JBGU74P.js";
5
+ } from "./chunk-GHYYFAQN.js";
6
6
 
7
7
  // src/commands/init.ts
8
8
  import { writeFile, mkdir, access } from "fs/promises";
@@ -331,7 +331,7 @@ Keeping existing configuration. Run \`${BRAND.cliCommand} dev\` to start.
331
331
  console.log(pc.dim("\nCreating configuration...\n"));
332
332
  const includePaths = [
333
333
  `${componentPath}/**/*.fragment.tsx`,
334
- `${componentPath}/**/*.segment.tsx`
334
+ `${componentPath}/**/*.fragment.tsx`
335
335
  // Legacy support
336
336
  ];
337
337
  const configPath = join(projectRoot, BRAND.configFile);
@@ -375,7 +375,7 @@ Keeping existing configuration. Run \`${BRAND.cliCommand} dev\` to start.
375
375
  if (scenario === "components" && runScan) {
376
376
  console.log(pc.dim("\nGenerating documentation from source code...\n"));
377
377
  try {
378
- const { scan } = await import("./scan-WY23TJCP.js");
378
+ const { scan } = await import("./scan-KQBKUS64.js");
379
379
  await scan({
380
380
  config: configPath,
381
381
  verbose: false
@@ -413,4 +413,4 @@ Keeping existing configuration. Run \`${BRAND.cliCommand} dev\` to start.
413
413
  export {
414
414
  init
415
415
  };
416
- //# sourceMappingURL=init-7CHRKQ7P.js.map
416
+ //# sourceMappingURL=init-EIM5WNMP.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["/**\n * fragments init - Smart interactive initialization\n *\n * Handles three scenarios:\n * 1. Stories found → Configure and load existing stories\n * 2. Components found (no stories) → Auto-generate documentation\n * 3. Fresh project → Guided setup with example component\n */\n\nimport { readFile, writeFile, mkdir, access } from \"node:fs/promises\";\nimport { resolve, join, relative } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport pc from \"picocolors\";\nimport { BRAND } from \"../core/index.js\";\nimport fg from \"fast-glob\";\nimport { input, confirm, select } from \"@inquirer/prompts\";\n\nexport interface InitOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Force overwrite existing config */\n force?: boolean;\n /** Non-interactive mode - auto-detect and use defaults */\n yes?: boolean;\n}\n\nexport interface InitResult {\n success: boolean;\n configPath?: string;\n scenario: \"stories\" | \"components\" | \"fresh\";\n storiesFound: number;\n componentsFound: number;\n errors: string[];\n}\n\ninterface DetectionResult {\n storyFiles: string[];\n componentFiles: string[];\n hasConfig: boolean;\n configPath: string | null;\n suggestedComponentPath: string;\n}\n\n/**\n * Detect what exists in the project\n */\nasync function detectProject(projectRoot: string): Promise<DetectionResult> {\n console.log(pc.dim(\"\\nScanning project...\\n\"));\n\n // Check for existing config\n const configPath = join(projectRoot, BRAND.configFile);\n const legacyConfigPath = join(projectRoot, BRAND.legacyConfigFile);\n let hasConfig = false;\n let foundConfigPath: string | null = null;\n\n try {\n await access(configPath);\n hasConfig = true;\n foundConfigPath = configPath;\n } catch {\n try {\n await access(legacyConfigPath);\n hasConfig = true;\n foundConfigPath = legacyConfigPath;\n } catch {\n // No config\n }\n }\n\n // Scan for story files\n const storyFiles = await fg(\n [\"**/*.stories.tsx\", \"**/*.stories.ts\", \"**/*.stories.jsx\", \"**/*.stories.js\"],\n {\n cwd: projectRoot,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/build/**\", \"**/.storybook/**\"],\n }\n );\n\n // Scan for component files (React components)\n const componentFiles = await fg(\n [\"**/components/**/*.tsx\", \"**/Components/**/*.tsx\", \"src/**/*.tsx\"],\n {\n cwd: projectRoot,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.stories.*\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/*.d.ts\",\n \"**/index.tsx\", // Skip barrel files\n ],\n }\n );\n\n // Filter to likely component files (capitalized names, not utility files)\n const likelyComponents = componentFiles.filter((f) => {\n const fileName = f.split(\"/\").pop() || \"\";\n return /^[A-Z]/.test(fileName) && !fileName.includes(\".styles\");\n });\n\n // Suggest component path based on what we found\n let suggestedComponentPath = \"src/components\";\n if (likelyComponents.length > 0) {\n const firstComponent = likelyComponents[0];\n const parts = firstComponent.split(\"/\");\n const componentsIndex = parts.findIndex(\n (p) => p.toLowerCase() === \"components\"\n );\n if (componentsIndex !== -1) {\n suggestedComponentPath = parts.slice(0, componentsIndex + 1).join(\"/\");\n }\n }\n\n return {\n storyFiles,\n componentFiles: likelyComponents,\n hasConfig,\n configPath: foundConfigPath,\n suggestedComponentPath,\n };\n}\n\n/**\n * Generate config file content\n */\nfunction generateConfig(options: {\n includePaths: string[];\n componentPaths: string[];\n framework: string;\n}): string {\n const includeStr = options.includePaths.map((p) => ` '${p}'`).join(\",\\n\");\n const componentStr = options.componentPaths.map((p) => ` '${p}'`).join(\",\\n\");\n\n return `import type { FragmentsConfig } from '@fragments-sdk/cli';\n\nconst config: FragmentsConfig = {\n // Glob patterns for finding fragment/story files\n include: [\n${includeStr}\n ],\n\n // Glob patterns to exclude\n exclude: ['**/node_modules/**'],\n\n // Glob patterns for finding component files (for auto-documentation)\n components: [\n${componentStr}\n ],\n\n // Framework (react, vue, svelte)\n framework: '${options.framework}',\n};\n\nexport default config;\n`;\n}\n\n/**\n * Generate example Button component\n */\nfunction generateExampleComponent(): string {\n return `import React from 'react';\n\nexport interface ButtonProps {\n /** Button label */\n children: React.ReactNode;\n /** Visual style variant */\n variant?: 'primary' | 'secondary' | 'ghost';\n /** Button size */\n size?: 'sm' | 'md' | 'lg';\n /** Disabled state */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport function Button({\n children,\n variant = 'primary',\n size = 'md',\n disabled = false,\n onClick,\n}: ButtonProps) {\n const baseStyles = 'inline-flex items-center justify-center font-medium rounded-md transition-colors';\n\n const variantStyles = {\n primary: 'bg-blue-600 text-white hover:bg-blue-700',\n secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',\n ghost: 'bg-transparent text-gray-700 hover:bg-gray-100',\n };\n\n const sizeStyles = {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n };\n\n return (\n <button\n className={\\`\\${baseStyles} \\${variantStyles[variant]} \\${sizeStyles[size]}\\`}\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n`;\n}\n\n/**\n * Generate example Button fragment file\n */\nfunction generateExampleFragment(): string {\n return `import React from 'react';\nimport { defineFragment } from '@fragments-sdk/cli';\nimport { Button } from './Button';\n\nexport default defineFragment({\n component: Button,\n\n meta: {\n name: 'Button',\n description: 'Interactive button for triggering actions',\n category: 'Actions',\n status: 'stable',\n },\n\n usage: {\n when: [\n 'Triggering an action (save, submit, delete)',\n 'Form submission',\n 'Opening dialogs or menus',\n ],\n whenNot: [\n 'Simple navigation (use Link)',\n 'Toggling state (use Switch)',\n ],\n guidelines: [\n 'Use Primary for the main action in a context',\n 'Only one Primary button per section',\n ],\n },\n\n props: {\n children: {\n type: 'node',\n required: true,\n description: 'Button label content',\n },\n variant: {\n type: 'enum',\n values: ['primary', 'secondary', 'ghost'],\n default: 'primary',\n description: 'Visual style variant',\n },\n size: {\n type: 'enum',\n values: ['sm', 'md', 'lg'],\n default: 'md',\n description: 'Button size',\n },\n },\n\n variants: [\n {\n name: 'Primary',\n description: 'Default action button',\n render: () => <Button variant=\"primary\">Save Changes</Button>,\n },\n {\n name: 'Secondary',\n description: 'Less prominent action',\n render: () => <Button variant=\"secondary\">Cancel</Button>,\n },\n {\n name: 'Ghost',\n description: 'Minimal visual weight',\n render: () => <Button variant=\"ghost\">Learn More</Button>,\n },\n {\n name: 'Sizes',\n description: 'Available size options',\n render: () => (\n <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Button size=\"sm\">Small</Button>\n <Button size=\"md\">Medium</Button>\n <Button size=\"lg\">Large</Button>\n </div>\n ),\n },\n ],\n});\n`;\n}\n\n/**\n * Start the dev server\n */\nfunction startDevServer(projectRoot: string): void {\n console.log(pc.dim(\"\\nStarting development server...\\n\"));\n\n // Use process.platform to determine the correct command\n const isWindows = process.platform === \"win32\";\n const cmd = isWindows ? \"npx.cmd\" : \"npx\";\n\n const child = spawn(cmd, [BRAND.cliCommand, \"dev\"], {\n cwd: projectRoot,\n stdio: \"inherit\",\n });\n\n child.on(\"error\", (err) => {\n console.error(pc.red(\"Failed to start dev server:\"), err.message);\n });\n}\n\n/**\n * Main init function - smart and interactive by default\n */\nexport async function init(options: InitOptions = {}): Promise<InitResult> {\n const projectRoot = resolve(options.projectRoot || process.cwd());\n const errors: string[] = [];\n\n console.log(pc.cyan(`\\n✨ Welcome to ${BRAND.name}!\\n`));\n\n // Step 1: Detect what exists\n const detection = await detectProject(projectRoot);\n\n // Check for existing config\n if (detection.hasConfig && !options.force) {\n console.log(pc.yellow(`⚠ Config already exists: ${BRAND.configFile}`));\n\n if (!options.yes) {\n const overwrite = await confirm({\n message: \"Do you want to reinitialize? (This will overwrite your config)\",\n default: false,\n });\n\n if (!overwrite) {\n console.log(pc.dim(`\\nKeeping existing configuration. Run \\`${BRAND.cliCommand} dev\\` to start.\\n`));\n return {\n success: true,\n scenario: \"stories\",\n storiesFound: detection.storyFiles.length,\n componentsFound: detection.componentFiles.length,\n errors: [],\n };\n }\n }\n }\n\n // Step 2: Determine scenario and show what we found\n let scenario: \"stories\" | \"components\" | \"fresh\";\n\n if (detection.storyFiles.length > 0) {\n scenario = \"stories\";\n console.log(pc.green(`✓ Found ${detection.storyFiles.length} Storybook story file(s)`));\n console.log(pc.dim(` ${detection.storyFiles.slice(0, 3).join(\"\\n \")}`));\n if (detection.storyFiles.length > 3) {\n console.log(pc.dim(` ... and ${detection.storyFiles.length - 3} more`));\n }\n console.log();\n console.log(\n pc.cyan(\"Great news! \") +\n \"Fragments can load your existing stories automatically.\"\n );\n } else if (detection.componentFiles.length > 0) {\n scenario = \"components\";\n console.log(pc.green(`✓ Found ${detection.componentFiles.length} component file(s)`));\n console.log(pc.dim(` ${detection.componentFiles.slice(0, 3).join(\"\\n \")}`));\n if (detection.componentFiles.length > 3) {\n console.log(pc.dim(` ... and ${detection.componentFiles.length - 3} more`));\n }\n console.log();\n console.log(\n pc.cyan(\"No stories found, but that's fine! \") +\n \"Fragments can auto-generate documentation from your TypeScript.\"\n );\n } else {\n scenario = \"fresh\";\n console.log(pc.yellow(\"No components or stories found.\"));\n console.log();\n console.log(pc.cyan(\"Let's create your first fragment!\"));\n }\n\n console.log();\n\n // Step 3: Gather configuration (interactive unless --yes)\n let componentPath = detection.suggestedComponentPath;\n let runScan = scenario === \"components\";\n let createExample = scenario === \"fresh\";\n let startServer = true;\n\n if (!options.yes) {\n // Ask about component location\n componentPath = await input({\n message: \"Where are your components located?\",\n default: detection.suggestedComponentPath,\n });\n\n if (scenario === \"components\") {\n // For component-only projects, ask about scanning\n runScan = await confirm({\n message: \"Auto-generate documentation from TypeScript?\",\n default: true,\n });\n } else {\n // Fresh project - ask about example\n createExample = await confirm({\n message: \"Create an example Button component to get started?\",\n default: true,\n });\n }\n\n // Ask about starting the server\n startServer = await confirm({\n message: \"Start the viewer now?\",\n default: true,\n });\n }\n\n // Step 4: Create configuration\n console.log(pc.dim(\"\\nCreating configuration...\\n\"));\n\n // Build include patterns\n // Note: Stories are loaded separately by the viewer, not via include patterns\n const includePaths: string[] = [\n `${componentPath}/**/*.fragment.tsx`,\n `${componentPath}/**/*.segment.tsx`, // Legacy support\n ];\n\n // Create config file\n const configPath = join(projectRoot, BRAND.configFile);\n const configContent = generateConfig({\n includePaths,\n componentPaths: [`${componentPath}/**/*.tsx`],\n framework: \"react\",\n });\n\n try {\n await writeFile(configPath, configContent, \"utf-8\");\n console.log(pc.green(`✓ Created ${BRAND.configFile}`));\n } catch (e) {\n errors.push(`Failed to create config: ${e}`);\n }\n\n // Step 5: Handle scenario-specific setup\n if (scenario === \"fresh\" && createExample) {\n // Create example component\n const exampleDir = join(projectRoot, componentPath, \"Button\");\n\n try {\n await mkdir(exampleDir, { recursive: true });\n\n // Write Button.tsx\n await writeFile(\n join(exampleDir, \"Button.tsx\"),\n generateExampleComponent(),\n \"utf-8\"\n );\n console.log(\n pc.green(`✓ Created ${relative(projectRoot, join(exampleDir, \"Button.tsx\"))}`)\n );\n\n // Write Button.fragment.tsx\n await writeFile(\n join(exampleDir, \"Button.fragment.tsx\"),\n generateExampleFragment(),\n \"utf-8\"\n );\n console.log(\n pc.green(\n `✓ Created ${relative(projectRoot, join(exampleDir, \"Button.fragment.tsx\"))}`\n )\n );\n } catch (e) {\n errors.push(`Failed to create example component: ${e}`);\n }\n }\n\n if (scenario === \"components\" && runScan) {\n // Run scan to generate fragments.json\n console.log(pc.dim(\"\\nGenerating documentation from source code...\\n\"));\n try {\n const { scan } = await import(\"./scan.js\");\n await scan({\n config: configPath,\n verbose: false,\n });\n } catch (e) {\n console.log(\n pc.yellow(`Note: Auto-documentation will run when you start the dev server.`)\n );\n }\n }\n\n // Step 6: Show next steps or start server\n if (errors.length === 0) {\n console.log(pc.green(\"\\n✓ Setup complete!\\n\"));\n\n if (startServer) {\n const serverMessage =\n scenario === \"stories\"\n ? `Your ${detection.storyFiles.length} stories are loading...`\n : scenario === \"components\"\n ? `Your ${detection.componentFiles.length} components are being documented...`\n : `Your first component is ready!`;\n\n console.log(pc.cyan(serverMessage));\n startDevServer(projectRoot);\n } else {\n console.log(pc.cyan(\"Next steps:\"));\n console.log(` 1. Run ${pc.bold(`${BRAND.cliCommand} dev`)} to start the viewer`);\n if (scenario === \"fresh\") {\n console.log(` 2. Edit ${pc.bold(`${componentPath}/Button/Button.fragment.tsx`)}`);\n }\n console.log();\n }\n }\n\n return {\n success: errors.length === 0,\n configPath: errors.length === 0 ? configPath : undefined,\n scenario,\n storiesFound: detection.storyFiles.length,\n componentsFound: detection.componentFiles.length,\n errors,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["/**\n * fragments init - Smart interactive initialization\n *\n * Handles three scenarios:\n * 1. Stories found → Configure and load existing stories\n * 2. Components found (no stories) → Auto-generate documentation\n * 3. Fresh project → Guided setup with example component\n */\n\nimport { readFile, writeFile, mkdir, access } from \"node:fs/promises\";\nimport { resolve, join, relative } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport pc from \"picocolors\";\nimport { BRAND } from \"../core/index.js\";\nimport fg from \"fast-glob\";\nimport { input, confirm, select } from \"@inquirer/prompts\";\n\nexport interface InitOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Force overwrite existing config */\n force?: boolean;\n /** Non-interactive mode - auto-detect and use defaults */\n yes?: boolean;\n}\n\nexport interface InitResult {\n success: boolean;\n configPath?: string;\n scenario: \"stories\" | \"components\" | \"fresh\";\n storiesFound: number;\n componentsFound: number;\n errors: string[];\n}\n\ninterface DetectionResult {\n storyFiles: string[];\n componentFiles: string[];\n hasConfig: boolean;\n configPath: string | null;\n suggestedComponentPath: string;\n}\n\n/**\n * Detect what exists in the project\n */\nasync function detectProject(projectRoot: string): Promise<DetectionResult> {\n console.log(pc.dim(\"\\nScanning project...\\n\"));\n\n // Check for existing config\n const configPath = join(projectRoot, BRAND.configFile);\n const legacyConfigPath = join(projectRoot, BRAND.legacyConfigFile);\n let hasConfig = false;\n let foundConfigPath: string | null = null;\n\n try {\n await access(configPath);\n hasConfig = true;\n foundConfigPath = configPath;\n } catch {\n try {\n await access(legacyConfigPath);\n hasConfig = true;\n foundConfigPath = legacyConfigPath;\n } catch {\n // No config\n }\n }\n\n // Scan for story files\n const storyFiles = await fg(\n [\"**/*.stories.tsx\", \"**/*.stories.ts\", \"**/*.stories.jsx\", \"**/*.stories.js\"],\n {\n cwd: projectRoot,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/build/**\", \"**/.storybook/**\"],\n }\n );\n\n // Scan for component files (React components)\n const componentFiles = await fg(\n [\"**/components/**/*.tsx\", \"**/Components/**/*.tsx\", \"src/**/*.tsx\"],\n {\n cwd: projectRoot,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.stories.*\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/*.d.ts\",\n \"**/index.tsx\", // Skip barrel files\n ],\n }\n );\n\n // Filter to likely component files (capitalized names, not utility files)\n const likelyComponents = componentFiles.filter((f) => {\n const fileName = f.split(\"/\").pop() || \"\";\n return /^[A-Z]/.test(fileName) && !fileName.includes(\".styles\");\n });\n\n // Suggest component path based on what we found\n let suggestedComponentPath = \"src/components\";\n if (likelyComponents.length > 0) {\n const firstComponent = likelyComponents[0];\n const parts = firstComponent.split(\"/\");\n const componentsIndex = parts.findIndex(\n (p) => p.toLowerCase() === \"components\"\n );\n if (componentsIndex !== -1) {\n suggestedComponentPath = parts.slice(0, componentsIndex + 1).join(\"/\");\n }\n }\n\n return {\n storyFiles,\n componentFiles: likelyComponents,\n hasConfig,\n configPath: foundConfigPath,\n suggestedComponentPath,\n };\n}\n\n/**\n * Generate config file content\n */\nfunction generateConfig(options: {\n includePaths: string[];\n componentPaths: string[];\n framework: string;\n}): string {\n const includeStr = options.includePaths.map((p) => ` '${p}'`).join(\",\\n\");\n const componentStr = options.componentPaths.map((p) => ` '${p}'`).join(\",\\n\");\n\n return `import type { FragmentsConfig } from '@fragments-sdk/cli';\n\nconst config: FragmentsConfig = {\n // Glob patterns for finding fragment/story files\n include: [\n${includeStr}\n ],\n\n // Glob patterns to exclude\n exclude: ['**/node_modules/**'],\n\n // Glob patterns for finding component files (for auto-documentation)\n components: [\n${componentStr}\n ],\n\n // Framework (react, vue, svelte)\n framework: '${options.framework}',\n};\n\nexport default config;\n`;\n}\n\n/**\n * Generate example Button component\n */\nfunction generateExampleComponent(): string {\n return `import React from 'react';\n\nexport interface ButtonProps {\n /** Button label */\n children: React.ReactNode;\n /** Visual style variant */\n variant?: 'primary' | 'secondary' | 'ghost';\n /** Button size */\n size?: 'sm' | 'md' | 'lg';\n /** Disabled state */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport function Button({\n children,\n variant = 'primary',\n size = 'md',\n disabled = false,\n onClick,\n}: ButtonProps) {\n const baseStyles = 'inline-flex items-center justify-center font-medium rounded-md transition-colors';\n\n const variantStyles = {\n primary: 'bg-blue-600 text-white hover:bg-blue-700',\n secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',\n ghost: 'bg-transparent text-gray-700 hover:bg-gray-100',\n };\n\n const sizeStyles = {\n sm: 'px-3 py-1.5 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n };\n\n return (\n <button\n className={\\`\\${baseStyles} \\${variantStyles[variant]} \\${sizeStyles[size]}\\`}\n disabled={disabled}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n`;\n}\n\n/**\n * Generate example Button fragment file\n */\nfunction generateExampleFragment(): string {\n return `import React from 'react';\nimport { defineFragment } from '@fragments-sdk/cli';\nimport { Button } from './Button';\n\nexport default defineFragment({\n component: Button,\n\n meta: {\n name: 'Button',\n description: 'Interactive button for triggering actions',\n category: 'Actions',\n status: 'stable',\n },\n\n usage: {\n when: [\n 'Triggering an action (save, submit, delete)',\n 'Form submission',\n 'Opening dialogs or menus',\n ],\n whenNot: [\n 'Simple navigation (use Link)',\n 'Toggling state (use Switch)',\n ],\n guidelines: [\n 'Use Primary for the main action in a context',\n 'Only one Primary button per section',\n ],\n },\n\n props: {\n children: {\n type: 'node',\n required: true,\n description: 'Button label content',\n },\n variant: {\n type: 'enum',\n values: ['primary', 'secondary', 'ghost'],\n default: 'primary',\n description: 'Visual style variant',\n },\n size: {\n type: 'enum',\n values: ['sm', 'md', 'lg'],\n default: 'md',\n description: 'Button size',\n },\n },\n\n variants: [\n {\n name: 'Primary',\n description: 'Default action button',\n render: () => <Button variant=\"primary\">Save Changes</Button>,\n },\n {\n name: 'Secondary',\n description: 'Less prominent action',\n render: () => <Button variant=\"secondary\">Cancel</Button>,\n },\n {\n name: 'Ghost',\n description: 'Minimal visual weight',\n render: () => <Button variant=\"ghost\">Learn More</Button>,\n },\n {\n name: 'Sizes',\n description: 'Available size options',\n render: () => (\n <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>\n <Button size=\"sm\">Small</Button>\n <Button size=\"md\">Medium</Button>\n <Button size=\"lg\">Large</Button>\n </div>\n ),\n },\n ],\n});\n`;\n}\n\n/**\n * Start the dev server\n */\nfunction startDevServer(projectRoot: string): void {\n console.log(pc.dim(\"\\nStarting development server...\\n\"));\n\n // Use process.platform to determine the correct command\n const isWindows = process.platform === \"win32\";\n const cmd = isWindows ? \"npx.cmd\" : \"npx\";\n\n const child = spawn(cmd, [BRAND.cliCommand, \"dev\"], {\n cwd: projectRoot,\n stdio: \"inherit\",\n });\n\n child.on(\"error\", (err) => {\n console.error(pc.red(\"Failed to start dev server:\"), err.message);\n });\n}\n\n/**\n * Main init function - smart and interactive by default\n */\nexport async function init(options: InitOptions = {}): Promise<InitResult> {\n const projectRoot = resolve(options.projectRoot || process.cwd());\n const errors: string[] = [];\n\n console.log(pc.cyan(`\\n✨ Welcome to ${BRAND.name}!\\n`));\n\n // Step 1: Detect what exists\n const detection = await detectProject(projectRoot);\n\n // Check for existing config\n if (detection.hasConfig && !options.force) {\n console.log(pc.yellow(`⚠ Config already exists: ${BRAND.configFile}`));\n\n if (!options.yes) {\n const overwrite = await confirm({\n message: \"Do you want to reinitialize? (This will overwrite your config)\",\n default: false,\n });\n\n if (!overwrite) {\n console.log(pc.dim(`\\nKeeping existing configuration. Run \\`${BRAND.cliCommand} dev\\` to start.\\n`));\n return {\n success: true,\n scenario: \"stories\",\n storiesFound: detection.storyFiles.length,\n componentsFound: detection.componentFiles.length,\n errors: [],\n };\n }\n }\n }\n\n // Step 2: Determine scenario and show what we found\n let scenario: \"stories\" | \"components\" | \"fresh\";\n\n if (detection.storyFiles.length > 0) {\n scenario = \"stories\";\n console.log(pc.green(`✓ Found ${detection.storyFiles.length} Storybook story file(s)`));\n console.log(pc.dim(` ${detection.storyFiles.slice(0, 3).join(\"\\n \")}`));\n if (detection.storyFiles.length > 3) {\n console.log(pc.dim(` ... and ${detection.storyFiles.length - 3} more`));\n }\n console.log();\n console.log(\n pc.cyan(\"Great news! \") +\n \"Fragments can load your existing stories automatically.\"\n );\n } else if (detection.componentFiles.length > 0) {\n scenario = \"components\";\n console.log(pc.green(`✓ Found ${detection.componentFiles.length} component file(s)`));\n console.log(pc.dim(` ${detection.componentFiles.slice(0, 3).join(\"\\n \")}`));\n if (detection.componentFiles.length > 3) {\n console.log(pc.dim(` ... and ${detection.componentFiles.length - 3} more`));\n }\n console.log();\n console.log(\n pc.cyan(\"No stories found, but that's fine! \") +\n \"Fragments can auto-generate documentation from your TypeScript.\"\n );\n } else {\n scenario = \"fresh\";\n console.log(pc.yellow(\"No components or stories found.\"));\n console.log();\n console.log(pc.cyan(\"Let's create your first fragment!\"));\n }\n\n console.log();\n\n // Step 3: Gather configuration (interactive unless --yes)\n let componentPath = detection.suggestedComponentPath;\n let runScan = scenario === \"components\";\n let createExample = scenario === \"fresh\";\n let startServer = true;\n\n if (!options.yes) {\n // Ask about component location\n componentPath = await input({\n message: \"Where are your components located?\",\n default: detection.suggestedComponentPath,\n });\n\n if (scenario === \"components\") {\n // For component-only projects, ask about scanning\n runScan = await confirm({\n message: \"Auto-generate documentation from TypeScript?\",\n default: true,\n });\n } else {\n // Fresh project - ask about example\n createExample = await confirm({\n message: \"Create an example Button component to get started?\",\n default: true,\n });\n }\n\n // Ask about starting the server\n startServer = await confirm({\n message: \"Start the viewer now?\",\n default: true,\n });\n }\n\n // Step 4: Create configuration\n console.log(pc.dim(\"\\nCreating configuration...\\n\"));\n\n // Build include patterns\n // Note: Stories are loaded separately by the viewer, not via include patterns\n const includePaths: string[] = [\n `${componentPath}/**/*.fragment.tsx`,\n `${componentPath}/**/*.fragment.tsx`, // Legacy support\n ];\n\n // Create config file\n const configPath = join(projectRoot, BRAND.configFile);\n const configContent = generateConfig({\n includePaths,\n componentPaths: [`${componentPath}/**/*.tsx`],\n framework: \"react\",\n });\n\n try {\n await writeFile(configPath, configContent, \"utf-8\");\n console.log(pc.green(`✓ Created ${BRAND.configFile}`));\n } catch (e) {\n errors.push(`Failed to create config: ${e}`);\n }\n\n // Step 5: Handle scenario-specific setup\n if (scenario === \"fresh\" && createExample) {\n // Create example component\n const exampleDir = join(projectRoot, componentPath, \"Button\");\n\n try {\n await mkdir(exampleDir, { recursive: true });\n\n // Write Button.tsx\n await writeFile(\n join(exampleDir, \"Button.tsx\"),\n generateExampleComponent(),\n \"utf-8\"\n );\n console.log(\n pc.green(`✓ Created ${relative(projectRoot, join(exampleDir, \"Button.tsx\"))}`)\n );\n\n // Write Button.fragment.tsx\n await writeFile(\n join(exampleDir, \"Button.fragment.tsx\"),\n generateExampleFragment(),\n \"utf-8\"\n );\n console.log(\n pc.green(\n `✓ Created ${relative(projectRoot, join(exampleDir, \"Button.fragment.tsx\"))}`\n )\n );\n } catch (e) {\n errors.push(`Failed to create example component: ${e}`);\n }\n }\n\n if (scenario === \"components\" && runScan) {\n // Run scan to generate fragments.json\n console.log(pc.dim(\"\\nGenerating documentation from source code...\\n\"));\n try {\n const { scan } = await import(\"./scan.js\");\n await scan({\n config: configPath,\n verbose: false,\n });\n } catch (e) {\n console.log(\n pc.yellow(`Note: Auto-documentation will run when you start the dev server.`)\n );\n }\n }\n\n // Step 6: Show next steps or start server\n if (errors.length === 0) {\n console.log(pc.green(\"\\n✓ Setup complete!\\n\"));\n\n if (startServer) {\n const serverMessage =\n scenario === \"stories\"\n ? `Your ${detection.storyFiles.length} stories are loading...`\n : scenario === \"components\"\n ? `Your ${detection.componentFiles.length} components are being documented...`\n : `Your first component is ready!`;\n\n console.log(pc.cyan(serverMessage));\n startDevServer(projectRoot);\n } else {\n console.log(pc.cyan(\"Next steps:\"));\n console.log(` 1. Run ${pc.bold(`${BRAND.cliCommand} dev`)} to start the viewer`);\n if (scenario === \"fresh\") {\n console.log(` 2. Edit ${pc.bold(`${componentPath}/Button/Button.fragment.tsx`)}`);\n }\n console.log();\n }\n }\n\n return {\n success: errors.length === 0,\n configPath: errors.length === 0 ? configPath : undefined,\n scenario,\n storiesFound: detection.storyFiles.length,\n componentsFound: detection.componentFiles.length,\n errors,\n };\n}\n"],"mappings":"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","names":[]}
package/dist/mcp-bin.js CHANGED
@@ -2,11 +2,11 @@
2
2
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
3
3
  import {
4
4
  generateContext
5
- } from "./chunk-TJ34N7C7.js";
5
+ } from "./chunk-GCZMFLDI.js";
6
6
  import {
7
7
  BRAND,
8
8
  DEFAULTS
9
- } from "./chunk-6JBGU74P.js";
9
+ } from "./chunk-GHYYFAQN.js";
10
10
 
11
11
  // src/mcp/server.ts
12
12
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -58,7 +58,7 @@ var _service = null;
58
58
  async function getService() {
59
59
  if (!_service) {
60
60
  try {
61
- _service = await import("./service-T2L7VLTE.js");
61
+ _service = await import("./service-ED2LNCTU.js");
62
62
  } catch {
63
63
  throw new Error(
64
64
  "Visual tools require playwright. Install it with: npm install playwright"
@@ -230,16 +230,16 @@ function createMcpServer(config) {
230
230
  }
231
231
  }
232
232
  );
233
- let segmentsData = null;
234
- const segmentPackageMap = /* @__PURE__ */ new Map();
233
+ let fragmentsData = null;
234
+ const fragmentPackageMap = /* @__PURE__ */ new Map();
235
235
  let defaultPackageName = null;
236
236
  let browserPool = null;
237
237
  let storageManager = null;
238
238
  let diffEngine = null;
239
239
  let isPoolWarming = false;
240
- async function loadSegments() {
241
- if (segmentsData) {
242
- return segmentsData;
240
+ async function loadFragments() {
241
+ if (fragmentsData) {
242
+ return fragmentsData;
243
243
  }
244
244
  const paths = findFragmentsJson(config.projectRoot);
245
245
  if (paths.length === 0) {
@@ -248,41 +248,41 @@ function createMcpServer(config) {
248
248
  );
249
249
  }
250
250
  const content = await readFile(paths[0], "utf-8");
251
- segmentsData = JSON.parse(content);
252
- if (!segmentsData.blocks && segmentsData.recipes) {
253
- segmentsData.blocks = segmentsData.recipes;
251
+ fragmentsData = JSON.parse(content);
252
+ if (!fragmentsData.blocks && fragmentsData.recipes) {
253
+ fragmentsData.blocks = fragmentsData.recipes;
254
254
  }
255
- if (segmentsData.packageName) {
256
- for (const name of Object.keys(segmentsData.segments)) {
257
- segmentPackageMap.set(name, segmentsData.packageName);
255
+ if (fragmentsData.packageName) {
256
+ for (const name of Object.keys(fragmentsData.fragments)) {
257
+ fragmentPackageMap.set(name, fragmentsData.packageName);
258
258
  }
259
259
  }
260
260
  for (let i = 1; i < paths.length; i++) {
261
261
  const extra = JSON.parse(await readFile(paths[i], "utf-8"));
262
262
  if (extra.packageName) {
263
- for (const name of Object.keys(extra.segments)) {
264
- segmentPackageMap.set(name, extra.packageName);
263
+ for (const name of Object.keys(extra.fragments)) {
264
+ fragmentPackageMap.set(name, extra.packageName);
265
265
  }
266
266
  }
267
- Object.assign(segmentsData.segments, extra.segments);
267
+ Object.assign(fragmentsData.fragments, extra.fragments);
268
268
  const extraBlocks = extra.blocks ?? extra.recipes;
269
269
  if (extraBlocks) {
270
- segmentsData.blocks = { ...segmentsData.blocks, ...extraBlocks };
270
+ fragmentsData.blocks = { ...fragmentsData.blocks, ...extraBlocks };
271
271
  }
272
272
  }
273
- return segmentsData;
273
+ return fragmentsData;
274
274
  }
275
- async function getPackageName(segmentName) {
276
- await loadSegments();
277
- if (segmentName) {
278
- const segPkg = segmentPackageMap.get(segmentName);
275
+ async function getPackageName(fragmentName) {
276
+ await loadFragments();
277
+ if (fragmentName) {
278
+ const segPkg = fragmentPackageMap.get(fragmentName);
279
279
  if (segPkg) return segPkg;
280
280
  }
281
281
  if (defaultPackageName) {
282
282
  return defaultPackageName;
283
283
  }
284
- if (segmentsData?.packageName) {
285
- defaultPackageName = segmentsData.packageName;
284
+ if (fragmentsData?.packageName) {
285
+ defaultPackageName = fragmentsData.packageName;
286
286
  return defaultPackageName;
287
287
  }
288
288
  const packageJsonPath = join(config.projectRoot, "package.json");
@@ -356,7 +356,7 @@ function createMcpServer(config) {
356
356
  // DISCOVER — list, suggest, context, alternatives
357
357
  // ================================================================
358
358
  case TOOL_NAMES.discover: {
359
- const data = await loadSegments();
359
+ const data = await loadFragments();
360
360
  const useCase = args2?.useCase ?? void 0;
361
361
  const componentForAlts = args2?.component ?? void 0;
362
362
  const category = args2?.category ?? void 0;
@@ -367,9 +367,9 @@ function createMcpServer(config) {
367
367
  const includeCode = args2?.includeCode ?? false;
368
368
  const includeRelations = args2?.includeRelations ?? false;
369
369
  if (compact || args2?.format && !useCase && !componentForAlts && !category && !search && !status) {
370
- const segments2 = Object.values(data.segments);
370
+ const fragments2 = Object.values(data.fragments);
371
371
  const allBlocks = Object.values(data.blocks ?? data.recipes ?? {});
372
- const { content: ctxContent, tokenEstimate } = generateContext(segments2, {
372
+ const { content: ctxContent, tokenEstimate } = generateContext(fragments2, {
373
373
  format,
374
374
  compact,
375
375
  include: {
@@ -411,7 +411,7 @@ function createMcpServer(config) {
411
411
  synonyms.forEach((syn) => expandedTerms.add(syn));
412
412
  }
413
413
  });
414
- const scored = Object.values(data.segments).map((s) => {
414
+ const scored = Object.values(data.fragments).map((s) => {
415
415
  let score = 0;
416
416
  const reasons = [];
417
417
  const nameLower = s.meta.name.toLowerCase();
@@ -535,14 +535,14 @@ function createMcpServer(config) {
535
535
  };
536
536
  }
537
537
  if (componentForAlts) {
538
- const segment = Object.values(data.segments).find(
538
+ const fragment = Object.values(data.fragments).find(
539
539
  (s) => s.meta.name.toLowerCase() === componentForAlts.toLowerCase()
540
540
  );
541
- if (!segment) {
541
+ if (!fragment) {
542
542
  throw new Error(`Component "${componentForAlts}" not found. Use fragments_discover to see available components.`);
543
543
  }
544
- const relations = segment.relations ?? [];
545
- const referencedBy = Object.values(data.segments).filter(
544
+ const relations = fragment.relations ?? [];
545
+ const referencedBy = Object.values(data.fragments).filter(
546
546
  (s) => s.relations?.some((r) => r.component.toLowerCase() === componentForAlts.toLowerCase())
547
547
  ).map((s) => ({
548
548
  component: s.meta.name,
@@ -553,8 +553,8 @@ function createMcpServer(config) {
553
553
  (r) => r.component.toLowerCase() === componentForAlts.toLowerCase()
554
554
  )?.note
555
555
  }));
556
- const sameCategory = Object.values(data.segments).filter(
557
- (s) => s.meta.category === segment.meta.category && s.meta.name.toLowerCase() !== componentForAlts.toLowerCase()
556
+ const sameCategory = Object.values(data.fragments).filter(
557
+ (s) => s.meta.category === fragment.meta.category && s.meta.name.toLowerCase() !== componentForAlts.toLowerCase()
558
558
  ).map((s) => ({
559
559
  component: s.meta.name,
560
560
  description: s.meta.description
@@ -563,8 +563,8 @@ function createMcpServer(config) {
563
563
  content: [{
564
564
  type: "text",
565
565
  text: JSON.stringify({
566
- component: segment.meta.name,
567
- category: segment.meta.category,
566
+ component: fragment.meta.name,
567
+ category: fragment.meta.category,
568
568
  directRelations: relations,
569
569
  referencedBy,
570
570
  sameCategory,
@@ -573,7 +573,7 @@ function createMcpServer(config) {
573
573
  }]
574
574
  };
575
575
  }
576
- const segments = Object.values(data.segments).filter((s) => {
576
+ const fragments = Object.values(data.fragments).filter((s) => {
577
577
  if (category && s.meta.category !== category) return false;
578
578
  if (status && (s.meta.status ?? "stable") !== status) return false;
579
579
  if (search) {
@@ -595,10 +595,10 @@ function createMcpServer(config) {
595
595
  content: [{
596
596
  type: "text",
597
597
  text: JSON.stringify({
598
- total: segments.length,
599
- segments,
600
- categories: [...new Set(segments.map((s) => s.category))],
601
- hint: segments.length === 0 ? "No components found. Try broader search terms or check available categories." : segments.length > 5 ? "Use fragments_discover with useCase for recommendations, or fragments_inspect for details on a specific component." : void 0
598
+ total: fragments.length,
599
+ fragments,
600
+ categories: [...new Set(fragments.map((s) => s.category))],
601
+ hint: fragments.length === 0 ? "No components found. Try broader search terms or check available categories." : fragments.length > 5 ? "Use fragments_discover with useCase for recommendations, or fragments_inspect for details on a specific component." : void 0
602
602
  }, null, 2)
603
603
  }]
604
604
  };
@@ -607,7 +607,7 @@ function createMcpServer(config) {
607
607
  // INSPECT — get + guidelines + example in one call
608
608
  // ================================================================
609
609
  case TOOL_NAMES.inspect: {
610
- const data = await loadSegments();
610
+ const data = await loadFragments();
611
611
  const componentName = args2?.component;
612
612
  const fields = args2?.fields;
613
613
  const variantName = args2?.variant ?? void 0;
@@ -616,14 +616,14 @@ function createMcpServer(config) {
616
616
  if (!componentName) {
617
617
  throw new Error("component is required");
618
618
  }
619
- const segment = Object.values(data.segments).find(
619
+ const fragment = Object.values(data.fragments).find(
620
620
  (s) => s.meta.name.toLowerCase() === componentName.toLowerCase()
621
621
  );
622
- if (!segment) {
622
+ if (!fragment) {
623
623
  throw new Error(`Component "${componentName}" not found. Use fragments_discover to see available components.`);
624
624
  }
625
- const pkgName = await getPackageName(segment.meta.name);
626
- let variants = segment.variants;
625
+ const pkgName = await getPackageName(fragment.meta.name);
626
+ let variants = fragment.variants;
627
627
  if (variantName) {
628
628
  const query = variantName.toLowerCase();
629
629
  let filtered = variants.filter(
@@ -643,7 +643,7 @@ function createMcpServer(config) {
643
643
  variants = filtered;
644
644
  } else {
645
645
  throw new Error(
646
- `Variant "${variantName}" not found for ${componentName}. Available: ${segment.variants.map((v) => v.name).join(", ")}`
646
+ `Variant "${variantName}" not found for ${componentName}. Available: ${fragment.variants.map((v) => v.name).join(", ")}`
647
647
  );
648
648
  }
649
649
  }
@@ -667,44 +667,44 @@ function createMcpServer(config) {
667
667
  return {
668
668
  variant: variant.name,
669
669
  description: variant.description,
670
- code: `<${segment.meta.name} />`,
670
+ code: `<${fragment.meta.name} />`,
671
671
  note: "No code example provided in fragment. Refer to props for customization."
672
672
  };
673
673
  });
674
- const propsReference = Object.entries(segment.props ?? {}).map(([propName, prop]) => ({
674
+ const propsReference = Object.entries(fragment.props ?? {}).map(([propName, prop]) => ({
675
675
  name: propName,
676
676
  type: prop.type,
677
677
  required: prop.required,
678
678
  default: prop.default,
679
679
  description: prop.description
680
680
  }));
681
- const propConstraints = Object.entries(segment.props ?? {}).filter(([, prop]) => prop.constraints && prop.constraints.length > 0).map(([pName, prop]) => ({
681
+ const propConstraints = Object.entries(fragment.props ?? {}).filter(([, prop]) => prop.constraints && prop.constraints.length > 0).map(([pName, prop]) => ({
682
682
  prop: pName,
683
683
  constraints: prop.constraints
684
684
  }));
685
685
  const fullResult = {
686
686
  // Component data (from old "get")
687
- meta: segment.meta,
688
- props: segment.props,
689
- variants: segment.variants,
690
- relations: segment.relations,
691
- contract: segment.contract,
692
- generated: segment._generated,
687
+ meta: fragment.meta,
688
+ props: fragment.props,
689
+ variants: fragment.variants,
690
+ relations: fragment.relations,
691
+ contract: fragment.contract,
692
+ generated: fragment._generated,
693
693
  // Guidelines (from old "guidelines")
694
694
  guidelines: {
695
- when: filterPlaceholders(segment.usage?.when),
696
- whenNot: filterPlaceholders(segment.usage?.whenNot),
697
- guidelines: segment.usage?.guidelines ?? [],
698
- accessibility: segment.usage?.accessibility ?? [],
695
+ when: filterPlaceholders(fragment.usage?.when),
696
+ whenNot: filterPlaceholders(fragment.usage?.whenNot),
697
+ guidelines: fragment.usage?.guidelines ?? [],
698
+ accessibility: fragment.usage?.accessibility ?? [],
699
699
  propConstraints,
700
- alternatives: segment.relations?.filter((r) => r.relationship === "alternative").map((r) => ({
700
+ alternatives: fragment.relations?.filter((r) => r.relationship === "alternative").map((r) => ({
701
701
  component: r.component,
702
702
  note: r.note
703
703
  })) ?? []
704
704
  },
705
705
  // Examples (from old "example")
706
706
  examples: {
707
- import: `import { ${segment.meta.name} } from '${pkgName}';`,
707
+ import: `import { ${fragment.meta.name} } from '${pkgName}';`,
708
708
  code: examples,
709
709
  propsReference
710
710
  }
@@ -721,7 +721,7 @@ function createMcpServer(config) {
721
721
  // BLOCKS — composition patterns
722
722
  // ================================================================
723
723
  case TOOL_NAMES.blocks: {
724
- const data = await loadSegments();
724
+ const data = await loadFragments();
725
725
  const blockName = args2?.name;
726
726
  const search = args2?.search?.toLowerCase() ?? void 0;
727
727
  const component = args2?.component?.toLowerCase() ?? void 0;
@@ -781,7 +781,7 @@ function createMcpServer(config) {
781
781
  // TOKENS — list CSS custom properties by category
782
782
  // ================================================================
783
783
  case TOOL_NAMES.tokens: {
784
- const data = await loadSegments();
784
+ const data = await loadFragments();
785
785
  const category = args2?.category?.toLowerCase() ?? void 0;
786
786
  const search = args2?.search?.toLowerCase() ?? void 0;
787
787
  const tokenData = data.tokens;
@@ -841,7 +841,7 @@ function createMcpServer(config) {
841
841
  // IMPLEMENT — one-shot discover + inspect + blocks + tokens
842
842
  // ================================================================
843
843
  case TOOL_NAMES.implement: {
844
- const data = await loadSegments();
844
+ const data = await loadFragments();
845
845
  const useCase = args2?.useCase;
846
846
  if (!useCase) {
847
847
  throw new Error("useCase is required");
@@ -866,7 +866,7 @@ function createMcpServer(config) {
866
866
  const synonyms = synonymMap[term];
867
867
  if (synonyms) synonyms.forEach((syn) => expandedTerms.add(syn));
868
868
  });
869
- const scored = Object.values(data.segments).map((s) => {
869
+ const scored = Object.values(data.fragments).map((s) => {
870
870
  let score = 0;
871
871
  const nameLower = s.meta.name.toLowerCase();
872
872
  if (searchTerms.some((t) => nameLower.includes(t))) score += 15;
@@ -881,11 +881,11 @@ function createMcpServer(config) {
881
881
  if (s.meta.category && searchTerms.some((t) => s.meta.category.toLowerCase().includes(t))) score += 8;
882
882
  if (s.meta.status === "stable") score += 5;
883
883
  if (s.meta.status === "deprecated") score -= 25;
884
- return { segment: s, score };
884
+ return { fragment: s, score };
885
885
  });
886
886
  const topMatches = scored.filter((s) => s.score >= 8).sort((a, b) => b.score - a.score).slice(0, 3);
887
887
  const components = await Promise.all(
888
- topMatches.map(async ({ segment: s, score }) => {
888
+ topMatches.map(async ({ fragment: s, score }) => {
889
889
  const pkgName = await getPackageName(s.meta.name);
890
890
  const examples = s.variants.slice(0, 2).map((v) => ({
891
891
  variant: v.name,
@@ -910,7 +910,7 @@ function createMcpServer(config) {
910
910
  const allBlocks = Object.values(data.blocks ?? data.recipes ?? {});
911
911
  const matchingBlocks = allBlocks.filter((b) => {
912
912
  const haystack = [b.name, b.description, ...b.tags ?? [], ...b.components, b.category].join(" ").toLowerCase();
913
- return searchTerms.some((t) => haystack.includes(t)) || topMatches.some(({ segment }) => b.components.some((c) => c.toLowerCase() === segment.meta.name.toLowerCase()));
913
+ return searchTerms.some((t) => haystack.includes(t)) || topMatches.some(({ fragment }) => b.components.some((c) => c.toLowerCase() === fragment.meta.name.toLowerCase()));
914
914
  }).slice(0, 2).map((b) => ({ name: b.name, description: b.description, components: b.components, code: b.code }));
915
915
  const tokenData = data.tokens;
916
916
  let relevantTokens;
@@ -1147,17 +1147,17 @@ Suggestion: ${result.suggestion}` : ""}`
1147
1147
  // FIX — unchanged
1148
1148
  // ================================================================
1149
1149
  case TOOL_NAMES.fix: {
1150
- const data = await loadSegments();
1150
+ const data = await loadFragments();
1151
1151
  const componentName = args2?.component;
1152
1152
  const variantName = args2?.variant ?? void 0;
1153
1153
  const fixType = args2?.fixType ?? "all";
1154
1154
  if (!componentName) {
1155
1155
  throw new Error("component is required");
1156
1156
  }
1157
- const segment = Object.values(data.segments).find(
1157
+ const fragment = Object.values(data.fragments).find(
1158
1158
  (s) => s.meta.name.toLowerCase() === componentName.toLowerCase()
1159
1159
  );
1160
- if (!segment) {
1160
+ if (!fragment) {
1161
1161
  throw new Error(`Component "${componentName}" not found. Use fragments_discover to see available components.`);
1162
1162
  }
1163
1163
  const baseUrl = config.viewerUrl ?? "http://localhost:6006";