@buoy-design/core 0.2.0 → 0.2.26

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Buoy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Example Code Analyzer - Example Code vs Production Code Analysis
3
+ *
4
+ * Detects story files and marks components as "example usage".
5
+ * Compares production code against story examples to understand intended usage.
6
+ *
7
+ * Phase 4.3 of BUOY_ROADMAP.md
8
+ */
9
+ import type { Component, DriftSignal } from "../../models/index.js";
10
+ export type ComponentContext = "production" | "example" | "test" | "unknown";
11
+ export interface ComponentWithContext extends Component {
12
+ /** Context where this component was found */
13
+ context: ComponentContext;
14
+ /** Related example components (for production components) */
15
+ relatedExamples?: Component[];
16
+ /** Related production components (for example components) */
17
+ relatedProduction?: Component[];
18
+ }
19
+ /**
20
+ * Determine if a file path is example/story code
21
+ */
22
+ export declare function isExampleFile(path: string): boolean;
23
+ /**
24
+ * Determine if a file path is test code
25
+ */
26
+ export declare function isTestFile(path: string): boolean;
27
+ /**
28
+ * Classify a component's context based on its file path
29
+ */
30
+ export declare function classifyComponentContext(component: Component): ComponentContext;
31
+ /**
32
+ * Annotate components with their context and link related components
33
+ */
34
+ export declare function annotateComponentContexts(components: Component[]): ComponentWithContext[];
35
+ /**
36
+ * Analyze example coverage - which production components have examples
37
+ */
38
+ export declare function analyzeExampleCoverage(components: Component[]): {
39
+ production: Component[];
40
+ withExamples: Component[];
41
+ withoutExamples: Component[];
42
+ exampleOnly: Component[];
43
+ coveragePercent: number;
44
+ };
45
+ /**
46
+ * Compare production component against its example usages
47
+ * Detects patterns used in examples that should be in production
48
+ */
49
+ export declare function compareProductionToExamples(production: ComponentWithContext): Array<{
50
+ type: "missing-variant" | "missing-prop" | "example-only-pattern";
51
+ description: string;
52
+ exampleSource: string;
53
+ }>;
54
+ /**
55
+ * Check example code compliance and generate drift signals
56
+ */
57
+ export declare function checkExampleCompliance(components: Component[]): DriftSignal[];
58
+ //# sourceMappingURL=example-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-analyzer.d.ts","sourceRoot":"","sources":["../../../src/analysis/analyzers/example-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAmB,MAAM,uBAAuB,CAAC;AAwCrF,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,oBAAqB,SAAQ,SAAS;IACrD,6CAA6C;IAC7C,OAAO,EAAE,gBAAgB,CAAC;IAC1B,6DAA6D;IAC7D,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,SAAS,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,SAAS,GAAG,gBAAgB,CAa/E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,SAAS,EAAE,GACtB,oBAAoB,EAAE,CA4BxB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,SAAS,EAAE,GACtB;IACD,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,eAAe,EAAE,SAAS,EAAE,CAAC;IAC7B,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB,CAmBA;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,oBAAoB,GAC/B,KAAK,CAAC;IACP,IAAI,EAAE,iBAAiB,GAAG,cAAc,GAAG,sBAAsB,CAAC;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAyDD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,WAAW,EAAE,CAmG7E"}
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Example Code Analyzer - Example Code vs Production Code Analysis
3
+ *
4
+ * Detects story files and marks components as "example usage".
5
+ * Compares production code against story examples to understand intended usage.
6
+ *
7
+ * Phase 4.3 of BUOY_ROADMAP.md
8
+ */
9
+ import { createStableDriftId } from "../../models/index.js";
10
+ /**
11
+ * Safely get path from component source (handles discriminated union)
12
+ */
13
+ function getSourcePath(source) {
14
+ if (source.type === "react" || source.type === "vue" || source.type === "svelte") {
15
+ return source.path;
16
+ }
17
+ return null;
18
+ }
19
+ // Patterns that identify example/story code
20
+ const EXAMPLE_FILE_PATTERNS = [
21
+ /\.stories\.[jt]sx?$/,
22
+ /\.story\.[jt]sx?$/,
23
+ /\.examples?\.[jt]sx?$/,
24
+ /\.demo\.[jt]sx?$/,
25
+ /\.showcase\.[jt]sx?$/,
26
+ /\/stories\//,
27
+ /\/examples?\//,
28
+ /\/demos?\//,
29
+ /\/playground\//,
30
+ /\/sandbox\//,
31
+ /__stories__\//,
32
+ /__examples__\//,
33
+ /\/docs\//,
34
+ /\.mdx$/,
35
+ ];
36
+ // Patterns that identify test code (not example, but also not production)
37
+ const TEST_FILE_PATTERNS = [
38
+ /\.test\.[jt]sx?$/,
39
+ /\.spec\.[jt]sx?$/,
40
+ /\/__tests__\//,
41
+ /\/tests?\//,
42
+ /\.e2e\.[jt]sx?$/,
43
+ ];
44
+ /**
45
+ * Determine if a file path is example/story code
46
+ */
47
+ export function isExampleFile(path) {
48
+ return EXAMPLE_FILE_PATTERNS.some((p) => p.test(path));
49
+ }
50
+ /**
51
+ * Determine if a file path is test code
52
+ */
53
+ export function isTestFile(path) {
54
+ return TEST_FILE_PATTERNS.some((p) => p.test(path));
55
+ }
56
+ /**
57
+ * Classify a component's context based on its file path
58
+ */
59
+ export function classifyComponentContext(component) {
60
+ const path = getSourcePath(component.source) || "";
61
+ if (isExampleFile(path)) {
62
+ return "example";
63
+ }
64
+ if (isTestFile(path)) {
65
+ return "test";
66
+ }
67
+ if (path) {
68
+ return "production";
69
+ }
70
+ return "unknown";
71
+ }
72
+ /**
73
+ * Annotate components with their context and link related components
74
+ */
75
+ export function annotateComponentContexts(components) {
76
+ const annotated = components.map((c) => ({
77
+ ...c,
78
+ context: classifyComponentContext(c),
79
+ }));
80
+ // Build lookup maps
81
+ const byName = new Map();
82
+ for (const comp of annotated) {
83
+ const name = comp.name.toLowerCase();
84
+ const existing = byName.get(name) || [];
85
+ existing.push(comp);
86
+ byName.set(name, existing);
87
+ }
88
+ // Link related components
89
+ for (const comp of annotated) {
90
+ const name = comp.name.toLowerCase();
91
+ const related = byName.get(name) || [];
92
+ if (comp.context === "production") {
93
+ comp.relatedExamples = related.filter((r) => r.context === "example" && r.id !== comp.id);
94
+ }
95
+ else if (comp.context === "example") {
96
+ comp.relatedProduction = related.filter((r) => r.context === "production" && r.id !== comp.id);
97
+ }
98
+ }
99
+ return annotated;
100
+ }
101
+ /**
102
+ * Analyze example coverage - which production components have examples
103
+ */
104
+ export function analyzeExampleCoverage(components) {
105
+ const annotated = annotateComponentContexts(components);
106
+ const production = annotated.filter((c) => c.context === "production");
107
+ const withExamples = production.filter((c) => (c.relatedExamples?.length || 0) > 0);
108
+ const withoutExamples = production.filter((c) => (c.relatedExamples?.length || 0) === 0);
109
+ const exampleOnly = annotated.filter((c) => c.context === "example" && (c.relatedProduction?.length || 0) === 0);
110
+ return {
111
+ production,
112
+ withExamples,
113
+ withoutExamples,
114
+ exampleOnly,
115
+ coveragePercent: production.length > 0
116
+ ? Math.round((withExamples.length / production.length) * 100)
117
+ : 100,
118
+ };
119
+ }
120
+ /**
121
+ * Compare production component against its example usages
122
+ * Detects patterns used in examples that should be in production
123
+ */
124
+ export function compareProductionToExamples(production) {
125
+ const issues = [];
126
+ if (!production.relatedExamples || production.relatedExamples.length === 0) {
127
+ return issues;
128
+ }
129
+ // Collect all props and variants used in examples
130
+ const exampleProps = new Set();
131
+ const exampleVariants = new Set();
132
+ for (const example of production.relatedExamples) {
133
+ for (const prop of example.props) {
134
+ exampleProps.add(prop.name.toLowerCase());
135
+ }
136
+ for (const variant of example.variants) {
137
+ exampleVariants.add(variant.name.toLowerCase());
138
+ }
139
+ }
140
+ // Compare against production props
141
+ const productionProps = new Set(production.props.map((p) => p.name.toLowerCase()));
142
+ const productionVariants = new Set(production.variants.map((v) => v.name.toLowerCase()));
143
+ // Props in examples but not in production
144
+ for (const prop of exampleProps) {
145
+ if (!productionProps.has(prop)) {
146
+ const exampleComp = production.relatedExamples.find((e) => e.props.some((p) => p.name.toLowerCase() === prop));
147
+ issues.push({
148
+ type: "missing-prop",
149
+ description: `Prop "${prop}" used in examples but not defined in production component`,
150
+ exampleSource: exampleComp ? getSourcePath(exampleComp.source) || "unknown" : "unknown",
151
+ });
152
+ }
153
+ }
154
+ // Variants in examples but not in production
155
+ for (const variant of exampleVariants) {
156
+ if (!productionVariants.has(variant)) {
157
+ const exampleComp = production.relatedExamples.find((e) => e.variants.some((v) => v.name.toLowerCase() === variant));
158
+ issues.push({
159
+ type: "missing-variant",
160
+ description: `Variant "${variant}" used in examples but not defined in production component`,
161
+ exampleSource: exampleComp ? getSourcePath(exampleComp.source) || "unknown" : "unknown",
162
+ });
163
+ }
164
+ }
165
+ return issues;
166
+ }
167
+ /**
168
+ * Check example code compliance and generate drift signals
169
+ */
170
+ export function checkExampleCompliance(components) {
171
+ const drifts = [];
172
+ const coverage = analyzeExampleCoverage(components);
173
+ // Flag production components without examples (info level)
174
+ for (const comp of coverage.withoutExamples) {
175
+ // Skip internal/utility components that typically don't need examples
176
+ const name = comp.name.toLowerCase();
177
+ if (name.includes("context") ||
178
+ name.includes("provider") ||
179
+ name.includes("wrapper") ||
180
+ name.includes("internal") ||
181
+ name.includes("utils")) {
182
+ continue;
183
+ }
184
+ drifts.push({
185
+ id: createStableDriftId("missing-documentation", comp.name),
186
+ type: "missing-documentation",
187
+ severity: "info",
188
+ source: {
189
+ entityType: "component",
190
+ entityId: comp.id,
191
+ entityName: comp.name,
192
+ location: getSourcePath(comp.source) || "",
193
+ },
194
+ message: `Component "${comp.name}" has no example/story files`,
195
+ details: {
196
+ suggestions: [
197
+ "Add a .stories.tsx file to document component usage",
198
+ "Create examples showing common use cases",
199
+ "Consider adding to Storybook for interactive documentation",
200
+ ],
201
+ },
202
+ detectedAt: new Date(),
203
+ });
204
+ }
205
+ // Compare production to examples for inconsistencies
206
+ const annotated = annotateComponentContexts(components);
207
+ for (const comp of annotated.filter((c) => c.context === "production")) {
208
+ const issues = compareProductionToExamples(comp);
209
+ for (const issue of issues) {
210
+ drifts.push({
211
+ id: createStableDriftId("semantic-mismatch", comp.name, {
212
+ property: issue.type,
213
+ }),
214
+ type: "semantic-mismatch",
215
+ severity: "warning",
216
+ source: {
217
+ entityType: "component",
218
+ entityId: comp.id,
219
+ entityName: comp.name,
220
+ location: getSourcePath(comp.source) || "",
221
+ },
222
+ message: `${comp.name}: ${issue.description}`,
223
+ details: {
224
+ expected: "Props/variants defined in production should match example usage",
225
+ actual: issue.description,
226
+ affectedFiles: [issue.exampleSource],
227
+ suggestions: [
228
+ "Add missing prop/variant to production component",
229
+ "Update examples to use only defined props/variants",
230
+ "Document any intentional differences",
231
+ ],
232
+ },
233
+ detectedAt: new Date(),
234
+ });
235
+ }
236
+ }
237
+ // Flag example-only components (might be orphaned examples)
238
+ for (const comp of coverage.exampleOnly) {
239
+ drifts.push({
240
+ id: createStableDriftId("orphaned-component", `example:${comp.name}`),
241
+ type: "orphaned-component",
242
+ severity: "info",
243
+ source: {
244
+ entityType: "component",
245
+ entityId: comp.id,
246
+ entityName: comp.name,
247
+ location: getSourcePath(comp.source) || "",
248
+ },
249
+ message: `Example "${comp.name}" has no corresponding production component`,
250
+ details: {
251
+ suggestions: [
252
+ "This might be a planned component - create the production version",
253
+ "If this is a demo-only component, document it as such",
254
+ "Remove if the example is outdated",
255
+ ],
256
+ },
257
+ detectedAt: new Date(),
258
+ });
259
+ }
260
+ return drifts;
261
+ }
262
+ //# sourceMappingURL=example-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-analyzer.js","sourceRoot":"","sources":["../../../src/analysis/analyzers/example-analyzer.ts"],"names":[],"mappings":"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"}
@@ -3,4 +3,7 @@ export * from "./duplicate-detector.js";
3
3
  export * from "./prop-analyzer.js";
