@fragments-sdk/cli 0.2.2

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 (259) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +106 -0
  3. package/dist/bin.d.ts +1 -0
  4. package/dist/bin.js +4783 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/chunk-4FDQSGKX.js +786 -0
  7. package/dist/chunk-4FDQSGKX.js.map +1 -0
  8. package/dist/chunk-7H2MMGYG.js +369 -0
  9. package/dist/chunk-7H2MMGYG.js.map +1 -0
  10. package/dist/chunk-BSCG3IP7.js +619 -0
  11. package/dist/chunk-BSCG3IP7.js.map +1 -0
  12. package/dist/chunk-LY2CFFPY.js +898 -0
  13. package/dist/chunk-LY2CFFPY.js.map +1 -0
  14. package/dist/chunk-MUZ6CM66.js +6636 -0
  15. package/dist/chunk-MUZ6CM66.js.map +1 -0
  16. package/dist/chunk-OAENNG3G.js +1489 -0
  17. package/dist/chunk-OAENNG3G.js.map +1 -0
  18. package/dist/chunk-XHNKNI6J.js +235 -0
  19. package/dist/chunk-XHNKNI6J.js.map +1 -0
  20. package/dist/core-DWKLGY4N.js +68 -0
  21. package/dist/core-DWKLGY4N.js.map +1 -0
  22. package/dist/generate-4LQNJ7SX.js +249 -0
  23. package/dist/generate-4LQNJ7SX.js.map +1 -0
  24. package/dist/index.d.ts +775 -0
  25. package/dist/index.js +41 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/init-EMVI47QG.js +416 -0
  28. package/dist/init-EMVI47QG.js.map +1 -0
  29. package/dist/mcp-bin.d.ts +1 -0
  30. package/dist/mcp-bin.js +1117 -0
  31. package/dist/mcp-bin.js.map +1 -0
  32. package/dist/scan-4YPRF7FV.js +12 -0
  33. package/dist/scan-4YPRF7FV.js.map +1 -0
  34. package/dist/service-QSZMZJBJ.js +208 -0
  35. package/dist/service-QSZMZJBJ.js.map +1 -0
  36. package/dist/static-viewer-MIPGZ4Z7.js +12 -0
  37. package/dist/static-viewer-MIPGZ4Z7.js.map +1 -0
  38. package/dist/test-SQ5ZHXWU.js +1067 -0
  39. package/dist/test-SQ5ZHXWU.js.map +1 -0
  40. package/dist/tokens-HSGMYK64.js +173 -0
  41. package/dist/tokens-HSGMYK64.js.map +1 -0
  42. package/dist/viewer-YRF4SQE4.js +11101 -0
  43. package/dist/viewer-YRF4SQE4.js.map +1 -0
  44. package/package.json +107 -0
  45. package/src/ai.ts +266 -0
  46. package/src/analyze.ts +265 -0
  47. package/src/bin.ts +916 -0
  48. package/src/build.ts +248 -0
  49. package/src/commands/a11y.ts +302 -0
  50. package/src/commands/add.ts +313 -0
  51. package/src/commands/audit.ts +195 -0
  52. package/src/commands/baseline.ts +221 -0
  53. package/src/commands/build.ts +144 -0
  54. package/src/commands/compare.ts +337 -0
  55. package/src/commands/context.ts +107 -0
  56. package/src/commands/dev.ts +107 -0
  57. package/src/commands/enhance.ts +858 -0
  58. package/src/commands/generate.ts +391 -0
  59. package/src/commands/init.ts +531 -0
  60. package/src/commands/link/figma.ts +645 -0
  61. package/src/commands/link/index.ts +10 -0
  62. package/src/commands/link/storybook.ts +267 -0
  63. package/src/commands/list.ts +49 -0
  64. package/src/commands/metrics.ts +114 -0
  65. package/src/commands/reset.ts +242 -0
  66. package/src/commands/scan.ts +537 -0
  67. package/src/commands/storygen.ts +207 -0
  68. package/src/commands/tokens.ts +251 -0
  69. package/src/commands/validate.ts +93 -0
  70. package/src/commands/verify.ts +215 -0
  71. package/src/core/composition.test.ts +262 -0
  72. package/src/core/composition.ts +255 -0
  73. package/src/core/config.ts +84 -0
  74. package/src/core/constants.ts +111 -0
  75. package/src/core/context.ts +380 -0
  76. package/src/core/defineSegment.ts +137 -0
  77. package/src/core/discovery.ts +337 -0
  78. package/src/core/figma.ts +263 -0
  79. package/src/core/fragment-types.ts +214 -0
  80. package/src/core/generators/context.ts +389 -0
  81. package/src/core/generators/index.ts +23 -0
  82. package/src/core/generators/registry.ts +364 -0
  83. package/src/core/generators/typescript-extractor.ts +374 -0
  84. package/src/core/importAnalyzer.ts +217 -0
  85. package/src/core/index.ts +149 -0
  86. package/src/core/loader.ts +155 -0
  87. package/src/core/node.ts +63 -0
  88. package/src/core/parser.ts +551 -0
  89. package/src/core/previewLoader.ts +172 -0
  90. package/src/core/schema/fragment.schema.json +189 -0
  91. package/src/core/schema/registry.schema.json +137 -0
  92. package/src/core/schema.ts +182 -0
  93. package/src/core/storyAdapter.test.ts +571 -0
  94. package/src/core/storyAdapter.ts +761 -0
  95. package/src/core/token-types.ts +287 -0
  96. package/src/core/types.ts +754 -0
  97. package/src/diff.ts +323 -0
  98. package/src/index.ts +43 -0
  99. package/src/mcp/__tests__/projectFields.test.ts +130 -0
  100. package/src/mcp/bin.ts +36 -0
  101. package/src/mcp/index.ts +8 -0
  102. package/src/mcp/server.ts +1310 -0
  103. package/src/mcp/utils.ts +54 -0
  104. package/src/mcp-bin.ts +36 -0
  105. package/src/migrate/__tests__/argTypes/argTypes.test.ts +189 -0
  106. package/src/migrate/__tests__/args/args.test.ts +452 -0
  107. package/src/migrate/__tests__/meta/meta.test.ts +198 -0
  108. package/src/migrate/__tests__/stories/stories.test.ts +278 -0
  109. package/src/migrate/__tests__/utils/utils.test.ts +371 -0
  110. package/src/migrate/__tests__/values/values.test.ts +303 -0
  111. package/src/migrate/bin.ts +108 -0
  112. package/src/migrate/converter.ts +658 -0
  113. package/src/migrate/detect.ts +196 -0
  114. package/src/migrate/index.ts +45 -0
  115. package/src/migrate/migrate.ts +163 -0
  116. package/src/migrate/parser.ts +1136 -0
  117. package/src/migrate/report.ts +624 -0
  118. package/src/migrate/types.ts +169 -0
  119. package/src/screenshot.ts +249 -0
  120. package/src/service/__tests__/ast-utils.test.ts +426 -0
  121. package/src/service/__tests__/enhance-scanner.test.ts +200 -0
  122. package/src/service/__tests__/figma/figma.test.ts +652 -0
  123. package/src/service/__tests__/metrics-store.test.ts +409 -0
  124. package/src/service/__tests__/patch-generator.test.ts +186 -0
  125. package/src/service/__tests__/props-extractor.test.ts +365 -0
  126. package/src/service/__tests__/token-registry.test.ts +267 -0
  127. package/src/service/analytics.ts +659 -0
  128. package/src/service/ast-utils.ts +444 -0
  129. package/src/service/browser-pool.ts +339 -0
  130. package/src/service/capture.ts +267 -0
  131. package/src/service/diff.ts +279 -0
  132. package/src/service/enhance/aggregator.ts +489 -0
  133. package/src/service/enhance/cache.ts +275 -0
  134. package/src/service/enhance/codebase-scanner.ts +357 -0
  135. package/src/service/enhance/context-generator.ts +529 -0
  136. package/src/service/enhance/doc-extractor.ts +523 -0
  137. package/src/service/enhance/index.ts +131 -0
  138. package/src/service/enhance/props-extractor.ts +665 -0
  139. package/src/service/enhance/scanner.ts +445 -0
  140. package/src/service/enhance/storybook-parser.ts +552 -0
  141. package/src/service/enhance/types.ts +346 -0
  142. package/src/service/enhance/variant-renderer.ts +479 -0
  143. package/src/service/figma.ts +1008 -0
  144. package/src/service/index.ts +249 -0
  145. package/src/service/metrics-store.ts +333 -0
  146. package/src/service/patch-generator.ts +349 -0
  147. package/src/service/report.ts +854 -0
  148. package/src/service/storage.ts +401 -0
  149. package/src/service/token-fixes.ts +281 -0
  150. package/src/service/token-parser.ts +504 -0
  151. package/src/service/token-registry.ts +721 -0
  152. package/src/service/utils.ts +172 -0
  153. package/src/setup.ts +241 -0
  154. package/src/shared/command-wrapper.ts +81 -0
  155. package/src/shared/dev-server-client.ts +199 -0
  156. package/src/shared/index.ts +8 -0
  157. package/src/shared/segment-loader.ts +59 -0
  158. package/src/shared/types.ts +147 -0
  159. package/src/static-viewer.ts +715 -0
  160. package/src/test/discovery.ts +172 -0
  161. package/src/test/index.ts +281 -0
  162. package/src/test/reporters/console.ts +194 -0
  163. package/src/test/reporters/json.ts +190 -0
  164. package/src/test/reporters/junit.ts +186 -0
  165. package/src/test/runner.ts +598 -0
  166. package/src/test/types.ts +245 -0
  167. package/src/test/watch.ts +200 -0
  168. package/src/validators.ts +152 -0
  169. package/src/viewer/__tests__/jsx-parser.test.ts +502 -0
  170. package/src/viewer/__tests__/render-utils.test.ts +232 -0
  171. package/src/viewer/__tests__/style-utils.test.ts +404 -0
  172. package/src/viewer/bin.ts +86 -0
  173. package/src/viewer/cli/health.ts +256 -0
  174. package/src/viewer/cli/index.ts +33 -0
  175. package/src/viewer/cli/scan.ts +124 -0
  176. package/src/viewer/cli/utils.ts +174 -0
  177. package/src/viewer/components/AccessibilityPanel.tsx +1404 -0
  178. package/src/viewer/components/ActionCapture.tsx +172 -0
  179. package/src/viewer/components/ActionsPanel.tsx +371 -0
  180. package/src/viewer/components/App.tsx +638 -0
  181. package/src/viewer/components/BottomPanel.tsx +224 -0
  182. package/src/viewer/components/CodePanel.tsx +589 -0
  183. package/src/viewer/components/CommandPalette.tsx +336 -0
  184. package/src/viewer/components/ComponentGraph.tsx +394 -0
  185. package/src/viewer/components/ComponentHeader.tsx +85 -0
  186. package/src/viewer/components/ContractPanel.tsx +234 -0
  187. package/src/viewer/components/ErrorBoundary.tsx +85 -0
  188. package/src/viewer/components/FigmaEmbed.tsx +231 -0
  189. package/src/viewer/components/FragmentEditor.tsx +485 -0
  190. package/src/viewer/components/HealthDashboard.tsx +452 -0
  191. package/src/viewer/components/HmrStatusIndicator.tsx +71 -0
  192. package/src/viewer/components/Icons.tsx +417 -0
  193. package/src/viewer/components/InteractionsPanel.tsx +720 -0
  194. package/src/viewer/components/IsolatedPreviewFrame.tsx +321 -0
  195. package/src/viewer/components/IsolatedRender.tsx +111 -0
  196. package/src/viewer/components/KeyboardShortcutsHelp.tsx +89 -0
  197. package/src/viewer/components/LandingPage.tsx +441 -0
  198. package/src/viewer/components/Layout.tsx +22 -0
  199. package/src/viewer/components/LeftSidebar.tsx +391 -0
  200. package/src/viewer/components/MultiViewportPreview.tsx +429 -0
  201. package/src/viewer/components/PreviewArea.tsx +404 -0
  202. package/src/viewer/components/PreviewFrameHost.tsx +310 -0
  203. package/src/viewer/components/PreviewPane.tsx +150 -0
  204. package/src/viewer/components/PreviewToolbar.tsx +176 -0
  205. package/src/viewer/components/PropsEditor.tsx +512 -0
  206. package/src/viewer/components/PropsTable.tsx +98 -0
  207. package/src/viewer/components/RelationsSection.tsx +57 -0
  208. package/src/viewer/components/ResizablePanel.tsx +328 -0
  209. package/src/viewer/components/RightSidebar.tsx +118 -0
  210. package/src/viewer/components/ScreenshotButton.tsx +90 -0
  211. package/src/viewer/components/Sidebar.tsx +169 -0
  212. package/src/viewer/components/SkeletonLoader.tsx +156 -0
  213. package/src/viewer/components/StoryRenderer.tsx +128 -0
  214. package/src/viewer/components/ThemeProvider.tsx +96 -0
  215. package/src/viewer/components/Toast.tsx +67 -0
  216. package/src/viewer/components/TokenStylePanel.tsx +708 -0
  217. package/src/viewer/components/UsageSection.tsx +95 -0
  218. package/src/viewer/components/VariantMatrix.tsx +350 -0
  219. package/src/viewer/components/VariantRenderer.tsx +131 -0
  220. package/src/viewer/components/VariantTabs.tsx +84 -0
  221. package/src/viewer/components/ViewportSelector.tsx +165 -0
  222. package/src/viewer/components/_future/CreatePage.tsx +836 -0
  223. package/src/viewer/composition-renderer.ts +381 -0
  224. package/src/viewer/constants/index.ts +1 -0
  225. package/src/viewer/constants/ui.ts +185 -0
  226. package/src/viewer/entry.tsx +299 -0
  227. package/src/viewer/hooks/index.ts +2 -0
  228. package/src/viewer/hooks/useA11yCache.ts +383 -0
  229. package/src/viewer/hooks/useA11yService.ts +498 -0
  230. package/src/viewer/hooks/useActions.ts +138 -0
  231. package/src/viewer/hooks/useAppState.ts +124 -0
  232. package/src/viewer/hooks/useFigmaIntegration.ts +132 -0
  233. package/src/viewer/hooks/useHmrStatus.ts +109 -0
  234. package/src/viewer/hooks/useKeyboardShortcuts.ts +222 -0
  235. package/src/viewer/hooks/usePreviewBridge.ts +347 -0
  236. package/src/viewer/hooks/useScrollSpy.ts +78 -0
  237. package/src/viewer/hooks/useUrlState.ts +330 -0
  238. package/src/viewer/hooks/useViewSettings.ts +125 -0
  239. package/src/viewer/index.html +28 -0
  240. package/src/viewer/index.ts +14 -0
  241. package/src/viewer/intelligence/healthReport.ts +505 -0
  242. package/src/viewer/intelligence/styleDrift.ts +340 -0
  243. package/src/viewer/intelligence/usageScanner.ts +309 -0
  244. package/src/viewer/jsx-parser.ts +485 -0
  245. package/src/viewer/postcss.config.js +6 -0
  246. package/src/viewer/preview-frame-entry.tsx +25 -0
  247. package/src/viewer/preview-frame.html +109 -0
  248. package/src/viewer/render-template.html +68 -0
  249. package/src/viewer/render-utils.ts +170 -0
  250. package/src/viewer/server.ts +276 -0
  251. package/src/viewer/style-utils.ts +414 -0
  252. package/src/viewer/styles/globals.css +355 -0
  253. package/src/viewer/tailwind.config.js +37 -0
  254. package/src/viewer/types/a11y.ts +197 -0
  255. package/src/viewer/utils/a11y-fixes.ts +471 -0
  256. package/src/viewer/utils/actionExport.ts +372 -0
  257. package/src/viewer/utils/colorSchemes.ts +201 -0
  258. package/src/viewer/utils/detectRelationships.ts +256 -0
  259. package/src/viewer/vite-plugin.ts +2143 -0
