@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.
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +4783 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-4FDQSGKX.js +786 -0
- package/dist/chunk-4FDQSGKX.js.map +1 -0
- package/dist/chunk-7H2MMGYG.js +369 -0
- package/dist/chunk-7H2MMGYG.js.map +1 -0
- package/dist/chunk-BSCG3IP7.js +619 -0
- package/dist/chunk-BSCG3IP7.js.map +1 -0
- package/dist/chunk-LY2CFFPY.js +898 -0
- package/dist/chunk-LY2CFFPY.js.map +1 -0
- package/dist/chunk-MUZ6CM66.js +6636 -0
- package/dist/chunk-MUZ6CM66.js.map +1 -0
- package/dist/chunk-OAENNG3G.js +1489 -0
- package/dist/chunk-OAENNG3G.js.map +1 -0
- package/dist/chunk-XHNKNI6J.js +235 -0
- package/dist/chunk-XHNKNI6J.js.map +1 -0
- package/dist/core-DWKLGY4N.js +68 -0
- package/dist/core-DWKLGY4N.js.map +1 -0
- package/dist/generate-4LQNJ7SX.js +249 -0
- package/dist/generate-4LQNJ7SX.js.map +1 -0
- package/dist/index.d.ts +775 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/init-EMVI47QG.js +416 -0
- package/dist/init-EMVI47QG.js.map +1 -0
- package/dist/mcp-bin.d.ts +1 -0
- package/dist/mcp-bin.js +1117 -0
- package/dist/mcp-bin.js.map +1 -0
- package/dist/scan-4YPRF7FV.js +12 -0
- package/dist/scan-4YPRF7FV.js.map +1 -0
- package/dist/service-QSZMZJBJ.js +208 -0
- package/dist/service-QSZMZJBJ.js.map +1 -0
- package/dist/static-viewer-MIPGZ4Z7.js +12 -0
- package/dist/static-viewer-MIPGZ4Z7.js.map +1 -0
- package/dist/test-SQ5ZHXWU.js +1067 -0
- package/dist/test-SQ5ZHXWU.js.map +1 -0
- package/dist/tokens-HSGMYK64.js +173 -0
- package/dist/tokens-HSGMYK64.js.map +1 -0
- package/dist/viewer-YRF4SQE4.js +11101 -0
- package/dist/viewer-YRF4SQE4.js.map +1 -0
- package/package.json +107 -0
- package/src/ai.ts +266 -0
- package/src/analyze.ts +265 -0
- package/src/bin.ts +916 -0
- package/src/build.ts +248 -0
- package/src/commands/a11y.ts +302 -0
- package/src/commands/add.ts +313 -0
- package/src/commands/audit.ts +195 -0
- package/src/commands/baseline.ts +221 -0
- package/src/commands/build.ts +144 -0
- package/src/commands/compare.ts +337 -0
- package/src/commands/context.ts +107 -0
- package/src/commands/dev.ts +107 -0
- package/src/commands/enhance.ts +858 -0
- package/src/commands/generate.ts +391 -0
- package/src/commands/init.ts +531 -0
- package/src/commands/link/figma.ts +645 -0
- package/src/commands/link/index.ts +10 -0
- package/src/commands/link/storybook.ts +267 -0
- package/src/commands/list.ts +49 -0
- package/src/commands/metrics.ts +114 -0
- package/src/commands/reset.ts +242 -0
- package/src/commands/scan.ts +537 -0
- package/src/commands/storygen.ts +207 -0
- package/src/commands/tokens.ts +251 -0
- package/src/commands/validate.ts +93 -0
- package/src/commands/verify.ts +215 -0
- package/src/core/composition.test.ts +262 -0
- package/src/core/composition.ts +255 -0
- package/src/core/config.ts +84 -0
- package/src/core/constants.ts +111 -0
- package/src/core/context.ts +380 -0
- package/src/core/defineSegment.ts +137 -0
- package/src/core/discovery.ts +337 -0
- package/src/core/figma.ts +263 -0
- package/src/core/fragment-types.ts +214 -0
- package/src/core/generators/context.ts +389 -0
- package/src/core/generators/index.ts +23 -0
- package/src/core/generators/registry.ts +364 -0
- package/src/core/generators/typescript-extractor.ts +374 -0
- package/src/core/importAnalyzer.ts +217 -0
- package/src/core/index.ts +149 -0
- package/src/core/loader.ts +155 -0
- package/src/core/node.ts +63 -0
- package/src/core/parser.ts +551 -0
- package/src/core/previewLoader.ts +172 -0
- package/src/core/schema/fragment.schema.json +189 -0
- package/src/core/schema/registry.schema.json +137 -0
- package/src/core/schema.ts +182 -0
- package/src/core/storyAdapter.test.ts +571 -0
- package/src/core/storyAdapter.ts +761 -0
- package/src/core/token-types.ts +287 -0
- package/src/core/types.ts +754 -0
- package/src/diff.ts +323 -0
- package/src/index.ts +43 -0
- package/src/mcp/__tests__/projectFields.test.ts +130 -0
- package/src/mcp/bin.ts +36 -0
- package/src/mcp/index.ts +8 -0
- package/src/mcp/server.ts +1310 -0
- package/src/mcp/utils.ts +54 -0
- package/src/mcp-bin.ts +36 -0
- package/src/migrate/__tests__/argTypes/argTypes.test.ts +189 -0
- package/src/migrate/__tests__/args/args.test.ts +452 -0
- package/src/migrate/__tests__/meta/meta.test.ts +198 -0
- package/src/migrate/__tests__/stories/stories.test.ts +278 -0
- package/src/migrate/__tests__/utils/utils.test.ts +371 -0
- package/src/migrate/__tests__/values/values.test.ts +303 -0
- package/src/migrate/bin.ts +108 -0
- package/src/migrate/converter.ts +658 -0
- package/src/migrate/detect.ts +196 -0
- package/src/migrate/index.ts +45 -0
- package/src/migrate/migrate.ts +163 -0
- package/src/migrate/parser.ts +1136 -0
- package/src/migrate/report.ts +624 -0
- package/src/migrate/types.ts +169 -0
- package/src/screenshot.ts +249 -0
- package/src/service/__tests__/ast-utils.test.ts +426 -0
- package/src/service/__tests__/enhance-scanner.test.ts +200 -0
- package/src/service/__tests__/figma/figma.test.ts +652 -0
- package/src/service/__tests__/metrics-store.test.ts +409 -0
- package/src/service/__tests__/patch-generator.test.ts +186 -0
- package/src/service/__tests__/props-extractor.test.ts +365 -0
- package/src/service/__tests__/token-registry.test.ts +267 -0
- package/src/service/analytics.ts +659 -0
- package/src/service/ast-utils.ts +444 -0
- package/src/service/browser-pool.ts +339 -0
- package/src/service/capture.ts +267 -0
- package/src/service/diff.ts +279 -0
- package/src/service/enhance/aggregator.ts +489 -0
- package/src/service/enhance/cache.ts +275 -0
- package/src/service/enhance/codebase-scanner.ts +357 -0
- package/src/service/enhance/context-generator.ts +529 -0
- package/src/service/enhance/doc-extractor.ts +523 -0
- package/src/service/enhance/index.ts +131 -0
- package/src/service/enhance/props-extractor.ts +665 -0
- package/src/service/enhance/scanner.ts +445 -0
- package/src/service/enhance/storybook-parser.ts +552 -0
- package/src/service/enhance/types.ts +346 -0
- package/src/service/enhance/variant-renderer.ts +479 -0
- package/src/service/figma.ts +1008 -0
- package/src/service/index.ts +249 -0
- package/src/service/metrics-store.ts +333 -0
- package/src/service/patch-generator.ts +349 -0
- package/src/service/report.ts +854 -0
- package/src/service/storage.ts +401 -0
- package/src/service/token-fixes.ts +281 -0
- package/src/service/token-parser.ts +504 -0
- package/src/service/token-registry.ts +721 -0
- package/src/service/utils.ts +172 -0
- package/src/setup.ts +241 -0
- package/src/shared/command-wrapper.ts +81 -0
- package/src/shared/dev-server-client.ts +199 -0
- package/src/shared/index.ts +8 -0
- package/src/shared/segment-loader.ts +59 -0
- package/src/shared/types.ts +147 -0
- package/src/static-viewer.ts +715 -0
- package/src/test/discovery.ts +172 -0
- package/src/test/index.ts +281 -0
- package/src/test/reporters/console.ts +194 -0
- package/src/test/reporters/json.ts +190 -0
- package/src/test/reporters/junit.ts +186 -0
- package/src/test/runner.ts +598 -0
- package/src/test/types.ts +245 -0
- package/src/test/watch.ts +200 -0
- package/src/validators.ts +152 -0
- package/src/viewer/__tests__/jsx-parser.test.ts +502 -0
- package/src/viewer/__tests__/render-utils.test.ts +232 -0
- package/src/viewer/__tests__/style-utils.test.ts +404 -0
- package/src/viewer/bin.ts +86 -0
- package/src/viewer/cli/health.ts +256 -0
- package/src/viewer/cli/index.ts +33 -0
- package/src/viewer/cli/scan.ts +124 -0
- package/src/viewer/cli/utils.ts +174 -0
- package/src/viewer/components/AccessibilityPanel.tsx +1404 -0
- package/src/viewer/components/ActionCapture.tsx +172 -0
- package/src/viewer/components/ActionsPanel.tsx +371 -0
- package/src/viewer/components/App.tsx +638 -0
- package/src/viewer/components/BottomPanel.tsx +224 -0
- package/src/viewer/components/CodePanel.tsx +589 -0
- package/src/viewer/components/CommandPalette.tsx +336 -0
- package/src/viewer/components/ComponentGraph.tsx +394 -0
- package/src/viewer/components/ComponentHeader.tsx +85 -0
- package/src/viewer/components/ContractPanel.tsx +234 -0
- package/src/viewer/components/ErrorBoundary.tsx +85 -0
- package/src/viewer/components/FigmaEmbed.tsx +231 -0
- package/src/viewer/components/FragmentEditor.tsx +485 -0
- package/src/viewer/components/HealthDashboard.tsx +452 -0
- package/src/viewer/components/HmrStatusIndicator.tsx +71 -0
- package/src/viewer/components/Icons.tsx +417 -0
- package/src/viewer/components/InteractionsPanel.tsx +720 -0
- package/src/viewer/components/IsolatedPreviewFrame.tsx +321 -0
- package/src/viewer/components/IsolatedRender.tsx +111 -0
- package/src/viewer/components/KeyboardShortcutsHelp.tsx +89 -0
- package/src/viewer/components/LandingPage.tsx +441 -0
- package/src/viewer/components/Layout.tsx +22 -0
- package/src/viewer/components/LeftSidebar.tsx +391 -0
- package/src/viewer/components/MultiViewportPreview.tsx +429 -0
- package/src/viewer/components/PreviewArea.tsx +404 -0
- package/src/viewer/components/PreviewFrameHost.tsx +310 -0
- package/src/viewer/components/PreviewPane.tsx +150 -0
- package/src/viewer/components/PreviewToolbar.tsx +176 -0
- package/src/viewer/components/PropsEditor.tsx +512 -0
- package/src/viewer/components/PropsTable.tsx +98 -0
- package/src/viewer/components/RelationsSection.tsx +57 -0
- package/src/viewer/components/ResizablePanel.tsx +328 -0
- package/src/viewer/components/RightSidebar.tsx +118 -0
- package/src/viewer/components/ScreenshotButton.tsx +90 -0
- package/src/viewer/components/Sidebar.tsx +169 -0
- package/src/viewer/components/SkeletonLoader.tsx +156 -0
- package/src/viewer/components/StoryRenderer.tsx +128 -0
- package/src/viewer/components/ThemeProvider.tsx +96 -0
- package/src/viewer/components/Toast.tsx +67 -0
- package/src/viewer/components/TokenStylePanel.tsx +708 -0
- package/src/viewer/components/UsageSection.tsx +95 -0
- package/src/viewer/components/VariantMatrix.tsx +350 -0
- package/src/viewer/components/VariantRenderer.tsx +131 -0
- package/src/viewer/components/VariantTabs.tsx +84 -0
- package/src/viewer/components/ViewportSelector.tsx +165 -0
- package/src/viewer/components/_future/CreatePage.tsx +836 -0
- package/src/viewer/composition-renderer.ts +381 -0
- package/src/viewer/constants/index.ts +1 -0
- package/src/viewer/constants/ui.ts +185 -0
- package/src/viewer/entry.tsx +299 -0
- package/src/viewer/hooks/index.ts +2 -0
- package/src/viewer/hooks/useA11yCache.ts +383 -0
- package/src/viewer/hooks/useA11yService.ts +498 -0
- package/src/viewer/hooks/useActions.ts +138 -0
- package/src/viewer/hooks/useAppState.ts +124 -0
- package/src/viewer/hooks/useFigmaIntegration.ts +132 -0
- package/src/viewer/hooks/useHmrStatus.ts +109 -0
- package/src/viewer/hooks/useKeyboardShortcuts.ts +222 -0
- package/src/viewer/hooks/usePreviewBridge.ts +347 -0
- package/src/viewer/hooks/useScrollSpy.ts +78 -0
- package/src/viewer/hooks/useUrlState.ts +330 -0
- package/src/viewer/hooks/useViewSettings.ts +125 -0
- package/src/viewer/index.html +28 -0
- package/src/viewer/index.ts +14 -0
- package/src/viewer/intelligence/healthReport.ts +505 -0
- package/src/viewer/intelligence/styleDrift.ts +340 -0
- package/src/viewer/intelligence/usageScanner.ts +309 -0
- package/src/viewer/jsx-parser.ts +485 -0
- package/src/viewer/postcss.config.js +6 -0
- package/src/viewer/preview-frame-entry.tsx +25 -0
- package/src/viewer/preview-frame.html +109 -0
- package/src/viewer/render-template.html +68 -0
- package/src/viewer/render-utils.ts +170 -0
- package/src/viewer/server.ts +276 -0
- package/src/viewer/style-utils.ts +414 -0
- package/src/viewer/styles/globals.css +355 -0
- package/src/viewer/tailwind.config.js +37 -0
- package/src/viewer/types/a11y.ts +197 -0
- package/src/viewer/utils/a11y-fixes.ts +471 -0
- package/src/viewer/utils/actionExport.ts +372 -0
- package/src/viewer/utils/colorSchemes.ts +201 -0
- package/src/viewer/utils/detectRelationships.ts +256 -0
- package/src/viewer/vite-plugin.ts +2143 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fragments/service
|
|
3
|
+
*
|
|
4
|
+
* Screenshot capture and verification service for Segments.
|
|
5
|
+
* Provides browser pool management, screenshot capture, and visual diff capabilities.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Browser pool
|
|
9
|
+
export {
|
|
10
|
+
BrowserPool,
|
|
11
|
+
BrowserPoolError,
|
|
12
|
+
getSharedPool,
|
|
13
|
+
shutdownSharedPool,
|
|
14
|
+
type BrowserPoolConfig,
|
|
15
|
+
} from "./browser-pool.js";
|
|
16
|
+
|
|
17
|
+
// Capture engine
|
|
18
|
+
export {
|
|
19
|
+
CaptureEngine,
|
|
20
|
+
CaptureError,
|
|
21
|
+
createCaptureEngine,
|
|
22
|
+
type CaptureOptions,
|
|
23
|
+
} from "./capture.js";
|
|
24
|
+
|
|
25
|
+
// Storage manager
|
|
26
|
+
export {
|
|
27
|
+
StorageManager,
|
|
28
|
+
StorageError,
|
|
29
|
+
createStorageManager,
|
|
30
|
+
type StorageConfig,
|
|
31
|
+
} from "./storage.js";
|
|
32
|
+
|
|
33
|
+
// Diff engine
|
|
34
|
+
export {
|
|
35
|
+
DiffEngine,
|
|
36
|
+
DiffError,
|
|
37
|
+
createDiffEngine,
|
|
38
|
+
type DiffOptions,
|
|
39
|
+
} from "./diff.js";
|
|
40
|
+
|
|
41
|
+
// Figma client
|
|
42
|
+
export {
|
|
43
|
+
FigmaClient,
|
|
44
|
+
FigmaError,
|
|
45
|
+
createFigmaClient,
|
|
46
|
+
type FigmaClientConfig,
|
|
47
|
+
type FigmaImageResult,
|
|
48
|
+
type FigmaUrlParts,
|
|
49
|
+
type FigmaComponent,
|
|
50
|
+
type FigmaFileComponents,
|
|
51
|
+
type FigmaVariant,
|
|
52
|
+
type FigmaComponentSetWithVariants,
|
|
53
|
+
// Design property types (Phase 3)
|
|
54
|
+
type FigmaColor,
|
|
55
|
+
type FigmaFill,
|
|
56
|
+
type FigmaStroke,
|
|
57
|
+
type FigmaEffect,
|
|
58
|
+
type FigmaTypography,
|
|
59
|
+
type FigmaDesignProperties,
|
|
60
|
+
type CSSDesignProperties,
|
|
61
|
+
type StyleDiffResult,
|
|
62
|
+
} from "./figma.js";
|
|
63
|
+
|
|
64
|
+
// Utilities
|
|
65
|
+
export {
|
|
66
|
+
ServiceError,
|
|
67
|
+
Timer,
|
|
68
|
+
computeHash,
|
|
69
|
+
createDeferred,
|
|
70
|
+
sleep,
|
|
71
|
+
bufferToBase64Url,
|
|
72
|
+
base64UrlToBuffer,
|
|
73
|
+
sanitizeFilename,
|
|
74
|
+
buildScreenshotPath,
|
|
75
|
+
formatMs,
|
|
76
|
+
retry,
|
|
77
|
+
} from "./utils.js";
|
|
78
|
+
|
|
79
|
+
// Analytics engine
|
|
80
|
+
export {
|
|
81
|
+
analyzeDesignSystem,
|
|
82
|
+
getGrade,
|
|
83
|
+
getScoreColor,
|
|
84
|
+
type DesignSystemAnalytics,
|
|
85
|
+
type ComponentInventory,
|
|
86
|
+
type ComponentSummary,
|
|
87
|
+
type CoverageAnalytics,
|
|
88
|
+
type QualityAnalytics,
|
|
89
|
+
type DistributionAnalytics,
|
|
90
|
+
type Recommendation,
|
|
91
|
+
} from "./analytics.js";
|
|
92
|
+
|
|
93
|
+
// HTML Report generator
|
|
94
|
+
export { generateHtmlReport } from "./report.js";
|
|
95
|
+
|
|
96
|
+
// Token parser and registry
|
|
97
|
+
export {
|
|
98
|
+
parseTokenFile,
|
|
99
|
+
parseTokenFiles,
|
|
100
|
+
hexToRgb,
|
|
101
|
+
rgbToHex,
|
|
102
|
+
parseRgb,
|
|
103
|
+
normalizeColor,
|
|
104
|
+
} from "./token-parser.js";
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
TokenRegistryManager,
|
|
108
|
+
getSharedTokenRegistry,
|
|
109
|
+
initializeSharedRegistry,
|
|
110
|
+
clearSharedRegistry,
|
|
111
|
+
createTokenRegistry,
|
|
112
|
+
} from "./token-registry.js";
|
|
113
|
+
|
|
114
|
+
// Token fix suggestions
|
|
115
|
+
export {
|
|
116
|
+
generateTokenFixes,
|
|
117
|
+
generateAIFixContext,
|
|
118
|
+
type TokenFixContext,
|
|
119
|
+
} from "./token-fixes.js";
|
|
120
|
+
|
|
121
|
+
// Patch generator
|
|
122
|
+
export {
|
|
123
|
+
generateTokenPatches,
|
|
124
|
+
generateCSSInJSPatches,
|
|
125
|
+
type Patch,
|
|
126
|
+
type PatchGenerationResult,
|
|
127
|
+
type PatchGenerationOptions,
|
|
128
|
+
} from "./patch-generator.js";
|
|
129
|
+
|
|
130
|
+
// AST utilities for style extraction and patching
|
|
131
|
+
export {
|
|
132
|
+
extractStyleLocations,
|
|
133
|
+
applyPatch,
|
|
134
|
+
applyPatches,
|
|
135
|
+
findStyleOccurrences,
|
|
136
|
+
type StyleLocation,
|
|
137
|
+
type PatchResult,
|
|
138
|
+
} from "./ast-utils.js";
|
|
139
|
+
|
|
140
|
+
// Metrics storage for compliance trends
|
|
141
|
+
export {
|
|
142
|
+
MetricsStore,
|
|
143
|
+
createMetricsStore,
|
|
144
|
+
type ComplianceSnapshot,
|
|
145
|
+
type MetricsTrend,
|
|
146
|
+
type MetricsQueryOptions,
|
|
147
|
+
} from "./metrics-store.js";
|
|
148
|
+
|
|
149
|
+
// Enhancement module - codebase analysis for AI documentation
|
|
150
|
+
export {
|
|
151
|
+
// Scanner
|
|
152
|
+
scanFileForImports,
|
|
153
|
+
scanFileForUsages,
|
|
154
|
+
scanFile,
|
|
155
|
+
scanCodebase,
|
|
156
|
+
incrementalScan,
|
|
157
|
+
getScanStats,
|
|
158
|
+
hasCachedAnalysis,
|
|
159
|
+
// Aggregator
|
|
160
|
+
aggregateComponentUsages,
|
|
161
|
+
aggregateAllUsages,
|
|
162
|
+
findCommonPropCombinations,
|
|
163
|
+
summarizePatternsForPrompt,
|
|
164
|
+
inferRelations,
|
|
165
|
+
inferAllRelations,
|
|
166
|
+
type ComponentRelation,
|
|
167
|
+
// Cache
|
|
168
|
+
loadCache,
|
|
169
|
+
saveCache,
|
|
170
|
+
createEmptyCache,
|
|
171
|
+
computeFileHash,
|
|
172
|
+
detectFileChanges,
|
|
173
|
+
getCacheStats,
|
|
174
|
+
// Doc Extractor
|
|
175
|
+
extractComponentDocs,
|
|
176
|
+
extractDocsFromSource,
|
|
177
|
+
findComponentSource,
|
|
178
|
+
extractAllComponentDocs,
|
|
179
|
+
// Storybook Parser
|
|
180
|
+
parseStoryFile,
|
|
181
|
+
parseStorySource,
|
|
182
|
+
findStoryFiles,
|
|
183
|
+
parseAllStories,
|
|
184
|
+
mergeStorybookIntoDoc,
|
|
185
|
+
type StoryExample,
|
|
186
|
+
type StorybookMeta,
|
|
187
|
+
type ArgType,
|
|
188
|
+
type ParsedStoryFile,
|
|
189
|
+
// AI Context Generator
|
|
190
|
+
generateComponentContext,
|
|
191
|
+
generateAIContextPackage,
|
|
192
|
+
generatePromptContext,
|
|
193
|
+
generateEnhancementSuggestions,
|
|
194
|
+
generateSystemPrompt,
|
|
195
|
+
generateUserPrompt,
|
|
196
|
+
isBoilerplate,
|
|
197
|
+
filterBoilerplate,
|
|
198
|
+
type ComponentContext,
|
|
199
|
+
type AIContextPackage,
|
|
200
|
+
type EnhancedProp,
|
|
201
|
+
// Props Extractor
|
|
202
|
+
extractPropsFromFile,
|
|
203
|
+
extractPropsFromSource,
|
|
204
|
+
extractPropsForComponent,
|
|
205
|
+
extractAllComponentProps,
|
|
206
|
+
convertToSegmentProps,
|
|
207
|
+
type ExtractedProp,
|
|
208
|
+
type PropsExtractionResult,
|
|
209
|
+
type PropsExtractionOptions,
|
|
210
|
+
// Variant Renderer
|
|
211
|
+
renderVariants,
|
|
212
|
+
renderAllComponentVariants,
|
|
213
|
+
checkStorybookRunning,
|
|
214
|
+
getStorybookStoryIds,
|
|
215
|
+
shutdownSharedPool as shutdownVariantPool,
|
|
216
|
+
type RenderedVariant,
|
|
217
|
+
type VariantRenderResult,
|
|
218
|
+
type VariantRenderOptions,
|
|
219
|
+
// Types
|
|
220
|
+
type ComponentUsage,
|
|
221
|
+
type UsageProps,
|
|
222
|
+
type ComponentImport,
|
|
223
|
+
type UsagePattern,
|
|
224
|
+
type FileContext,
|
|
225
|
+
type ComponentAnalysis,
|
|
226
|
+
type UsageAnalysis,
|
|
227
|
+
type AnalysisCache,
|
|
228
|
+
type ScanProgress,
|
|
229
|
+
type ScanOptions,
|
|
230
|
+
type FileChanges,
|
|
231
|
+
type ExtractedDocs,
|
|
232
|
+
type ComponentEnhancement,
|
|
233
|
+
type EnhancementResult,
|
|
234
|
+
} from "./enhance/index.js";
|
|
235
|
+
|
|
236
|
+
// Re-export types and constants from core for convenience
|
|
237
|
+
export { BRAND, DEFAULTS } from "../core/index.js";
|
|
238
|
+
export type {
|
|
239
|
+
Screenshot,
|
|
240
|
+
ScreenshotMetadata,
|
|
241
|
+
DiffResult,
|
|
242
|
+
BoundingBox,
|
|
243
|
+
BaselineInfo,
|
|
244
|
+
Manifest,
|
|
245
|
+
VerifyRequest,
|
|
246
|
+
VerifyResult,
|
|
247
|
+
Viewport,
|
|
248
|
+
Theme,
|
|
249
|
+
} from "../core/index.js";
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Store
|
|
3
|
+
*
|
|
4
|
+
* Persists compliance metrics over time for trend analysis.
|
|
5
|
+
* Stores snapshots in .segments/metrics/ directory.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFile, writeFile, mkdir, readdir } from "node:fs/promises";
|
|
9
|
+
import { join, dirname } from "node:path";
|
|
10
|
+
import { BRAND } from "../core/index.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A single compliance snapshot for a component
|
|
14
|
+
*/
|
|
15
|
+
export interface ComplianceSnapshot {
|
|
16
|
+
/** ISO timestamp when snapshot was taken */
|
|
17
|
+
timestamp: string;
|
|
18
|
+
|
|
19
|
+
/** Component name */
|
|
20
|
+
component: string;
|
|
21
|
+
|
|
22
|
+
/** Compliance percentage (0-100) */
|
|
23
|
+
compliance: number;
|
|
24
|
+
|
|
25
|
+
/** Number of violations */
|
|
26
|
+
violations: number;
|
|
27
|
+
|
|
28
|
+
/** Detailed violation info */
|
|
29
|
+
violationDetails?: Array<{
|
|
30
|
+
property: string;
|
|
31
|
+
issue: string;
|
|
32
|
+
severity: "error" | "warning";
|
|
33
|
+
}>;
|
|
34
|
+
|
|
35
|
+
/** Git commit hash if available */
|
|
36
|
+
commitHash?: string;
|
|
37
|
+
|
|
38
|
+
/** Branch name if available */
|
|
39
|
+
branch?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Aggregated metrics for trend analysis
|
|
44
|
+
*/
|
|
45
|
+
export interface MetricsTrend {
|
|
46
|
+
/** Component name or 'system' for aggregate */
|
|
47
|
+
component: string;
|
|
48
|
+
|
|
49
|
+
/** Time period */
|
|
50
|
+
period: "day" | "week" | "month";
|
|
51
|
+
|
|
52
|
+
/** Data points */
|
|
53
|
+
dataPoints: Array<{
|
|
54
|
+
date: string;
|
|
55
|
+
compliance: number;
|
|
56
|
+
violations: number;
|
|
57
|
+
}>;
|
|
58
|
+
|
|
59
|
+
/** Trend direction */
|
|
60
|
+
trend: "improving" | "stable" | "declining";
|
|
61
|
+
|
|
62
|
+
/** Average compliance over period */
|
|
63
|
+
averageCompliance: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Options for metrics queries
|
|
68
|
+
*/
|
|
69
|
+
export interface MetricsQueryOptions {
|
|
70
|
+
/** Number of days to look back (default: 30) */
|
|
71
|
+
days?: number;
|
|
72
|
+
|
|
73
|
+
/** Filter by component */
|
|
74
|
+
component?: string;
|
|
75
|
+
|
|
76
|
+
/** Group by period */
|
|
77
|
+
groupBy?: "day" | "week" | "month";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Metrics Store for persisting compliance data
|
|
82
|
+
*/
|
|
83
|
+
export class MetricsStore {
|
|
84
|
+
private readonly projectRoot: string;
|
|
85
|
+
private readonly metricsDir: string;
|
|
86
|
+
|
|
87
|
+
constructor(projectRoot: string) {
|
|
88
|
+
this.projectRoot = projectRoot;
|
|
89
|
+
this.metricsDir = join(projectRoot, BRAND.dataDir, "metrics");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Save a compliance snapshot
|
|
94
|
+
*/
|
|
95
|
+
async saveSnapshot(snapshot: ComplianceSnapshot): Promise<string> {
|
|
96
|
+
// Ensure metrics directory exists
|
|
97
|
+
await mkdir(this.metricsDir, { recursive: true });
|
|
98
|
+
|
|
99
|
+
// Create filename with timestamp and component
|
|
100
|
+
const date = new Date(snapshot.timestamp);
|
|
101
|
+
const dateStr = date.toISOString().split("T")[0]; // YYYY-MM-DD
|
|
102
|
+
const filename = `${dateStr}_${snapshot.component}.json`;
|
|
103
|
+
const filepath = join(this.metricsDir, filename);
|
|
104
|
+
|
|
105
|
+
// Append to existing file for the day or create new
|
|
106
|
+
let snapshots: ComplianceSnapshot[] = [];
|
|
107
|
+
try {
|
|
108
|
+
const existing = await readFile(filepath, "utf-8");
|
|
109
|
+
snapshots = JSON.parse(existing);
|
|
110
|
+
} catch {
|
|
111
|
+
// File doesn't exist, start fresh
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
snapshots.push(snapshot);
|
|
115
|
+
|
|
116
|
+
await writeFile(filepath, JSON.stringify(snapshots, null, 2));
|
|
117
|
+
|
|
118
|
+
return filepath;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get compliance history for a component
|
|
123
|
+
*/
|
|
124
|
+
async getHistory(
|
|
125
|
+
component: string,
|
|
126
|
+
options: MetricsQueryOptions = {}
|
|
127
|
+
): Promise<ComplianceSnapshot[]> {
|
|
128
|
+
const { days = 30 } = options;
|
|
129
|
+
|
|
130
|
+
const snapshots: ComplianceSnapshot[] = [];
|
|
131
|
+
const cutoffDate = new Date();
|
|
132
|
+
cutoffDate.setDate(cutoffDate.getDate() - days);
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const files = await readdir(this.metricsDir);
|
|
136
|
+
|
|
137
|
+
for (const file of files) {
|
|
138
|
+
if (!file.endsWith(".json")) continue;
|
|
139
|
+
|
|
140
|
+
// Check if file is within date range
|
|
141
|
+
const dateStr = file.split("_")[0];
|
|
142
|
+
const fileDate = new Date(dateStr);
|
|
143
|
+
if (fileDate < cutoffDate) continue;
|
|
144
|
+
|
|
145
|
+
// Check if file matches component
|
|
146
|
+
if (component !== "all" && !file.includes(`_${component}.json`)) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const content = await readFile(join(this.metricsDir, file), "utf-8");
|
|
152
|
+
const fileSnapshots: ComplianceSnapshot[] = JSON.parse(content);
|
|
153
|
+
|
|
154
|
+
// Filter to matching component
|
|
155
|
+
const matching = component === "all"
|
|
156
|
+
? fileSnapshots
|
|
157
|
+
: fileSnapshots.filter((s) => s.component === component);
|
|
158
|
+
|
|
159
|
+
snapshots.push(...matching);
|
|
160
|
+
} catch {
|
|
161
|
+
// Skip malformed files
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
} catch {
|
|
165
|
+
// Metrics directory doesn't exist
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Sort by timestamp
|
|
170
|
+
snapshots.sort(
|
|
171
|
+
(a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
return snapshots;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Get system-wide compliance history
|
|
179
|
+
*/
|
|
180
|
+
async getSystemHistory(options: MetricsQueryOptions = {}): Promise<ComplianceSnapshot[]> {
|
|
181
|
+
return this.getHistory("all", options);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Calculate compliance trend for a component
|
|
186
|
+
*/
|
|
187
|
+
async getTrend(
|
|
188
|
+
component: string,
|
|
189
|
+
options: MetricsQueryOptions = {}
|
|
190
|
+
): Promise<MetricsTrend> {
|
|
191
|
+
const { days = 30, groupBy = "day" } = options;
|
|
192
|
+
|
|
193
|
+
const snapshots = await this.getHistory(component, { days });
|
|
194
|
+
|
|
195
|
+
// Group by period
|
|
196
|
+
const groups = new Map<string, ComplianceSnapshot[]>();
|
|
197
|
+
|
|
198
|
+
for (const snapshot of snapshots) {
|
|
199
|
+
const date = new Date(snapshot.timestamp);
|
|
200
|
+
let key: string;
|
|
201
|
+
|
|
202
|
+
switch (groupBy) {
|
|
203
|
+
case "week":
|
|
204
|
+
// Get ISO week
|
|
205
|
+
const weekStart = new Date(date);
|
|
206
|
+
weekStart.setDate(date.getDate() - date.getDay());
|
|
207
|
+
key = weekStart.toISOString().split("T")[0];
|
|
208
|
+
break;
|
|
209
|
+
case "month":
|
|
210
|
+
key = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`;
|
|
211
|
+
break;
|
|
212
|
+
case "day":
|
|
213
|
+
default:
|
|
214
|
+
key = date.toISOString().split("T")[0];
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const existing = groups.get(key) || [];
|
|
219
|
+
existing.push(snapshot);
|
|
220
|
+
groups.set(key, existing);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Calculate aggregates for each period
|
|
224
|
+
const dataPoints: MetricsTrend["dataPoints"] = [];
|
|
225
|
+
|
|
226
|
+
for (const [date, periodSnapshots] of groups) {
|
|
227
|
+
const avgCompliance =
|
|
228
|
+
periodSnapshots.reduce((sum, s) => sum + s.compliance, 0) /
|
|
229
|
+
periodSnapshots.length;
|
|
230
|
+
const totalViolations = periodSnapshots.reduce(
|
|
231
|
+
(sum, s) => sum + s.violations,
|
|
232
|
+
0
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
dataPoints.push({
|
|
236
|
+
date,
|
|
237
|
+
compliance: Math.round(avgCompliance * 100) / 100,
|
|
238
|
+
violations: totalViolations,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Sort by date
|
|
243
|
+
dataPoints.sort((a, b) => a.date.localeCompare(b.date));
|
|
244
|
+
|
|
245
|
+
// Determine trend
|
|
246
|
+
let trend: MetricsTrend["trend"] = "stable";
|
|
247
|
+
if (dataPoints.length >= 2) {
|
|
248
|
+
const first = dataPoints.slice(0, Math.ceil(dataPoints.length / 2));
|
|
249
|
+
const second = dataPoints.slice(Math.ceil(dataPoints.length / 2));
|
|
250
|
+
|
|
251
|
+
const firstAvg =
|
|
252
|
+
first.reduce((sum, d) => sum + d.compliance, 0) / first.length;
|
|
253
|
+
const secondAvg =
|
|
254
|
+
second.reduce((sum, d) => sum + d.compliance, 0) / second.length;
|
|
255
|
+
|
|
256
|
+
const diff = secondAvg - firstAvg;
|
|
257
|
+
if (diff > 2) trend = "improving";
|
|
258
|
+
else if (diff < -2) trend = "declining";
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const averageCompliance =
|
|
262
|
+
dataPoints.length > 0
|
|
263
|
+
? dataPoints.reduce((sum, d) => sum + d.compliance, 0) / dataPoints.length
|
|
264
|
+
: 0;
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
component,
|
|
268
|
+
period: groupBy,
|
|
269
|
+
dataPoints,
|
|
270
|
+
trend,
|
|
271
|
+
averageCompliance: Math.round(averageCompliance * 100) / 100,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Generate an ASCII sparkline for terminal display
|
|
277
|
+
*/
|
|
278
|
+
generateSparkline(dataPoints: Array<{ compliance: number }>): string {
|
|
279
|
+
if (dataPoints.length === 0) return "─";
|
|
280
|
+
|
|
281
|
+
const chars = " ▁▂▃▄▅▆▇█";
|
|
282
|
+
const values = dataPoints.map((d) => d.compliance);
|
|
283
|
+
const min = Math.min(...values);
|
|
284
|
+
const max = Math.max(...values);
|
|
285
|
+
const range = max - min || 1;
|
|
286
|
+
|
|
287
|
+
return values
|
|
288
|
+
.map((v) => {
|
|
289
|
+
const normalized = (v - min) / range;
|
|
290
|
+
const index = Math.round(normalized * (chars.length - 1));
|
|
291
|
+
return chars[index];
|
|
292
|
+
})
|
|
293
|
+
.join("");
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Delete old metrics beyond retention period
|
|
298
|
+
*/
|
|
299
|
+
async cleanup(retentionDays: number = 90): Promise<number> {
|
|
300
|
+
const cutoffDate = new Date();
|
|
301
|
+
cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
|
|
302
|
+
|
|
303
|
+
let deleted = 0;
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
const files = await readdir(this.metricsDir);
|
|
307
|
+
const { unlink } = await import("node:fs/promises");
|
|
308
|
+
|
|
309
|
+
for (const file of files) {
|
|
310
|
+
if (!file.endsWith(".json")) continue;
|
|
311
|
+
|
|
312
|
+
const dateStr = file.split("_")[0];
|
|
313
|
+
const fileDate = new Date(dateStr);
|
|
314
|
+
|
|
315
|
+
if (fileDate < cutoffDate) {
|
|
316
|
+
await unlink(join(this.metricsDir, file));
|
|
317
|
+
deleted++;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
} catch {
|
|
321
|
+
// Metrics directory doesn't exist
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return deleted;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Create a metrics store instance
|
|
330
|
+
*/
|
|
331
|
+
export function createMetricsStore(projectRoot: string): MetricsStore {
|
|
332
|
+
return new MetricsStore(projectRoot);
|
|
333
|
+
}
|