4
4
  export * from "./accessibility-analyzer.js";
5
5
  export * from "./pattern-analyzer.js";
6
+ export * from "./variant-analyzer.js";
7
+ export * from "./token-utility-analyzer.js";
8
+ export * from "./example-analyzer.js";
6
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analysis/analyzers/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analysis/analyzers/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AAGtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
@@ -3,4 +3,8 @@ export * from "./duplicate-detector.js";
3
3
  export * from "./prop-analyzer.js";
4
4
  export * from "./accessibility-analyzer.js";
5
5
  export * from "./pattern-analyzer.js";
6
+ // Phase 4 analyzers
7
+ export * from "./variant-analyzer.js";
8
+ export * from "./token-utility-analyzer.js";
9
+ export * from "./example-analyzer.js";
6
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analysis/analyzers/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analysis/analyzers/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AAEtC,oBAAoB;AACpB,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Token Utility Analyzer - Design Token Utility Function Detection
3
+ *
4
+ * Detects design token utility functions in the codebase (e.g., getSpacing, getRadius)
5
+ * and flags hardcoded values that could use these utilities instead.
6
+ *
7
+ * Phase 4.2 of BUOY_ROADMAP.md
8
+ */
9
+ import type { Component, DriftSignal } from "../../models/index.js";
10
+ export declare const TOKEN_UTILITY_PATTERNS: {
11
+ pattern: RegExp;
12
+ category: string;
13
+ name: string;
14
+ }[];
15
+ export interface DetectedUtility {
16
+ /** Utility function name */
17
+ name: string;
18
+ /** Category of token (spacing, color, etc.) */
19
+ category: string;
20
+ /** File where utility was found */
21
+ file: string;
22
+ /** Line number if available */
23
+ line?: number;
24
+ }
25
+ export interface UtilityAnalysisResult {
26
+ /** Utilities detected in the codebase */
27
+ availableUtilities: DetectedUtility[];
28
+ /** Map of category -> utility names */
29
+ utilitiesByCategory: Map<string, string[]>;
30
+ }
31
+ /**
32
+ * Detect token utility functions from source file contents
33
+ *
34
+ * Note: Component metadata doesn't include source code, so utilities must be
35
+ * detected from file content provided separately (e.g., via additional theme files).
36
+ */
37
+ export declare function detectTokenUtilities(_components: Component[], additionalSources?: Array<{
38
+ content: string;
39
+ file: string;
40
+ }>): UtilityAnalysisResult;
41
+ /**
42
+ * Check if hardcoded values could use available token utilities
43
+ */
44
+ export declare function checkTokenUtilityUsage(components: Component[], utilityAnalysis: UtilityAnalysisResult): DriftSignal[];
45
+ /**
46
+ * Generate a summary of token utility usage in the codebase
47
+ */
48
+ export declare function summarizeTokenUtilityUsage(components: Component[], utilityAnalysis: UtilityAnalysisResult): {
49
+ totalComponents: number;
50
+ componentsWithHardcodedValues: number;
51
+ componentsUsingUtilities: number;
52
+ hardcodedByCategory: Map<string, number>;
53
+ suggestions: string[];
54
+ };
55
+ //# sourceMappingURL=token-utility-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-utility-analyzer.d.ts","sourceRoot":"","sources":["../../../src/analysis/analyzers/token-utility-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAmB,MAAM,uBAAuB,CAAC;AAcrF,eAAO,MAAM,sBAAsB;;;;GA6ClC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,yCAAyC;IACzC,kBAAkB,EAAE,eAAe,EAAE,CAAC;IACtC,uCAAuC;IACvC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC5C;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,SAAS,EAAE,EACxB,iBAAiB,CAAC,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC3D,qBAAqB,CA6BvB;AAsBD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,SAAS,EAAE,EACvB,eAAe,EAAE,qBAAqB,GACrC,WAAW,EAAE,CA2Cf;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,SAAS,EAAE,EACvB,eAAe,EAAE,qBAAqB,GACrC;IACD,eAAe,EAAE,MAAM,CAAC;IACxB,6BAA6B,EAAE,MAAM,CAAC;IACtC,wBAAwB,EAAE,MAAM,CAAC;IACjC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAuCA"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Token Utility Analyzer - Design Token Utility Function Detection
3
+ *
4
+ * Detects design token utility functions in the codebase (e.g., getSpacing, getRadius)
5
+ * and flags hardcoded values that could use these utilities instead.
6
+ *
7
+ * Phase 4.2 of BUOY_ROADMAP.md
8
+ */
9
+ import { createStableDriftId } from "../../models/index.js";
10
+ /**
11
+ * Safely get path from component source (handles discriminated union)
12
+ */
13
+ function getSourcePath(source) {
14
+ if (source.type === "react" || source.type === "vue" || source.type === "svelte") {
15
+ return source.path;
16
+ }
17
+ return null;
18
+ }
19
+ // Common design token utility function patterns
20
+ export const TOKEN_UTILITY_PATTERNS = [
21
+ // Spacing utilities
22
+ { pattern: /\bgetSpacing\b/, category: "spacing", name: "getSpacing" },
23
+ { pattern: /\bspacing\(/, category: "spacing", name: "spacing()" },
24
+ { pattern: /\btheme\.spacing\b/, category: "spacing", name: "theme.spacing" },
25
+ { pattern: /\bspace\[/, category: "spacing", name: "space[]" },
26
+ // Border radius utilities
27
+ { pattern: /\bgetRadius\b/, category: "radius", name: "getRadius" },
28
+ { pattern: /\bradii\(/, category: "radius", name: "radii()" },
29
+ { pattern: /\btheme\.radii\b/, category: "radius", name: "theme.radii" },
30
+ { pattern: /\bborderRadius\[/, category: "radius", name: "borderRadius[]" },
31
+ // Font size utilities
32
+ { pattern: /\bgetFontSize\b/, category: "fontSize", name: "getFontSize" },
33
+ { pattern: /\bfontSize\(/, category: "fontSize", name: "fontSize()" },
34
+ { pattern: /\btheme\.fontSizes\b/, category: "fontSize", name: "theme.fontSizes" },
35
+ { pattern: /\bfontSizes\[/, category: "fontSize", name: "fontSizes[]" },
36
+ // Color utilities
37
+ { pattern: /\bgetColor\b/, category: "color", name: "getColor" },
38
+ { pattern: /\bcolors\(/, category: "color", name: "colors()" },
39
+ { pattern: /\btheme\.colors\b/, category: "color", name: "theme.colors" },
40
+ { pattern: /\bcolors\[/, category: "color", name: "colors[]" },
41
+ // Shadow utilities
42
+ { pattern: /\bgetShadow\b/, category: "shadow", name: "getShadow" },
43
+ { pattern: /\bshadows\(/, category: "shadow", name: "shadows()" },
44
+ { pattern: /\btheme\.shadows\b/, category: "shadow", name: "theme.shadows" },
45
+ // Generic token utilities
46
+ { pattern: /\bgetToken\b/, category: "generic", name: "getToken" },
47
+ { pattern: /\buseToken\b/, category: "generic", name: "useToken" },
48
+ { pattern: /\btoken\(/, category: "generic", name: "token()" },
49
+ { pattern: /\bcssVar\(/, category: "generic", name: "cssVar()" },
50
+ { pattern: /\b--[a-z]+-[a-z]+/, category: "cssVariable", name: "CSS Variable" },
51
+ // Chakra-style utilities
52
+ { pattern: /\buseStyleConfig\b/, category: "generic", name: "useStyleConfig" },
53
+ { pattern: /\buseTheme\b/, category: "generic", name: "useTheme" },
54
+ // Mantine-style utilities
55
+ { pattern: /\buseMantineTheme\b/, category: "generic", name: "useMantineTheme" },
56
+ { pattern: /\brem\(/, category: "spacing", name: "rem()" },
57
+ { pattern: /\bem\(/, category: "spacing", name: "em()" },
58
+ ];
59
+ /**
60
+ * Detect token utility functions from source file contents
61
+ *
62
+ * Note: Component metadata doesn't include source code, so utilities must be
63
+ * detected from file content provided separately (e.g., via additional theme files).
64
+ */
65
+ export function detectTokenUtilities(_components, additionalSources) {
66
+ const utilities = [];
67
+ const seenUtilities = new Set();
68
+ // Scan additional sources (e.g., theme files, config files)
69
+ if (additionalSources) {
70
+ for (const source of additionalSources) {
71
+ for (const util of TOKEN_UTILITY_PATTERNS) {
72
+ if (util.pattern.test(source.content) && !seenUtilities.has(util.name)) {
73
+ seenUtilities.add(util.name);
74
+ utilities.push({
75
+ name: util.name,
76
+ category: util.category,
77
+ file: source.file,
78
+ });
79
+ }
80
+ }
81
+ }
82
+ }
83
+ // Group by category
84
+ const utilitiesByCategory = new Map();
85
+ for (const util of utilities) {
86
+ const existing = utilitiesByCategory.get(util.category) || [];
87
+ existing.push(util.name);
88
+ utilitiesByCategory.set(util.category, existing);
89
+ }
90
+ return { availableUtilities: utilities, utilitiesByCategory };
91
+ }
92
+ /**
93
+ * Map hardcoded value type to utility category
94
+ */
95
+ function mapValueTypeToCategory(type) {
96
+ switch (type) {
97
+ case "spacing":
98
+ case "fontSize":
99
+ return "spacing";
100
+ case "color":
101
+ return "color";
102
+ case "borderRadius":
103
+ case "radius":
104
+ return "radius";
105
+ case "shadow":
106
+ return "shadow";
107
+ default:
108
+ return null;
109
+ }
110
+ }
111
+ /**
112
+ * Check if hardcoded values could use available token utilities
113
+ */
114
+ export function checkTokenUtilityUsage(components, utilityAnalysis) {
115
+ const drifts = [];
116
+ for (const component of components) {
117
+ const hardcodedValues = component.metadata.hardcodedValues || [];
118
+ for (const hardcoded of hardcodedValues) {
119
+ const category = mapValueTypeToCategory(hardcoded.type);
120
+ if (!category)
121
+ continue;
122
+ const availableUtils = utilityAnalysis.utilitiesByCategory.get(category);
123
+ if (!availableUtils || availableUtils.length === 0)
124
+ continue;
125
+ // Found a hardcoded value that has a utility available
126
+ drifts.push({
127
+ id: createStableDriftId("hardcoded-value", component.name, {
128
+ property: hardcoded.property,
129
+ actual: hardcoded.value,
130
+ }),
131
+ type: "hardcoded-value",
132
+ severity: "info",
133
+ source: {
134
+ entityType: "component",
135
+ entityId: component.id,
136
+ entityName: component.name,
137
+ location: hardcoded.location || getSourcePath(component.source) || "",
138
+ },
139
+ message: `Component "${component.name}" has hardcoded ${hardcoded.type} value "${hardcoded.value}" that could use ${availableUtils[0]}`,
140
+ details: {
141
+ expected: `Use token utility: ${availableUtils.join(" or ")}`,
142
+ actual: `Hardcoded value: ${hardcoded.value}`,
143
+ suggestions: [
144
+ `Replace "${hardcoded.value}" with ${availableUtils[0]}(...)`,
145
+ `Available utilities: ${availableUtils.join(", ")}`,
146
+ `Check if a design token exists for this value`,
147
+ ],
148
+ },
149
+ detectedAt: new Date(),
150
+ });
151
+ }
152
+ }
153
+ return drifts;
154
+ }
155
+ /**
156
+ * Generate a summary of token utility usage in the codebase
157
+ */
158
+ export function summarizeTokenUtilityUsage(components, utilityAnalysis) {
159
+ const componentsWithHardcoded = components.filter((c) => (c.metadata.hardcodedValues?.length || 0) > 0);
160
+ // Count hardcoded values by category
161
+ const hardcodedByCategory = new Map();
162
+ for (const component of components) {
163
+ for (const h of component.metadata.hardcodedValues || []) {
164
+ const category = mapValueTypeToCategory(h.type);
165
+ if (category) {
166
+ hardcodedByCategory.set(category, (hardcodedByCategory.get(category) || 0) + 1);
167
+ }
168
+ }
169
+ }
170
+ // Generate suggestions
171
+ const suggestions = [];
172
+ for (const [category, count] of hardcodedByCategory) {
173
+ const utils = utilityAnalysis.utilitiesByCategory.get(category);
174
+ if (utils && utils.length > 0) {
175
+ suggestions.push(`${count} hardcoded ${category} values could use ${utils[0]}`);
176
+ }
177
+ else {
178
+ suggestions.push(`Consider adding a token utility for ${category} (${count} hardcoded values)`);
179
+ }
180
+ }
181
+ return {
182
+ totalComponents: components.length,
183
+ componentsWithHardcodedValues: componentsWithHardcoded.length,
184
+ // Note: Utility usage count requires source code analysis which is done at scan time
185
+ componentsUsingUtilities: 0,
186
+ hardcodedByCategory,
187
+ suggestions,
188
+ };
189
+ }
190
+ //# sourceMappingURL=token-utility-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-utility-analyzer.js","sourceRoot":"","sources":["../../../src/analysis/analyzers/token-utility-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Variant Analyzer - Cross-Variant Consistency Checking
3
+ *
4
+ * Detects components in variant directories (e.g., registry/default/, registry/new-york/)
5
+ * and flags differences between same-named components across variants.
6
+ *
7
+ * Phase 4.1 of BUOY_ROADMAP.md
8
+ */
9
+ import type { Component, DriftSignal, Severity } from "../../models/index.js";
10
+ export interface VariantGroup {
11
+ /** Component name (shared across variants) */
12
+ componentName: string;
13
+ /** Map of variant name -> component */
14
+ variants: Map<string, Component>;
15
+ }
16
+ export interface VariantDifference {
17
+ /** Type of difference */
18
+ type: "prop-missing" | "prop-type" | "variant-missing" | "style-value";
19
+ /** Affected prop or variant name */
20
+ field: string;
21
+ /** Variant A name and value */
22
+ variantA: {
23
+ name: string;
24
+ value: unknown;
25
+ };
26
+ /** Variant B name and value */
27
+ variantB: {
28
+ name: string;
29
+ value: unknown;
30
+ };
31
+ /** Severity of the difference */
32
+ severity: Severity;
33
+ }
34
+ /**
35
+ * Extract variant name from component path
36
+ * @returns variant name or null if not in a variant directory
37
+ */
38
+ export declare function extractVariantName(path: string): string | null;
39
+ /**
40
+ * Group components by name across variants
41
+ */
42
+ export declare function groupComponentsByVariant(components: Component[]): VariantGroup[];
43
+ /**
44
+ * Compare two components across variants and find differences
45
+ */
46
+ export declare function compareVariants(componentA: Component, variantA: string, componentB: Component, variantB: string): VariantDifference[];
47
+ /**
48
+ * Check all component variants for consistency and generate drift signals
49
+ */
50
+ export declare function checkVariantConsistency(components: Component[]): DriftSignal[];
51
+ //# sourceMappingURL=variant-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variant-analyzer.d.ts","sourceRoot":"","sources":["../../../src/analysis/analyzers/variant-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAmB,MAAM,uBAAuB,CAAC;AA6B/F,MAAM,WAAW,YAAY;IAC3B,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,IAAI,EAAE,cAAc,GAAG,WAAW,GAAG,iBAAiB,GAAG,aAAa,CAAC;IACvE,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,+BAA+B;IAC/B,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,iCAAiC;IACjC,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ9D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAkChF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,SAAS,EACrB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,SAAS,EACrB,QAAQ,EAAE,MAAM,GACf,iBAAiB,EAAE,CAsGrB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,WAAW,EAAE,CA2F9E"}
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Variant Analyzer - Cross-Variant Consistency Checking
3
+ *
4
+ * Detects components in variant directories (e.g., registry/default/, registry/new-york/)
5
+ * and flags differences between same-named components across variants.
6
+ *
7
+ * Phase 4.1 of BUOY_ROADMAP.md
8
+ */
9
+ import { createStableDriftId } from "../../models/index.js";
10
+ /**
11
+ * Safely get path from component source (handles discriminated union)
12
+ */
13
+ function getSourcePath(source) {
14
+ if (source.type === "react" || source.type === "vue" || source.type === "svelte") {
15
+ return source.path;
16
+ }
17
+ return null;
18
+ }
19
+ // Common variant directory patterns
20
+ const VARIANT_PATTERNS = [
21
+ // shadcn/ui registry variants
22
+ /registry\/([^/]+)\/ui\//,
23
+ /registry\/([^/]+)\/components\//,
24
+ /registry\/([^/]+)\/blocks\//,
25
+ // Generic theme/style variants
26
+ /themes?\/([^/]+)\//,
27
+ /styles?\/([^/]+)\//,
28
+ /variants?\/([^/]+)\//,
29
+ // Platform variants
30
+ /platforms?\/([^/]+)\//,
31
+ // Brand variants
32
+ /brands?\/([^/]+)\//,
33
+ ];
34
+ /**
35
+ * Extract variant name from component path
36
+ * @returns variant name or null if not in a variant directory
37
+ */
38
+ export function extractVariantName(path) {
39
+ for (const pattern of VARIANT_PATTERNS) {
40
+ const match = path.match(pattern);
41
+ if (match && match[1]) {
42
+ return match[1];
43
+ }
44
+ }
45
+ return null;
46
+ }
47
+ /**
48
+ * Group components by name across variants
49
+ */
50
+ export function groupComponentsByVariant(components) {
51
+ const groups = new Map();
52
+ for (const component of components) {
53
+ const path = getSourcePath(component.source) || "";
54
+ const variantName = extractVariantName(path);
55
+ if (!variantName)
56
+ continue;
57
+ const normalizedName = component.name.toLowerCase();
58
+ let variantMap = groups.get(normalizedName);
59
+ if (!variantMap) {
60
+ variantMap = new Map();
61
+ groups.set(normalizedName, variantMap);
62
+ }
63
+ // Store only the first component found for each variant
64
+ if (!variantMap.has(variantName)) {
65
+ variantMap.set(variantName, component);
66
+ }
67
+ }
68
+ // Filter to only groups with multiple variants
69
+ const result = [];
70
+ for (const [name, variants] of groups) {
71
+ if (variants.size > 1) {
72
+ result.push({
73
+ componentName: name,
74
+ variants,
75
+ });
76
+ }
77
+ }
78
+ return result;
79
+ }
80
+ /**
81
+ * Compare two components across variants and find differences
82
+ */
83
+ export function compareVariants(componentA, variantA, componentB, variantB) {
84
+ const differences = [];
85
+ // Compare props
86
+ const propsA = new Map(componentA.props.map((p) => [p.name.toLowerCase(), p]));
87
+ const propsB = new Map(componentB.props.map((p) => [p.name.toLowerCase(), p]));
88
+ // Props in A but not in B
89
+ for (const [name, prop] of propsA) {
90
+ if (!propsB.has(name)) {
91
+ differences.push({
92
+ type: "prop-missing",
93
+ field: prop.name,
94
+ variantA: { name: variantA, value: prop },
95
+ variantB: { name: variantB, value: undefined },
96
+ severity: prop.required ? "warning" : "info",
97
+ });
98
+ }
99
+ else {
100
+ const propB = propsB.get(name);
101
+ if (prop.type !== propB.type) {
102
+ differences.push({
103
+ type: "prop-type",
104
+ field: prop.name,
105
+ variantA: { name: variantA, value: prop.type },
106
+ variantB: { name: variantB, value: propB.type },
107
+ severity: "warning",
108
+ });
109
+ }
110
+ }
111
+ }
112
+ // Props in B but not in A
113
+ for (const [name, prop] of propsB) {
114
+ if (!propsA.has(name)) {
115
+ differences.push({
116
+ type: "prop-missing",
117
+ field: prop.name,
118
+ variantA: { name: variantA, value: undefined },
119
+ variantB: { name: variantB, value: prop },
120
+ severity: prop.required ? "warning" : "info",
121
+ });
122
+ }
123
+ }
124
+ // Compare component variants (sizes, colors, etc.)
125
+ const variantsA = new Set(componentA.variants.map((v) => v.name.toLowerCase()));
126
+ const variantsB = new Set(componentB.variants.map((v) => v.name.toLowerCase()));
127
+ for (const variant of variantsA) {
128
+ if (!variantsB.has(variant)) {
129
+ differences.push({
130
+ type: "variant-missing",
131
+ field: variant,
132
+ variantA: { name: variantA, value: true },
133
+ variantB: { name: variantB, value: false },
134
+ severity: "info",
135
+ });
136
+ }
137
+ }
138
+ for (const variant of variantsB) {
139
+ if (!variantsA.has(variant)) {
140
+ differences.push({
141
+ type: "variant-missing",
142
+ field: variant,
143
+ variantA: { name: variantA, value: false },
144
+ variantB: { name: variantB, value: true },
145
+ severity: "info",
146
+ });
147
+ }
148
+ }
149
+ // Compare hardcoded values (style differences)
150
+ const hardcodedA = componentA.metadata.hardcodedValues || [];
151
+ const hardcodedB = componentB.metadata.hardcodedValues || [];
152
+ // Group by property for comparison
153
+ const styleMapA = new Map();
154
+ const styleMapB = new Map();
155
+ for (const h of hardcodedA) {
156
+ styleMapA.set(h.property, h.value);
157
+ }
158
+ for (const h of hardcodedB) {
159
+ styleMapB.set(h.property, h.value);
160
+ }
161
+ // Check for same property with different values
162
+ for (const [prop, valueA] of styleMapA) {
163
+ const valueB = styleMapB.get(prop);
164
+ if (valueB && valueA !== valueB) {
165
+ differences.push({
166
+ type: "style-value",
167
+ field: prop,
168
+ variantA: { name: variantA, value: valueA },
169
+ variantB: { name: variantB, value: valueB },
170
+ severity: "warning",
171
+ });
172
+ }
173
+ }
174
+ return differences;
175
+ }
176
+ /**
177
+ * Check all component variants for consistency and generate drift signals
178
+ */
179
+ export function checkVariantConsistency(components) {
180
+ const drifts = [];
181
+ const groups = groupComponentsByVariant(components);
182
+ for (const group of groups) {
183
+ const variantNames = Array.from(group.variants.keys());
184
+ // Compare each pair of variants
185
+ for (let i = 0; i < variantNames.length; i++) {
186
+ for (let j = i + 1; j < variantNames.length; j++) {
187
+ const variantA = variantNames[i];
188
+ const variantB = variantNames[j];
189
+ const componentA = group.variants.get(variantA);
190
+ const componentB = group.variants.get(variantB);
191
+ const differences = compareVariants(componentA, variantA, componentB, variantB);
192
+ if (differences.length > 0) {
193
+ // Group differences by severity
194
+ const critical = differences.filter((d) => d.severity === "critical");
195
+ const warnings = differences.filter((d) => d.severity === "warning");
196
+ const severity = critical.length > 0 ? "critical" : warnings.length > 0 ? "warning" : "info";
197
+ // Create a summary of differences
198
+ const diffSummary = differences
199
+ .slice(0, 5)
200
+ .map((d) => {
201
+ if (d.type === "prop-missing") {
202
+ const hasIt = d.variantA.value ? d.variantA.name : d.variantB.name;
203
+ return `${d.field} only in ${hasIt}`;
204
+ }
205
+ else if (d.type === "prop-type") {
206
+ return `${d.field}: ${d.variantA.value} vs ${d.variantB.value}`;
207
+ }
208
+ else if (d.type === "style-value") {
209
+ return `${d.field}: ${d.variantA.value} vs ${d.variantB.value}`;
210
+ }
211
+ return `${d.field} differs`;
212
+ })
213
+ .join(", ");
214
+ const moreCount = differences.length - 5;
215
+ const summary = moreCount > 0 ? `${diffSummary}, +${moreCount} more` : diffSummary;
216
+ drifts.push({
217
+ id: createStableDriftId("value-divergence", group.componentName, {
218
+ property: `${variantA}-vs-${variantB}`,
219
+ }),
220
+ type: "value-divergence",
221
+ severity,
222
+ source: {
223
+ entityType: "component",
224
+ entityId: componentA.id,
225
+ entityName: componentA.name,
226
+ location: getSourcePath(componentA.source) || "",
227
+ },
228
+ target: {
229
+ entityType: "component",
230
+ entityId: componentB.id,
231
+ entityName: componentB.name,
232
+ location: getSourcePath(componentB.source) || "",
233
+ },
234
+ message: `Component "${group.componentName}" has ${differences.length} difference${differences.length > 1 ? "s" : ""} between ${variantA} and ${variantB} variants: ${summary}`,
235
+ details: {
236
+ expected: `Consistent implementation across variants`,
237
+ actual: `${differences.length} differences found`,
238
+ diff: JSON.stringify(differences.map((d) => ({
239
+ type: d.type,
240
+ field: d.field,
241
+ [d.variantA.name]: d.variantA.value,
242
+ [d.variantB.name]: d.variantB.value,
243
+ })), null, 2),
244
+ suggestions: [
245
+ "Review variant differences for intentionality",
246
+ "Document intentional differences in design system documentation",
247
+ "Align implementations if differences are unintentional",
248
+ ],
249
+ },
250
+ detectedAt: new Date(),
251
+ });
252
+ }
253
+ }
254
+ }
255
+ }
256
+ return drifts;
257
+ }
258
+ //# sourceMappingURL=variant-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variant-analyzer.js","sourceRoot":"","sources":["../../../src/analysis/analyzers/variant-analyzer.ts"],"names":[],"mappings":"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"}
@@ -5,4 +5,7 @@ export { MATCHING_CONFIG, NAMING_CONFIG, TOKEN_SUGGESTION_CONFIG, SCANNER_CONFIG
5
5
  export { generateAuditReport, findCloseMatches, calculateHealthScore, type AuditValue, type AuditReport, type CategoryStats, type FileIssue, type CloseMatch, } from "./audit.js";
6
6
  export { DriftAggregator, createStrategy, builtInStrategies, type DriftGroup, type AggregationResult, type GroupingStrategy, type AggregatorOptions, type BuiltInStrategyType, } from "./drift-aggregator.js";
7
7
  export { detectRepeatedPatterns, normalizeClassPattern, groupPatterns, type ClassOccurrence, type PatternAnalyzerOptions, } from "./analyzers/pattern-analyzer.js";
8
+ export { checkVariantConsistency, groupComponentsByVariant, compareVariants, extractVariantName, type VariantGroup, type VariantDifference, } from "./analyzers/variant-analyzer.js";
9
+ export { detectTokenUtilities, checkTokenUtilityUsage, summarizeTokenUtilityUsage, TOKEN_UTILITY_PATTERNS, type DetectedUtility, type UtilityAnalysisResult, } from "./analyzers/token-utility-analyzer.js";
10
+ export { checkExampleCompliance, analyzeExampleCoverage, annotateComponentContexts, classifyComponentContext, isExampleFile, isTestFile, type ComponentContext, type ComponentWithContext, } from "./analyzers/example-analyzer.js";
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analysis/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,sBAAsB,EACtB,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analysis/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,sBAAsB,EACtB,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,eAAe,EACf,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,qBAAqB,GAC3B,MAAM,uCAAuC,CAAC;AAG/C,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,aAAa,EACb,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC"}
@@ -11,4 +11,10 @@ export { generateAuditReport, findCloseMatches, calculateHealthScore, } from "./
11
11
  export { DriftAggregator, createStrategy, builtInStrategies, } from "./drift-aggregator.js";
12
12
  // Pattern analyzer (experimental)
13
13
  export { detectRepeatedPatterns, normalizeClassPattern, groupPatterns, } from "./analyzers/pattern-analyzer.js";
14
+ // Variant analyzer (Phase 4.1)
15
+ export { checkVariantConsistency, groupComponentsByVariant, compareVariants, extractVariantName, } from "./analyzers/variant-analyzer.js";
16
+ // Token utility analyzer (Phase 4.2)
17
+ export { detectTokenUtilities, checkTokenUtilityUsage, summarizeTokenUtilityUsage, TOKEN_UTILITY_PATTERNS, } from "./analyzers/token-utility-analyzer.js";
18
+ // Example code analyzer (Phase 4.3)
19
+ export { checkExampleCompliance, analyzeExampleCoverage, annotateComponentContexts, classifyComponentContext, isExampleFile, isTestFile, } from "./analyzers/example-analyzer.js";
14
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analysis/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAOnB,MAAM,oBAAoB,CAAC;AAE5B,6BAA6B;AAC7B,OAAO,EACL,sBAAsB,GAEvB,MAAM,wBAAwB,CAAC;AAEhC,mBAAmB;AACnB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,yBAAyB;AACzB,OAAO,EACL,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,eAAe;AACf,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,GAMrB,MAAM,YAAY,CAAC;AAEpB,oBAAoB;AACpB,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,GAMlB,MAAM,uBAAuB,CAAC;AAE/B,kCAAkC;AAClC,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,GAGd,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analysis/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAOnB,MAAM,oBAAoB,CAAC;AAE5B,6BAA6B;AAC7B,OAAO,EACL,sBAAsB,GAEvB,MAAM,wBAAwB,CAAC;AAEhC,mBAAmB;AACnB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,yBAAyB;AACzB,OAAO,EACL,eAAe,EACf,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,eAAe;AACf,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,GAMrB,MAAM,YAAY,CAAC;AAEpB,oBAAoB;AACpB,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,GAMlB,MAAM,uBAAuB,CAAC;AAE/B,kCAAkC;AAClC,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,GAGd,MAAM,iCAAiC,CAAC;AAEzC,+BAA+B;AAC/B,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,eAAe,EACf,kBAAkB,GAGnB,MAAM,iCAAiC,CAAC;AAEzC,qCAAqC;AACrC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,sBAAsB,GAGvB,MAAM,uCAAuC,CAAC;AAE/C,oCAAoC;AACpC,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,aAAa,EACb,UAAU,GAGX,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Pure type re-exports for Worker-compatible environments.
3
+ * Import from '@buoy-design/core/types' to avoid pulling in
4
+ * Node.js dependencies (fs, glob, simple-git).
5
+ */
6
+ export type { DriftSignal, DriftType, Severity, DriftSource, DriftDetails, DriftResolution, DriftResolutionType, GitContext, } from './models/drift.js';
7
+ export { DriftTypeSchema, SeveritySchema, DriftSignalSchema, DriftSourceSchema, DriftDetailsSchema, DRIFT_TYPE_LABELS, DRIFT_TYPE_DESCRIPTIONS, SEVERITY_LABELS, getSeverityWeight, getDefaultSeverity, } from './models/drift.js';
8
+ export type { DesignToken, TokenCategory, TokenValue, ColorValue, SpacingValue, TypographyValue, ShadowValue, BorderValue, RawValue, TokenSource, TokenMetadata, } from './models/token.js';
9
+ export type { Component, PropDefinition, VariantDefinition, AccessibilityInfo, HardcodedValue, ComponentSource, } from './models/component.js';
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,WAAW,EACX,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,UAAU,GACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACV,WAAW,EACX,aAAa,EACb,UAAU,EACV,UAAU,EACV,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,QAAQ,EACR,WAAW,EACX,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACV,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,uBAAuB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Pure type re-exports for Worker-compatible environments.
3
+ * Import from '@buoy-design/core/types' to avoid pulling in
4
+ * Node.js dependencies (fs, glob, simple-git).
5
+ */
6
+ export { DriftTypeSchema, SeveritySchema, DriftSignalSchema, DriftSourceSchema, DriftDetailsSchema, DRIFT_TYPE_LABELS, DRIFT_TYPE_DESCRIPTIONS, SEVERITY_LABELS, getSeverityWeight, getDefaultSeverity, } from './models/drift.js';
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-design/core",
3
- "version": "0.2.0",
3
+ "version": "0.2.26",
4
4
  "description": "Core domain models and analysis for Buoy design drift detection",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,16 +38,12 @@
38
38
  "./analysis": {
39
39
  "types": "./dist/analysis/index.d.ts",
40
40
  "import": "./dist/analysis/index.js"
41
+ },
42
+ "./types": {
43
+ "types": "./dist/types.d.ts",
44
+ "import": "./dist/types.js"
41
45
  }
42
46
  },
43
- "scripts": {
44
- "build": "tsc",
45
- "dev": "tsc --watch",
46
- "typecheck": "tsc --noEmit",
47
- "clean": "rm -rf dist",
48
- "test": "vitest run",
49
- "test:watch": "vitest"
50
- },
51
47
  "dependencies": {
52
48
  "glob": "^11.0.0",
53
49
  "graphology": "^0.26.0",
@@ -57,5 +53,13 @@
57
53
  },
58
54
  "devDependencies": {
59
55
  "typescript": "^5.7.2"
56
+ },
57
+ "scripts": {
58
+ "build": "tsc",
59
+ "dev": "tsc --watch",
60
+ "typecheck": "tsc --noEmit",
61
+ "clean": "rm -rf dist",
62
+ "test": "vitest run",
63
+ "test:watch": "vitest"
60
64
  }
61
- }
65
+ }