@@ -0,0 +1,529 @@
1
+ /**
2
+ * AI Context Generator
3
+ *
4
+ * Packages codebase analysis, documentation, and Storybook examples
5
+ * into structured context for AI-powered documentation generation.
6
+ */
7
+
8
+ import type {
9
+ ComponentAnalysis,
10
+ UsageAnalysis,
11
+ ExtractedDocs,
12
+ ComponentEnhancement,
13
+ } from "./types.js";
14
+ import type { ParsedStoryFile, StoryExample } from "./storybook-parser.js";
15
+ import type { PropsExtractionResult, ExtractedProp } from "./props-extractor.js";
16
+ import { summarizePatternsForPrompt, type ComponentRelation } from "./aggregator.js";
17
+
18
+ /**
19
+ * Boilerplate patterns that should be filtered from AI suggestions
20
+ */
21
+ const BOILERPLATE_PATTERNS = [
22
+ /component is needed/i,
23
+ /alternative.*appropriate/i,
24
+ /use (?:this|the) component when/i,
25
+ /don'?t use (?:this|the) component/i,
26
+ /when you need (?:this|a|the) component/i,
27
+ /TODO:/i,
28
+ /FIXME:/i,
29
+ /TBD/i,
30
+ /placeholder/i,
31
+ /\[.*\]/, // Placeholder brackets like [describe when]
32
+ ];
33
+
34
+ /**
35
+ * Check if text matches any boilerplate pattern
36
+ */
37
+ export function isBoilerplate(text: string): boolean {
38
+ return BOILERPLATE_PATTERNS.some((pattern) => pattern.test(text));
39
+ }
40
+
41
+ /**
42
+ * Filter out boilerplate suggestions
43
+ */
44
+ export function filterBoilerplate(suggestions: string[]): string[] {
45
+ return suggestions.filter((s) => !isBoilerplate(s));
46
+ }
47
+
48
+ /**
49
+ * Enhanced prop data from TypeScript extraction
50
+ */
51
+ export interface EnhancedProp {
52
+ name: string;
53
+ type: string;
54
+ description: string;
55
+ required: boolean;
56
+ defaultValue?: unknown;
57
+ enumValues?: string[];
58
+ deprecated?: string;
59
+ }
60
+
61
+ /**
62
+ * Full context for AI enhancement of a single component
63
+ */
64
+ export interface ComponentContext {
65
+ componentName: string;
66
+ sourceFile: string;
67
+
68
+ // Existing documentation
69
+ existingDocs: {
70
+ description?: string;
71
+ props: Array<{
72
+ name: string;
73
+ type: string;
74
+ description?: string;
75
+ required: boolean;
76
+ }>;
77
+ examples: string[];
78
+ tags: Record<string, string>;
79
+ };
80
+
81
+ // Enhanced props from TypeScript extraction
82
+ extractedProps?: EnhancedProp[];
83
+
84
+ // Component relationships inferred from usage patterns
85
+ relations?: Array<{
86
+ component: string;
87
+ relationship: "parent" | "sibling" | "child";
88
+ frequency: number;
89
+ }>;
90
+
91
+ // Usage analysis
92
+ usageAnalysis: {
93
+ totalUsages: number;
94
+ uniqueFiles: number;
95
+ topPatterns: Array<{
96
+ props: Record<string, unknown>;
97
+ count: number;
98
+ sampleContext?: string;
99
+ }>;
100
+ contexts: Array<{
101
+ type: string;
102
+ count: number;
103
+ }>;
104
+ };
105
+
106
+ // Storybook examples
107
+ storybook?: {
108
+ title?: string;
109
+ description?: string;
110
+ stories: Array<{
111
+ name: string;
112
+ displayName: string;
113
+ description?: string;
114
+ args: Record<string, unknown>;
115
+ code: string;
116
+ }>;
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Full context package for AI enhancement session
122
+ */
123
+ export interface AIContextPackage {
124
+ projectName: string;
125
+ totalComponents: number;
126
+ components: ComponentContext[];
127
+ globalPatterns: {
128
+ mostUsedComponents: Array<{ name: string; usages: number }>;
129
+ commonPropCombinations: Array<{ props: string[]; count: number }>;
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Generate full context for a single component
135
+ */
136
+ export function generateComponentContext(
137
+ componentName: string,
138
+ analysis: ComponentAnalysis | undefined,
139
+ docs: ExtractedDocs | undefined,
140
+ storyFile: ParsedStoryFile | undefined,
141
+ propsExtraction?: PropsExtractionResult,
142
+ relations?: ComponentRelation[]
143
+ ): ComponentContext {
144
+ const context: ComponentContext = {
145
+ componentName,
146
+ sourceFile: analysis?.sourceFile || propsExtraction?.filePath || docs?.filePath || "unknown",
147
+ existingDocs: {
148
+ description: docs?.description,
149
+ props: docs?.props || [],
150
+ examples: docs?.examples || [],
151
+ tags: docs?.tags || {},
152
+ },
153
+ usageAnalysis: {
154
+ totalUsages: analysis?.totalUsages || 0,
155
+ uniqueFiles: analysis?.uniqueFiles || 0,
156
+ topPatterns: [],
157
+ contexts: [],
158
+ },
159
+ };
160
+
161
+ // Add enhanced props from TypeScript extraction (preferred source)
162
+ if (propsExtraction?.success && propsExtraction.props.length > 0) {
163
+ context.extractedProps = propsExtraction.props.map((p) => ({
164
+ name: p.name,
165
+ type: p.type,
166
+ description: p.description,
167
+ required: p.required,
168
+ defaultValue: p.defaultValue,
169
+ enumValues: p.enumValues,
170
+ deprecated: p.deprecated,
171
+ }));
172
+ }
173
+
174
+ // Add inferred relations
175
+ if (relations && relations.length > 0) {
176
+ context.relations = relations.slice(0, 10).map((r) => ({
177
+ component: r.component,
178
+ relationship: r.relationship,
179
+ frequency: r.frequency,
180
+ }));
181
+ }
182
+
183
+ // Add usage patterns
184
+ if (analysis?.patterns) {
185
+ context.usageAnalysis.topPatterns = analysis.patterns.slice(0, 10).map((p) => ({
186
+ props: p.props,
187
+ count: p.count,
188
+ sampleContext: p.sampleContexts[0],
189
+ }));
190
+ }
191
+
192
+ // Add context types
193
+ if (analysis?.contexts) {
194
+ context.usageAnalysis.contexts = analysis.contexts.map((c) => ({
195
+ type: c.type,
196
+ count: c.count,
197
+ }));
198
+ }
199
+
200
+ // Add Storybook data
201
+ if (storyFile) {
202
+ context.storybook = {
203
+ title: storyFile.meta.title,
204
+ description: storyFile.meta.description,
205
+ stories: storyFile.stories.map((s) => ({
206
+ name: s.name,
207
+ displayName: s.displayName,
208
+ description: s.description,
209
+ args: s.args,
210
+ code: s.code,
211
+ })),
212
+ };
213
+ }
214
+
215
+ return context;
216
+ }
217
+
218
+ /**
219
+ * Generate full AI context package for all components
220
+ */
221
+ export function generateAIContextPackage(
222
+ projectName: string,
223
+ usageAnalysis: UsageAnalysis,
224
+ allDocs: Map<string, ExtractedDocs>,
225
+ allStories: Map<string, ParsedStoryFile>
226
+ ): AIContextPackage {
227
+ const components: ComponentContext[] = [];
228
+
229
+ // Get all unique component names
230
+ const allComponentNames = new Set<string>();
231
+ for (const name of Object.keys(usageAnalysis.components)) {
232
+ allComponentNames.add(name);
233
+ }
234
+ for (const name of allDocs.keys()) {
235
+ allComponentNames.add(name);
236
+ }
237
+ for (const name of allStories.keys()) {
238
+ allComponentNames.add(name);
239
+ }
240
+
241
+ // Generate context for each component
242
+ for (const componentName of allComponentNames) {
243
+ const analysis = usageAnalysis.components[componentName];
244
+ const docs = allDocs.get(componentName);
245
+ const storyFile = allStories.get(componentName);
246
+
247
+ const context = generateComponentContext(
248
+ componentName,
249
+ analysis,
250
+ docs,
251
+ storyFile
252
+ );
253
+ components.push(context);
254
+ }
255
+
256
+ // Sort by usage count
257
+ components.sort(
258
+ (a, b) => b.usageAnalysis.totalUsages - a.usageAnalysis.totalUsages
259
+ );
260
+
261
+ // Calculate global patterns
262
+ const mostUsedComponents = Object.values(usageAnalysis.components)
263
+ .map((c) => ({ name: c.name, usages: c.totalUsages }))
264
+ .sort((a, b) => b.usages - a.usages)
265
+ .slice(0, 20);
266
+
267
+ return {
268
+ projectName,
269
+ totalComponents: components.length,
270
+ components,
271
+ globalPatterns: {
272
+ mostUsedComponents,
273
+ commonPropCombinations: [], // Would need aggregation across all components
274
+ },
275
+ };
276
+ }
277
+
278
+ /**
279
+ * Generate a focused prompt context for a single component
280
+ */
281
+ export function generatePromptContext(context: ComponentContext): string {
282
+ const lines: string[] = [];
283
+
284
+ lines.push(`# Component: ${context.componentName}`);
285
+ lines.push(`Source: ${context.sourceFile}`);
286
+ lines.push("");
287
+
288
+ // Existing documentation
289
+ if (context.existingDocs.description) {
290
+ lines.push("## Current Description");
291
+ lines.push(context.existingDocs.description);
292
+ lines.push("");
293
+ }
294
+
295
+ // Enhanced props from TypeScript extraction (preferred)
296
+ if (context.extractedProps && context.extractedProps.length > 0) {
297
+ lines.push("## Props (from TypeScript)");
298
+ for (const prop of context.extractedProps) {
299
+ const required = prop.required ? "(required)" : "(optional)";
300
+ const deprecated = prop.deprecated ? " [DEPRECATED]" : "";
301
+ const defaultVal = prop.defaultValue !== undefined
302
+ ? ` (default: ${JSON.stringify(prop.defaultValue)})`
303
+ : "";
304
+ const desc = prop.description || "";
305
+
306
+ lines.push(`- **${prop.name}**: \`${prop.type}\` ${required}${deprecated}${defaultVal}`);
307
+ if (desc) {
308
+ lines.push(` ${desc}`);
309
+ }
310
+ if (prop.enumValues && prop.enumValues.length > 0) {
311
+ lines.push(` Values: ${prop.enumValues.map(v => `"${v}"`).join(" | ")}`);
312
+ }
313
+ }
314
+ lines.push("");
315
+ } else if (context.existingDocs.props.length > 0) {
316
+ // Fallback to existing docs props
317
+ lines.push("## Props");
318
+ for (const prop of context.existingDocs.props) {
319
+ const required = prop.required ? "(required)" : "(optional)";
320
+ const desc = prop.description || "No description";
321
+ lines.push(`- **${prop.name}**: \`${prop.type}\` ${required} - ${desc}`);
322
+ }
323
+ lines.push("");
324
+ }
325
+
326
+ // Component relationships
327
+ if (context.relations && context.relations.length > 0) {
328
+ lines.push("## Related Components");
329
+ const parents = context.relations.filter((r) => r.relationship === "parent");
330
+ const siblings = context.relations.filter((r) => r.relationship === "sibling");
331
+
332
+ if (parents.length > 0) {
333
+ lines.push("### Commonly Used Inside");
334
+ for (const rel of parents.slice(0, 5)) {
335
+ lines.push(`- **${rel.component}**: ${rel.frequency} times`);
336
+ }
337
+ }
338
+
339
+ if (siblings.length > 0) {
340
+ lines.push("### Often Used With");
341
+ for (const rel of siblings.slice(0, 5)) {
342
+ lines.push(`- **${rel.component}**: appears together in ${rel.frequency} files`);
343
+ }
344
+ }
345
+ lines.push("");
346
+ }
347
+
348
+ // Usage patterns
349
+ if (context.usageAnalysis.totalUsages > 0) {
350
+ lines.push("## Usage Analysis");
351
+ lines.push(
352
+ `Found ${context.usageAnalysis.totalUsages} usages across ${context.usageAnalysis.uniqueFiles} files.`
353
+ );
354
+ lines.push("");
355
+
356
+ if (context.usageAnalysis.topPatterns.length > 0) {
357
+ lines.push("### Most Common Patterns");
358
+ for (const pattern of context.usageAnalysis.topPatterns.slice(0, 5)) {
359
+ const propsStr =
360
+ Object.keys(pattern.props).length > 0
361
+ ? Object.entries(pattern.props)
362
+ .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
363
+ .join(", ")
364
+ : "(no props)";
365
+ lines.push(`- ${propsStr}: ${pattern.count} times`);
366
+ }
367
+ lines.push("");
368
+ }
369
+
370
+ if (context.usageAnalysis.contexts.length > 0) {
371
+ lines.push("### Where It's Used");
372
+ for (const ctx of context.usageAnalysis.contexts) {
373
+ lines.push(`- ${ctx.type}: ${ctx.count} times`);
374
+ }
375
+ lines.push("");
376
+ }
377
+
378
+ // Sample code context
379
+ const samplePattern = context.usageAnalysis.topPatterns.find(
380
+ (p) => p.sampleContext
381
+ );
382
+ if (samplePattern?.sampleContext) {
383
+ lines.push("### Sample Usage Context");
384
+ lines.push("```tsx");
385
+ lines.push(samplePattern.sampleContext.trim());
386
+ lines.push("```");
387
+ lines.push("");
388
+ }
389
+ }
390
+
391
+ // Storybook examples
392
+ if (context.storybook && context.storybook.stories.length > 0) {
393
+ lines.push("## Storybook Examples");
394
+ for (const story of context.storybook.stories.slice(0, 5)) {
395
+ lines.push(`### ${story.displayName}`);
396
+ if (story.description) {
397
+ lines.push(story.description);
398
+ }
399
+ lines.push("```tsx");
400
+ lines.push(story.code);
401
+ lines.push("```");
402
+ lines.push("");
403
+ }
404
+ }
405
+
406
+ return lines.join("\n");
407
+ }
408
+
409
+ /**
410
+ * Generate enhancement suggestions based on context
411
+ */
412
+ export function generateEnhancementSuggestions(
413
+ context: ComponentContext
414
+ ): ComponentEnhancement {
415
+ const suggestions: ComponentEnhancement = {
416
+ componentName: context.componentName,
417
+ suggestions: {
418
+ when: [],
419
+ whenNot: [],
420
+ examples: [],
421
+ },
422
+ confidence: 0,
423
+ reasoning: [],
424
+ };
425
+
426
+ // Analyze context types to suggest "when" scenarios
427
+ if (context.usageAnalysis.contexts.length > 0) {
428
+ for (const ctx of context.usageAnalysis.contexts) {
429
+ if (ctx.count >= 2) {
430
+ suggestions.suggestions.when.push(
431
+ `Use in ${ctx.type} components (found in ${ctx.count} places)`
432
+ );
433
+ suggestions.reasoning.push(
434
+ `Component is commonly used in ${ctx.type} contexts`
435
+ );
436
+ }
437
+ }
438
+ }
439
+
440
+ // Analyze usage patterns
441
+ const highUsagePatterns = context.usageAnalysis.topPatterns.filter(
442
+ (p) => p.count >= 3
443
+ );
444
+ if (highUsagePatterns.length > 0) {
445
+ for (const pattern of highUsagePatterns.slice(0, 3)) {
446
+ const props = Object.entries(pattern.props);
447
+ if (props.length > 0) {
448
+ const propDesc = props.map(([k, v]) => `${k}="${v}"`).join(", ");
449
+ suggestions.suggestions.when.push(
450
+ `Use with ${propDesc} (common pattern, ${pattern.count} occurrences)`
451
+ );
452
+ }
453
+ }
454
+ }
455
+
456
+ // Generate examples from Storybook
457
+ if (context.storybook?.stories) {
458
+ for (const story of context.storybook.stories.slice(0, 3)) {
459
+ if (story.code) {
460
+ suggestions.suggestions.examples.push(story.code);
461
+ }
462
+ }
463
+ }
464
+
465
+ // Calculate confidence based on available data
466
+ let confidence = 0;
467
+ if (context.usageAnalysis.totalUsages > 10) confidence += 30;
468
+ else if (context.usageAnalysis.totalUsages > 5) confidence += 20;
469
+ else if (context.usageAnalysis.totalUsages > 0) confidence += 10;
470
+
471
+ if (context.storybook?.stories && context.storybook.stories.length > 0) {
472
+ confidence += 25;
473
+ }
474
+
475
+ // Enhanced props from TypeScript extraction are more valuable
476
+ if (context.extractedProps && context.extractedProps.length > 0) {
477
+ confidence += 25;
478
+ } else if (context.existingDocs.props.length > 0) {
479
+ confidence += 15;
480
+ }
481
+
482
+ if (context.usageAnalysis.contexts.length > 0) {
483
+ confidence += 20;
484
+ }
485
+
486
+ suggestions.confidence = Math.min(confidence, 100);
487
+
488
+ return suggestions;
489
+ }
490
+
491
+ /**
492
+ * Generate the system prompt for AI enhancement
493
+ */
494
+ export function generateSystemPrompt(): string {
495
+ return `You are a technical writer specializing in React component documentation. Your task is to generate clear, actionable "when to use" and "when not to use" documentation based on actual usage patterns found in a codebase.
496
+
497
+ Guidelines:
498
+ 1. Be specific and actionable - avoid vague statements
499
+ 2. Base recommendations on observed usage patterns
500
+ 3. Consider the contexts where components are used (forms, modals, tables, etc.)
501
+ 4. Include concrete examples when available
502
+ 5. Mention prop combinations that are commonly used together
503
+ 6. Note any patterns that suggest best practices or anti-patterns
504
+
505
+ Format your response as JSON with this structure:
506
+ {
507
+ "when": ["scenario 1", "scenario 2", ...],
508
+ "whenNot": ["anti-pattern 1", "anti-pattern 2", ...],
509
+ "examples": ["<Component prop=\\"value\\" />", ...]
510
+ }`;
511
+ }
512
+
513
+ /**
514
+ * Generate the user prompt for a specific component
515
+ */
516
+ export function generateUserPrompt(context: ComponentContext): string {
517
+ const promptContext = generatePromptContext(context);
518
+
519
+ return `Based on the following usage analysis, generate "when" and "whenNot" documentation for this component.
520
+
521
+ ${promptContext}
522
+
523
+ Requirements:
524
+ 1. Generate 2-4 "when" scenarios based on the actual usage patterns
525
+ 2. Generate 1-3 "whenNot" scenarios (anti-patterns or inappropriate use cases)
526
+ 3. Include 1-3 example code snippets showing common usage patterns
527
+
528
+ If there isn't enough usage data to make confident recommendations, indicate that in your response.`;
529
+ }